WIP CZ: Reversed some functions of bots.

Cleanup.
This commit is contained in:
s1lentq 2016-01-19 17:54:31 +06:00
parent 51e921b0f6
commit 6f51a65ae9
84 changed files with 13485 additions and 7251 deletions

View File

@ -28,7 +28,7 @@ Archive's bin directory contains 2 subdirectories, 'bugfixed' and 'pure'
## Current status ## Current status
<ul> <ul>
<li> Counter-Strike 1.6 - 100%</li> <li> Counter-Strike 1.6 - 100%</li>
<li> Counter-Strike: Condition Zero - 63%</li> <li> Counter-Strike: Condition Zero - 90%</li>
</ul> </ul>
## Build instructions ## Build instructions

View File

@ -170,7 +170,7 @@ void setupToolchain(NativeBinarySpec b)
'_vsnprintf': 'vsnprintf', '_vsnprintf': 'vsnprintf',
'_write' : 'write', '_write' : 'write',
'_close' : 'close', '_close' : 'close',
'_vsnwprintf' : 'vsnwprintf' '_vsnwprintf' : 'vswprintf'
]) ])
cfg.linkerOptions.args '-no-opt-class-analysis' cfg.linkerOptions.args '-no-opt-class-analysis'

View File

@ -39,7 +39,7 @@
typedef double float_precision; typedef double float_precision;
#else // HOOK_GAMEDLL #else // PLAY_GAMEDLL
typedef float float_precision; typedef float float_precision;
@ -76,6 +76,22 @@ T Q_max(T a, T b) { return (a > b) ? a : b; }
template <typename T> template <typename T>
T clamp(T a, T min, T max) { return (a > max) ? max : (a < min) ? min : a; } T clamp(T a, T min, T max) { return (a > max) ? max : (a < min) ? min : a; }
// bitwise operators templates
template<class T, class type=typename std::underlying_type<T>::type>
inline T operator~ (T a) { return (T)~(type)a; }
template<class T, class type=typename std::underlying_type<T>::type>
inline T operator| (T a, T b) { return (T)((type)a | (type)b); }
template<class T, class type=typename std::underlying_type<T>::type>
inline T operator& (T a, T b) { return (T)((type)a & (type)b); }
template<class T, class type=typename std::underlying_type<T>::type>
inline T operator^ (T a, T b) { return (T)((type)a ^ (type)b); }
template<class T, class type=typename std::underlying_type<T>::type>
inline T& operator|= (T& a, T b){ return (T&)((type&)a |= (type)b); }
template<class T, class type=typename std::underlying_type<T>::type>
inline T& operator&= (T& a, T b){ return (T&)((type&)a &= (type)b); }
template<class T, class type=typename std::underlying_type<T>::type>
inline T& operator^= (T& a, T b){ return (T&)((type&)a ^= (type)b); }
#define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];} #define VectorSubtract(a,b,c) {(c)[0]=(a)[0]-(b)[0];(c)[1]=(a)[1]-(b)[1];(c)[2]=(a)[2]-(b)[2];}
#define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];} #define VectorAdd(a,b,c) {(c)[0]=(a)[0]+(b)[0];(c)[1]=(a)[1]+(b)[1];(c)[2]=(a)[2]+(b)[2];}
#define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];} #define VectorCopy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];}

View File

@ -32,12 +32,9 @@
#pragma once #pragma once
#endif #endif
#define ACTIVITY_NOT_AVAILABLE -1
typedef enum typedef enum
{ {
//TODO: i think it need added (from hlbeta2) ACT_INVALID = -1,
//ACT_INVALID = -1,
ACT_RESET = 0, // Set m_Activity to this invalid value to force a reset to m_IdealActivity ACT_RESET = 0, // Set m_Activity to this invalid value to force a reset to m_IdealActivity
ACT_IDLE, ACT_IDLE,

View File

@ -119,7 +119,7 @@ int LookupActivity(void *pmodel, entvars_t *pev, int activity)
} }
} }
return ACTIVITY_NOT_AVAILABLE; return ACT_INVALID;
} }
/* <1539a> ../cstrike/dlls/animation.cpp:149 */ /* <1539a> ../cstrike/dlls/animation.cpp:149 */
@ -134,7 +134,7 @@ int LookupActivityHeaviest(void *pmodel, entvars_t *pev, int activity)
mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex); mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
int weight = 0; int weight = 0;
int seq = ACTIVITY_NOT_AVAILABLE; int seq = ACT_INVALID;
for (int i = 0; i < pstudiohdr->numseq; i++) for (int i = 0; i < pstudiohdr->numseq; i++)
{ {
@ -179,13 +179,16 @@ int LookupSequence(void *pmodel, const char *label)
return 0; return 0;
} }
// Look up by sequence name.
mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex); mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
for (int i = 0; i < pstudiohdr->numseq; i++) for (int i = 0; i < pstudiohdr->numseq; i++)
{ {
if (!Q_stricmp(pseqdesc[i].label, label)) if (!Q_stricmp(pseqdesc[i].label, label))
return i; return i;
} }
return -1;
// Not found
return ACT_INVALID;
} }
/* <1518c> ../cstrike/dlls/animation.cpp:215 */ /* <1518c> ../cstrike/dlls/animation.cpp:215 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@
#define UNDEFINED_COUNT 0xFFFF #define UNDEFINED_COUNT 0xFFFF
#define MAX_PLACES_PER_MAP 64 #define MAX_PLACES_PER_MAP 64
#define UNDEFINED_SUBJECT (-1) #define UNDEFINED_SUBJECT (-1)
#define COUNT_MANY 4 #define COUNT_MANY 4 // equal to or greater than this is "many"
class CCSBot; class CCSBot;
class BotChatterInterface; class BotChatterInterface;
@ -43,27 +43,41 @@ class BotChatterInterface;
typedef unsigned int PlaceCriteria; typedef unsigned int PlaceCriteria;
typedef unsigned int CountCriteria; typedef unsigned int CountCriteria;
// A meme is a unit information that bots use to
// transmit information to each other via the radio
/* <2fe97b> ../cstrike/dlls/bot/cs_bot_chatter.h:42 */ /* <2fe97b> ../cstrike/dlls/bot/cs_bot_chatter.h:42 */
class BotMeme class BotMeme
{ {
public: public:
NOBODY void Transmit(CCSBot *sender) const; void Transmit(CCSBot *sender) const; // transmit meme to other bots
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const = 0; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const = 0; // cause the given bot to act on this meme
};/* size: 4, cachelines: 1, members: 1 */ };/* size: 4, cachelines: 1, members: 1 */
class BotAllHostagesGoneMeme: public BotMeme class BotAllHostagesGoneMeme: public BotMeme
{ {
public: public:
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; // cause the given bot to act on this meme
#ifdef HOOK_GAMEDLL
void Interpret_(CCSBot *sender, CCSBot *receiver) const;
#endif //HOOK_GAMEDLL
};/* size: 4, cachelines: 1, members: 1 */ };/* size: 4, cachelines: 1, members: 1 */
class BotHostageBeingTakenMeme: public BotMeme class BotHostageBeingTakenMeme: public BotMeme
{ {
public: public:
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; // cause the given bot to act on this meme
#ifdef HOOK_GAMEDLL
void Interpret_(CCSBot *sender, CCSBot *receiver) const;
#endif //HOOK_GAMEDLL
};/* size: 4, cachelines: 1, members: 1 */ };/* size: 4, cachelines: 1, members: 1 */
@ -75,7 +89,14 @@ public:
{ {
m_place = place; m_place = place;
} }
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; // cause the given bot to act on this meme
#ifdef HOOK_GAMEDLL
void Interpret_(CCSBot *sender, CCSBot *receiver) const;
#endif //HOOK_GAMEDLL
private: private:
Place m_place; Place m_place;
@ -85,24 +106,27 @@ private:
class BotBombsiteStatusMeme: public BotMeme class BotBombsiteStatusMeme: public BotMeme
{ {
public: public:
enum StatusType enum StatusType { CLEAR, PLANTED };
{
CLEAR = 0,
PLANTED
};
BotBombsiteStatusMeme(int zoneIndex, StatusType status) BotBombsiteStatusMeme(int zoneIndex, StatusType status)
{ {
m_zoneIndex = zoneIndex; m_zoneIndex = zoneIndex;
m_status = status; m_status = status;
} }
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; // cause the given bot to act on this meme
#ifdef HOOK_GAMEDLL
void Interpret_(CCSBot *sender, CCSBot *receiver) const;
#endif //HOOK_GAMEDLL
private: private:
int m_zoneIndex; int m_zoneIndex; // the bombsite
StatusType m_status; StatusType m_status; // whether it is cleared or the bomb is there (planted)
};/* size: 12, cachelines: 1, members: 3 */ };/* size: 12, cachelines: 1, members: 3 */
/* <2ff6de> ../cstrike/dlls/bot/cs_bot_chatter.h:87 */ /* <2ff6de> ../cstrike/dlls/bot/cs_bot_chatter.h:87 */
class BotBombStatusMeme: public BotMeme class BotBombStatusMeme: public BotMeme
{ {
@ -112,8 +136,16 @@ public:
m_state = state; m_state = state;
m_pos = pos; m_pos = pos;
} }
public: public:
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; // cause the given bot to act on this meme
#ifdef HOOK_GAMEDLL
void Interpret_(CCSBot *sender, CCSBot *receiver) const;
#endif //HOOK_GAMEDLL
private: private:
CSGameState::BombState m_state; CSGameState::BombState m_state;
Vector m_pos; Vector m_pos;
@ -124,7 +156,13 @@ private:
class BotFollowMeme: public BotMeme class BotFollowMeme: public BotMeme
{ {
public: public:
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; // cause the given bot to act on this meme
#ifdef HOOK_GAMEDLL
void Interpret_(CCSBot *sender, CCSBot *receiver) const;
#endif //HOOK_GAMEDLL
};/* size: 4, cachelines: 1, members: 1 */ };/* size: 4, cachelines: 1, members: 1 */
@ -136,7 +174,14 @@ public:
{ {
m_pos = pos; m_pos = pos;
} }
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; // cause the given bot to act on this meme
#ifdef HOOK_GAMEDLL
void Interpret_(CCSBot *sender, CCSBot *receiver) const;
#endif //HOOK_GAMEDLL
private: private:
Vector m_pos; Vector m_pos;
@ -146,7 +191,13 @@ private:
class BotWhereBombMeme: public BotMeme class BotWhereBombMeme: public BotMeme
{ {
public: public:
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; // cause the given bot to act on this meme
#ifdef HOOK_GAMEDLL
void Interpret_(CCSBot *sender, CCSBot *receiver) const;
#endif //HOOK_GAMEDLL
};/* size: 4, cachelines: 1, members: 1 */ };/* size: 4, cachelines: 1, members: 1 */
@ -154,13 +205,19 @@ public:
class BotRequestReportMeme: public BotMeme class BotRequestReportMeme: public BotMeme
{ {
public: public:
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; virtual void Interpret(CCSBot *sender, CCSBot *receiver) const; // cause the given bot to act on this meme
#ifdef HOOK_GAMEDLL
void Interpret_(CCSBot *sender, CCSBot *receiver) const;
#endif //HOOK_GAMEDLL
};/* size: 4, cachelines: 1, members: 1 */ };/* size: 4, cachelines: 1, members: 1 */
enum BotStatementType enum BotStatementType
{ {
REPORT_VISIBLE_ENEMIES = 0, REPORT_VISIBLE_ENEMIES,
REPORT_ENEMY_ACTION, REPORT_ENEMY_ACTION,
REPORT_MY_CURRENT_TASK, REPORT_MY_CURRENT_TASK,
REPORT_MY_INTENTION, REPORT_MY_INTENTION,
@ -171,13 +228,17 @@ enum BotStatementType
REPORT_MY_PLAN, REPORT_MY_PLAN,
REPORT_INFORMATION, REPORT_INFORMATION,
REPORT_EMOTE, REPORT_EMOTE,
REPORT_ACKNOWLEDGE, REPORT_ACKNOWLEDGE, // affirmative or negative
REPORT_ENEMIES_REMAINING, REPORT_ENEMIES_REMAINING,
REPORT_FRIENDLY_FIRE, REPORT_FRIENDLY_FIRE,
REPORT_KILLED_FRIEND, REPORT_KILLED_FRIEND,
//REPORT_ENEMY_LOST
NUM_BOT_STATEMENT_TYPES, NUM_BOT_STATEMENT_TYPES,
}; };
// BotSpeakables are the smallest unit of bot chatter.
// They represent a specific wav file of a phrase, and the criteria for which it is useful
class BotSpeakable class BotSpeakable
{ {
public: public:
@ -194,53 +255,45 @@ public:
typedef std::STD_VECTOR<BotSpeakable *> BotSpeakableVector; typedef std::STD_VECTOR<BotSpeakable *> BotSpeakableVector;
typedef std::STD_VECTOR<BotSpeakableVector *> BotVoiceBankVector; typedef std::STD_VECTOR<BotSpeakableVector *> BotVoiceBankVector;
// The BotPhrase class is a collection of Speakables associated with a name, ID, and criteria
class BotPhrase class BotPhrase
{ {
public: public:
NOBODY BotPhrase(unsigned int id, bool isPlace); char *GetSpeakable(int bankIndex, float *duration = NULL) const; // return a random speakable and its duration in seconds that meets the current criteria
NOBODY ~BotPhrase(void);
NOBODY void InitVoiceBank(int bankIndex);
char *GetSpeakable(int bankIndex, float *duration = NULL) const;
// NOTE: Criteria must be set just before the GetSpeakable() call, since they are shared among all bots
void ClearCriteria(void) const; void ClearCriteria(void) const;
void SetPlaceCriteria(PlaceCriteria place) const; void SetPlaceCriteria(PlaceCriteria place) const; // all returned phrases must have this place criteria
void SetCountCriteria(CountCriteria count) const; void SetCountCriteria(CountCriteria count) const; // all returned phrases must have this count criteria
const char *GetName(void) const { return m_name; }
Place GetID(void) const { return m_id; }
GameEventType GetRadioEquivalent(void) const { return m_radioEvent; }
bool IsImportant(void) const { return m_isImportant; } // return true if this phrase is part of an important statement
bool IsPlace(void) const { return m_isPlace; }
void Randomize(void); // randomly shuffle the speakable order
#ifndef HOOK_GAMEDLL
private:
#endif // HOOK_GAMEDLL
const char *GetName(void) const
{
return m_name;
}
Place GetID(void) const
{
return m_id;
}
GameEventType GetRadioEquivalent(void) const
{
return m_radioEvent;
}
bool IsImportant(void) const
{
return m_isImportant;
}
bool IsPlace(void) const
{
return m_isPlace;
}
NOBODY void Randomize(void);
//private:
public:
friend class BotPhraseManager; friend class BotPhraseManager;
BotPhrase(unsigned int id, bool isPlace);
~BotPhrase(void);
char *m_name; char *m_name;
Place m_id; Place m_id;
bool m_isPlace; bool m_isPlace; // true if this is a Place phrase
GameEventType m_radioEvent; GameEventType m_radioEvent;
bool m_isImportant; bool m_isImportant; // mission-critical statement
mutable BotVoiceBankVector m_voiceBank;
std::STD_VECTOR<int> m_count; mutable BotVoiceBankVector m_voiceBank; // array of voice banks (arrays of speakables)
mutable std::STD_VECTOR< int > m_index; std::STD_VECTOR<int> m_count; // number of speakables
int m_numVoiceBanks; mutable std::STD_VECTOR< int > m_index; // index of next speakable to return
int m_numVoiceBanks; // number of voice banks that have been initialized
void InitVoiceBank(int bankIndex); // sets up the vector of voice banks for the first bankIndex voice banks
mutable PlaceCriteria m_placeCriteria; mutable PlaceCriteria m_placeCriteria;
mutable CountCriteria m_countCriteria; mutable CountCriteria m_countCriteria;
@ -271,33 +324,30 @@ inline void BotPhrase::SetCountCriteria(CountCriteria count) const
class BotPhraseManager class BotPhraseManager
{ {
public: public:
NOBODY BotPhraseManager(void); BotPhraseManager(void);
NOBODY ~BotPhraseManager(void); ~BotPhraseManager(void);
// initialize phrase system from database file for a specific voice bank (0 is the default voice bank) // initialize phrase system from database file for a specific voice bank (0 is the default voice bank)
NOBODY bool Initialize(const char *filename, int bankIndex); bool Initialize(const char *filename, int bankIndex);
// invoked when round resets // invoked when round resets
void OnRoundRestart(void); void OnRoundRestart(void);
// invoked when map changes // invoked when map changes
NOBODY void OnMapChange(void); void OnMapChange(void);
Place NameToID(const char *name) const; Place NameToID(const char *name) const;
const char *IDToName(Place id) const; const char *IDToName(Place id) const;
// given a name, return the associated phrase collection // given a name, return the associated phrase collection
NOBODY const BotPhrase *GetPhrase(const char *name) const; const BotPhrase *GetPhrase(const char *name) const;
// given a name, return the associated Place phrase collection // given a name, return the associated Place phrase collection
NOBODY const BotPhrase *GetPlace(const char *name) const; const BotPhrase *GetPlace(const char *name) const;
// given an id, return the associated Place phrase collection // given an id, return the associated Place phrase collection
NOBODY const BotPhrase *GetPlace(PlaceCriteria place) const; const BotPhrase *GetPlace(PlaceCriteria place) const;
const BotPhraseList *GetPlaceList(void) const const BotPhraseList *GetPlaceList(void) const { return &m_placeList; }
{
return &m_placeList;
}
// return time last statement of given type was emitted by a teammate for the given place // return time last statement of given type was emitted by a teammate for the given place
float GetPlaceStatementInterval(Place place) const; float GetPlaceStatementInterval(Place place) const;
@ -307,8 +357,6 @@ public:
#ifndef HOOK_GAMEDLL #ifndef HOOK_GAMEDLL
private: private:
#else
public:
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
int FindPlaceIndex(Place where) const; int FindPlaceIndex(Place where) const;
@ -338,12 +386,14 @@ inline int BotPhraseManager::FindPlaceIndex(Place where) const
if (m_placeStatementHistory[i].placeID == where) if (m_placeStatementHistory[i].placeID == where)
return i; return i;
} }
if (m_placeCount < MAX_PLACES_PER_MAP) if (m_placeCount < MAX_PLACES_PER_MAP)
{ {
m_placeStatementHistory[++m_placeCount].placeID = where; m_placeStatementHistory[++m_placeCount].placeID = where;
m_placeStatementHistory[++m_placeCount].timer.Invalidate(); m_placeStatementHistory[++m_placeCount].timer.Invalidate();
return m_placeCount-1; return m_placeCount - 1;
} }
return -1; return -1;
} }
@ -365,6 +415,7 @@ inline float BotPhraseManager::GetPlaceStatementInterval(Place place) const
inline void BotPhraseManager::ResetPlaceStatementInterval(Place place) const inline void BotPhraseManager::ResetPlaceStatementInterval(Place place) const
{ {
int index = FindPlaceIndex(place); int index = FindPlaceIndex(place);
if (index < 0) if (index < 0)
return; return;
@ -374,56 +425,38 @@ inline void BotPhraseManager::ResetPlaceStatementInterval(Place place) const
m_placeStatementHistory[index].timer.Reset(); m_placeStatementHistory[index].timer.Reset();
} }
// Statements are meaningful collections of phrases
class BotStatement class BotStatement
{ {
public: public:
NOBODY BotStatement(BotChatterInterface *chatter, BotStatementType type, float expireDuration); BotStatement(BotChatterInterface *chatter, BotStatementType type, float expireDuration);
NOBODY ~BotStatement(void); ~BotStatement(void);
public: public:
BotChatterInterface *GetChatter(void) const BotChatterInterface *GetChatter(void) const { return m_chatter; }
{ CCSBot *GetOwner(void) const;
return m_chatter;
} BotStatementType GetType(void) const { return m_type; } // return the type of statement this is
NOBODY CCSBot *GetOwner(void) const; bool IsImportant(void) const; // return true if this statement is "important" and not personality chatter
BotStatementType GetType(void) const
{ bool HasSubject(void) const { return (m_subject != UNDEFINED_SUBJECT); }
return m_type; void SetSubject(int playerID) { m_subject = playerID; } // who this statement is about
} int GetSubject(void) const { return m_subject; } // who this statement is about
NOBODY bool IsImportant(void) const;
bool HasSubject(void) const bool HasPlace(void) const { return (GetPlace()) ? true : false; }
{ Place GetPlace(void) const; // if this statement refers to a specific place, return that place
return (m_subject != UNDEFINED_SUBJECT); void SetPlace(Place where) { m_place = where; } // explicitly set place
}
void SetSubject(int playerID) bool HasCount(void) const; // return true if this statement has an associated count
{
m_subject = playerID; bool IsRedundant(const BotStatement *say) const; // return true if this statement is the same as the given one
} bool IsObsolete(void) const; // return true if this statement is no longer appropriate to say
int GetSubject(void) const void Convert(const BotStatement *say); // possibly change what were going to say base on what teammate is saying
{
return m_subject; void AppendPhrase(const BotPhrase *phrase);
}
bool HasPlace(void) const void SetStartTime(float timestamp) { m_startTime = timestamp; } // define the earliest time this statement can be spoken
{ float GetStartTime(void) const { return m_startTime; }
return (GetPlace()) ? true : false;
}
NOBODY Place GetPlace(void) const;
void SetPlace(Place where)
{
m_place = where;
}
NOBODY bool HasCount(void) const;
NOBODY bool IsRedundant(const BotStatement *say) const;
NOBODY bool IsObsolete(void) const;
NOBODY void Convert(const BotStatement *say);
NOBODY void AppendPhrase(const BotPhrase *phrase);
void SetStartTime(float timestamp)
{
m_startTime = timestamp;
}
float GetStartTime(void) const
{
return m_startTime;
}
enum ConditionType enum ConditionType
{ {
@ -433,8 +466,8 @@ public:
NUM_CONDITIONS, NUM_CONDITIONS,
}; };
NOBODY void AddCondition(ConditionType condition); void AddCondition(ConditionType condition); // conditions must be true for the statement to be spoken
NOBODY bool IsValid(void) const; bool IsValid(void) const; // verify all attached conditions
enum ContextType enum ContextType
{ {
@ -444,34 +477,33 @@ public:
LONG_DELAY, LONG_DELAY,
ACCUMULATE_ENEMIES_DELAY, ACCUMULATE_ENEMIES_DELAY,
}; };
NOBODY void AppendPhrase(ContextType contextPhrase); void AppendPhrase(ContextType contextPhrase); // special phrases that depend on the context
bool Update(void); // emit statement over time, return false if statement is done
bool IsSpeaking(void) const { return m_isSpeaking; } // return true if this statement is currently being spoken
float GetTimestamp(void) const { return m_timestamp; } // get time statement was created (but not necessarily started talking)
void AttachMeme(BotMeme *meme); // attach a meme to this statement, to be transmitted to other friendly bots when spoken
NOBODY bool Update(void);
NOBODY bool IsSpeaking(void) const
{
return m_isSpeaking;
}
NOBODY float GetTimestamp(void) const
{
return m_timestamp;
}
NOBODY void AttachMeme(BotMeme *meme);
public: public:
friend class BotChatterInterface; friend class BotChatterInterface;
BotChatterInterface *m_chatter; BotChatterInterface *m_chatter; // the chatter system this statement is part of
BotStatement *m_next;
BotStatement *m_prev; BotStatement *m_next, *m_prev; // linked list hooks
BotStatementType m_type;
int m_subject; BotStatementType m_type; // what kind of statement this is
Place m_place; int m_subject; // who this subject is about
BotMeme *m_meme; Place m_place; // explicit place - note some phrases have implicit places as well
float m_timestamp; BotMeme *m_meme; // a statement can only have a single meme for now
float m_startTime;
float m_expireTime; float m_timestamp; // time when message was created
float m_speakTimestamp; float m_startTime; // the earliest time this statement can be spoken
bool m_isSpeaking; float m_expireTime; // time when this statement is no longer valid
float m_nextTime; float m_speakTimestamp; // time when message began being spoken
bool m_isSpeaking; // true if this statement is current being spoken
float m_nextTime; // time for next phrase to begin
enum { MAX_BOT_PHRASES = 4 }; enum { MAX_BOT_PHRASES = 4 };
struct struct
@ -482,115 +514,124 @@ public:
const BotPhrase *phrase; const BotPhrase *phrase;
ContextType context; ContextType context;
}; };
} m_statement[ MAX_BOT_PHRASES ];
}
m_statement[ MAX_BOT_PHRASES ];
enum { MAX_BOT_CONDITIONS = 4 }; enum { MAX_BOT_CONDITIONS = 4 };
ConditionType m_condition[ MAX_BOT_CONDITIONS ]; // conditions that must be true for the statement to be said
ConditionType m_condition[ MAX_BOT_CONDITIONS ];
int m_conditionCount; int m_conditionCount;
int m_index;
int m_index; // m_index refers to the phrase currently being spoken, or -1 if we havent started yet
int m_count; int m_count;
};/* size: 112, cachelines: 2, members: 18 */ };/* size: 112, cachelines: 2, members: 18 */
// This class defines the interface to the bot radio chatter system
class BotChatterInterface class BotChatterInterface
{ {
public: public:
BotChatterInterface(void) {}; BotChatterInterface(void) {};
NOBODY BotChatterInterface(CCSBot *me); BotChatterInterface(CCSBot *me);
NOBODY ~BotChatterInterface(); ~BotChatterInterface();
NOBODY void Reset(void); void Reset(void); // reset to initial state
NOBODY void Update(void); void Update(void); // process ongoing chatter
NOBODY void OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other); void OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other); // invoked when event occurs in the game (some events have NULL entities)
NOBODY void OnDeath(void); void OnDeath(void); // invoked when we die
enum VerbosityType enum VerbosityType
{ {
NORMAL, NORMAL, // full chatter
MINIMAL, MINIMAL, // only scenario-critical events
RADIO, RADIO, // use the standard radio instead
OFF, OFF // no chatter at all
}; };
VerbosityType GetVerbosity(void) const; // return our current level of verbosity
VerbosityType GetVerbosity(void) const; CCSBot *GetOwner(void) const { return m_me; }
NOBODY CCSBot *GetOwner(void) const bool IsTalking(void) const; // return true if we are currently talking
{ float GetRadioSilenceDuration(void); // return time since any teammate said anything
return m_me; void ResetRadioSilenceDuration(void);
}
bool IsTalking(void) const;
NOBODY float GetRadioSilenceDuration(void);
NOBODY void ResetRadioSilenceDuration(void);
enum { MUST_ADD = 1 }; enum { MUST_ADD = 1 };
void AddStatement(BotStatement *statement, bool mustAdd = false); // register a statement for speaking
void RemoveStatement(BotStatement *statement); // remove a statement
NOBODY void AddStatement(BotStatement *statement, bool mustAdd = false); BotStatement *GetActiveStatement(void); // returns the statement that is being spoken, or is next to be spoken if no-one is speaking now
NOBODY void RemoveStatement(BotStatement *statement); BotStatement *GetStatement(void) const; // returns our current statement, or NULL if we aren't speaking
NOBODY BotStatement *GetActiveStatement(void); int GetPitch(void) const { return m_pitch; }
BotStatement *GetStatement(void) const;
int GetPitch(void) const
{
return m_pitch;
}
// things the bots can say
void Say(const char *phraseName, float lifetime = 3.0f, float delay = 0.0f); void Say(const char *phraseName, float lifetime = 3.0f, float delay = 0.0f);
NOBODY void AnnouncePlan(const char *phraseName, Place place); void AnnouncePlan(const char *phraseName, Place place);
NOBODY void Affirmative(void); void Affirmative(void);
NOBODY void Negative(void); void Negative(void);
NOBODY void EnemySpotted(void); void EnemySpotted(void); // report enemy sightings
NOBODY void KilledMyEnemy(int victimID); void KilledMyEnemy(int victimID);
NOBODY void EnemiesRemaining(void); void EnemiesRemaining(void);
NOBODY void Clear(Place place); NOXREF void Clear(Place place);
NOBODY void ReportIn(void);
NOBODY void ReportingIn(void);
NOBODY bool NeedBackup(void);
NOBODY void PinnedDown(void);
NOBODY void Scared(void);
NOBODY void HeardNoise(const Vector *pos);
NOBODY void TheyPickedUpTheBomb(void);
NOBODY void GoingToPlantTheBomb(Place place);
NOBODY void BombsiteClear(int zoneIndex);
NOBODY void FoundPlantedBomb(int zoneIndex);
NOBODY void PlantingTheBomb(Place place);
NOBODY void SpottedBomber(CBasePlayer *bomber);
NOBODY void SpottedLooseBomb(CBaseEntity *bomb);
NOBODY void GuardingLooseBomb(CBaseEntity *bomb);
NOBODY void RequestBombLocation(void);
NOBODY void GuardingHostages(Place place, bool isPlan);
NOBODY void GuardingHostageEscapeZone(bool isPlan);
NOBODY void HostagesBeingTaken(void);
NOBODY void HostagesTaken(void);
NOBODY void TalkingToHostages(void);
NOBODY void EscortingHostages(void);
NOBODY void HostageDown(void);
NOBODY void CelebrateWin(void);
NOBODY void Encourage(const char *phraseName, float repeatInterval = 10.0f, float lifetime = 3.0f); void ReportIn(void); // ask for current situation
NOBODY void KilledFriend(void); void ReportingIn(void); // report current situation
NOBODY void FriendlyFire(void);
public: bool NeedBackup(void);
static CountdownTimer m_encourageTimer; void PinnedDown(void);
static IntervalTimer m_radioSilenceInterval[2]; void Scared(void);
void HeardNoise(const Vector *pos);
void TheyPickedUpTheBomb(void);
void GoingToPlantTheBomb(Place place);
void BombsiteClear(int zoneIndex);
void FoundPlantedBomb(int zoneIndex);
void PlantingTheBomb(Place place);
void SpottedBomber(CBasePlayer *bomber);
void SpottedLooseBomb(CBaseEntity *bomb);
NOXREF void GuardingLooseBomb(CBaseEntity *bomb);
void RequestBombLocation(void);
void GuardingHostages(Place place, bool isPlan);
void GuardingHostageEscapeZone(bool isPlan);
void HostagesBeingTaken(void);
void HostagesTaken(void);
void TalkingToHostages(void);
void EscortingHostages(void);
NOXREF void HostageDown(void);
void CelebrateWin(void);
void Encourage(const char *phraseName, float repeatInterval = 10.0f, float lifetime = 3.0f); // "encourage" the player to do the scenario
void KilledFriend(void);
void FriendlyFire(void);
bool SeesAtLeastOneEnemy(void) const { return m_seeAtLeastOneEnemy; }
#ifndef HOOK_GAMEDLL
private: private:
#endif // HOOK_GAMEDLL
NOBODY void ReportEnemies(void); BotStatement *m_statementList; // list of all active/pending messages for this bot
NOBODY bool ShouldSpeak(void) const; void ReportEnemies(void); // track nearby enemy count and generate enemy activity statements
bool ShouldSpeak(void) const; // return true if we speaking makes sense now
BotStatement *m_statementList; CCSBot *m_me; // the bot this chatter is for
CCSBot *m_me;
bool m_seeAtLeastOneEnemy; bool m_seeAtLeastOneEnemy;
float m_timeWhenSawFirstEnemy; float m_timeWhenSawFirstEnemy;
bool m_reportedEnemies; bool m_reportedEnemies;
bool m_requestedBombLocation; bool m_requestedBombLocation; // true if we already asked where the bomb has been planted
int m_pitch; int m_pitch;
static IntervalTimer IMPL(m_radioSilenceInterval)[2]; // one timer for each team
IntervalTimer m_needBackupInterval; IntervalTimer m_needBackupInterval;
IntervalTimer m_spottedBomberInterval; IntervalTimer m_spottedBomberInterval;
IntervalTimer m_scaredInterval; IntervalTimer m_scaredInterval;
@ -598,6 +639,8 @@ private:
CountdownTimer m_spottedLooseBombTimer; CountdownTimer m_spottedLooseBombTimer;
CountdownTimer m_heardNoiseTimer; CountdownTimer m_heardNoiseTimer;
CountdownTimer m_escortingHostageTimer; CountdownTimer m_escortingHostageTimer;
static CountdownTimer IMPL(m_encourageTimer); // timer to know when we can "encourage" the human player again - shared by all bots
};/* size: 64, cachelines: 1, members: 16 */ };/* size: 64, cachelines: 1, members: 16 */
/* <2fec2d> ../cstrike/dlls/bot/cs_bot_chatter.h:572 */ /* <2fec2d> ../cstrike/dlls/bot/cs_bot_chatter.h:572 */
@ -623,8 +666,11 @@ inline BotChatterInterface::VerbosityType BotChatterInterface::GetVerbosity(void
/* <2fec4a> ../cstrike/dlls/bot/cs_bot_chatter.h:590 */ /* <2fec4a> ../cstrike/dlls/bot/cs_bot_chatter.h:590 */
inline bool BotChatterInterface::IsTalking(void) const inline bool BotChatterInterface::IsTalking(void) const
{ {
if (m_statementList) if (m_statementList != NULL)
{
return m_statementList->IsSpeaking(); return m_statementList->IsSpeaking();
}
return false; return false;
} }
@ -647,14 +693,14 @@ extern CBaseEntity *g_pSelectedZombieSpawn;
/* <5c4dcf> ../cstrike/dlls/bot/cs_bot_chatter.h:604 */ /* <5c4dcf> ../cstrike/dlls/bot/cs_bot_chatter.h:604 */
inline void BotChatterInterface::Say(const char *phraseName, float lifetime, float delay) inline void BotChatterInterface::Say(const char *phraseName, float lifetime, float delay)
{ {
/*BotStatement *say = new BotStatement(this, REPORT_MY_INTENTION, lifetime); BotStatement *say = new BotStatement(this, REPORT_MY_INTENTION, lifetime);
say->AppendPhrase(TheBotPhrases->GetPhrase(phraseName)); say->AppendPhrase(TheBotPhrases->GetPhrase(phraseName));
if (delay > 0.0f) if (delay > 0.0f)
say->SetStartTime(gpGlobals->curtime + delay); say->SetStartTime(gpGlobals->time + delay);
AddStatement(say);*/ AddStatement(say);
} }
const Vector *GetRandomSpotAtPlace(Place place); const Vector *GetRandomSpotAtPlace(Place place);
@ -664,12 +710,12 @@ const Vector *GetRandomSpotAtPlace(Place place);
typedef void (BotStatement::*APPEND_PHRASE_CONTEXT)(BotStatement::ContextType); typedef void (BotStatement::*APPEND_PHRASE_CONTEXT)(BotStatement::ContextType);
typedef void (BotStatement::*APPEND_PHRASE_BOTPHRASE)(const BotPhrase *); typedef void (BotStatement::*APPEND_PHRASE_BOTPHRASE)(const BotPhrase *);
typedef const BotPhraseManager *(BotPhraseManager::*GET_PLACE_NAME)(const char *name) const; typedef const BotPhrase *(BotPhraseManager::*GET_PLACE_NAME)(const char *name) const;
typedef const BotPhraseManager *(BotPhraseManager::*GET_PLACE_PLACE)(PlaceCriteria place) const; typedef const BotPhrase *(BotPhraseManager::*GET_PLACE_PLACE)(PlaceCriteria place) const;
#endif // HOOK_GAMEDLL
// refs // refs
extern void (*pBotPhrase__Randomize)(void); extern void (*pBotPhrase__Randomize)(void);
#endif // HOOK_GAMEDLL
#endif // CS_BOT_CHATTER_H #endif // CS_BOT_CHATTER_H

View File

@ -1,7 +1,7 @@
#include "precompiled.h" #include "precompiled.h"
/* <31d087> ../cstrike/dlls/bot/cs_bot_event.cpp:22 */ /* <31d087> ../cstrike/dlls/bot/cs_bot_event.cpp:22 */
void CCSBot::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBaseEntity *other) NOBODY void CCSBot::__MAKE_VHOOK(OnEvent)(GameEventType event, CBaseEntity *entity, CBaseEntity *other)
{ {
// { // {
// class CCSBotManager *ctrl; // 63 // class CCSBotManager *ctrl; // 63

View File

@ -1,7 +1,76 @@
#include "precompiled.h" #include "precompiled.h"
/*
* Globals initialization
*/
#ifndef HOOK_GAMEDLL
cvar_t cv_bot_traceview = { "bot_traceview", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_stop = { "bot_stop", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_show_nav = { "bot_show_nav", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_show_danger = { "bot_show_danger", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_nav_edit = { "bot_nav_edit", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_nav_zdraw = { "bot_nav_zdraw", "4", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_walk = { "bot_walk", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_difficulty = { "bot_difficulty", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_debug = { "bot_debug", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_quicksave = { "bot_quicksave", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_quota = { "bot_quota", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_quota_match = { "bot_quota_match", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_prefix = { "bot_prefix", "", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_allow_rogues = { "bot_allow_rogues", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_allow_pistols = { "bot_allow_pistols", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_allow_shotguns = { "bot_allow_shotguns", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_allow_sub_machine_guns = { "bot_allow_sub_machine_guns", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_allow_rifles = { "bot_allow_rifles", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_allow_machine_guns = { "bot_allow_machine_guns", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_allow_grenades = { "bot_allow_grenades", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_allow_snipers = { "bot_allow_snipers", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_allow_shield = { "bot_allow_shield", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_join_team = { "bot_join_team", "any", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_join_after_player = { "bot_join_after_player", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_auto_vacate = { "bot_auto_vacate", "1", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_zombie = { "bot_zombie", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_defer_to_human = { "bot_defer_to_human", "0", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_chatter = { "bot_chatter", "normal", FCVAR_SERVER, 0.0f, NULL };
cvar_t cv_bot_profile_db = { "bot_profile_db", "BotProfile.db", FCVAR_SERVER, 0.0f, NULL };
#else // HOOK_GAMEDLL
cvar_t cv_bot_traceview;
cvar_t cv_bot_stop;
cvar_t cv_bot_show_nav;
cvar_t cv_bot_show_danger;
cvar_t cv_bot_nav_edit;
cvar_t cv_bot_nav_zdraw;
cvar_t cv_bot_walk;
cvar_t cv_bot_difficulty;
cvar_t cv_bot_debug;
cvar_t cv_bot_quicksave;
cvar_t cv_bot_quota;
cvar_t cv_bot_quota_match;
cvar_t cv_bot_prefix;
cvar_t cv_bot_allow_rogues;
cvar_t cv_bot_allow_pistols;
cvar_t cv_bot_allow_shotguns;
cvar_t cv_bot_allow_sub_machine_guns;
cvar_t cv_bot_allow_rifles;
cvar_t cv_bot_allow_machine_guns;
cvar_t cv_bot_allow_grenades;
cvar_t cv_bot_allow_snipers;
cvar_t cv_bot_allow_shield;
cvar_t cv_bot_join_team;
cvar_t cv_bot_join_after_player;
cvar_t cv_bot_auto_vacate;
cvar_t cv_bot_zombie;
cvar_t cv_bot_defer_to_human;
cvar_t cv_bot_chatter;
cvar_t cv_bot_profile_db;
#endif // HOOK_GAMEDLL
/* <333bca> ../cstrike/dlls/bot/cs_bot_init.cpp:57 */ /* <333bca> ../cstrike/dlls/bot/cs_bot_init.cpp:57 */
NOBODY void InstallBotControl(void) void InstallBotControl(void)
{ {
if (TheBots != NULL) if (TheBots != NULL)
{ {
@ -11,6 +80,8 @@ NOBODY void InstallBotControl(void)
TheBots = new CCSBotManager; TheBots = new CCSBotManager;
} }
// Engine callback for custom server commands
/* <333cb3> ../cstrike/dlls/bot/cs_bot_init.cpp:68 */ /* <333cb3> ../cstrike/dlls/bot/cs_bot_init.cpp:68 */
void Bot_ServerCommand(void) void Bot_ServerCommand(void)
{ {
@ -58,52 +129,35 @@ void Bot_RegisterCvars(void)
} }
} }
// Constructor
/* <333d1e> ../cstrike/dlls/bot/cs_bot_init.cpp:129 */ /* <333d1e> ../cstrike/dlls/bot/cs_bot_init.cpp:129 */
//CCSBot::CCSBot(void) CCSBot::CCSBot(void) : m_chatter(this), m_gameState(this)
//{ {
// CountdownTimer(CountdownTimer *const this); // 129 ;
// IdleState(IdleState *const this); // 129 }
// MoveToState(MoveToState *const this); // 129
// HuntState(HuntState *const this); // 129 // Prepare bot for action
// FetchBombState(FetchBombState *const this); // 129
// AttackState(AttackState *const this); // 129
// InvestigateNoiseState(InvestigateNoiseState *const this); // 129
// BuyState(BuyState *const this); // 129
// PlantBombState(PlantBombState *const this); // 129
// DefuseBombState(DefuseBombState *const this); // 129
// HideState(HideState *const this); // 129
// EscapeFromBombState(EscapeFromBombState *const this); // 129
// FollowState(FollowState *const this); // 129
// UseEntityState(UseEntityState *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// IntervalTimer(IntervalTimer *const this); // 129
// _List_iterator(_List_iterator<CNavArea*> *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
// CountdownTimer(CountdownTimer *const this); // 129
//}
/* <3342ac> ../cstrike/dlls/bot/cs_bot_init.cpp:137 */ /* <3342ac> ../cstrike/dlls/bot/cs_bot_init.cpp:137 */
NOBODY bool CCSBot::__MAKE_VHOOK(Initialize)(const BotProfile *profile) bool CCSBot::__MAKE_VHOOK(Initialize)(const BotProfile *profile)
{ {
// extend
CBot::Initialize(profile); CBot::Initialize(profile);
// CS bot initialization
m_diedLastRound = false; m_diedLastRound = false;
m_morale = POSITIVE; m_morale = POSITIVE; // starting a new round makes everyone a little happy
m_combatRange = RANDOM_FLOAT(325, 425);
m_navNodeList = NULL; m_navNodeList = NULL;
m_currentNode = NULL; m_currentNode = NULL;
m_combatRange = RANDOM_FLOAT(325, 425); // set initial safe time guess for this map
m_name[0] = '\0'; m_safeTime = 15.0f + 5.0f * GetProfile()->GetAggression();
m_safeTime = m_profile->GetAggression() * 5 + 15;
m_name[0] = '\000';
ResetValues(); ResetValues();
StartNormalProcess(); StartNormalProcess();
@ -111,18 +165,13 @@ NOBODY bool CCSBot::__MAKE_VHOOK(Initialize)(const BotProfile *profile)
return true; return true;
} }
void (*pCCSBot__ResetValues)(void); // Reset internal data to initial state
/* <3341dc> ../cstrike/dlls/bot/cs_bot_init.cpp:167 */ /* <3341dc> ../cstrike/dlls/bot/cs_bot_init.cpp:167 */
NOBODY void __declspec(naked) CCSBot::ResetValues(void) void CCSBot::ResetValues(void)
{ {
__asm m_chatter.Reset();
{ m_gameState.Reset();
jmp pCCSBot__ResetValues
}
/*
m_chatter.Reset();//TODO: Reverse me
m_gameState.Reset();//TODO: Reverse me
m_avoid = NULL; m_avoid = NULL;
m_avoidTimestamp = 0.0f; m_avoidTimestamp = 0.0f;
@ -136,28 +185,28 @@ NOBODY void __declspec(naked) CCSBot::ResetValues(void)
m_pathLength = 0; m_pathLength = 0;
m_pathIndex = 0; m_pathIndex = 0;
m_areaEnteredTimestamp = 0.0f; m_areaEnteredTimestamp = 0.0f;
m_currentArea = NULL; m_currentArea = NULL;
m_lastKnownArea = NULL; m_lastKnownArea = NULL;
m_avoidFriendTimer.Invalidate(); m_avoidFriendTimer.Invalidate();
m_isFriendInTheWay = false; m_isFriendInTheWay = false;
m_isWaitingBehindFriend = false; m_isWaitingBehindFriend = false;
m_disposition = ENGAGE_AND_INVESTIGATE; m_disposition = ENGAGE_AND_INVESTIGATE;
m_enemy = NULL; m_enemy = NULL;
m_isWaitingToTossGrenade = false; m_isWaitingToTossGrenade = false;
m_wasSafe = true; m_wasSafe = true;
m_nearbyEnemyCount = 0; m_nearbyEnemyCount = 0;
m_enemyPlace = 0; m_enemyPlace = 0;
m_nearbyFriendCount = 0; m_nearbyFriendCount = 0;
m_closestVisibleFriend = NULL; m_closestVisibleFriend = NULL;
m_closestVisibleHumanFriend = NULL; m_closestVisibleHumanFriend = NULL;
for (int w = 0; w < ARRAYSIZE(m_watchInfo); w++) for (int w = 0; w < ARRAYSIZE(m_watchInfo); ++w)
{ {
m_watchInfo[w].timestamp = 0.0f; m_watchInfo[w].timestamp = 0.0f;
m_watchInfo[w].isEnemy = false; m_watchInfo[w].isEnemy = false;
@ -165,24 +214,20 @@ NOBODY void __declspec(naked) CCSBot::ResetValues(void)
m_isEnemyVisible = false; m_isEnemyVisible = false;
m_visibleEnemyParts = NONE; m_visibleEnemyParts = NONE;
m_lastSawEnemyTimestamp = 0.0f; m_lastSawEnemyTimestamp = 0.0f;
m_firstSawEnemyTimestamp = 0.0f; m_firstSawEnemyTimestamp = 0.0f;
m_currentEnemyAcquireTimestamp = 0.0f; m_currentEnemyAcquireTimestamp = 0.0f;
m_isLastEnemyDead = true; m_isLastEnemyDead = true;
m_attacker = NULL; m_attacker = NULL;
m_attackedTimestamp = 0.0f; m_attackedTimestamp = 0.0f;
m_enemyDeathTimestamp = 0.0f; m_enemyDeathTimestamp = 0.0f;
m_lastVictimID = 0; m_lastVictimID = 0;
m_isAimingAtEnemy = false; m_isAimingAtEnemy = false;
m_fireWeaponTimestamp = 0.0f; m_fireWeaponTimestamp = 0.0f;
m_equipTimer.Invalidate(); m_equipTimer.Invalidate();
m_isFollowing = false; m_isFollowing = false;
m_leader = NULL; m_leader = NULL;
m_followTimestamp = 0.0f; m_followTimestamp = 0.0f;
m_allowAutoFollowTime = 0.0f; m_allowAutoFollowTime = 0.0f;
@ -193,47 +238,40 @@ NOBODY void __declspec(naked) CCSBot::ResetValues(void)
m_lookAroundStateTimestamp = 0.0f; m_lookAroundStateTimestamp = 0.0f;
m_inhibitLookAroundTimestamp = 0.0f; m_inhibitLookAroundTimestamp = 0.0f;
m_lookPitch = 0.0f; m_lookPitch = 0.0f;
m_lookPitchVel = 0.0f; m_lookPitchVel = 0.0f;
m_lookYaw = 0.0f; m_lookYaw = 0.0f;
m_lookYawVel = 0.0f; m_lookYawVel = 0.0f;
m_aimOffsetTimestamp = 0.0f; m_aimOffsetTimestamp = 0.0f;
m_aimSpreadTimestamp = 0.0f; m_aimSpreadTimestamp = 0.0f;
m_lookAtSpotState = NOT_LOOKING_AT_SPOT; m_lookAtSpotState = NOT_LOOKING_AT_SPOT;
m_spotEncounter = NULL;
m_spotEncounter = NULL;
m_spotCheckTimestamp = 0.0f; m_spotCheckTimestamp = 0.0f;
m_peripheralTimestamp = 0.0f; m_peripheralTimestamp = 0.0f;
m_avgVelIndex = 0; m_avgVelIndex = 0;
m_avgVelCount = 0; m_avgVelCount = 0;
if (pev) m_lastOrigin = (pev != NULL) ? pev->origin : Vector(0, 0, 0);
{
m_lastOrigin = pev->origin;
}
else
m_lastOrigin = Vector(0, 0, 0);
m_lastRadioCommand = EVENT_INVALID; m_lastRadioCommand = EVENT_INVALID;
m_lastRadioRecievedTimestamp = 0.0f; m_lastRadioRecievedTimestamp = 0.0f;
m_lastRadioSentTimestamp = 0.0f; m_lastRadioSentTimestamp = 0.0f;
m_radioSubject = NULL; m_radioSubject = NULL;
m_noisePosition = Vector(0, 0, 0);
m_noiseTimestamp = 0.0f;
m_noiseCheckTimestamp = 0.0f;
m_voiceFeedbackEndTimestamp = 0.0f; m_voiceFeedbackEndTimestamp = 0.0f;
m_hostageEscortCount = 0; m_hostageEscortCount = 0;
m_hostageEscortCountTimestamp = 0.0f; m_hostageEscortCountTimestamp = 0.0f;
m_noisePosition = Vector(0, 0, 0);
m_noiseTimestamp = 0.0f;
m_noiseCheckTimestamp = 0.0f;
m_isNoiseTravelRangeChecked = false; m_isNoiseTravelRangeChecked = false;
m_stateTimestamp = 0.0f;
m_stateTimestamp = 0.0f;
m_task = SEEK_AND_DESTROY; m_task = SEEK_AND_DESTROY;
m_taskEntity = NULL; m_taskEntity = NULL;
@ -245,38 +283,49 @@ NOBODY void __declspec(naked) CCSBot::ResetValues(void)
StandUp(); StandUp();
Run(); Run();
m_pathLadder = NULL;
m_mustRunTimer.Invalidate(); m_mustRunTimer.Invalidate();
m_repathTimer.Invalidate(); m_repathTimer.Invalidate();
m_pathLadder = NULL;
m_huntState.ClearHuntArea(); m_huntState.ClearHuntArea();
// adjust morale - if we died, our morale decreased, // adjust morale - if we died, our morale decreased,
// but if we live, no adjustement (round win/loss also adjusts morale // but if we live, no adjustement (round win/loss also adjusts morale
if (m_diedLastRound) if (m_diedLastRound)
{
DecreaseMorale(); DecreaseMorale();
}
m_diedLastRound = false; m_diedLastRound = false;
// IsRogue() randomly changes this
m_isRogue = false; m_isRogue = false;
m_surpriseDelay = 0.0f; m_surpriseDelay = 0.0f;
m_surpriseTimestamp = 0.0f; m_surpriseTimestamp = 0.0f;
// even though these are EHANDLEs, they need to be NULL-ed
m_goalEntity = NULL; m_goalEntity = NULL;
m_avoid = NULL; m_avoid = NULL;
m_enemy = NULL; m_enemy = NULL;
#ifdef REGAMEDLL_FIXES
for (int i = 0; i < MAX_ENEMY_QUEUE; ++i)
{
m_enemyQueue[i].player = NULL;
m_enemyQueue[i].isReloading = false;
m_enemyQueue[i].isProtectedByShield = false;
}
#endif // REGAMEDLL_FIXES
// start in idle state // start in idle state
StopAttacking();//TODO: Reverse me StopAttacking();
Idle();//TODO: Reverse me Idle();
*/
} }
// Called when bot is placed in map, and when bots are reset after a round ends.
// NOTE: For some reason, this can be called twice when a bot is added.
/* <3342e4> ../cstrike/dlls/bot/cs_bot_init.cpp:336 */ /* <3342e4> ../cstrike/dlls/bot/cs_bot_init.cpp:336 */
NOBODY void CCSBot::__MAKE_VHOOK(SpawnBot)(void) void CCSBot::__MAKE_VHOOK(SpawnBot)(void)
{ {
CCSBotManager *ctrl = TheCSBots(); CCSBotManager *ctrl = TheCSBots();
@ -288,7 +337,7 @@ NOBODY void CCSBot::__MAKE_VHOOK(SpawnBot)(void)
SetState(&m_buyState); SetState(&m_buyState);
SetTouch(&CCSBot::BotTouch); SetTouch(&CCSBot::BotTouch);
if (!TheNavAreaList.empty() && !ctrl->IsLearningMap()) if (TheNavAreaList.empty() && !ctrl->IsLearningMap())
{ {
ctrl->SetLearningMapFlag(); ctrl->SetLearningMapFlag();
StartLearnProcess(); StartLearnProcess();
@ -296,8 +345,11 @@ NOBODY void CCSBot::__MAKE_VHOOK(SpawnBot)(void)
} }
/* <3338f7> ../cstrike/dlls/bot/cs_bot_init.cpp:366 */ /* <3338f7> ../cstrike/dlls/bot/cs_bot_init.cpp:366 */
NOBODY void CCSBot::__MAKE_VHOOK(RoundRespawn)(void) void CCSBot::__MAKE_VHOOK(RoundRespawn)(void)
{ {
// do the normal player spawn process
CBasePlayer::RoundRespawn();
EndVoiceFeedback();
} }
/* <334332> ../cstrike/dlls/bot/cs_bot_init.cpp:378 */ /* <334332> ../cstrike/dlls/bot/cs_bot_init.cpp:378 */
@ -305,11 +357,9 @@ void CCSBot::Disconnect(void)
{ {
EndVoiceFeedback(); EndVoiceFeedback();
if (m_processMode) if (m_processMode != PROCESS_NORMAL)
{ {
MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress); hideProgressMeter();
WRITE_BYTE(FLAG_PROGRESS_HIDE);
MESSAGE_END();
} }
} }

View File

@ -1,64 +1,126 @@
#include "precompiled.h" #include "precompiled.h"
/* const float updateTimesliceDuration = 0.5f;
* Globals initialization
*/
#ifndef HOOK_GAMEDLL
const float updateTimesliceDuration = 0.0f;
#else
const float updateTimesliceDuration = 0.0;//TODO: what value?? check it.
#endif // HOOK_GAMEDLL
int _navAreaCount; int _navAreaCount;
int _currentIndex; int _currentIndex;
/* <343cbe> ../cstrike/dlls/bot/cs_bot_learn.cpp:95 */ /* <343cbe> ../cstrike/dlls/bot/cs_bot_learn.cpp:95 */
NOBODY inline class CNavNode *LadderEndSearch(CBaseEntity *entity, const Vector *pos, NavDirType mountDir) inline CNavNode *LadderEndSearch(CBaseEntity *entity, const Vector *pos, NavDirType mountDir)
{ {
// { Vector center = *pos;
// Vector center; // 97 AddDirectionVector(&center, mountDir, HalfHumanWidth);
// {
// int d; // 103 // Test the ladder dismount point first, then each cardinal direction one and two steps away
// {
// Vector tryPos; // 105 for (int d = (-1); d < 2 * NUM_DIRECTIONS; ++d)
// Vector tryNormal; // 118 {
// float const fudge; // 123 Vector tryPos = center;
// TraceResult result; // 124
// } if (d >= NUM_DIRECTIONS)
// } AddDirectionVector(&tryPos, (NavDirType)(d - NUM_DIRECTIONS), GenerationStepSize * 2.0f);
// } else if (d >= 0)
AddDirectionVector(&tryPos, (NavDirType)d, GenerationStepSize);
// step up a rung, to ensure adjacent floors are below us
tryPos.z += GenerationStepSize;
SnapToGrid(&tryPos);
// adjust height to account for sloping areas
Vector tryNormal;
if (GetGroundHeight(&tryPos, &tryPos.z, &tryNormal) == false)
continue;
// make sure this point is not on the other side of a wall
const float fudge = 2.0f;
TraceResult result;
UTIL_TraceLine(center + Vector(0, 0, fudge), tryPos + Vector(0, 0, fudge), ignore_monsters, dont_ignore_glass, ENT(entity->pev), &result);
#ifndef REGAMEDLL_FIXES
if (result.flFraction != 1.0f)
continue;
#else
if (result.flFraction != 1.0f || result.fStartSolid)
continue;
#endif // REGAMEDLL_ADD
// if no node exists here, create one and continue the search
if (CNavNode::GetNode(&tryPos) == NULL)
{
return new CNavNode(&tryPos, &tryNormal, NULL);
}
}
return NULL;
} }
/* <343a56> ../cstrike/dlls/bot/cs_bot_learn.cpp:30 */ /* <343a56> ../cstrike/dlls/bot/cs_bot_learn.cpp:30 */
NOBODY CNavNode *CCSBot::AddNode(const Vector *destPos, const Vector *normal, NavDirType dir, CNavNode *source) CNavNode *CCSBot::AddNode(const Vector *destPos, const Vector *normal, NavDirType dir, CNavNode *source)
{ {
// { // check if a node exists at this location
// class CNavNode *node; // 34 CNavNode *node = const_cast<CNavNode *>(CNavNode::GetNode(destPos));
// bool useNew; // 37
// float const zTolerance; // 48 // if no node exists, create one
// TraceResult result; // 63 bool useNew = false;
// Vector floor; // 64 if (node == NULL)
// Vector ceiling; // 64 {
// bool crouch; // 65 node = new CNavNode(destPos, normal, source);
// MarkAsVisited(CNavNode *const this, useNew = true;
// enum NavDirType dir); // 52 }
// {
// float y; // 66 // connect source node to new node
// { source->ConnectTo(node, dir);
// float x; // 68
// } // optimization: if deltaZ changes very little, assume connection is commutative
// } const float zTolerance = 10.0f; // 50.0f;
// SetAttributes(CNavNode *const this, if (fabs(source->GetPosition()->z - destPos->z) < zTolerance)
// unsigned char bits); // 89 {
// } node->ConnectTo(source, OppositeDirection(dir));
node->MarkAsVisited(OppositeDirection(dir));
}
if (useNew)
{
// new node becomes current node
m_currentNode = node;
}
Vector ceiling;
Vector floor;
TraceResult result;
bool crouch = false;
const float epsilon = 0.1f;
for (float y = -16.0f; y <= 16.0f + epsilon; y += 16.0f)
{
for (float x = -16.0f; x <= 16.0f + epsilon; x += 16.0f)
{
floor = *destPos + Vector(x, y, 5.0f);
ceiling = *destPos + Vector(x, y, 72.0f - epsilon);
UTIL_TraceLine(floor, ceiling, ignore_monsters, dont_ignore_glass, ENT(pev), &result);
if (result.flFraction != 1.0f)
{
crouch = true;
break;
}
}
if (crouch)
{
node->SetAttributes(NAV_CROUCH);
break;
}
}
return node;
} }
/* <343b40> ../cstrike/dlls/bot/cs_bot_learn.cpp:150 */ /* <343b40> ../cstrike/dlls/bot/cs_bot_learn.cpp:150 */
NOXREF void drawProgressMeter(float progress, char *title) void drawProgressMeter(float progress, char *title)
{ {
MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress); MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress);
WRITE_BYTE(FLAG_PROGRESS_DRAW); WRITE_BYTE(FLAG_PROGRESS_DRAW);
@ -68,7 +130,7 @@ NOXREF void drawProgressMeter(float progress, char *title)
} }
/* <3435ce> ../cstrike/dlls/bot/cs_bot_learn.cpp:159 */ /* <3435ce> ../cstrike/dlls/bot/cs_bot_learn.cpp:159 */
NOXREF void startProgressMeter(const char *title) void startProgressMeter(const char *title)
{ {
MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress); MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress);
WRITE_BYTE(FLAG_PROGRESS_START); WRITE_BYTE(FLAG_PROGRESS_START);
@ -77,7 +139,7 @@ NOXREF void startProgressMeter(const char *title)
} }
/* <3435a8> ../cstrike/dlls/bot/cs_bot_learn.cpp:167 */ /* <3435a8> ../cstrike/dlls/bot/cs_bot_learn.cpp:167 */
NOXREF void hideProgressMeter(void) void hideProgressMeter(void)
{ {
MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress); MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress);
WRITE_BYTE(FLAG_PROGRESS_HIDE); WRITE_BYTE(FLAG_PROGRESS_HIDE);
@ -85,115 +147,228 @@ NOXREF void hideProgressMeter(void)
} }
/* <343b63> ../cstrike/dlls/bot/cs_bot_learn.cpp:182 */ /* <343b63> ../cstrike/dlls/bot/cs_bot_learn.cpp:182 */
NOBODY void CCSBot::StartLearnProcess(void) void CCSBot::StartLearnProcess(void)
{ {
// {
// Vector pos; // 192
// Vector normal; // 195
// startProgressMeter(const char *title); // 184
// drawProgressMeter(float progress,
// char *title); // 185
// Vector(Vector *const this,
// const Vector &v); // 192
// SnapToGrid(Vector *pos); // 193
// StartNormalProcess(CCSBot *const this); // 199
// }
Vector pos;
Vector normal;
startProgressMeter("#CZero_LearningMap"); startProgressMeter("#CZero_LearningMap");
drawProgressMeter(0, "#CZero_LearningMap"); drawProgressMeter(0, "#CZero_LearningMap");
BuildLadders();
Vector normal;
Vector pos = pev->origin;
SnapToGrid(&pos.x);
SnapToGrid(&pos.y);
if (!GetGroundHeight(&pos, &pos.z, &normal))
{
CONSOLE_ECHO("ERROR: Start position invalid\n\n");
m_processMode = PROCESS_NORMAL;
return;
}
m_currentNode = new CNavNode(&pos, &normal);
m_goalPosition = pev->origin;
m_processMode = PROCESS_LEARN;
} }
// Search the world and build a map of possible movements.
// The algorithm begins at the bot's current location, and does a recursive search
// outwards, tracking all valid steps and generating a directed graph of CNavNodes.
// Sample the map one "step" in a cardinal direction to learn the map.
// Returns true if sampling needs to continue, or false if done.
/* <343d37> ../cstrike/dlls/bot/cs_bot_learn.cpp:217 */ /* <343d37> ../cstrike/dlls/bot/cs_bot_learn.cpp:217 */
NOBODY bool CCSBot::LearnStep(void) bool CCSBot::LearnStep(void)
{ {
// { UNTESTED
// int dir; // 249 // take a step
// { while (true)
// float feetOffset; // 256 {
// Vector pos; // 259 if (m_currentNode == NULL)
// int cx; // 262 {
// int cy; // 263 // search is exhausted - continue search from ends of ladders
// TraceResult result; // 283 NavLadderList::iterator iter;
// Vector from; // 284 for (iter = TheNavLadderList.begin(); iter != TheNavLadderList.end(); ++iter)
// Vector to; // 284 {
// Vector toNormal; // 289 CNavLadder *ladder = (*iter);
// Vector fromOrigin; // 298
// Vector toOrigin; // 299 // check ladder bottom
// bool walkable; // 303 if ((m_currentNode = LadderEndSearch(ladder->m_entity, &ladder->m_bottom, ladder->m_dir)) != 0)
// IsEntityWalkable(entvars_t *entity, break;
// unsigned int flags); // 362
// { // check ladder top
// float toGround; // 309 if ((m_currentNode = LadderEndSearch(ladder->m_entity, &ladder->m_top, ladder->m_dir)) != 0)
// float fromGround; // 310 break;
// float epsilon; // 312 }
// {
// Vector delta; // 322 if (m_currentNode == NULL)
// float const inc; // 323 {
// float along; // 324 // all seeds exhausted, sampling complete
// bool done; // 325 GenerateNavigationAreaMesh();
// float ground; // 326 return false;
// Vector normal; // 327 }
// operator-(const Vector *const this, }
// const Vector &v); // 322
// { // Take a step from this node
// Vector p; // 333 for (int dir = NORTH; dir < NUM_DIRECTIONS; dir++)
// operator*(const Vector *const this, {
// float fl); // 343 if (!m_currentNode->HasVisited((NavDirType)dir))
// operator+(const Vector *const this, {
// const Vector &v); // 343 float feetOffset = pev->origin.z - GetFeetZ();
// }
// } // start at current node position
// } Vector pos = *m_currentNode->GetPosition();
// VARS(edict_t *pent); // 362
// GetFeetZ(const class CCSBot *const this); // 256 // snap to grid
// Vector(Vector *const this, int cx = SnapToGrid(pos.x);
// const Vector &v); // 259 int cy = SnapToGrid(pos.y);
// MarkAsVisited(CNavNode *const this,
// enum NavDirType dir); // 280 // attempt to move to adjacent node
// operator+(const Vector *const this, switch (dir)
// const Vector &v); // 294 {
// operator+(const Vector *const this, case NORTH: cy -= GenerationStepSize; break;
// const Vector &v); // 298 case SOUTH: cy += GenerationStepSize; break;
// operator+(const Vector *const this, case EAST: cx += GenerationStepSize; break;
// const Vector &v); // 299 case WEST: cx -= GenerationStepSize; break;
// { }
// class CNavNode *newNode; // 376
// AddNode(CCSBot *const this, pos.x = cx;
// const Vector *destPos, pos.y = cy;
// const Vector *normal,
// enum NavDirType dir, m_generationDir = (NavDirType)dir;
// class CNavNode *source); // 376
// } // mark direction as visited
// } m_currentNode->MarkAsVisited(m_generationDir);
// HasVisited(CNavNode *const this,
// enum NavDirType dir); // 251 // test if we can move to new position
// } TraceResult result;
// { Vector from, to;
// iterator iter; // 225
// { // modify position to account for change in ground level during step
// class CNavLadder *ladder; // 227 to.x = pos.x;
// LadderEndSearch(CBaseEntity *entity, to.y = pos.y;
// const Vector *pos, Vector toNormal;
// enum NavDirType mountDir); // 230 if (GetGroundHeight(&pos, &to.z, &toNormal) == false)
// LadderEndSearch(CBaseEntity *entity, {
// const Vector *pos, return true;
// enum NavDirType mountDir); // 234 }
// }
// operator++(_List_iterator<CNavLadder*> *const this); // 225 from = *m_currentNode->GetPosition();
// }
Vector fromOrigin = from + Vector(0, 0, feetOffset);
Vector toOrigin = to + Vector(0, 0, feetOffset);
UTIL_SetOrigin(pev, toOrigin);
UTIL_TraceLine(fromOrigin, toOrigin, ignore_monsters, dont_ignore_glass, ENT(pev), &result);
bool walkable;
if (result.flFraction == 1.0f && !result.fStartSolid)
{
// the trace didnt hit anything - clear
float toGround = to.z;
float fromGround = from.z;
float epsilon = 0.1f;
// check if ledge is too high to reach or will cause us to fall to our death
if (toGround - fromGround > JumpCrouchHeight + epsilon || fromGround - toGround > DeathDrop)
{
walkable = false;
}
else
{
// check surface normals along this step to see if we would cross any impassable slopes
Vector delta = to - from;
const float inc = 2.0f;
float along = inc;
bool done = false;
float ground;
Vector normal;
walkable = true;
while (!done)
{
Vector p;
// need to guarantee that we test the exact edges
if (along >= GenerationStepSize)
{
p = to;
done = true;
}
else
{
p = from + delta * (along / GenerationStepSize);
}
if (GetGroundHeight(&p, &ground, &normal) == false)
{
walkable = false;
break;
}
// check for maximum allowed slope
if (normal.z < 0.7f)
{
walkable = false;
break;
}
along += inc;
}
}
}
// TraceLine hit something...
else
{
if (IsEntityWalkable(VARS(result.pHit), WALK_THRU_EVERYTHING))
{
walkable = true;
}
else
{
walkable = false;
}
}
#ifdef REGAMEDLL_FIXES
// if we're incrementally generating, don't overlap existing nav areas
CNavArea *overlap = TheNavAreaGrid.GetNavArea(&to, HumanHeight);
if (overlap != NULL)
{
walkable = false;
}
#endif // REGAMEDLL_FIXES
if (walkable)
{
// we can move here
// create a new navigation node, and update current node pointer
CNavNode *newNode = AddNode(&to, &toNormal, m_generationDir, m_currentNode);
}
return true;
}
}
// all directions have been searched from this node - pop back to its parent and continue
m_currentNode = m_currentNode->GetParent();
}
} }
/* <34489e> ../cstrike/dlls/bot/cs_bot_learn.cpp:392 */ /* <34489e> ../cstrike/dlls/bot/cs_bot_learn.cpp:392 */
NOBODY void CCSBot::UpdateLearnProcess(void) void CCSBot::UpdateLearnProcess(void)
{ {
// { float startTime = g_engfuncs.pfnTime();
// float startTime; // 394 while (g_engfuncs.pfnTime() - startTime >= updateTimesliceDuration)
// } {
if (LearnStep() == false)
{
StartAnalyzeAlphaProcess();
break;
}
}
} }
/* <344750> ../cstrike/dlls/bot/cs_bot_learn.cpp:409 */ /* <344750> ../cstrike/dlls/bot/cs_bot_learn.cpp:409 */
@ -213,72 +388,114 @@ void CCSBot::StartAnalyzeAlphaProcess(void)
} }
/* <34396c> ../cstrike/dlls/bot/cs_bot_learn.cpp:427 */ /* <34396c> ../cstrike/dlls/bot/cs_bot_learn.cpp:427 */
NOBODY inline bool CCSBot::AnalyzeAlphaStep(void) bool CCSBot::AnalyzeAlphaStep(void)
{ {
// { if (m_analyzeIter == TheNavAreaList.end())
// class CNavArea *area; // 432 return false;
// }
CNavArea *area = (*m_analyzeIter);
++_currentIndex;
area->ComputeHidingSpots();
area->ComputeApproachAreas();
++m_analyzeIter;
return true;
} }
/* <3448de> ../cstrike/dlls/bot/cs_bot_learn.cpp:443 */ /* <3448de> ../cstrike/dlls/bot/cs_bot_learn.cpp:443 */
NOBODY void CCSBot::UpdateAnalyzeAlphaProcess(void) void CCSBot::UpdateAnalyzeAlphaProcess(void)
{ {
// { float startTime = g_engfuncs.pfnTime();
// float startTime; // 445 float progress = _currentIndex / _navAreaCount * 50.0f;
// float progress; // 462
// AnalyzeAlphaStep(CCSBot *const this); // 451 while (AnalyzeAlphaStep())
// drawProgressMeter(float progress, {
// char *title); // 454 if (g_engfuncs.pfnTime() - startTime >= updateTimesliceDuration)
// StartAnalyzeBetaProcess(CCSBot *const this); // 456 {
// drawProgressMeter(float progress, drawProgressMeter(progress, "#CZero_AnalyzingHidingSpots");
// char *title); // 463 return;
// } }
}
drawProgressMeter(50, "#CZero_AnalyzingHidingSpots");
CleanupApproachAreaAnalysisPrep();
StartAnalyzeBetaProcess();
} }
/* <344aed> ../cstrike/dlls/bot/cs_bot_learn.cpp:467 */ /* <344aed> ../cstrike/dlls/bot/cs_bot_learn.cpp:467 */
NOBODY void CCSBot::StartAnalyzeBetaProcess(void) void CCSBot::StartAnalyzeBetaProcess(void)
{ {
// size(const class list<CNavArea*, std::allocator<CNavArea*>> *const this); // 471 m_processMode = PROCESS_ANALYZE_BETA;
m_analyzeIter = TheNavAreaList.begin();
_navAreaCount = TheNavAreaList.size();
_currentIndex = 0;
} }
/* <3437c8> ../cstrike/dlls/bot/cs_bot_learn.cpp:479 */ /* <3437c8> ../cstrike/dlls/bot/cs_bot_learn.cpp:479 */
NOBODY inline bool CCSBot::AnalyzeBetaStep(void) bool CCSBot::AnalyzeBetaStep(void)
{ {
// { if (m_analyzeIter == TheNavAreaList.end())
// class CNavArea *area; // 484 return false;
// }
CNavArea *area = (*m_analyzeIter);
++_currentIndex;
area->ComputeSpotEncounters();
area->ComputeSniperSpots();
++m_analyzeIter;
return true;
} }
/* <344b8d> ../cstrike/dlls/bot/cs_bot_learn.cpp:495 */ /* <344b8d> ../cstrike/dlls/bot/cs_bot_learn.cpp:495 */
NOBODY void CCSBot::UpdateAnalyzeBetaProcess(void) void CCSBot::UpdateAnalyzeBetaProcess(void)
{ {
// { float startTime = g_engfuncs.pfnTime();
// float startTime; // 497 float progress = (_currentIndex / _navAreaCount + 1.0f) * 50.0f;
// float progress; // 512
// AnalyzeBetaStep(CCSBot *const this); // 503 while (AnalyzeBetaStep())
// drawProgressMeter(float progress, {
// char *title); // 506 if (g_engfuncs.pfnTime() - startTime >= updateTimesliceDuration)
// StartSaveProcess(CCSBot *const this); // 507 {
// drawProgressMeter(float progress, drawProgressMeter(progress, "#CZero_AnalyzingApproachPoints");
// char *title); // 513 return;
// } }
}
drawProgressMeter(100, "#CZero_AnalyzingApproachPoints");
StartSaveProcess();
} }
/* <344d1f> ../cstrike/dlls/bot/cs_bot_learn.cpp:517 */ /* <344d1f> ../cstrike/dlls/bot/cs_bot_learn.cpp:517 */
NOBODY void CCSBot::StartSaveProcess(void) void CCSBot::StartSaveProcess(void)
{ {
m_processMode = PROCESS_SAVE;
} }
/* <344d41> ../cstrike/dlls/bot/cs_bot_learn.cpp:527 */ /* <344d41> ../cstrike/dlls/bot/cs_bot_learn.cpp:527 */
NOBODY void CCSBot::UpdateSaveProcess(void) void CCSBot::UpdateSaveProcess(void)
{ {
// { char filename[256];
// char filename; // 530 char msg[256];
// char msg; // 538 char cmd[128];
// char cmd; // 548
// hideProgressMeter(void); // 542 GET_GAME_DIR(filename);
// StartNormalProcess(CCSBot *const this); // 545 filename[Q_strlen(filename)] = '\\';
// } Q_strcat(filename, TheBots->GetNavMapFilename());
HintMessageToAllPlayers("Saving...");
SaveNavigationMap(filename);
Q_sprintf(msg, "Navigation file '%s' saved.", filename);
HintMessageToAllPlayers(msg);
hideProgressMeter();
StartNormalProcess();
Q_sprintf(cmd, "map %s\n", STRING(gpGlobals->mapname));
SERVER_COMMAND(cmd);
} }
/* <344e24> ../cstrike/dlls/bot/cs_bot_learn.cpp:554 */ /* <344e24> ../cstrike/dlls/bot/cs_bot_learn.cpp:554 */

View File

@ -1,92 +1,214 @@
#include "precompiled.h" #include "precompiled.h"
// Listen for enemy noises, and determine if we should react to them.
// Returns true if heard a noise and should move to investigate.
/* <354545> ../cstrike/dlls/bot/cs_bot_listen.cpp:17 */ /* <354545> ../cstrike/dlls/bot/cs_bot_listen.cpp:17 */
NOBODY bool CCSBot::ShouldInvestigateNoise(float *retNoiseDist) bool CCSBot::ShouldInvestigateNoise(float *retNoiseDist)
{ {
// IsNoiseHeard(const class CCSBot *const this); // 32 if (m_isNoiseTravelRangeChecked)
// { return false;
// float const noiseCheckInterval; // 36
// Vector toNoise; // 44 // don't investigate noises during safe time
// float noiseDist; // 45 if (!IsWellPastSafe())
// float const maxNoiseDist; // 46 return false;
// float const oneStoreyHeight; // 49
// float chance; // 72 // if our disposition is not to investigate, dont investigate
// operator-(const Vector *const this, if (GetDisposition() != ENGAGE_AND_INVESTIGATE)
// const Vector &v); // 44 return false;
// Length(const Vector *const this); // 45
// { // listen for enemy noises
// class PathCost pc; // 53 if (IsNoiseHeard() && gpGlobals->time - m_noiseCheckTimestamp >= 0.25f)
// float travelDistToNoise; // 54 {
// float const tooFar; // 58 m_noiseCheckTimestamp = gpGlobals->time;
// NavAreaTravelDistance<PathCost>(CNavArea *startArea, Vector toNoise = m_noisePosition - pev->origin;
// class CNavArea *endArea, float noiseDist = toNoise.Length();
// class PathCost &costFunc); // 54
// } float const oneStoreyHeight = 120.0f;
// { if (abs(int64(toNoise.z)) > oneStoreyHeight)
// float friendFactor; // 78 {
// } PathCost pc(this);
// } float travelDistToNoise = NavAreaTravelDistance(m_lastKnownArea, m_noiseArea, pc);
m_isNoiseTravelRangeChecked = true;
const float tooFar = 1500.0f;
if (travelDistToNoise < 0.0f || travelDistToNoise > tooFar)
return false;
if (noiseDist <= travelDistToNoise)
noiseDist = travelDistToNoise;
}
// if we are hiding, only react to noises very nearby, depending on how aggressive we are
if (IsAtHidingSpot() && noiseDist > 100.0f + 400.0f * GetProfile()->GetAggression())
return false;
// chance of investigating is inversely proportional to distance
const float maxNoiseDist = 2000.0f;
float chance = (1.0f - (noiseDist / maxNoiseDist));
// modify chance by number of friends remaining
// if we have lots of friends, presumably one of them is closer and will check it out
if (GetFriendsRemaining() >= 3)
{
float friendFactor = 0.05f * GetFriendsRemaining();
if (friendFactor > 0.5f)
friendFactor = 0.5f;
chance -= friendFactor;
}
if (RANDOM_FLOAT(0.0f, 1.0f) <= chance)
{
if (retNoiseDist)
*retNoiseDist = noiseDist;
return true;
}
}
return false;
} }
// Return true if we hear nearby threatening enemy gunfire within given range
// -1 == infinite range
/* <354c8d> ../cstrike/dlls/bot/cs_bot_listen.cpp:104 */ /* <354c8d> ../cstrike/dlls/bot/cs_bot_listen.cpp:104 */
NOBODY bool CCSBot::CanHearNearbyEnemyGunfire(float range) bool CCSBot::CanHearNearbyEnemyGunfire(float range) const
{ {
// { // only attend to noise if it just happened
// float gunfireDistSq; // 125 if (gpGlobals->time - m_noiseTimestamp > 0.5f)
// float enemyDistSq; // 126 return false;
// float const muchCloserSq; // 127
// operator-(const Vector *const this, // gunfire is high priority
// const Vector &v); // 126 if (m_noisePriority < PRIORITY_HIGH)
// operator-(const Vector *const this, return false;
// const Vector &v); // 125
// LengthSquared(const Vector *const this); // 125 // check noise range
// LengthSquared(const Vector *const this); // 126 if (range > 0.0f && (pev->origin - m_noisePosition).IsLengthGreaterThan(range))
// } return false;
// CanSeeNoisePosition(const class CCSBot *const this); // 119
// operator-(const Vector *const this, // if we dont have line of sight, it's not threatening (cant get shot)
// const Vector &v); // 115 if (!CanSeeNoisePosition())
// IsLengthGreaterThan(const Vector *const this, return false;
// float length); // 115
if (IsAttacking() && m_enemy != NULL)
{
// gunfire is only threatening if it is closer than our current enemy
float gunfireDistSq = (m_noisePosition - pev->origin).LengthSquared();
float enemyDistSq = (m_enemy->pev->origin - pev->origin).LengthSquared();
const float muchCloserSq = 100.0f * 100.0f;
if (gunfireDistSq > enemyDistSq - muchCloserSq)
return false;
}
return true;
} }
// Return true if we directly see where we think the noise came from
// NOTE: Dont check FOV, since this is used to determine if we should turn our head to look at the noise
// NOTE: Dont use IsVisible(), because smoke shouldnt cause us to not look toward noises
/* <354e7b> ../cstrike/dlls/bot/cs_bot_listen.cpp:141 */ /* <354e7b> ../cstrike/dlls/bot/cs_bot_listen.cpp:141 */
NOBODY bool CCSBot::CanSeeNoisePosition(void) bool CCSBot::CanSeeNoisePosition(void) const
{ {
// { TraceResult result;
// TraceResult result; // 143 UTIL_TraceLine(GetEyePosition(), m_noisePosition + Vector(0, 0, HalfHumanHeight), ignore_monsters, ignore_glass, ENT(pev), &result);
// operator+(const Vector *const this,
// const Vector &v); // 144 if (result.flFraction == 1.0f)
// GetEyePosition(const class CCSBot *const this); // 144 {
// } // we can see the source of the noise
return true;
}
return false;
} }
// Return true if we decided to look towards the most recent noise source
// Assumes m_noisePosition is valid.
/* <354f48> ../cstrike/dlls/bot/cs_bot_listen.cpp:160 */ /* <354f48> ../cstrike/dlls/bot/cs_bot_listen.cpp:160 */
NOBODY bool CCSBot::UpdateLookAtNoise(void) bool CCSBot::UpdateLookAtNoise(void)
{ {
// { // make sure a noise exists
// bool nearbyThreat; // 176 if (!IsNoiseHeard() || gpGlobals->time - m_noiseTimestamp > 0.5f)
// float const recentThreatTime; // 177 return false;
// float const closeThreatRange; // 178
// Vector spot; // 190 bool nearbyThreat = false;
// enum PriorityType pri; // 231 float const recentThreatTime = 5.0f;
// IsNoiseHeard(const class CCSBot *const this); // 163 if (GetTimeSinceLastSawEnemy() < recentThreatTime)
// operator-(const Vector *const this, {
// const Vector &v); // 181 const float closeThreatRange = 750.0f;
// IsLengthLessThan(const Vector *const this, if ((pev->origin - m_lastEnemyPosition).IsLengthLessThan(closeThreatRange))
// float length); // 181 {
// CanSeeNoisePosition(const class CCSBot *const this); // 193 nearbyThreat = true;
// { }
// int nearIdx; // 200 }
// float nearRangeSq; // 201
// { Vector spot;
// int i; // 202
// { // if we have clear line of sight to noise position, look directly at it
// float distanceSq; // 206 if ((!IsAtHidingSpot() && nearbyThreat) || CanSeeNoisePosition())
// operator-(const Vector *const this, {
// const Vector &v); // 206 // TODO: adjust noise Z to keep consistent with current height while fighting
// LengthSquared(const Vector *const this); // 206 spot = m_noisePosition + Vector(0, 0, HalfHumanHeight);
// } }
// } else
// } {
// } // line of sight is blocked, bend it
if (m_approachPointCount == 0)
return false;
int nearIdx = -1;
float nearRangeSq = 9.9999998e10f;
for (int i = 0; i < m_approachPointCount; ++i)
{
float distanceSq = (m_approachPoint[i] - m_noisePosition).LengthSquared();
if (distanceSq < nearRangeSq)
{
nearRangeSq = distanceSq;
nearIdx = i;
}
}
if (nearIdx != -1)
{
// line of sight is blocked, bend it
if (BendLineOfSight(&pev->origin, &m_approachPoint[nearIdx], &spot) == false)
return false;
spot.z += HalfHumanHeight;
}
else
{
// prior bend failed
return false;
}
}
// it's always important to look at enemy noises, because they come from ... enemies!
PriorityType pri = (GetNoisePriority() == PRIORITY_HIGH) ? PRIORITY_HIGH : PRIORITY_MEDIUM;
// look longer if we're hiding
if (IsAtHidingSpot())
{
// if there is only one enemy left, look for a long time
if (GetEnemiesRemaining() == 1)
{
SetLookAt("Noise", &spot, pri, RANDOM_FLOAT(5.0f, 15.0f), true);
}
else
{
SetLookAt("Noise", &spot, pri, RANDOM_FLOAT(2.0f, 5.0f), true);
}
}
else
{
SetLookAt("Noise", &spot, pri, RANDOM_FLOAT(1.0f, 2.0f), true);
}
return true;
} }

File diff suppressed because it is too large Load Diff

View File

@ -36,36 +36,6 @@
#define TheBots (*pTheBots) #define TheBots (*pTheBots)
#define cv_bot_traceview (*pcv_bot_traceview)
#define cv_bot_stop (*pcv_bot_stop)
#define cv_bot_show_nav (*pcv_bot_show_nav)
#define cv_bot_show_danger (*pcv_bot_show_danger)
#define cv_bot_nav_edit (*pcv_bot_nav_edit)
#define cv_bot_nav_zdraw (*pcv_bot_nav_zdraw)
#define cv_bot_walk (*pcv_bot_walk)
#define cv_bot_difficulty (*pcv_bot_difficulty)
#define cv_bot_debug (*pcv_bot_debug)
#define cv_bot_quicksave (*pcv_bot_quicksave)
#define cv_bot_quota (*pcv_bot_quota)
#define cv_bot_quota_match (*pcv_bot_quota_match)
#define cv_bot_prefix (*pcv_bot_prefix)
#define cv_bot_allow_rogues (*pcv_bot_allow_rogues)
#define cv_bot_allow_pistols (*pcv_bot_allow_pistols)
#define cv_bot_allow_shotguns (*pcv_bot_allow_shotguns)
#define cv_bot_allow_sub_machine_guns (*pcv_bot_allow_sub_machine_guns)
#define cv_bot_allow_rifles (*pcv_bot_allow_rifles)
#define cv_bot_allow_machine_guns (*pcv_bot_allow_machine_guns)
#define cv_bot_allow_grenades (*pcv_bot_allow_grenades)
#define cv_bot_allow_snipers (*pcv_bot_allow_snipers)
#define cv_bot_allow_shield (*pcv_bot_allow_shield)
#define cv_bot_join_team (*pcv_bot_join_team)
#define cv_bot_join_after_player (*pcv_bot_join_after_player)
#define cv_bot_auto_vacate (*pcv_bot_auto_vacate)
#define cv_bot_zombie (*pcv_bot_zombie)
#define cv_bot_defer_to_human (*pcv_bot_defer_to_human)
#define cv_bot_chatter (*pcv_bot_chatter)
#define cv_bot_profile_db (*pcv_bot_profile_db)
//#define m_flNextCVarCheck (*pm_flNextCVarCheck) //#define m_flNextCVarCheck (*pm_flNextCVarCheck)
//#define m_isMapDataLoaded (*pm_isMapDataLoaded) //#define m_isMapDataLoaded (*pm_isMapDataLoaded)
//#define m_editCmd (*pm_editCmd) //#define m_editCmd (*pm_editCmd)
@ -77,57 +47,28 @@
extern CBotManager *TheBots; extern CBotManager *TheBots;
extern cvar_t cv_bot_traceview; // The manager for Counter-Strike specific bots
extern cvar_t cv_bot_stop;
extern cvar_t cv_bot_show_nav;
extern cvar_t cv_bot_show_danger;
extern cvar_t cv_bot_nav_edit;
extern cvar_t cv_bot_nav_zdraw;
extern cvar_t cv_bot_walk;
extern cvar_t cv_bot_difficulty;
extern cvar_t cv_bot_debug;
extern cvar_t cv_bot_quicksave;
extern cvar_t cv_bot_quota;
extern cvar_t cv_bot_quota_match;
extern cvar_t cv_bot_prefix;
extern cvar_t cv_bot_allow_rogues;
extern cvar_t cv_bot_allow_pistols;
extern cvar_t cv_bot_allow_shotguns;
extern cvar_t cv_bot_allow_sub_machine_guns;
extern cvar_t cv_bot_allow_rifles;
extern cvar_t cv_bot_allow_machine_guns;
extern cvar_t cv_bot_allow_grenades;
extern cvar_t cv_bot_allow_snipers;
extern cvar_t cv_bot_allow_shield;
extern cvar_t cv_bot_join_team;
extern cvar_t cv_bot_join_after_player;
extern cvar_t cv_bot_auto_vacate;
extern cvar_t cv_bot_zombie;
extern cvar_t cv_bot_defer_to_human;
extern cvar_t cv_bot_chatter;
extern cvar_t cv_bot_profile_db;
class CCSBotManager: public CBotManager class CCSBotManager: public CBotManager
{ {
public: public:
CCSBotManager(void); CCSBotManager();
public:
virtual void ClientDisconnect(CBasePlayer *pPlayer); virtual void ClientDisconnect(CBasePlayer *pPlayer);
virtual BOOL ClientCommand(CBasePlayer *pPlayer, const char *pcmd); virtual BOOL ClientCommand(CBasePlayer *pPlayer, const char *pcmd);
virtual void ServerActivate(void); virtual void ServerActivate(void);
virtual void ServerDeactivate(void); virtual void ServerDeactivate(void);
NOBODY virtual void ServerCommand(const char *pcmd); virtual void ServerCommand(const char *pcmd);
virtual void AddServerCommand(const char *cmd); virtual void AddServerCommand(const char *cmd);
virtual void AddServerCommands(void); virtual void AddServerCommands(void);
virtual void RestartRound(void); virtual void RestartRound(void); // (EXTEND) invoked when a new round begins
NOBODY virtual void StartFrame(void); virtual void StartFrame(void); // (EXTEND) called each frame
virtual void OnEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL); virtual void OnEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL);
NOBODY virtual unsigned int GetPlayerPriority(CBasePlayer *player) const; virtual unsigned int GetPlayerPriority(CBasePlayer *player) const; // return priority of player (0 = max pri)
NOBODY virtual bool IsImportantPlayer(CBasePlayer *player); virtual bool IsImportantPlayer(CBasePlayer *player) const; // return true if player is important to scenario (VIP, bomb carrier, etc)
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -142,31 +83,19 @@ public:
void StartFrame_(void); void StartFrame_(void);
void OnEvent_(GameEventType event, CBaseEntity *entity, CBaseEntity *other); void OnEvent_(GameEventType event, CBaseEntity *entity, CBaseEntity *other);
unsigned int GetPlayerPriority_(CBasePlayer *player) const; unsigned int GetPlayerPriority_(CBasePlayer *player) const;
bool IsImportantPlayer_(CBasePlayer *player); bool IsImportantPlayer_(CBasePlayer *player) const;
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
public: public:
void ValidateMapData(void); void ValidateMapData(void);
bool IsLearningMap(void) bool IsLearningMap(void) const { return IMPL(m_isLearningMap); }
{ void SetLearningMapFlag(void) { IMPL(m_isLearningMap) = true;}
return IMPL(m_isLearningMap); bool IsAnalysisRequested(void) const { return IMPL(m_isAnalysisRequested); }
} void RequestAnalysis(void) { IMPL(m_isAnalysisRequested) = true; }
void SetLearningMapFlag(void) void AckAnalysisRequest(void) { IMPL(m_isAnalysisRequested) = false; }
{
IMPL(m_isLearningMap) = true; // difficulty levels
}
bool IsAnalysisRequested(void)
{
return IMPL(m_isAnalysisRequested);
}
void RequestAnalysis(void)
{
IMPL(m_isAnalysisRequested) = true;
}
void AckAnalysisRequest(void)
{
IMPL(m_isAnalysisRequested) = false;
}
static BotDifficultyType GetDifficultyLevel(void) static BotDifficultyType GetDifficultyLevel(void)
{ {
if (cv_bot_difficulty.value < 0.9f) if (cv_bot_difficulty.value < 0.9f)
@ -181,41 +110,42 @@ public:
return BOT_EXPERT; return BOT_EXPERT;
} }
// the supported game scenarios
enum GameScenarioType enum GameScenarioType
{ {
SCENARIO_DEATHMATCH, SCENARIO_DEATHMATCH,
SCENARIO_DEFUSE_BOMB, SCENARIO_DEFUSE_BOMB,
SCENARIO_RESCUE_HOSTAGES, SCENARIO_RESCUE_HOSTAGES,
SCENARIO_ESCORT_VIP, SCENARIO_ESCORT_VIP
}; };
GameScenarioType GetScenario(void) GameScenarioType GetScenario(void) const { return m_gameScenario; }
{
return m_gameScenario;
}
enum { MAX_ZONES = 4, MAX_ZONE_NAV_AREAS = 16 }; // "zones"
// depending on the game mode, these are bomb zones, rescue zones, etc.
enum { MAX_ZONES = 4 }; // max # of zones in a map
enum { MAX_ZONE_NAV_AREAS = 16 }; // max # of nav areas in a zone
struct Zone struct Zone
{ {
CBaseEntity *m_entity; CBaseEntity *m_entity; // the map entity
CNavArea *m_area[MAX_ZONE_NAV_AREAS]; CNavArea *m_area[MAX_ZONE_NAV_AREAS]; // nav areas that overlap this zone
int m_areaCount; int m_areaCount;
Vector m_center; Vector m_center;
bool m_isLegacy; bool m_isLegacy; // if true, use pev->origin and 256 unit radius as zone
int m_index; int m_index;
Extent m_extent; Extent m_extent;
};/* size: 116, cachelines: 2, members: 7 */ };/* size: 116, cachelines: 2, members: 7 */
const Zone *GetZone(int i) const const Zone *GetZone(int i) const { return &m_zone[i]; }
{ const Zone *GetZone(const Vector *pos) const; // return the zone that contains the given position
return &m_zone[i]; const Zone *GetClosestZone(const Vector *pos) const; // return the closest zone to the given position
} const Zone *GetClosestZone(const CBaseEntity *entity) const { return GetClosestZone(&entity->pev->origin); } // return the closest zone to the given entity
NOBODY const Zone *GetZone(const Vector *pos) const; int GetZoneCount(void) const { return m_zoneCount; }
const Zone *GetClosestZone(const Vector *pos) const;
const Zone *GetClosestZone(const CBaseEntity *entity) const const Vector *GetRandomPositionInZone(const Zone *zone) const;
{ CNavArea *GetRandomAreaInZone(const Zone *zone) const;
return GetClosestZone(&entity->pev->origin);
} // Return the zone closest to the given position, using the given cost heuristic
template<typename CostFunctor> template<typename CostFunctor>
const Zone *GetClosestZone(CNavArea *startArea, CostFunctor costFunc, float *travelDistance = NULL) const const Zone *GetClosestZone(CNavArea *startArea, CostFunctor costFunc, float *travelDistance = NULL) const
{ {
@ -225,7 +155,7 @@ public:
if (startArea == NULL) if (startArea == NULL)
return NULL; return NULL;
for (int i = 0; i < m_zoneCount; i++) for (int i = 0; i < m_zoneCount; ++i)
{ {
if (m_zone[i].m_areaCount == 0) if (m_zone[i].m_areaCount == 0)
continue; continue;
@ -233,7 +163,9 @@ public:
if (m_zone[i].m_isBlocked) if (m_zone[i].m_isBlocked)
continue; continue;
// just use the first overlapping nav area as a reasonable approximation
float dist = NavAreaTravelDistance(startArea, m_zone[i].m_area[0], costFunc); float dist = NavAreaTravelDistance(startArea, m_zone[i].m_area[0], costFunc);
if (dist >= 0.0f && dist < closeDist) if (dist >= 0.0f && dist < closeDist)
{ {
closeZone = &m_zone[i]; closeZone = &m_zone[i];
@ -241,17 +173,11 @@ public:
} }
} }
if (travelDistance) if (travelDistance != NULL)
*travelDistance = closeDist; *travelDistance = closeDist;
return closeZone; return closeZone;
} }
int GetZoneCount(void) const
{
return m_zoneCount;
}
NOBODY const Vector *GetRandomPositionInZone(const Zone *zone) const;
NOBODY CNavArea *GetRandomAreaInZone(const Zone *zone) const;
// pick a zone at random and return it // pick a zone at random and return it
const Zone *GetRandomZone(void) const const Zone *GetRandomZone(void) const
@ -261,172 +187,89 @@ public:
return &m_zone[ RANDOM_LONG(0, m_zoneCount - 1) ]; return &m_zone[ RANDOM_LONG(0, m_zoneCount - 1) ];
} }
// returns true if bomb has been planted
bool IsBombPlanted(void) const bool IsBombPlanted(void) const { return m_isBombPlanted; } // returns true if bomb has been planted
{ float GetBombPlantTimestamp(void) const { return m_bombPlantTimestamp; } // return time bomb was planted
return m_isBombPlanted; bool IsTimeToPlantBomb(void) const { return (gpGlobals->time >= m_earliestBombPlantTimestamp); } // return true if it's ok to try to plant bomb
} CBasePlayer *GetBombDefuser(void) const { return m_bombDefuser; } // return the player currently defusing the bomb, or NULL
// return time bomb was planted float GetBombTimeLeft(void) const; // get the time remaining before the planted bomb explodes
float GetBombPlantTimestamp(void) CBaseEntity *GetLooseBomb(void) { return m_looseBomb; } // return the bomb if it is loose on the ground
{ CNavArea *GetLooseBombArea(void) const { return m_looseBombArea; } // return area that bomb is in/near
return m_bombPlantTimestamp;
}
// return true if it's ok to try to plant bomb
bool IsTimeToPlantBomb(void) const
{
return (gpGlobals->time >= m_earliestBombPlantTimestamp);
}
CBasePlayer *GetBombDefuser(void) const
{
return m_bombDefuser;
}
NOBODY float GetBombTimeLeft(void) const;
// return the bomb if it is loose on the ground
CBaseEntity *GetLooseBomb(void)
{
return m_looseBomb;
}
// return area that bomb is in/near
CNavArea *GetLooseBombArea(void) const
{
return m_looseBombArea;
}
void SetLooseBomb(CBaseEntity *bomb); void SetLooseBomb(CBaseEntity *bomb);
NOBODY float GetRadioMessageTimestamp(GameEventType event, int teamID);
NOBODY float GetRadioMessageInterval(GameEventType event, int teamID); float GetRadioMessageTimestamp(GameEventType event, int teamID) const; // return the last time the given radio message was sent for given team
NOBODY void SetRadioMessageTimestamp(GameEventType event, int teamID); float GetRadioMessageInterval(GameEventType event, int teamID) const; // return the interval since the last time this message was sent
void SetRadioMessageTimestamp(GameEventType event, int teamID);
void ResetRadioMessageTimestamps(void); void ResetRadioMessageTimestamps(void);
// return the last time anyone has seen an enemy float GetLastSeenEnemyTimestamp(void) const { return m_lastSeenEnemyTimestamp; } // return the last time anyone has seen an enemy
float GetLastSeenEnemyTimestamp(void) const void SetLastSeenEnemyTimestamp(void) { m_lastSeenEnemyTimestamp = gpGlobals->time; }
{
return m_lastSeenEnemyTimestamp;
}
void SetLastSeenEnemyTimestamp(void)
{
m_lastSeenEnemyTimestamp = gpGlobals->time;
}
float GetRoundStartTime(void) const
{
return m_roundStartTimestamp;
}
// return the elapsed time since the current round began
float GetElapsedRoundTime(void) const
{
return gpGlobals->time - m_roundStartTimestamp;
}
bool AllowRogues(void) const
{
return cv_bot_allow_rogues.value != 0;
}
bool AllowPistols(void) const
{
return cv_bot_allow_pistols.value != 0;
}
bool AllowShotguns(void) const
{
return cv_bot_allow_shotguns.value != 0;
}
bool AllowSubMachineGuns(void) const
{
return cv_bot_allow_sub_machine_guns.value != 0;
}
bool AllowRifles(void) const
{
return cv_bot_allow_rifles.value != 0;
}
bool AllowMachineGuns(void) const
{
return cv_bot_allow_machine_guns.value != 0;
}
bool AllowGrenades(void) const
{
return cv_bot_allow_grenades.value != 0;
}
bool AllowSnipers(void) const
{
return cv_bot_allow_snipers.value != 0;
}
bool AllowTacticalShield(void) const
{
return cv_bot_allow_shield.value != 0;
}
bool AllowFriendlyFireDamage(void) const
{
return friendlyfire.value != 0;
}
bool IsWeaponUseable(CBasePlayerItem *item) const;
bool IsDefenseRushing(void) const
{
return m_isDefenseRushing;
}
NOBODY bool IsOnDefense(CBasePlayer *player) const;
NOBODY bool IsOnOffense(CBasePlayer *player) const;
bool IsRoundOver(void) const
{
return m_isRoundOver;
}
unsigned int GetNavPlace(void) const
{
return m_navPlace;
}
void SetNavPlace(unsigned int place)
{
m_navPlace = place;
}
enum SkillType float GetRoundStartTime(void) const { return m_roundStartTimestamp; }
{ float GetElapsedRoundTime(void) const { return gpGlobals->time - m_roundStartTimestamp; } // return the elapsed time since the current round began
LOW,
AVERAGE, bool AllowRogues(void) const { return cv_bot_allow_rogues.value != 0.0f; }
HIGH, bool AllowPistols(void) const { return cv_bot_allow_pistols.value != 0.0f; }
RANDOM bool AllowShotguns(void) const { return cv_bot_allow_shotguns.value != 0.0f; }
}; bool AllowSubMachineGuns(void) const { return cv_bot_allow_sub_machine_guns.value != 0.0f; }
bool AllowRifles(void) const { return cv_bot_allow_rifles.value != 0.0f; }
bool AllowMachineGuns(void) const { return cv_bot_allow_machine_guns.value != 0.0f; }
bool AllowGrenades(void) const { return cv_bot_allow_grenades.value != 0.0f; }
bool AllowSnipers(void) const { return cv_bot_allow_snipers.value != 0.0f; }
bool AllowTacticalShield(void) const { return cv_bot_allow_shield.value != 0.0f; }
bool AllowFriendlyFireDamage(void) const { return friendlyfire.value != 0.0f; }
bool IsWeaponUseable(CBasePlayerItem *item) const; // return true if the bot can use this weapon
bool IsDefenseRushing(void) const { return m_isDefenseRushing; } // returns true if defense team has "decided" to rush this round
bool IsOnDefense(CBasePlayer *player) const; // return true if this player is on "defense"
bool IsOnOffense(CBasePlayer *player) const; // return true if this player is on "offense"
bool IsRoundOver(void) const { return m_isRoundOver; } // return true if the round has ended
unsigned int GetNavPlace(void) const { return m_navPlace; }
void SetNavPlace(unsigned int place) { m_navPlace = place; }
enum SkillType { LOW, AVERAGE, HIGH, RANDOM };
NOXREF NOBODY const char *GetRandomBotName(SkillType skill); NOXREF NOBODY const char *GetRandomBotName(SkillType skill);
NOBODY static void MonitorBotCVars(void); static void MonitorBotCVars(void);
NOBODY static void MaintainBotQuota(void); static void MaintainBotQuota(void);
NOBODY static bool AddBot(const BotProfile *profile, BotProfileTeamType team); NOBODY static bool AddBot(const BotProfile *profile, BotProfileTeamType team);
NOBODY static bool BotAddCommand(BotProfileTeamType team, bool isFromConsole = true);
#define FROM_CONSOLE true
static bool BotAddCommand(BotProfileTeamType team, bool isFromConsole = false); // process the "bot_add" console command
#ifndef HOOK_GAMEDLL #ifndef HOOK_GAMEDLL
private: private:
#else
public:
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
static float IMPL(m_flNextCVarCheck); static float IMPL(m_flNextCVarCheck);
static bool IMPL(m_isMapDataLoaded); static bool IMPL(m_isMapDataLoaded); // true if we've attempted to load map data
static bool IMPL(m_isLearningMap); static bool IMPL(m_isLearningMap);
static bool IMPL(m_isAnalysisRequested); static bool IMPL(m_isAnalysisRequested);
#ifdef HOOK_GAMEDLL
private:
#endif // HOOK_GAMEDLL
GameScenarioType m_gameScenario;// TODO: must be on Windows offsetof - 16 GameScenarioType m_gameScenario; // what kind of game are we playing
Zone m_zone[ MAX_ZONES ]; Zone m_zone[ MAX_ZONES ];
int m_zoneCount; int m_zoneCount;
bool m_isBombPlanted;
float m_bombPlantTimestamp; bool m_isBombPlanted; // true if bomb has been planted
float m_earliestBombPlantTimestamp; float m_bombPlantTimestamp; // time bomb was planted
CBasePlayer *m_bombDefuser; float m_earliestBombPlantTimestamp; // don't allow planting until after this time has elapsed
EHANDLE m_looseBomb; CBasePlayer *m_bombDefuser; // the player currently defusing a bomb
CNavArea *m_looseBombArea; EHANDLE m_looseBomb; // will be non-NULL if bomb is loose on the ground
bool m_isRoundOver; CNavArea *m_looseBombArea; // area that bomb is is/near
bool m_isRoundOver; // true if the round has ended
float m_radioMsgTimestamp[24][2]; float m_radioMsgTimestamp[24][2];
float m_lastSeenEnemyTimestamp; float m_lastSeenEnemyTimestamp;
float m_roundStartTimestamp; float m_roundStartTimestamp; // the time when the current round began
bool m_isDefenseRushing;
bool m_isDefenseRushing; // whether defensive team is rushing this round or not
#ifndef HOOK_GAMEDLL
private:
#else
public:
#endif // HOOK_GAMEDLL
static NavEditCmdType IMPL(m_editCmd); static NavEditCmdType IMPL(m_editCmd);
#ifdef HOOK_GAMEDLL
private:
#endif // HOOK_GAMEDLL
unsigned int m_navPlace; unsigned int m_navPlace;
CountdownTimer m_respawnTimer; CountdownTimer m_respawnTimer;
bool m_isRespawnStarted; bool m_isRespawnStarted;
@ -448,7 +291,7 @@ inline CCSBotManager *TheCSBots(void)
} }
void PrintAllEntities(void); void PrintAllEntities(void);
NOBODY void UTIL_DrawBox(Extent *extent, int lifetime, int red, int green, int blue); void UTIL_DrawBox(Extent *extent, int lifetime, int red, int green, int blue);
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL

View File

@ -1,218 +1,468 @@
#include "precompiled.h" #include "precompiled.h"
// Reset the stuck-checker.
/* <37c284> ../cstrike/dlls/bot/cs_bot_nav.cpp:16 */ /* <37c284> ../cstrike/dlls/bot/cs_bot_nav.cpp:16 */
NOBODY void CCSBot::ResetStuckMonitor(void) void CCSBot::ResetStuckMonitor(void)
{ {
if (m_isStuck)
{
if (IsLocalPlayerWatchingMe() && cv_bot_debug.value > 0.0f)
{
EMIT_SOUND(edict(), CHAN_ITEM, "buttons/bell1.wav", VOL_NORM, ATTN_NORM);
}
}
m_isStuck = false;
m_stuckTimestamp = 0.0f;
m_stuckJumpTimestamp = 0.0f;
m_avgVelIndex = 0;
m_avgVelCount = 0;
m_areaEnteredTimestamp = gpGlobals->time;
} }
// Test if we have become stuck
/* <37c2a6> ../cstrike/dlls/bot/cs_bot_nav.cpp:37 */ /* <37c2a6> ../cstrike/dlls/bot/cs_bot_nav.cpp:37 */
NOBODY void CCSBot::StuckCheck(void) void CCSBot::StuckCheck(void)
{ {
// { if (m_isStuck)
// Vector delta; // 42 {
// float const unstuckRange; // 44 // we are stuck - see if we have moved far enough to be considered unstuck
// operator-(const Vector *const this, Vector delta = pev->origin - m_stuckSpot;
// const Vector &v); // 42
// IsLengthGreaterThan(const Vector *const this, const float unstuckRange = 75.0f;
// float length); // 45 if (delta.IsLengthGreaterThan(unstuckRange))
// ResetStuckMonitor(CCSBot *const this); // 48 {
// } // we are no longer stuck
// { ResetStuckMonitor();
// Vector vel; // 57 PrintIfWatched("UN-STUCK\n");
// float moveDist; // 64 }
// float deltaT; // 66 }
// operator-(const Vector *const this, else
// const Vector &v); // 57 {
// Length(const Vector *const this); // 64 // check if we are stuck
// { // compute average velocity over a short period (for stuck check)
// float avgVel; // 81 Vector vel = pev->origin - m_lastOrigin;
// float stuckVel; // 88
// { // if we are jumping, ignore Z
// int t; // 82 if (IsJumping())
// } vel.z = 0.0f;
// }
// } // cannot be Length2D, or will break ladder movement (they are only Z)
float moveDist = vel.Length();
float deltaT = g_flBotFullThinkInterval;
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 bots will get "stuck" when going down ladders
float stuckVel = (IsUsingLadder()) ? 10.0f : 20.0f;
if (avgVel < stuckVel)
{
// we are stuck - note when and where we initially become stuck
m_stuckTimestamp = gpGlobals->time;
m_stuckSpot = pev->origin;
m_stuckJumpTimestamp = gpGlobals->time + RANDOM_FLOAT(0.0f, 0.5f);
PrintIfWatched("STUCK\n");
if (IsLocalPlayerWatchingMe() && cv_bot_debug.value > 0.0f)
{
EMIT_SOUND(ENT(pev), CHAN_ITEM, "buttons/button11.wav", VOL_NORM, ATTN_NORM);
}
m_isStuck = true;
}
}
}
// always need to track this
m_lastOrigin = pev->origin;
} }
// Check if we need to jump due to height change
/* <37c05d> ../cstrike/dlls/bot/cs_bot_nav.cpp:114 */ /* <37c05d> ../cstrike/dlls/bot/cs_bot_nav.cpp:114 */
NOBODY bool CCSBot::DiscontinuityJump(float ground, bool onlyJumpDown, bool mustJump) bool CCSBot::DiscontinuityJump(float ground, bool onlyJumpDown, bool mustJump)
{ {
// { // don't try to jump again.
// float dz; // 119 if (m_isJumpCrouching)
// } return false;
float_precision dz = ground - GetFeetZ();
if (dz > StepHeight && !onlyJumpDown)
{
// dont restrict jump time when going up
if (Jump(MUST_JUMP))
{
m_isJumpCrouching = true;
m_isJumpCrouched = false;
StandUp();
m_jumpCrouchTimestamp = gpGlobals->time;
return true;
}
}
else if (!IsUsingLadder() && dz < -JumpHeight)
{
if (Jump(mustJump))
{
m_isJumpCrouching = true;
m_isJumpCrouched = false;
StandUp();
m_jumpCrouchTimestamp = gpGlobals->time;
return true;
}
}
return false;
} }
// Find "simple" ground height, treating current nav area as part of the floor
/* <37c448> ../cstrike/dlls/bot/cs_bot_nav.cpp:154 */ /* <37c448> ../cstrike/dlls/bot/cs_bot_nav.cpp:154 */
NOBODY bool CCSBot::GetSimpleGroundHeightWithFloor(const Vector *pos, float *height, Vector *normal) bool CCSBot::GetSimpleGroundHeightWithFloor(const Vector *pos, float *height, Vector *normal)
{ {
// GetSimpleGroundHeightWithFloor(CCSBot *const this, if (GetSimpleGroundHeight(pos, height, normal))
// const Vector *pos, {
// float *height, // our current nav area also serves as a ground polygon
// Vector *normal); // 154 if (m_lastKnownArea != NULL && m_lastKnownArea->IsOverlapping(pos))
{
*height = Q_max((*height), m_lastKnownArea->GetZ(pos));
}
return true;
}
return false;
} }
/* <37c4b8> ../cstrike/dlls/bot/cs_bot_nav.cpp:172 */ /* <37c4b8> ../cstrike/dlls/bot/cs_bot_nav.cpp:172 */
NOBODY Place CCSBot::GetPlace(void) Place CCSBot::GetPlace(void) const
{ {
if (m_lastKnownArea != NULL)
return m_lastKnownArea->GetPlace();
return UNDEFINED_PLACE;
} }
/* <37c4de> ../cstrike/dlls/bot/cs_bot_nav.cpp:184 */ /* <37c4de> ../cstrike/dlls/bot/cs_bot_nav.cpp:184 */
NOBODY void CCSBot::MoveTowardsPosition(const Vector *pos) void CCSBot::MoveTowardsPosition(const Vector *pos)
{ {
// { // Jump up on ledges
// float angle; // 249 // Because we may not be able to get to our goal position and enter the next
// class Vector2D dir; // 251 // area because our extent collides with a nearby vertical ledge, make sure
// class Vector2D lat; // 252 // we look far enough ahead to avoid this situation.
// class Vector2D to; // 255 // Can't look too far ahead, or bots will try to jump up slopes.
// float toProj; // 259
// float latProj; // 260 // NOTE: We need to do this frequently to catch edges at the right time
// float const c; // 262 // TODO: Look ahead *along path* instead of straight line
// { if ((m_lastKnownArea == NULL || !(m_lastKnownArea->GetAttributes() & NAV_NO_JUMP)) &&
// float ground; // 200 !IsOnLadder() && !m_isJumpCrouching)
// Vector aheadRay; // 201 {
// bool jumped; // 207 float ground;
// NormalizeInPlace(Vector *const this); // 202 Vector aheadRay(pos->x - pev->origin.x, pos->y - pev->origin.y, 0);
// { aheadRay.NormalizeInPlace();
// float const farLookAheadRange; // 210
// Vector normal; // 211 // look far ahead to allow us to smoothly jump over gaps, ledges, etc
// Vector stepAhead; // 212 // only jump if ground is flat at lookahead spot to avoid jumping up slopes
// operator*(float fl, bool jumped = false;
// const Vector &v); // 212
// GetSimpleGroundHeightWithFloor(CCSBot *const this, if (IsRunning())
// const Vector *pos, {
// float *height, const float farLookAheadRange = 80.0f;
// Vector *normal); // 215 Vector normal;
// operator+(const Vector *const this, Vector stepAhead = pev->origin + farLookAheadRange * aheadRay;
// const Vector &v); // 212 stepAhead.z += HalfHumanHeight;
// DiscontinuityJump(CCSBot *const this,
// float ground, if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground, &normal))
// bool onlyJumpDown, {
// bool mustJump); // 218 if (normal.z > 0.9f)
// } jumped = DiscontinuityJump(ground, ONLY_JUMP_DOWN);
// { }
// float const lookAheadRange; // 225 }
// Vector stepAhead; // 226
// operator*(float fl, if (!jumped)
// const Vector &v); // 226 {
// operator+(const Vector *const this, // close up jumping
// const Vector &v); // 226 // cant be less or will miss jumps over low walls
// GetSimpleGroundHeightWithFloor(CCSBot *const this, const float lookAheadRange = 30.0f;
// const Vector *pos, Vector stepAhead = pev->origin + lookAheadRange * aheadRay;
// float *height, stepAhead.z += HalfHumanHeight;
// Vector *normal); // 228
// DiscontinuityJump(CCSBot *const this, if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
// float ground, {
// bool onlyJumpDown, jumped = DiscontinuityJump(ground);
// bool mustJump); // 230 }
// } }
// {
// float const lookAheadRange; // 237 if (!jumped)
// Vector stepAhead; // 238 {
// operator*(float fl, // about to fall gap-jumping
// const Vector &v); // 238 const float lookAheadRange = 10.0f;
// operator+(const Vector *const this, Vector stepAhead = pev->origin + lookAheadRange * aheadRay;
// const Vector &v); // 238 stepAhead.z += HalfHumanHeight;
// GetSimpleGroundHeightWithFloor(CCSBot *const this,
// const Vector *pos, if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
// float *height, {
// Vector *normal); // 240 jumped = DiscontinuityJump(ground, ONLY_JUMP_DOWN, MUST_JUMP);
// DiscontinuityJump(CCSBot *const this, }
// float ground, }
// bool onlyJumpDown, }
// bool mustJump); // 242
// } // compute our current forward and lateral vectors
// } float angle = pev->v_angle.y;
// NormalizeInPlace(Vector2D *const this); // 256
// } Vector2D dir(BotCOS(angle), BotSIN(angle));
Vector2D lat(-dir.y, dir.x);
// compute unit vector to goal position
Vector2D to(pos->x - pev->origin.x, pos->y - pev->origin.y);
to.NormalizeInPlace();
// move towards the position independant of our view direction
float toProj = to.x * dir.x + to.y * dir.y;
float latProj = to.x * lat.x + to.y * lat.y;
const float c = 0.25f;
if (toProj > c)
MoveForward();
else if (toProj < -c)
MoveBackward();
// if we are avoiding someone via strafing, don't override
if (m_avoid != NULL)
return;
if (latProj >= c)
StrafeLeft();
else if (latProj <= -c)
StrafeRight();
} }
// Move away from position, independant of view angle
/* <37ca96> ../cstrike/dlls/bot/cs_bot_nav.cpp:282 */ /* <37ca96> ../cstrike/dlls/bot/cs_bot_nav.cpp:282 */
NOBODY void CCSBot::MoveAwayFromPosition(const Vector *pos) NOXREF void CCSBot::MoveAwayFromPosition(const Vector *pos)
{ {
// { // compute our current forward and lateral vectors
// float angle; // 285 float angle = pev->v_angle[ YAW ];
// class Vector2D dir; // 287
// class Vector2D lat; // 288 Vector2D dir(BotCOS(angle), BotSIN(angle));
// class Vector2D to; // 291 Vector2D lat(-dir.y, dir.x);
// float toProj; // 295
// float latProj; // 296 // compute unit vector to goal position
// float const c; // 298 Vector2D to(pos->x - pev->origin.x, pos->y - pev->origin.y);
// NormalizeInPlace(Vector2D *const this); // 292 to.NormalizeInPlace();
// }
// move away from the position independant of our view direction
float toProj = to.x * dir.x + to.y * dir.y;
float latProj = to.x * lat.x + to.y * lat.y;
const float c = 0.5f;
if (toProj > c)
MoveBackward();
else if (toProj < -c)
MoveForward();
if (latProj >= c)
StrafeRight();
else if (latProj <= -c)
StrafeLeft();
} }
// Strafe (sidestep) away from position, independant of view angle
/* <37cb85> ../cstrike/dlls/bot/cs_bot_nav.cpp:314 */ /* <37cb85> ../cstrike/dlls/bot/cs_bot_nav.cpp:314 */
NOBODY void CCSBot::StrafeAwayFromPosition(const Vector *pos) void CCSBot::StrafeAwayFromPosition(const Vector *pos)
{ {
// { // compute our current forward and lateral vectors
// float angle; // 317 float angle = pev->v_angle[ YAW ];
// class Vector2D dir; // 319
// class Vector2D lat; // 320 Vector2D dir(BotCOS(angle), BotSIN(angle));
// class Vector2D to; // 323 Vector2D lat(-dir.y, dir.x);
// float latProj; // 326
// NormalizeInPlace(Vector2D *const this); // 324 // compute unit vector to goal position
// } Vector2D to(pos->x - pev->origin.x, pos->y - pev->origin.y);
to.NormalizeInPlace();
float latProj = to.x * lat.x + to.y * lat.y;
if (latProj >= 0.0f)
StrafeRight();
else
StrafeLeft();
} }
// For getting un-stuck
/* <37cc52> ../cstrike/dlls/bot/cs_bot_nav.cpp:338 */ /* <37cc52> ../cstrike/dlls/bot/cs_bot_nav.cpp:338 */
NOBODY void CCSBot::Wiggle(void) void CCSBot::Wiggle(void)
{ {
// ResetStuckMonitor(CCSBot *const this); // 342 if (IsCrouching())
{
ResetStuckMonitor();
return;
}
// for wiggling
if (gpGlobals->time >= m_wiggleTimestamp)
{
m_wiggleDirection = (NavRelativeDirType)RANDOM_LONG(0, 3);
m_wiggleTimestamp = RANDOM_FLOAT(0.5, 1.5) + gpGlobals->time;
}
// TODO: implement checking of the movement to fall down
switch (m_wiggleDirection)
{
case LEFT:
StrafeLeft();
break;
case RIGHT:
StrafeRight();
break;
case FORWARD:
MoveForward();
break;
case BACKWARD:
MoveBackward();
break;
}
if (gpGlobals->time >= m_stuckJumpTimestamp)
{
if (Jump())
{
m_stuckJumpTimestamp = RANDOM_FLOAT(1.0, 2.0) + gpGlobals->time;
}
}
} }
// Determine approach points from eye position and approach areas of current area
/* <37cc94> ../cstrike/dlls/bot/cs_bot_nav.cpp:383 */ /* <37cc94> ../cstrike/dlls/bot/cs_bot_nav.cpp:383 */
NOBODY void CCSBot::ComputeApproachPoints(void) void CCSBot::ComputeApproachPoints(void)
{ {
// { m_approachPointCount = 0;
// Vector eye; // 391
// Vector ap; // 393 if (m_lastKnownArea == NULL)
// float halfWidth; // 394 {
// Vector(Vector *const this, return;
// const Vector &v); // 391 }
// {
// int i; // 395 // assume we're crouching for now
// { Vector eye = pev->origin;
// const class ApproachInfo *info; // 397
// Vector bendPoint; // 415 Vector ap;
// } float halfWidth;
// GetApproachInfoCount(const class CNavArea *const this); // 395 for (int i = 0; i < m_lastKnownArea->GetApproachInfoCount() && m_approachPointCount < MAX_APPROACH_POINTS; ++i)
// } {
// } const CNavArea::ApproachInfo *info = m_lastKnownArea->GetApproachInfo(i);
if (info->here.area == NULL || info->prev.area == NULL)
{
continue;
}
// compute approach point (approach area is "info->here")
if (info->prevToHereHow <= GO_WEST)
{
info->prev.area->ComputePortal(info->here.area, (NavDirType)info->prevToHereHow, &ap, &halfWidth);
ap.z = info->here.area->GetZ(&ap);
}
else
{
// use the area's center as an approach point
ap = *info->here.area->GetCenter();
}
// "bend" our line of sight around corners until we can see the approach point
Vector bendPoint;
if (BendLineOfSight(&eye, &ap, &bendPoint))
{
m_approachPoint[ m_approachPointCount++ ] = bendPoint;
}
}
} }
/* <37cd67> ../cstrike/dlls/bot/cs_bot_nav.cpp:422 */ /* <37cd67> ../cstrike/dlls/bot/cs_bot_nav.cpp:422 */
NOBODY void CCSBot::DrawApproachPoints(void) void CCSBot::DrawApproachPoints(void)
{ {
// { for (int i = 0; i < m_approachPointCount; ++i)
// int i; // 427 {
// operator+(const Vector *const this, UTIL_DrawBeamPoints(m_approachPoint[i], m_approachPoint[i] + Vector(0, 0, 50), 3, 0, 255, 255);
// const Vector &v); // 428 }
// Vector(Vector *const this,
// const Vector &v); // 428
// }
} }
// Find the approach point that is nearest to our current path, ahead of us
/* <37ce12> ../cstrike/dlls/bot/cs_bot_nav.cpp:435 */ /* <37ce12> ../cstrike/dlls/bot/cs_bot_nav.cpp:435 */
NOBODY bool CCSBot::FindApproachPointNearestPath(const Vector *pos) NOXREF bool CCSBot::FindApproachPointNearestPath(Vector *pos)
{ {
// { if (!HasPath())
// Vector target; // 446 return false;
// Vector close; // 446
// float targetRangeSq; // 447 // make sure approach points are accurate
// bool found; // 448 ComputeApproachPoints();
// int start; // 450
// int end; // 451 if (m_approachPointCount == 0)
// float const nearPathSq; // 457 return false;
// {
// int i; // 459 Vector target = Vector(0, 0, 0), close;
// { float targetRangeSq = 0.0f;
// float rangeSq; // 464 bool found = false;
// operator-(const Vector *const this,
// const Vector &v); // 464 int start = m_pathIndex;
// LengthSquared(const Vector *const this); // 464 int end = m_pathLength;
// }
// } // We dont want the strictly closest point, but the farthest approach point
// operator+(const Vector *const this, // from us that is near our path
// const Vector &v); // 478 const float nearPathSq = 10000.0f;
// }
for (int i = 0; i < m_approachPointCount; ++i)
{
if (FindClosestPointOnPath(&m_approachPoint[i], start, end, &close) == false)
continue;
float rangeSq = (m_approachPoint[i] - close).LengthSquared();
if (rangeSq > nearPathSq)
continue;
if (rangeSq > targetRangeSq)
{
target = close;
targetRangeSq = rangeSq;
found = true;
}
}
if (found)
{
*pos = target + Vector(0, 0, HalfHumanHeight);
return true;
}
return false;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,215 @@
#include "precompiled.h" #include "precompiled.h"
/* <3a397f> ../cstrike/dlls/bot/cs_bot_radio.cpp:220 */ // Returns true if the radio message is an order to do something
NOBODY void CCSBot::StartVoiceFeedback(float duration) // NOTE: "Report in" is not considered a "command" because it doesnt ask the bot to go somewhere, or change its mind
/* <3a3689> ../cstrike/dlls/bot/cs_bot_radio.cpp:19 */
bool CCSBot::IsRadioCommand(GameEventType event) const
{ {
// { if (event == EVENT_RADIO_AFFIRMATIVE
// class CBasePlayer *pPlayer; // 227 || event == EVENT_RADIO_NEGATIVE
// MESSAGE_BEGIN(int msg_dest, || event == EVENT_RADIO_ENEMY_SPOTTED
// int msg_type, || event == EVENT_RADIO_SECTOR_CLEAR
// const float *pOrigin, || event == EVENT_RADIO_REPORTING_IN
// entvars_t *ent); // 230 || event == EVENT_RADIO_REPORT_IN_TEAM
// edict(CBaseEntity *const this); // 232 || event == EVENT_RADIO_ENEMY_DOWN)
// ENTINDEX(edict_t *pEdict); // 232 return false;
// }
return true;
}
// Respond to radio commands from HUMAN players
/* <3a36e0> ../cstrike/dlls/bot/cs_bot_radio.cpp:37 */
void CCSBot::RespondToRadioCommands(void)
{
// bots use the chatter system to respond to each other
if (m_radioSubject != NULL && m_radioSubject->IsPlayer())
{
CBasePlayer *player = m_radioSubject;
if (player->IsBot())
{
m_lastRadioCommand = EVENT_INVALID;
return;
}
}
if (m_lastRadioCommand == EVENT_INVALID)
return;
// a human player has issued a radio command
GetChatter()->ResetRadioSilenceDuration();
// if we are doing something important, ignore the radio
// unless it is a "report in" request - we can do that while we continue to do other things
// TODO: Create "uninterruptable" flag
if (m_lastRadioCommand != EVENT_RADIO_REPORT_IN_TEAM)
{
if (IsBusy())
{
// consume command
m_lastRadioCommand = EVENT_INVALID;
return;
}
}
// wait for reaction time before responding
// delay needs to be long enough for the radio message we're responding to to finish
float respondTime = 1.0f + 2.0f * GetProfile()->GetReactionTime();
if (IsRogue())
respondTime += 2.0f;
if (gpGlobals->time - m_lastRadioRecievedTimestamp < respondTime)
return;
// rogues won't follow commands, unless already following the player
if (!IsFollowing() && IsRogue())
{
if (IsRadioCommand(m_lastRadioCommand))
{
GetChatter()->Negative();
}
// consume command
m_lastRadioCommand = EVENT_INVALID;
return;
}
CBasePlayer *player = m_radioSubject;
if (player == NULL)
return;
// respond to command
bool canDo = false;
const float inhibitAutoFollowDuration = 60.0f;
switch (m_lastRadioCommand)
{
case EVENT_RADIO_REPORT_IN_TEAM:
{
GetChatter()->ReportingIn();
break;
}
case EVENT_RADIO_FOLLOW_ME:
case EVENT_RADIO_COVER_ME:
case EVENT_RADIO_STICK_TOGETHER_TEAM:
case EVENT_RADIO_REGROUP_TEAM:
{
if (!IsFollowing())
{
Follow(player);
player->AllowAutoFollow();
canDo = true;
}
break;
}
case EVENT_RADIO_ENEMY_SPOTTED:
case EVENT_RADIO_NEED_BACKUP:
case EVENT_RADIO_TAKING_FIRE:
{
if (!IsFollowing())
{
Follow(player);
GetChatter()->Say("OnMyWay");
player->AllowAutoFollow();
canDo = false;
}
break;
}
case EVENT_RADIO_TEAM_FALL_BACK:
{
if (TryToRetreat())
canDo = true;
break;
}
case EVENT_RADIO_HOLD_THIS_POSITION:
{
// find the leader's area
SetTask(HOLD_POSITION);
StopFollowing();
player->InhibitAutoFollow(inhibitAutoFollowDuration);
Hide(TheNavAreaGrid.GetNearestNavArea(&m_radioPosition));
canDo = true;
break;
}
case EVENT_RADIO_GO_GO_GO:
case EVENT_RADIO_STORM_THE_FRONT:
{
StopFollowing();
Hunt();
canDo = true;
player->InhibitAutoFollow(inhibitAutoFollowDuration);
break;
}
case EVENT_RADIO_GET_OUT_OF_THERE:
{
if (TheCSBots()->IsBombPlanted())
{
EscapeFromBomb();
player->InhibitAutoFollow(inhibitAutoFollowDuration);
canDo = true;
}
break;
}
case EVENT_RADIO_SECTOR_CLEAR:
{
// if this is a defusal scenario, and the bomb is planted,
// and a human player cleared a bombsite, check it off our list too
if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_DEFUSE_BOMB)
{
if (m_iTeam == CT && TheCSBots()->IsBombPlanted())
{
const CCSBotManager::Zone *zone = TheCSBots()->GetClosestZone(player);
if (zone != NULL)
{
GetGameState()->ClearBombsite(zone->m_index);
// if we are huting for the planted bomb, re-select bombsite
if (GetTask() == FIND_TICKING_BOMB)
Idle();
canDo = true;
}
}
}
break;
}
default:
// ignore all other radio commands for now
return;
}
if (canDo)
{
// affirmative
GetChatter()->Affirmative();
// if we agreed to follow a new command, put away our grenade
if (IsRadioCommand(m_lastRadioCommand) && IsUsingGrenade())
{
EquipBestWeapon();
}
}
// consume command
m_lastRadioCommand = EVENT_INVALID;
}
// Send voice chatter. Also sends the entindex.
/* <3a397f> ../cstrike/dlls/bot/cs_bot_radio.cpp:220 */
void CCSBot::StartVoiceFeedback(float duration)
{
m_voiceFeedbackStartTimestamp = gpGlobals->time;
m_voiceFeedbackEndTimestamp = duration + gpGlobals->time;
CBasePlayer *pPlayer = NULL;
while ((pPlayer = GetNextRadioRecipient(pPlayer)) != NULL)
{
MESSAGE_BEGIN(MSG_ONE, gmsgBotVoice, NULL, pPlayer->pev);
WRITE_BYTE(1); // active is talking
WRITE_BYTE(entindex()); // client index speaking
MESSAGE_END();
}
} }
/* <3a3a32> ../cstrike/dlls/bot/cs_bot_radio.cpp:241 */ /* <3a3a32> ../cstrike/dlls/bot/cs_bot_radio.cpp:241 */
@ -28,37 +226,109 @@ void CCSBot::EndVoiceFeedback(bool force)
MESSAGE_END(); MESSAGE_END();
} }
// Decide if we should move to help the player, return true if we will
/* <3a3bcd> ../cstrike/dlls/bot/cs_bot_radio.cpp:259 */ /* <3a3bcd> ../cstrike/dlls/bot/cs_bot_radio.cpp:259 */
NOBODY bool CCSBot::RespondToHelpRequest(CBasePlayer *them, Place place, float maxRange) bool CCSBot::RespondToHelpRequest(CBasePlayer *them, Place place, float maxRange)
{ {
// { if (IsRogue())
// class PathCost pc; // 272 return false;
// float travelDistance; // 273
// NavAreaTravelDistance<PathCost>(CNavArea *startArea, // if we're busy, ignore
// class CNavArea *endArea, if (IsBusy())
// class PathCost &costFunc); // 273 return false;
// }
// { // if we are too far away, ignore
// float rangeSq; // 287 if (maxRange > 0.0f)
// float const close; // 288 {
// operator-(const Vector *const this, // compute actual travel distance
// const Vector &v); // 287 PathCost pc(this);
// LengthSquared(const Vector *const this); // 287 float_precision travelDistance = NavAreaTravelDistance(m_lastKnownArea, TheNavAreaGrid.GetNearestNavArea(&them->pev->origin), pc);
// } if (travelDistance < 0.0f)
// { return false;
// const Vector *pos; // 301
// } if (travelDistance > maxRange)
// Say(BotChatterInterface *const this, return false;
// const char *phraseName, }
// float lifetime,
// float delay); // 309 if (place == UNDEFINED_PLACE)
{
// if we have no "place" identifier, go directly to them
// if we are already there, ignore
float rangeSq = (them->pev->origin - pev->origin).LengthSquared();
const float close = 750.0f * 750.0f;
if (rangeSq < close)
return true;
MoveTo(&them->pev->origin, FASTEST_ROUTE);
}
else
{
// if we are already there, ignore
if (GetPlace() == place)
return true;
// go to where help is needed
const Vector *pos = GetRandomSpotAtPlace(place);
if (pos != NULL)
{
MoveTo(pos, FASTEST_ROUTE);
}
else
{
MoveTo(&them->pev->origin, FASTEST_ROUTE);
}
}
// acknowledge
GetChatter()->Say("OnMyWay");
return true;
} }
// Send a radio message
/* <3a4316> ../cstrike/dlls/bot/cs_bot_radio.cpp:319 */ /* <3a4316> ../cstrike/dlls/bot/cs_bot_radio.cpp:319 */
NOBODY void CCSBot::SendRadioMessage(GameEventType event) void CCSBot::SendRadioMessage(GameEventType event)
{ {
// { // make sure this is a radio event
// class CCSBotManager *ctrl; // 328 if (event <= EVENT_START_RADIO_1 || event >= EVENT_END_RADIO)
// char slot; // 333 {
// } return;
}
CCSBotManager *ctrl = TheCSBots();
PrintIfWatched("%3.1f: SendRadioMessage( %s )\n", gpGlobals->time, GameEventName[ event ]);
// note the time the message was sent
ctrl->SetRadioMessageTimestamp(event, m_iTeam);
m_lastRadioSentTimestamp = gpGlobals->time;
char slot[2];
slot[1] = '\000';
if (event > EVENT_START_RADIO_1 && event < EVENT_START_RADIO_2)
{
slot[0] = event - EVENT_START_RADIO_1;
ClientCommand("radio1");
//Radio1(this, event - EVENT_START_RADIO_3);
}
else if (event > EVENT_START_RADIO_2 && event < EVENT_START_RADIO_3)
{
slot[0] = event - EVENT_START_RADIO_2;
ClientCommand("radio2");
//Radio2(this, event - EVENT_START_RADIO_3);
}
else
{
slot[0] = event - EVENT_START_RADIO_3;
ClientCommand("radio3");
//Radio3(this, event - EVENT_START_RADIO_3);
}
ClientCommand("menuselect", slot);
ClientCommand("menuselect", "10");
} }

View File

@ -1,19 +1,18 @@
#include "precompiled.h" #include "precompiled.h"
// This method is the ONLY legal way to change a bot's current state
/* <3b3a2a> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:16 */ /* <3b3a2a> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:16 */
void CCSBot::SetState(BotState *state) void CCSBot::SetState(BotState *state)
{ {
PrintIfWatched("SetState: %s -> %s\n", (m_state != NULL) ? m_state->GetName() : "NULL", state->GetName()); PrintIfWatched("SetState: %s -> %s\n", (m_state != NULL) ? m_state->GetName() : "NULL", state->GetName());
// if we changed state from within the special Attack state, we are no longer attacking
if (m_isAttacking) if (m_isAttacking)
{
StopAttacking(); StopAttacking();
}
if (m_state) if (m_state != NULL)
{
m_state->OnExit(this); m_state->OnExit(this);
}
state->OnEnter(this); state->OnEnter(this);
@ -29,144 +28,256 @@ void CCSBot::Idle(void)
} }
/* <3b3afa> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:41 */ /* <3b3afa> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:41 */
NOBODY void CCSBot::EscapeFromBomb(void) void CCSBot::EscapeFromBomb(void)
{ {
// SetTask(CCSBot::EscapeFromBomb(// enum TaskType task, SetTask(ESCAPE_FROM_BOMB);
// class CBaseEntity *entity); // 43 SetState(&m_escapeFromBombState);
} }
/* <3b3b4b> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:48 */ /* <3b3b4b> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:48 */
NOBODY void CCSBot::Follow(CBasePlayer *player) void CCSBot::Follow(CBasePlayer *player)
{ {
// SetTask(CCSBot *const this, if (player == NULL)
// enum TaskType task, return;
// class CBaseEntity *entity); // 60
// SetLeader(FollowState *const this, // note when we began following
// class CBasePlayer *player); // 61 if (!m_isFollowing || m_leader != player)
m_followTimestamp = gpGlobals->time;
m_isFollowing = true;
m_leader = player;
SetTask(FOLLOW);
m_followState.SetLeader(player);
SetState(&m_followState);
} }
// Continue following our leader after finishing what we were doing
/* <3b3bd1> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:69 */ /* <3b3bd1> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:69 */
NOBODY void CCSBot::ContinueFollowing(void) void CCSBot::ContinueFollowing(void)
{ {
// { SetTask(FOLLOW);
// class CBasePlayer *leader; // 73 m_followState.SetLeader(m_leader);
// SetTask(CCSBot *const this, SetState(&m_followState);
// enum TaskType task,
// class CBaseEntity *entity); // 71
// SetLeader(FollowState *const this,
// class CBasePlayer *player); // 74
// }
} }
// Stop following
/* <3b3c57> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:83 */ /* <3b3c57> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:83 */
NOBODY void CCSBot::StopFollowing(void) void CCSBot::StopFollowing(void)
{ {
m_isFollowing = false;
m_leader = NULL;
m_allowAutoFollowTime = gpGlobals->time + 10.0f;
} }
// Begin process of rescuing hostages
/* <3b3c7e> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:94 */ /* <3b3c7e> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:94 */
NOBODY void CCSBot::RescueHostages(void) void CCSBot::RescueHostages(void)
{ {
// SetTask(CCSBot::RescueHostages(// enum TaskType task, SetTask(RESCUE_HOSTAGES);
// class CBaseEntity *entity); // 96
} }
// Use the entity
/* <3b3cc9> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:103 */ /* <3b3cc9> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:103 */
NOBODY void CCSBot::UseEntity(CBaseEntity *entity) void CCSBot::UseEntity(CBaseEntity *entity)
{ {
// SetEntity(UseEntityState *const this, m_useEntityState.SetEntity(entity);
// class CBaseEntity *entity); // 105 SetState(&m_useEntityState);
} }
// DEPRECATED: Use TryToHide() instead.
// Move to a hiding place.
// If 'searchFromArea' is non-NULL, hiding spots are looked for from that area first.
/* <3b3d23> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:116 */ /* <3b3d23> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:116 */
NOBODY void CCSBot::Hide(CNavArea *searchFromArea, float duration, float hideRange, bool holdPosition) void CCSBot::Hide(CNavArea *searchFromArea, float duration, float hideRange, bool holdPosition)
{ {
// { DestroyPath();
// class CNavArea *source; // 120
// Vector sourcePos; // 121 CNavArea *source;
// const Vector *pos; // 146 Vector sourcePos;
// DestroyPath(CCSBot *const this); // 118 if (searchFromArea)
// SetDuration(HideState *const this, {
// float time); // 142 source = searchFromArea;
// SetSearchArea(HideState *const this, sourcePos = *searchFromArea->GetCenter();
// class CNavArea *area); // 140 }
// SetSearchRange(HideState *const this, else
// float range); // 141 {
// SetHoldPosition(HideState *const this, source = m_lastKnownArea;
// bool hold); // 143 sourcePos = pev->origin;
// SetHidingSpot(HideState *const this, }
// const Vector *pos); // 154
// Idle(CCSBot *const this); // 160 if (source == NULL)
// } {
PrintIfWatched("Hide from area is NULL.\n");
Idle();
return;
}
m_hideState.SetSearchArea(source);
m_hideState.SetSearchRange(hideRange);
m_hideState.SetDuration(duration);
m_hideState.SetHoldPosition(holdPosition);
// search around source area for a good hiding spot
Vector useSpot;
const Vector *pos = FindNearbyHidingSpot(this, &sourcePos, source, hideRange, IsSniper());
if (pos == NULL)
{
PrintIfWatched("No available hiding spots.\n");
// hide at our current position
useSpot = pev->origin;
}
else
{
useSpot = *pos;
}
m_hideState.SetHidingSpot(useSpot);
// build a path to our new hiding spot
if (ComputePath(TheNavAreaGrid.GetNavArea(&useSpot), &useSpot, FASTEST_ROUTE) == false)
{
PrintIfWatched("Can't pathfind to hiding spot\n");
Idle();
return;
}
SetState(&m_hideState);
} }
// Move to the given hiding place
/* <3b3e98> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:171 */ /* <3b3e98> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:171 */
NOBODY void CCSBot::Hide(const Vector *hidingSpot, float duration, bool holdPosition) void CCSBot::Hide(const Vector *hidingSpot, float duration, bool holdPosition)
{ {
// { CNavArea *hideArea = TheNavAreaGrid.GetNearestNavArea(hidingSpot);
// class CNavArea *hideArea; // 173 if (hideArea == NULL)
// DestroyPath(CCSBot *const this); // 181 {
// SetHoldPosition(HideState *const this, PrintIfWatched("Hiding spot off nav mesh\n");
// bool hold); // 186 Idle();
// SetSearchArea(HideState *const this, return;
// class CNavArea *area); // 183 }
// SetSearchRange(HideState *const this,
// float range); // 184 DestroyPath();
// SetDuration(HideState *const this,
// float time); // 185 m_hideState.SetSearchArea(hideArea);
// SetHidingSpot(HideState *const this, m_hideState.SetSearchRange(750.0f);
// const Vector *pos); // 187 m_hideState.SetDuration(duration);
// Idle(CCSBot *const this); // 193 m_hideState.SetHoldPosition(holdPosition);
// } m_hideState.SetHidingSpot(*hidingSpot);
// build a path to our new hiding spot
if (ComputePath(hideArea, hidingSpot, FASTEST_ROUTE) == false)
{
PrintIfWatched("Can't pathfind to hiding spot\n");
Idle();
return;
}
SetState(&m_hideState);
} }
// Try to hide nearby. Return true if hiding, false if can't hide here.
// If 'searchFromArea' is non-NULL, hiding spots are looked for from that area first.
/* <3b3fc1> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:205 */ /* <3b3fc1> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:205 */
NOBODY bool CCSBot::TryToHide(CNavArea *searchFromArea, float duration, float hideRange, bool holdPosition, bool useNearest) bool CCSBot::TryToHide(CNavArea *searchFromArea, float duration, float hideRange, bool holdPosition, bool useNearest)
{ {
// { CNavArea *source;
// class CNavArea *source; // 207 Vector sourcePos;
// Vector sourcePos; // 208 if (searchFromArea)
// const Vector *pos; // 232 {
// SetDuration(HideState *const this, source = searchFromArea;
// float time); // 228 sourcePos = *searchFromArea->GetCenter();
// SetSearchArea(HideState *const this, }
// class CNavArea *area); // 226 else
// SetSearchRange(HideState *const this, {
// float range); // 227 source = m_lastKnownArea;
// SetHoldPosition(HideState *const this, sourcePos = pev->origin;
// bool hold); // 229 }
// SetHidingSpot(HideState *const this,
// const Vector *pos); // 239 if (source == NULL)
// } {
PrintIfWatched("Hide from area is NULL.\n");
return false;
}
m_hideState.SetSearchArea(source);
m_hideState.SetSearchRange(hideRange);
m_hideState.SetDuration(duration);
m_hideState.SetHoldPosition(holdPosition);
// search around source area for a good hiding spot
const Vector *pos = FindNearbyHidingSpot(this, &sourcePos, source, hideRange, IsSniper(), useNearest);
if (pos == NULL)
{
PrintIfWatched("No available hiding spots.\n");
return false;
}
m_hideState.SetHidingSpot(*pos);
// build a path to our new hiding spot
if (ComputePath(TheNavAreaGrid.GetNavArea(pos), pos, FASTEST_ROUTE) == false)
{
PrintIfWatched("Can't pathfind to hiding spot\n");
return false;
}
SetState(&m_hideState);
return true;
} }
// Retreat to a nearby hiding spot, away from enemies
/* <3b40ed> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:256 */ /* <3b40ed> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:256 */
NOBODY bool CCSBot::TryToRetreat(void) bool CCSBot::TryToRetreat(void)
{ {
// { const float maxRange = 1000.0f;
// const Vector *spot; // 258 const Vector *spot = FindNearbyRetreatSpot(this, maxRange);
// {
// float holdTime; // 265 if (spot != NULL)
// Hide(CCSBot *const this, {
// const Vector *hidingSpot, // ignore enemies for a second to give us time to hide
// float duration, // reaching our hiding spot clears our disposition
// bool holdPosition); // 268 IgnoreEnemies(10.0f);
// }
// } float holdTime = RANDOM_FLOAT(3.0f, 15.0f);
StandUp();
Run();
Hide(spot, holdTime);
PrintIfWatched("Retreating to a safe spot!\n");
return true;
}
return false;
} }
/* <3b426a> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:280 */ /* <3b426a> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:280 */
NOBODY void CCSBot::Hunt(void) void CCSBot::Hunt(void)
{ {
SetState(&m_huntState);
} }
// Attack our the given victim
// NOTE: Attacking does not change our task.
/* <3b4291> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:290 */ /* <3b4291> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:290 */
NOBODY void CCSBot::Attack(CBasePlayer *victim) void CCSBot::Attack(CBasePlayer *victim)
{ {
if (victim == NULL) if (victim == NULL)
return; return;
// zombies never attack // zombies never attack
if (cv_bot_zombie.value) if (cv_bot_zombie.value != 0.0f)
return; return;
// cannot attack if we are reloading // cannot attack if we are reloading
@ -183,11 +294,11 @@ NOBODY void CCSBot::Attack(CBasePlayer *victim)
if (IsAtHidingSpot()) if (IsAtHidingSpot())
m_attackState.SetCrouchAndHold((RANDOM_FLOAT(0, 100) < 60.0f) != 0); m_attackState.SetCrouchAndHold((RANDOM_FLOAT(0, 100) < 60.0f) != 0);
else else
m_attackState.SetCrouchAndHold(0); m_attackState.SetCrouchAndHold(false);
PrintIfWatched("ATTACK BEGIN (reaction time = %g (+ update time), surprise time = %g, attack delay = %g)\n"); PrintIfWatched("ATTACK BEGIN (reaction time = %g (+ update time), surprise time = %g, attack delay = %g)\n");
m_isAttacking = true; m_isAttacking = true;
m_attackState.OnEnter(this);// TODO: Reverse me m_attackState.OnEnter(this);
// cheat a bit and give the bot the initial location of its victim // cheat a bit and give the bot the initial location of its victim
m_lastEnemyPosition = victim->pev->origin; m_lastEnemyPosition = victim->pev->origin;
@ -196,11 +307,9 @@ NOBODY void CCSBot::Attack(CBasePlayer *victim)
// compute the angle difference between where are looking, and where we need to look // compute the angle difference between where are looking, and where we need to look
Vector toEnemy = victim->pev->origin - pev->origin; Vector toEnemy = victim->pev->origin - pev->origin;
Vector idealAngle; Vector idealAngle = UTIL_VecToAngles(toEnemy);
idealAngle = UTIL_VecToAngles(toEnemy); float deltaYaw = abs((int)(m_lookYaw - idealAngle.y));
float deltaYaw = (float)abs(m_lookYaw - idealAngle.y);
while (deltaYaw > 180.0f) while (deltaYaw > 180.0f)
deltaYaw -= 360.0f; deltaYaw -= 360.0f;
@ -220,11 +329,13 @@ NOBODY void CCSBot::Attack(CBasePlayer *victim)
m_aimOffsetTimestamp = gpGlobals->time + RANDOM_FLOAT(0.25f + turn, 1.5f); m_aimOffsetTimestamp = gpGlobals->time + RANDOM_FLOAT(0.25f + turn, 1.5f);
} }
// Exit the Attack state
/* <3b4416> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:366 */ /* <3b4416> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:366 */
void CCSBot::StopAttacking(void) void CCSBot::StopAttacking(void)
{ {
PrintIfWatched("ATTACK END\n"); PrintIfWatched("ATTACK END\n");
m_attackState.OnExit(this);//TODO: Reverse me m_attackState.OnExit(this);
m_isAttacking = false; m_isAttacking = false;
// if we are following someone, go to the Idle state after the attack to decide whether we still want to follow // if we are following someone, go to the Idle state after the attack to decide whether we still want to follow
@ -240,11 +351,19 @@ bool CCSBot::IsAttacking(void) const
return m_isAttacking; return m_isAttacking;
} }
// Return true if we are escaping from the bomb
/* <3b449f> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:387 */ /* <3b449f> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:387 */
NOBODY bool CCSBot::IsEscapingFromBomb(void) const bool CCSBot::IsEscapingFromBomb(void) const
{ {
if (m_state == static_cast<const BotState *>(&m_escapeFromBombState))
return true;
return false;
} }
// Return true if we are defusing the bomb
/* <3b44c6> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:399 */ /* <3b44c6> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:399 */
bool CCSBot::IsDefusingBomb(void) const bool CCSBot::IsDefusingBomb(void) const
{ {
@ -254,6 +373,8 @@ bool CCSBot::IsDefusingBomb(void) const
return false; return false;
} }
// Return true if we are hiding
/* <3b44ed> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:411 */ /* <3b44ed> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:411 */
bool CCSBot::IsHiding(void) const bool CCSBot::IsHiding(void) const
{ {
@ -263,6 +384,8 @@ bool CCSBot::IsHiding(void) const
return false; return false;
} }
// Return true if we are hiding and at our hiding spot
/* <3b450f> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:423 */ /* <3b450f> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:423 */
bool CCSBot::IsAtHidingSpot(void) const bool CCSBot::IsAtHidingSpot(void) const
{ {
@ -272,16 +395,30 @@ bool CCSBot::IsAtHidingSpot(void) const
return m_hideState.IsAtSpot(); return m_hideState.IsAtSpot();
} }
// Return true if we are huting
/* <3b454a> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:435 */ /* <3b454a> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:435 */
NOBODY bool CCSBot::IsHunting(void) const bool CCSBot::IsHunting(void) const
{ {
if (m_state == static_cast<const BotState *>(&m_huntState))
return true;
return false;
} }
// Return true if we are in the MoveTo state
/* <3b4571> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:447 */ /* <3b4571> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:447 */
NOBODY bool CCSBot::IsMovingTo(void) const bool CCSBot::IsMovingTo(void) const
{ {
if (m_state == static_cast<const BotState *>(&m_moveToState))
return true;
return false;
} }
// Return true if we are buying
/* <3b4598> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:460 */ /* <3b4598> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:460 */
bool CCSBot::IsBuying(void) const bool CCSBot::IsBuying(void) const
{ {
@ -291,31 +428,40 @@ bool CCSBot::IsBuying(void) const
return false; return false;
} }
// Move to potentially distant position
/* <3b45bf> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:472 */ /* <3b45bf> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:472 */
NOBODY void CCSBot::MoveTo(const Vector *pos, RouteType route) void CCSBot::MoveTo(const Vector *pos, RouteType route)
{ {
// SetGoalPosition(MoveToState *const this, m_moveToState.SetGoalPosition(*pos);
// const Vector *pos); // 474 m_moveToState.SetRouteType(route);
// SetRouteType(MoveToState *const this, SetState(&m_moveToState);
// enum RouteType route); // 475
} }
/* <3b463c> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:480 */ /* <3b463c> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:480 */
NOBODY void CCSBot::PlantBomb(void) void CCSBot::PlantBomb(void)
{ {
SetState(&m_plantBombState);
} }
// Bomb has been dropped - go get it
/* <3b4663> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:489 */ /* <3b4663> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:489 */
NOBODY void CCSBot::FetchBomb(void) void CCSBot::FetchBomb(void)
{ {
SetState(&m_fetchBombState);
} }
/* <3b468a> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:495 */ /* <3b468a> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:495 */
NOBODY void CCSBot::DefuseBomb(void) void CCSBot::DefuseBomb(void)
{ {
SetState(&m_defuseBombState);
} }
// Investigate recent enemy noise
/* <3b46b1> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:504 */ /* <3b46b1> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:504 */
NOBODY void CCSBot::InvestigateNoise(void) void CCSBot::InvestigateNoise(void)
{ {
SetState(&m_investigateNoiseState);
} }

View File

@ -1,5 +1,7 @@
#include "precompiled.h" #include "precompiled.h"
// Lightweight maintenance, invoked frequently
/* <3c635f> ../cstrike/dlls/bot/cs_bot_update.cpp:26 */ /* <3c635f> ../cstrike/dlls/bot/cs_bot_update.cpp:26 */
void CCSBot::__MAKE_VHOOK(Upkeep)(void) void CCSBot::__MAKE_VHOOK(Upkeep)(void)
{ {
@ -11,10 +13,12 @@ void CCSBot::__MAKE_VHOOK(Upkeep)(void)
if (m_isRapidFiring) if (m_isRapidFiring)
TogglePrimaryAttack(); TogglePrimaryAttack();
// aiming must be smooth - update often
if (IsAimingAtEnemy()) if (IsAimingAtEnemy())
{ {
UpdateAimOffset(); UpdateAimOffset();
// aim at enemy, if he's still alive
if (m_enemy != NULL) if (m_enemy != NULL)
{ {
float feetOffset = pev->origin.z - GetFeetZ(); float feetOffset = pev->origin.z - GetFeetZ();
@ -30,13 +34,14 @@ void CCSBot::__MAKE_VHOOK(Upkeep)(void)
m_aimSpot = m_enemy->pev->origin; m_aimSpot = m_enemy->pev->origin;
bool aimBlocked = false; bool aimBlocked = false;
const float sharpshooter = 0.8f;
if (IsUsingAWP() || IsUsingShotgun() || IsUsingMachinegun() || GetProfile()->GetSkill() < 0.8f if (IsUsingAWP() || IsUsingShotgun() || IsUsingMachinegun() || GetProfile()->GetSkill() < sharpshooter
|| (IsActiveWeaponRecoilHigh() && !IsUsingPistol() && !IsUsingSniperRifle())) || (IsActiveWeaponRecoilHigh() && !IsUsingPistol() && !IsUsingSniperRifle()))
{ {
if (IsEnemyPartVisible(CHEST)) if (IsEnemyPartVisible(CHEST))
{ {
// No headshots in this game, go for the chest. // No headshots, go for the chest.
aimBlocked = true; aimBlocked = true;
} }
} }
@ -130,11 +135,12 @@ void CCSBot::__MAKE_VHOOK(Upkeep)(void)
} }
float driftAmplitude = 2.0f; float driftAmplitude = 2.0f;
const float sharpshooter = 0.5f;
// have view "drift" very slowly, so view looks "alive" // have view "drift" very slowly, so view looks "alive"
if (IsUsingSniperRifle() && IsUsingScope()) if (IsUsingSniperRifle() && IsUsingScope())
driftAmplitude = sharpshooter; {
driftAmplitude = 0.5f;
}
m_lookYaw += driftAmplitude * BotCOS(33.0f * gpGlobals->time); m_lookYaw += driftAmplitude * BotCOS(33.0f * gpGlobals->time);
m_lookPitch += driftAmplitude * BotSIN(13.0f * gpGlobals->time); m_lookPitch += driftAmplitude * BotSIN(13.0f * gpGlobals->time);
@ -147,7 +153,7 @@ void CCSBot::__MAKE_VHOOK(Upkeep)(void)
void (*pCCSBot__Update)(void); void (*pCCSBot__Update)(void);
/* <3c6e1e> ../cstrike/dlls/bot/cs_bot_update.cpp:208 */ /* <3c6e1e> ../cstrike/dlls/bot/cs_bot_update.cpp:208 */
void __declspec(naked) CCSBot::__MAKE_VHOOK(Update)(void) NOBODY void __declspec(naked) CCSBot::__MAKE_VHOOK(Update)(void)
{ {
__asm __asm
{ {
@ -326,6 +332,12 @@ void __declspec(naked) CCSBot::__MAKE_VHOOK(Update)(void)
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
// NavAreaBuildPath<PathCost> hook
bool NavAreaBuildPath__PathCost__wrapper(CNavArea *startArea, CNavArea *goalArea, const Vector *goalPos, PathCost &costFunc, CNavArea **closestArea)
{
return NavAreaBuildPath(startArea, goalArea, goalPos, costFunc, closestArea);
}
void CCSBot::Upkeep(void) void CCSBot::Upkeep(void)
{ {
Upkeep_(); Upkeep_();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,292 +1,702 @@
#include "precompiled.h" #include "precompiled.h"
/* <3fca3c> ../cstrike/dlls/bot/cs_gamestate.cpp:13 */
NOBODY CSGameState::CSGameState(void)
{
}
/* <3fcd6b> ../cstrike/dlls/bot/cs_gamestate.cpp:27 */ /* <3fcd6b> ../cstrike/dlls/bot/cs_gamestate.cpp:27 */
NOBODY CSGameState::CSGameState(CCSBot *owner) CSGameState::CSGameState(CCSBot *owner)
{ {
// IntervalTimer(IntervalTimer *const this); // 27 m_owner = owner;
// { m_isRoundOver = false;
// int i; // 41 m_bombState = MOVING;
// }
// IntervalTimer(IntervalTimer *const this); // 27 m_lastSawBomber.Invalidate();
// CountdownTimer(CountdownTimer *const this); // 27 m_lastSawLooseBomb.Invalidate();
m_validateInterval.Invalidate();
m_isPlantedBombPosKnown = false;
m_plantedBombsite = UNKNOWN;
m_bombsiteCount = 0;
m_bombsiteSearchIndex = 0;
for (int i = 0; i < MAX_HOSTAGES; ++i)
{
HostageInfo *info = &m_hostage[i];
info->hostage = NULL;
info->knownPos = Vector(0, 0, 0);
info->isValid = false;
info->isAlive = false;
info->isFree = true;
}
} }
// Reset at round start
/* <3fd4f4> ../cstrike/dlls/bot/cs_gamestate.cpp:55 */ /* <3fd4f4> ../cstrike/dlls/bot/cs_gamestate.cpp:55 */
NOBODY void CSGameState::Reset(void) void CSGameState::Reset(void)
{ {
// { int i;
// class CCSBotManager *ctrl; // 66 CCSBotManager *ctrl = TheCSBots();
// int i; // 69
// Invalidate(IntervalTimer *const this); // 61 m_isRoundOver = false;
// Invalidate(IntervalTimer *const this); // 62
// { // bomb
// int swap; // 81 m_bombState = MOVING;
// int rnd; // 82 m_lastSawBomber.Invalidate();
// } m_lastSawLooseBomb.Invalidate();
// } m_bombsiteCount = ctrl->GetZoneCount();
m_isPlantedBombPosKnown = false;
m_plantedBombsite = UNKNOWN;
for (i = 0; i < m_bombsiteCount; ++i)
{
m_isBombsiteClear[i] = false;
m_bombsiteSearchOrder[i] = i;
}
// shuffle the bombsite search order
// allows T's to plant at random site, and TEAM_CT's to search in a random order
// NOTE: VS6 std::random_shuffle() doesn't work well with an array of two elements (most maps)
for (i = 0; i < m_bombsiteCount; ++i)
{
int swap = m_bombsiteSearchOrder[i];
int rnd = RANDOM_LONG(i, m_bombsiteCount - 1);
m_bombsiteSearchOrder[i] = m_bombsiteSearchOrder[rnd];
m_bombsiteSearchOrder[rnd] = swap;
}
m_bombsiteSearchIndex = 0;
InitializeHostageInfo();
} }
// Update game state based on events we have received
/* <3fce67> ../cstrike/dlls/bot/cs_gamestate.cpp:97 */ /* <3fce67> ../cstrike/dlls/bot/cs_gamestate.cpp:97 */
NOBODY void CSGameState::OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other) void CSGameState::OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other)
{ {
// SetBombState(CSGameState *const this, switch (event)
// enum BombState state); // 104 {
// UpdatePlantedBomb(CSGameState *const this, case EVENT_BOMB_PLANTED:
// const Vector *pos); // 109 SetBombState(PLANTED);
// SetBombState(CSGameState *const this, if (m_owner->m_iTeam == TERRORIST && other != NULL)
// enum BombState state); // 117 {
// SetBombState(CSGameState *const this, UpdatePlantedBomb(&other->pev->origin);
// enum BombState state); // 124 }
break;
case EVENT_BOMB_DEFUSED:
SetBombState(DEFUSED);
break;
case EVENT_BOMB_EXPLODED:
SetBombState(EXPLODED);
break;
case EVENT_ALL_HOSTAGES_RESCUED:
m_allHostagesRescued = true;
break;
case EVENT_TERRORISTS_WIN:
case EVENT_CTS_WIN:
case EVENT_ROUND_DRAW:
m_isRoundOver = true;
break;
default:
break;
}
} }
// True if round has been won or lost (but not yet reset)
/* <3fcf9c> ../cstrike/dlls/bot/cs_gamestate.cpp:144 */ /* <3fcf9c> ../cstrike/dlls/bot/cs_gamestate.cpp:144 */
NOBODY bool CSGameState::IsRoundOver(void) const bool CSGameState::IsRoundOver(void) const
{ {
return m_isRoundOver;
} }
/* <3fcfc6> ../cstrike/dlls/bot/cs_gamestate.cpp:150 */ /* <3fcfc6> ../cstrike/dlls/bot/cs_gamestate.cpp:150 */
NOBODY void CSGameState::SetBombState(BombState state) void CSGameState::SetBombState(BombState state)
{ {
// if state changed, reset "last seen" timestamps
if (m_bombState != state)
{
m_bombState = state;
}
} }
/* <3fcff2> ../cstrike/dlls/bot/cs_gamestate.cpp:160 */ /* <3fcff2> ../cstrike/dlls/bot/cs_gamestate.cpp:160 */
NOBODY void CSGameState::UpdateLooseBomb(const Vector *pos) void CSGameState::UpdateLooseBomb(const Vector *pos)
{ {
// SetBombState(CSGameState *const this, m_looseBombPos = *pos;
// enum BombState state); // 166 m_lastSawLooseBomb.Reset();
// Reset(IntervalTimer *const this); // 163
// we saw the loose bomb, update our state
SetBombState(LOOSE);
} }
/* <3fd06e> ../cstrike/dlls/bot/cs_gamestate.cpp:170 */ /* <3fd06e> ../cstrike/dlls/bot/cs_gamestate.cpp:170 */
NOBODY float CSGameState::TimeSinceLastSawLooseBomb(void) const float CSGameState::TimeSinceLastSawLooseBomb(void) const
{ {
// GetElapsedTime(const class IntervalTimer *const this); // 172 return m_lastSawLooseBomb.GetElapsedTime();
} }
/* <3fd0f4> ../cstrike/dlls/bot/cs_gamestate.cpp:176 */ /* <3fd0f4> ../cstrike/dlls/bot/cs_gamestate.cpp:176 */
NOBODY bool CSGameState::IsLooseBombLocationKnown(void) const bool CSGameState::IsLooseBombLocationKnown(void) const
{ {
// HasStarted(const class IntervalTimer *const this); // 181 if (m_bombState != LOOSE)
return false;
return (m_lastSawLooseBomb.HasStarted()) ? true : false;
} }
/* <3fd135> ../cstrike/dlls/bot/cs_gamestate.cpp:185 */ /* <3fd135> ../cstrike/dlls/bot/cs_gamestate.cpp:185 */
NOBODY void CSGameState::UpdateBomber(const Vector *pos) void CSGameState::UpdateBomber(const Vector *pos)
{ {
// Reset(IntervalTimer *const this); // 188 m_bomberPos = *pos;
// SetBombState(CSGameState *const this, m_lastSawBomber.Reset();
// enum BombState state); // 191
// we saw the bomber, update our state
SetBombState(MOVING);
} }
/* <3fd1b1> ../cstrike/dlls/bot/cs_gamestate.cpp:195 */ /* <3fd1b1> ../cstrike/dlls/bot/cs_gamestate.cpp:195 */
NOBODY float CSGameState::TimeSinceLastSawBomber(void) const float CSGameState::TimeSinceLastSawBomber(void) const
{ {
// GetElapsedTime(const class IntervalTimer *const this); // 197 return m_lastSawBomber.GetElapsedTime();
} }
/* <3fd237> ../cstrike/dlls/bot/cs_gamestate.cpp:201 */ /* <3fd237> ../cstrike/dlls/bot/cs_gamestate.cpp:201 */
NOBODY bool CSGameState::IsPlantedBombLocationKnown(void) const bool CSGameState::IsPlantedBombLocationKnown(void) const
{ {
if (m_bombState != PLANTED)
return false;
return m_isPlantedBombPosKnown;
} }
// Return the zone index of the planted bombsite, or UNKNOWN
/* <3fd25a> ../cstrike/dlls/bot/cs_gamestate.cpp:213 */ /* <3fd25a> ../cstrike/dlls/bot/cs_gamestate.cpp:213 */
NOBODY int CSGameState::GetPlantedBombsite(void) const int CSGameState::GetPlantedBombsite(void) const
{ {
if (m_bombState != PLANTED)
return UNKNOWN;
return m_plantedBombsite;
} }
// Return true if we are currently in the bombsite where the bomb is planted
/* <3fd284> ../cstrike/dlls/bot/cs_gamestate.cpp:225 */ /* <3fd284> ../cstrike/dlls/bot/cs_gamestate.cpp:225 */
NOBODY bool CSGameState::IsAtPlantedBombsite(void) const bool CSGameState::IsAtPlantedBombsite(void) const
{ {
// { if (m_bombState != PLANTED)
// class CCSBotManager *ctrl; // 230 return false;
// const class Zone *zone; // 231
// } CCSBotManager *ctrl = TheCSBots();
const CCSBotManager::Zone *zone = ctrl->GetClosestZone(&m_owner->pev->origin);
if (zone != NULL)
{
return (m_plantedBombsite == zone->m_index);
}
return false;
} }
// Return the zone index of the next bombsite to search
/* <3fd2d2> ../cstrike/dlls/bot/cs_gamestate.cpp:246 */ /* <3fd2d2> ../cstrike/dlls/bot/cs_gamestate.cpp:246 */
NOBODY int CSGameState::GetNextBombsiteToSearch(void) int CSGameState::GetNextBombsiteToSearch(void)
{ {
// { if (m_bombsiteCount <= 0)
// int i; // 251 return 0;
// {
// int z; // 256 int i;
// } // return next non-cleared bombsite index
// } for (i = m_bombsiteSearchIndex; i < m_bombsiteCount; ++i)
{
int z = m_bombsiteSearchOrder[i];
if (!m_isBombsiteClear[z])
{
m_bombsiteSearchIndex = i;
return z;
}
}
// all the bombsites are clear, someone must have been mistaken - start search over
for (i = 0; i < m_bombsiteCount; ++i)
{
m_isBombsiteClear[i] = false;
}
m_bombsiteSearchIndex = 0;
return GetNextBombsiteToSearch();
} }
// Returns position of bomb in its various states (moving, loose, planted),
// or NULL if we don't know where the bomb is
/* <3fd32c> ../cstrike/dlls/bot/cs_gamestate.cpp:277 */ /* <3fd32c> ../cstrike/dlls/bot/cs_gamestate.cpp:277 */
NOBODY const Vector *CSGameState::GetBombPosition(void) const const Vector *CSGameState::GetBombPosition(void) const
{ {
// HasStarted(const class IntervalTimer *const this); // 283 switch (m_bombState)
{
case MOVING:
{
if (!m_lastSawBomber.HasStarted())
return NULL;
return &m_bomberPos;
}
case LOOSE:
{
if (IsLooseBombLocationKnown())
return &m_looseBombPos;
return NULL;
}
case PLANTED:
{
if (IsPlantedBombLocationKnown())
return &m_plantedBombPos;
return NULL;
}
}
return NULL;
} }
// We see the planted bomb at 'pos'
/* <3fd373> ../cstrike/dlls/bot/cs_gamestate.cpp:313 */ /* <3fd373> ../cstrike/dlls/bot/cs_gamestate.cpp:313 */
NOBODY void CSGameState::UpdatePlantedBomb(const Vector *pos) void CSGameState::UpdatePlantedBomb(const Vector *pos)
{ {
// { CCSBotManager *ctrl = TheCSBots();
// class CCSBotManager *ctrl; // 315 const CCSBotManager::Zone *zone = ctrl->GetClosestZone(pos);
// const class Zone *zone; // 316
// SetBombState(CSGameState *const this, if (zone == NULL)
// enum BombState state); // 330 {
// } CONSOLE_ECHO("ERROR: Bomb planted outside of a zone!\n");
m_plantedBombsite = UNKNOWN;
}
else
{
m_plantedBombsite = zone->m_index;
}
m_plantedBombPos = *pos;
m_isPlantedBombPosKnown = true;
SetBombState(PLANTED);
} }
// Someone told us where the bomb is planted
/* <3fd3dd> ../cstrike/dlls/bot/cs_gamestate.cpp:337 */ /* <3fd3dd> ../cstrike/dlls/bot/cs_gamestate.cpp:337 */
NOBODY void CSGameState::MarkBombsiteAsPlanted(int zoneIndex) void CSGameState::MarkBombsiteAsPlanted(int zoneIndex)
{ {
// SetBombState(CSGameState *const this, m_plantedBombsite = zoneIndex;
// enum BombState state); // 340 SetBombState(PLANTED);
} }
// Someone told us a bombsite is clear
/* <3fd43a> ../cstrike/dlls/bot/cs_gamestate.cpp:347 */ /* <3fd43a> ../cstrike/dlls/bot/cs_gamestate.cpp:347 */
NOBODY void CSGameState::ClearBombsite(int zoneIndex) void CSGameState::ClearBombsite(int zoneIndex)
{ {
if (zoneIndex >= 0 && zoneIndex < m_bombsiteCount)
m_isBombsiteClear[zoneIndex] = true;
} }
/* <3fd475> ../cstrike/dlls/bot/cs_gamestate.cpp:354 */ /* <3fd475> ../cstrike/dlls/bot/cs_gamestate.cpp:354 */
NOBODY bool CSGameState::IsBombsiteClear(int zoneIndex) const bool CSGameState::IsBombsiteClear(int zoneIndex) const
{ {
if (zoneIndex >= 0 && zoneIndex < m_bombsiteCount)
return m_isBombsiteClear[zoneIndex];
return false;
} }
/* <3fd4b0> ../cstrike/dlls/bot/cs_gamestate.cpp:367 */ /* <3fd4b0> ../cstrike/dlls/bot/cs_gamestate.cpp:367 */
NOBODY void CSGameState::InitializeHostageInfo(void) void CSGameState::InitializeHostageInfo(void)
{ {
// { m_hostageCount = 0;
// class CBaseEntity *hostage; // 373 m_allHostagesRescued = 0;
// } m_haveSomeHostagesBeenTaken = 0;
CBaseEntity *hostage = NULL;
while ((hostage = UTIL_FindEntityByClassname(hostage, "hostage_entity")) != NULL)
{
if (m_hostageCount >= MAX_HOSTAGES)
break;
if (hostage->pev->takedamage != DAMAGE_YES)
continue;
m_hostage[m_hostageCount].hostage = static_cast<CHostage *>(hostage);
m_hostage[m_hostageCount].knownPos = hostage->pev->origin;
m_hostage[m_hostageCount].isValid = true;
m_hostage[m_hostageCount].isAlive = true;
m_hostage[m_hostageCount].isFree = true;
++m_hostageCount;
}
} }
// Return the closest free and live hostage
// If we are a CT this information is perfect.
// Otherwise, this is based on our individual memory of the game state.
// If NULL is returned, we don't think there are any hostages left, or we dont know where they are.
// NOTE: a T can remember a hostage who has died. knowPos will be filled in, but NULL will be
// returned, since CHostages get deleted when they die.
/* <3fd5ab> ../cstrike/dlls/bot/cs_gamestate.cpp:398 */ /* <3fd5ab> ../cstrike/dlls/bot/cs_gamestate.cpp:398 */
NOBODY CHostage *CSGameState::GetNearestFreeHostage(Vector *knowPos) CHostage *CSGameState::GetNearestFreeHostage(Vector *knowPos) const
{ {
// { if (m_owner == NULL)
// class CNavArea *startArea; // 403 return NULL;
// class CHostage *close; // 407
// const Vector *closePos; // 408 CNavArea *startArea = m_owner->GetLastKnownArea();
// float closeDistance; // 409
// { if (startArea == NULL)
// int i; // 411 return NULL;
// {
// const Vector *hostagePos; // 413 CHostage *close = NULL;
// class CNavArea *hostageArea; // 435 const Vector *closePos = NULL;
// { float closeDistance = 9999999999.9f;
// class ShortestPathCost pc; // 438
// float travelDistance; // 439 for (int i = 0; i < m_hostageCount; ++i)
// NavAreaTravelDistance<ShortestPathCost>(CNavArea *startArea, {
// class CNavArea *endArea, CHostage *hostage = m_hostage[i].hostage;
// class ShortestPathCost &costFunc); // 439 const Vector *hostagePos = NULL;
// }
// IsValid(CHostage *const this); // 418 if (m_owner->m_iTeam == CT)
// IsFollowingSomeone(CHostage *const this); // 421 {
// } // we know exactly where the hostages are, and if they are alive
// } if (!m_hostage[i].hostage || !m_hostage[i].hostage->IsValid())
// } continue;
if (m_hostage[i].hostage->IsFollowingSomeone())
continue;
hostagePos = &hostage->pev->origin;
}
else
{
// use our memory of where we think the hostages are
if (m_hostage[i].isValid == false)
continue;
hostagePos = &m_hostage[i].knownPos;
}
CNavArea *hostageArea = TheNavAreaGrid.GetNearestNavArea(hostagePos);
if (hostageArea != NULL)
{
ShortestPathCost pc;
float travelDistance = NavAreaTravelDistance(startArea, hostageArea, pc);
if (travelDistance >= 0.0f && travelDistance < closeDistance)
{
closePos = hostagePos;
closeDistance = travelDistance;
close = hostage;
}
}
}
// return where we think the hostage is
if (knowPos != NULL && closePos != NULL)
{
knowPos = const_cast<Vector *>(closePos);
}
return close;
} }
// Return the location of a "free" hostage, or NULL if we dont know of any
/* <3fdbd3> ../cstrike/dlls/bot/cs_gamestate.cpp:461 */ /* <3fdbd3> ../cstrike/dlls/bot/cs_gamestate.cpp:461 */
NOBODY const Vector *CSGameState::GetRandomFreeHostagePosition(void) const Vector *CSGameState::GetRandomFreeHostagePosition(void)
{ {
// { // TODO: use static?
// const Vector *freePos; // 466 const Vector *freePos[MAX_HOSTAGES];
// int freeCount; // 467 int freeCount = 0;
// {
// int i; // 469 if (m_owner == NULL)
// { return NULL;
// const class HostageInfo *info; // 471
// IsFollowingSomeone(CHostage *const this); // 480 for (int i = 0; i < m_hostageCount; ++i)
// } {
// } const HostageInfo *info = &m_hostage[i];
// } const Vector *hostagePos = NULL;
if (m_owner->m_iTeam == CT)
{
// we know exactly where the hostages are, and if they are alive
if (!info->hostage || !info->hostage->IsAlive())
continue;
// escorted hostages are not "free"
if (info->hostage->IsFollowingSomeone())
continue;
freePos[ freeCount++ ] = &info->hostage->pev->origin;
}
else
{
// use our memory of where we think the hostages are
if (info->isValid == false)
continue;
freePos[ freeCount++ ] = &info->knownPos;
}
}
if (freeCount)
{
return freePos[RANDOM_LONG(0, freeCount - 1)];
}
return NULL;
} }
// If we can see any of the positions where we think a hostage is, validate it
// Return status of any changes (a hostage died or was moved)
/* <3fdcd2> ../cstrike/dlls/bot/cs_gamestate.cpp:509 */ /* <3fdcd2> ../cstrike/dlls/bot/cs_gamestate.cpp:509 */
NOBODY unsigned char CSGameState::ValidateHostagePositions(void) CSGameState::ValidateStatusType CSGameState::ValidateHostagePositions(void)
{ {
// { // limit how often we validate
// float const validateInterval; // 515 if (!m_validateInterval.IsElapsed())
// TraceResult result; // 520 return NO_CHANGE;
// unsigned char status; // 521
// int i; // 523 const float validateInterval = 0.5f;
// int startValidCount; // 524 m_validateInterval.Start(validateInterval);
// int endValidCount; // 605
// IsElapsed(const class CountdownTimer *const this); // 512 // check the status of hostages
// Start(CountdownTimer *const this, ValidateStatusType status = NO_CHANGE;
// float duration); // 516
// { int i;
// class HostageInfo *info; // 531 int startValidCount = 0;
// { for (i = 0; i < m_hostageCount; ++i)
// float const tolerance; // 594 {
// IsValid(CHostage *const this); // 576 if (m_hostage[i].isValid)
// IsFollowingSomeone(CHostage *const this); // 586 ++startValidCount;
// operator-(const Vector *const this, }
// const Vector &v); // 595
// IsLengthGreaterThan(const Vector *const this, for (i = 0; i < m_hostageCount; ++i)
// float length); // 595 {
// } HostageInfo *info = &m_hostage[i];
// IsFollowingSomeone(CHostage *const this); // 541
// } if (!info->hostage)
// } continue;
// if we can see a hostage, update our knowledge of it
if (m_owner->IsVisible(&info->hostage->pev->origin, CHECK_FOV))
{
if (info->hostage->pev->takedamage == DAMAGE_YES)
{
// live hostage
// if hostage is being escorted by a CT, we don't "see" it, we see the CT
if (info->hostage->IsFollowingSomeone())
{
info->isValid = false;
}
else
{
info->knownPos = info->hostage->pev->origin;
info->isValid = true;
}
}
else
{
// dead hostage
// if we thought it was alive, this is news to us
if (info->isAlive)
status |= HOSTAGE_DIED;
info->isAlive = false;
info->isValid = false;
}
continue;
}
// if we dont know where this hostage is, nothing to validate
if (!info->isValid)
continue;
// can't directly see this hostage
// check line of sight to where we think this hostage is, to see if we noticed that is has moved
if (m_owner->IsVisible(&info->knownPos, CHECK_FOV))
{
// we can see where we thought the hostage was - verify it is still there and alive
if (info->hostage->pev->takedamage != DAMAGE_YES)
{
// since we have line of sight to an invalid hostage, it must be dead
// discovered that hostage has been killed
status |= HOSTAGE_DIED;
info->isAlive = false;
info->isValid = false;
continue;
}
if (info->hostage->IsFollowingSomeone())
{
// discovered the hostage has been taken
status |= HOSTAGE_GONE;
info->isValid = false;
continue;
}
const float tolerance = 50.0f;
if ((info->hostage->pev->origin - info->knownPos).IsLengthGreaterThan(tolerance))
{
// discovered that hostage has been moved
status |= HOSTAGE_GONE;
info->isValid = false;
continue;
}
}
}
int endValidCount = 0;
for (i = 0; i < m_hostageCount; ++i)
{
if (m_hostage[i].isValid)
++endValidCount;
}
if (endValidCount == 0 && startValidCount > 0)
{
// we discovered all the hostages are gone
status &= ~HOSTAGE_GONE;
status |= HOSTAGES_ALL_GONE;
}
return status;
} }
// Return the nearest visible free hostage
// Since we can actually see any hostage we return, we know its actual position
/* <3fdef7> ../cstrike/dlls/bot/cs_gamestate.cpp:626 */ /* <3fdef7> ../cstrike/dlls/bot/cs_gamestate.cpp:626 */
NOBODY CHostage *CSGameState::GetNearestVisibleFreeHostage(void) CHostage *CSGameState::GetNearestVisibleFreeHostage(void) const
{ {
// { CHostage *close = NULL;
// class CHostage *close; // 628 float closeRangeSq = 999999999.9f;
// float closeRangeSq; // 629 float rangeSq;
// float rangeSq; // 630
// Vector pos; // 632 Vector pos;
// {
// int i; // 634 for (int i = 0; i < m_hostageCount; ++i)
// { {
// const class HostageInfo *info; // 636 const HostageInfo *info = &m_hostage[i];
// IsFollowingSomeone(CHostage *const this); // 643
// operator+(const Vector *const this, if (!info->hostage)
// const Vector &v); // 647 continue;
// operator-(const Vector *const this,
// const Vector &v); // 648 // if the hostage is dead or rescued, its not free
// LengthSquared(const Vector *const this); // 648 if (info->hostage->pev->takedamage != DAMAGE_YES)
// } continue;
// }
// } // if this hostage is following someone, its not free
if (info->hostage->IsFollowingSomeone())
continue;
// TODO: Use travel distance here
pos = info->hostage->pev->origin + Vector(0, 0, HumanHeight * 0.75f);
rangeSq = (pos - m_owner->pev->origin).LengthSquared();
if (rangeSq < closeRangeSq)
{
if (!m_owner->IsVisible(&pos))
continue;
close = info->hostage;
closeRangeSq = rangeSq;
}
}
return close;
} }
// Return true if there are no free hostages
/* <3fe064> ../cstrike/dlls/bot/cs_gamestate.cpp:668 */ /* <3fe064> ../cstrike/dlls/bot/cs_gamestate.cpp:668 */
NOBODY bool CSGameState::AreAllHostagesBeingRescued(void) bool CSGameState::AreAllHostagesBeingRescued(void) const
{ {
// { // if the hostages have all been rescued, they are not being rescued any longer
// bool isAllDead; // 674 if (m_allHostagesRescued)
// { return false;
// int i; // 676
// { bool isAllDead = true;
// const class HostageInfo *info; // 678
// IsValid(CHostage *const this); // 683 for (int i = 0; i < m_hostageCount; ++i)
// IsFollowingSomeone(CHostage *const this); // 685 {
// } const HostageInfo *info = &m_hostage[i];
// }
// } if (m_owner->m_iTeam == CT)
{
// CT's have perfect knowledge via their radar
if (info->hostage != NULL && info->hostage->IsValid())
{
if (!info->hostage->IsFollowingSomeone())
return false;
isAllDead = false;
}
}
else
{
if (info->isValid && info->isAlive)
return false;
if (info->isAlive)
isAllDead = false;
}
}
// if all of the remaining hostages are dead, they arent being rescued
if (isAllDead)
return false;
return true;
} }
// All hostages have been rescued or are dead
/* <3fe148> ../cstrike/dlls/bot/cs_gamestate.cpp:712 */ /* <3fe148> ../cstrike/dlls/bot/cs_gamestate.cpp:712 */
NOBODY bool CSGameState::AreAllHostagesGone(void) bool CSGameState::AreAllHostagesGone(void) const
{ {
// { if (m_allHostagesRescued)
// int i; // 718 return true;
// {
// const class HostageInfo *info; // 720 // do we know that all the hostages are dead
// } for (int i = 0; i < m_hostageCount; ++i)
// } {
const HostageInfo *info = &m_hostage[i];
if (m_owner->m_iTeam == CT)
{
// CT's have perfect knowledge via their radar
if (info->hostage->IsAlive())// == DAMAGE_YES)
return false;
}
else
{
if (info->isValid && info->isAlive)
return false;
}
}
return true;
} }
// Someone told us all the hostages are gone
/* <3fe1a2> ../cstrike/dlls/bot/cs_gamestate.cpp:742 */ /* <3fe1a2> ../cstrike/dlls/bot/cs_gamestate.cpp:742 */
NOBODY void CSGameState::AllHostagesGone(void) void CSGameState::AllHostagesGone(void)
{ {
// { for (int i = 0; i < m_hostageCount; ++i)
// int i; // 744 m_hostage[i].isValid = false;
// }
} }

View File

@ -33,29 +33,19 @@
#endif #endif
class CCSBot; class CCSBot;
//class CHostage;
// This class represents the game state as known by a particular bot
class CSGameState class CSGameState
{ {
public: public:
CSGameState(void); CSGameState() {};
CSGameState(CCSBot *owner); CSGameState(CCSBot *owner);
struct HostageInfo void Reset(void);
{ void OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other); // Event handling
CHostage *hostage; bool IsRoundOver(void) const; // true if round has been won or lost (but not yet reset)
Vector knownPos;
bool isValid;
bool isAlive;
bool isFree;
};/* size: 20, cachelines: 1, members: 5 */
NOBODY void Reset(void);
// Event handling
NOBODY void OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other);
// true if round has been won or lost (but not yet reset)
NOBODY bool IsRoundOver(void) const;
// bomb defuse scenario
enum BombState enum BombState
{ {
MOVING, // being carried by a Terrorist MOVING, // being carried by a Terrorist
@ -64,106 +54,101 @@ public:
DEFUSED, // the bomb has been defused DEFUSED, // the bomb has been defused
EXPLODED, // the bomb has exploded EXPLODED, // the bomb has exploded
}; };
bool IsBombMoving(void) const
{ bool IsBombMoving(void) const { return (m_bombState == MOVING); }
return (m_bombState == MOVING); bool IsBombLoose(void) const { return (m_bombState == LOOSE); }
} bool IsBombPlanted(void) const { return (m_bombState == PLANTED); }
bool IsBombLoose(void) const bool IsBombDefused(void) const { return (m_bombState == DEFUSED); }
{ bool IsBombExploded(void) const { return (m_bombState == EXPLODED); }
return (m_bombState == LOOSE);
} void UpdateLooseBomb(const Vector *pos); // we see the loose bomb
bool IsBombPlanted(void) const float TimeSinceLastSawLooseBomb(void) const; // how long has is been since we saw the loose bomb
{ bool IsLooseBombLocationKnown(void) const; // do we know where the loose bomb is
return (m_bombState == PLANTED);
} void UpdateBomber(const Vector *pos); // we see the bomber
bool IsBombDefused(void) const float TimeSinceLastSawBomber(void) const; // how long has is been since we saw the bomber
{
return (m_bombState == DEFUSED); void UpdatePlantedBomb(const Vector *pos); // we see the planted bomb
} bool IsPlantedBombLocationKnown(void) const; // do we know where the bomb was planted
bool IsBombExploded(void) const void MarkBombsiteAsPlanted(int zoneIndex); // mark bombsite as the location of the planted bomb
{
return (m_bombState == EXPLODED);
}
// we see the loose bomb
NOBODY void UpdateLooseBomb(const Vector *pos);
// how long has is been since we saw the loose bomb
NOBODY float TimeSinceLastSawLooseBomb(void) const;
// do we know where the loose bomb is
NOBODY bool IsLooseBombLocationKnown(void) const;
// we see the bomber
NOBODY void UpdateBomber(const Vector *pos);
// how long has is been since we saw the bomber
NOBODY float TimeSinceLastSawBomber(void) const;
// we see the planted bomb
NOBODY void UpdatePlantedBomb(const Vector *pos);
// do we know where the bomb was planted
NOBODY bool IsPlantedBombLocationKnown(void) const;
// mark bombsite as the location of the planted bomb
NOBODY void MarkBombsiteAsPlanted(int zoneIndex);
enum { UNKNOWN = -1 }; enum { UNKNOWN = -1 };
// return the zone index of the planted bombsite, or UNKNOWN int GetPlantedBombsite(void) const; // return the zone index of the planted bombsite, or UNKNOWN
NOBODY int GetPlantedBombsite(void) const; bool IsAtPlantedBombsite(void) const; // return true if we are currently in the bombsite where the bomb is planted
// return true if we are currently in the bombsite where the bomb is planted
NOBODY bool IsAtPlantedBombsite(void) const;
// return the zone index of the next bombsite to search
NOBODY int GetNextBombsiteToSearch(void);
// return true if given bombsite has been cleared
NOBODY bool IsBombsiteClear(int zoneIndex) const;
// mark bombsite as clear
NOBODY void ClearBombsite(int zoneIndex);
// return where we think the bomb is, or NULL if we don't know
NOBODY const Vector *GetBombPosition(void) const;
NOBODY CHostage *GetNearestFreeHostage(Vector *knowPos); int GetNextBombsiteToSearch(void); // return the zone index of the next bombsite to search
NOBODY const Vector *GetRandomFreeHostagePosition(void); bool IsBombsiteClear(int zoneIndex) const; // return true if given bombsite has been cleared
NOBODY bool AreAllHostagesBeingRescued(void); void ClearBombsite(int zoneIndex); // mark bombsite as clear
NOBODY bool AreAllHostagesGone(void);
NOBODY void AllHostagesGone(void);
bool HaveSomeHostagesBeenTaken(void)
{
return m_haveSomeHostagesBeenTaken;
}
void HostageWasTaken(void)
{
m_haveSomeHostagesBeenTaken = true;
}
NOBODY CHostage *GetNearestVisibleFreeHostage(void);
NOBODY unsigned char ValidateHostagePositions(void);
NOBODY void SetBombState(BombState state);
BombState GetBombState(void)
{
return m_bombState;
}
CBaseEntity *GetNearestHostage(void)
{
UNTESTED
// TODO: Not implemented
//CHostage *pHostage = g_pHostages->GetClosestHostage(m_owner->pev->origin); const Vector *GetBombPosition(void) const; // return where we think the bomb is, or NULL if we don't know
//return GetClassPtr((CHostage *)pHostage->pev);
} // hostage rescue scenario
NOBODY void InitializeHostageInfo(void); CHostage *GetNearestFreeHostage(Vector *knowPos = NULL) const; // return the closest free hostage, and where we think it is (knowPos)
const Vector *GetRandomFreeHostagePosition(void);
bool AreAllHostagesBeingRescued(void) const; // return true if there are no free hostages
bool AreAllHostagesGone(void) const; // all hostages have been rescued or are dead
void AllHostagesGone(void); // someone told us all the hostages are gone
bool HaveSomeHostagesBeenTaken(void) const { return m_haveSomeHostagesBeenTaken; } // return true if one or more hostages have been moved by the CT's
void HostageWasTaken(void) { m_haveSomeHostagesBeenTaken = true; } // someone told us a CT is talking to a hostage
CHostage *GetNearestVisibleFreeHostage(void) const;
// hostage rescue scenario
enum ValidateStatusType:uint8
{
NO_CHANGE = 0x00,
HOSTAGE_DIED = 0x01,
HOSTAGE_GONE = 0x02,
HOSTAGES_ALL_GONE = 0x04
};
ValidateStatusType ValidateHostagePositions(void); // update our knowledge with what we currently see - returns bitflag events
#ifndef HOOK_GAMEDLL
private: private:
CCSBot *m_owner; #endif // HOOK_GAMEDLL
bool m_isRoundOver;
BombState m_bombState; CCSBot *m_owner; // who owns this gamestate
bool m_isRoundOver; // true if round is over, but no yet reset
// bomb defuse scenario
void SetBombState(BombState state);
BombState GetBombState(void) { return m_bombState; }
BombState m_bombState; // what we think the bomb is doing
IntervalTimer m_lastSawBomber; IntervalTimer m_lastSawBomber;
Vector m_bomberPos; Vector m_bomberPos;
IntervalTimer m_lastSawLooseBomb; IntervalTimer m_lastSawLooseBomb;
Vector m_looseBombPos; Vector m_looseBombPos;
bool m_isBombsiteClear[4];
int m_bombsiteSearchOrder[4]; bool m_isBombsiteClear[4]; // corresponds to zone indices in CCSBotManager
int m_bombsiteSearchOrder[4]; // randomized order of bombsites to search
int m_bombsiteCount; int m_bombsiteCount;
int m_bombsiteSearchIndex; int m_bombsiteSearchIndex; // the next step in the search
int m_plantedBombsite;
bool m_isPlantedBombPosKnown; int m_plantedBombsite; // zone index of the bombsite where the planted bomb is
bool m_isPlantedBombPosKnown; // if true, we know the exact location of the bomb
Vector m_plantedBombPos; Vector m_plantedBombPos;
struct HostageInfo m_hostage[12];
int m_hostageCount; // hostage rescue scenario
struct HostageInfo
{
CHostage *hostage;
Vector knownPos;
bool isValid;
bool isAlive;
bool isFree; // not being escorted by a CT
}
m_hostage[ MAX_HOSTAGES ];
int m_hostageCount; // number of hostages left in map
CountdownTimer m_validateInterval; CountdownTimer m_validateInterval;
bool m_allHostagesRescued; NOXREF CBaseEntity *GetNearestHostage(void) const; // return the closest live hostage
bool m_haveSomeHostagesBeenTaken; void InitializeHostageInfo(void); // initialize our knowledge of the number and location of hostages
bool m_allHostagesRescued; // if true, so every hostages been is rescued
bool m_haveSomeHostagesBeenTaken; // true if a hostage has been moved by a CT (and we've seen it)
};/* size: 348, cachelines: 6, members: 19 */ };/* size: 348, cachelines: 6, members: 19 */

View File

@ -1,7 +1,7 @@
#include "precompiled.h" #include "precompiled.h"
/* <519735> ../cstrike/dlls/bot/states/cs_bot_attack.cpp:16 */ /* <519735> ../cstrike/dlls/bot/states/cs_bot_attack.cpp:16 */
NOBODY void AttackState::OnEnter(CCSBot *me) NOBODY void AttackState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// { // {
// class CBasePlayer *enemy; // 18 // class CBasePlayer *enemy; // 18
@ -43,7 +43,7 @@ NOBODY void AttackState::StopAttacking(CCSBot *me)
} }
/* <51997e> ../cstrike/dlls/bot/states/cs_bot_attack.cpp:152 */ /* <51997e> ../cstrike/dlls/bot/states/cs_bot_attack.cpp:152 */
NOBODY void AttackState::OnUpdate(CCSBot *me) NOBODY void AttackState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// class CBasePlayerWeapon *weapon; // 161 // class CBasePlayerWeapon *weapon; // 161
@ -149,7 +149,7 @@ NOBODY void AttackState::OnUpdate(CCSBot *me)
} }
/* <5198d4> ../cstrike/dlls/bot/states/cs_bot_attack.cpp:578 */ /* <5198d4> ../cstrike/dlls/bot/states/cs_bot_attack.cpp:578 */
NOBODY void AttackState::OnExit(CCSBot *me) NOBODY void AttackState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
// ForgetNoise(CCSBot *const this); // 585 // ForgetNoise(CCSBot *const this); // 585
// PopPostureContext(CBot *const this); // 589 // PopPostureContext(CBot *const this); // 589
@ -157,3 +157,22 @@ NOBODY void AttackState::OnExit(CCSBot *me)
// StopRapidFire(CCSBot *const this); // 597 // StopRapidFire(CCSBot *const this); // 597
// ClearSurpriseDelay(CCSBot *const this); // 598 // ClearSurpriseDelay(CCSBot *const this); // 598
} }
#ifdef HOOK_GAMEDLL
void AttackState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void AttackState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void AttackState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -6,7 +6,7 @@ NOBODY bool HasDefaultPistol(CCSBot *me)
} }
/* <5299e4> ../cstrike/dlls/bot/states/cs_bot_buy.cpp:37 */ /* <5299e4> ../cstrike/dlls/bot/states/cs_bot_buy.cpp:37 */
NOBODY void BuyState::OnEnter(CCSBot *me) NOBODY void BuyState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// { // {
// class CCSBotManager *ctrl; // 48 // class CCSBotManager *ctrl; // 48
@ -27,7 +27,7 @@ NOBODY inline WeaponType GetWeaponType(const char *alias)
} }
/* <529753> ../cstrike/dlls/bot/states/cs_bot_buy.cpp:241 */ /* <529753> ../cstrike/dlls/bot/states/cs_bot_buy.cpp:241 */
NOBODY void BuyState::OnUpdate(CCSBot *me) NOBODY void BuyState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// bool inBuyZone; // 273 // bool inBuyZone; // 273
@ -84,6 +84,25 @@ NOBODY void BuyState::OnUpdate(CCSBot *me)
} }
/* <5296f1> ../cstrike/dlls/bot/states/cs_bot_buy.cpp:529 */ /* <5296f1> ../cstrike/dlls/bot/states/cs_bot_buy.cpp:529 */
NOBODY void BuyState::OnExit(CCSBot *me) NOBODY void BuyState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
} }
#ifdef HOOK_GAMEDLL
void BuyState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void BuyState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void BuyState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,7 +1,7 @@
#include "precompiled.h" #include "precompiled.h"
/* <539f0e> ../cstrike/dlls/bot/states/cs_bot_defuse_bomb.cpp:16 */ /* <539f0e> ../cstrike/dlls/bot/states/cs_bot_defuse_bomb.cpp:16 */
NOBODY void DefuseBombState::OnEnter(CCSBot *me) NOBODY void DefuseBombState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// Say(BotChatterInterface *const this, // Say(BotChatterInterface *const this,
// const char *phraseName, // const char *phraseName,
@ -10,7 +10,7 @@ NOBODY void DefuseBombState::OnEnter(CCSBot *me)
} }
/* <539eac> ../cstrike/dlls/bot/states/cs_bot_defuse_bomb.cpp:27 */ /* <539eac> ../cstrike/dlls/bot/states/cs_bot_defuse_bomb.cpp:27 */
NOBODY void DefuseBombState::OnUpdate(CCSBot *me) NOBODY void DefuseBombState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// const Vector *bombPos; // 29 // const Vector *bombPos; // 29
@ -19,10 +19,29 @@ NOBODY void DefuseBombState::OnUpdate(CCSBot *me)
} }
/* <539e36> ../cstrike/dlls/bot/states/cs_bot_defuse_bomb.cpp:73 */ /* <539e36> ../cstrike/dlls/bot/states/cs_bot_defuse_bomb.cpp:73 */
NOBODY void DefuseBombState::OnExit(CCSBot *me) NOBODY void DefuseBombState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
// SetTask(CCSBot *const this, // SetTask(CCSBot *const this,
// enum TaskType task, // enum TaskType task,
// class CBaseEntity *entity); // 77 // class CBaseEntity *entity); // 77
// ClearLookAt(CCSBot *const this); // 79 // ClearLookAt(CCSBot *const this); // 79
} }
#ifdef HOOK_GAMEDLL
void DefuseBombState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void DefuseBombState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void DefuseBombState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,13 +1,13 @@
#include "precompiled.h" #include "precompiled.h"
/* <5499ae> ../cstrike/dlls/bot/states/cs_bot_escape_from_bomb.cpp:16 */ /* <5499ae> ../cstrike/dlls/bot/states/cs_bot_escape_from_bomb.cpp:16 */
NOBODY void EscapeFromBombState::OnEnter(CCSBot *me) NOBODY void EscapeFromBombState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// DestroyPath(CCSBot *const this); // 20 // DestroyPath(CCSBot *const this); // 20
} }
/* <549be9> ../cstrike/dlls/bot/states/cs_bot_escape_from_bomb.cpp:28 */ /* <549be9> ../cstrike/dlls/bot/states/cs_bot_escape_from_bomb.cpp:28 */
NOBODY void EscapeFromBombState::OnUpdate(CCSBot *me) NOBODY void EscapeFromBombState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// const Vector *bombPos; // 30 // const Vector *bombPos; // 30
@ -21,6 +21,25 @@ NOBODY void EscapeFromBombState::OnUpdate(CCSBot *me)
} }
/* <549976> ../cstrike/dlls/bot/states/cs_bot_escape_from_bomb.cpp:60 */ /* <549976> ../cstrike/dlls/bot/states/cs_bot_escape_from_bomb.cpp:60 */
NOBODY void EscapeFromBombState::OnExit(CCSBot *me) NOBODY void EscapeFromBombState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
} }
#ifdef HOOK_GAMEDLL
void EscapeFromBombState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void EscapeFromBombState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void EscapeFromBombState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,13 +1,13 @@
#include "precompiled.h" #include "precompiled.h"
/* <5587b3> ../cstrike/dlls/bot/states/cs_bot_fetch_bomb.cpp:17 */ /* <5587b3> ../cstrike/dlls/bot/states/cs_bot_fetch_bomb.cpp:17 */
NOBODY void FetchBombState::OnEnter(CCSBot *me) NOBODY void FetchBombState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// DestroyPath(CCSBot *const this); // 19 // DestroyPath(CCSBot *const this); // 19
} }
/* <5587fa> ../cstrike/dlls/bot/states/cs_bot_fetch_bomb.cpp:26 */ /* <5587fa> ../cstrike/dlls/bot/states/cs_bot_fetch_bomb.cpp:26 */
NOBODY void FetchBombState::OnUpdate(CCSBot *me) NOBODY void FetchBombState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// class CCSBotManager *ctrl; // 28 // class CCSBotManager *ctrl; // 28
@ -15,3 +15,17 @@ NOBODY void FetchBombState::OnUpdate(CCSBot *me)
// GetLooseBomb(CCSBotManager *const this); // 30 // GetLooseBomb(CCSBotManager *const this); // 30
// } // }
} }
#ifdef HOOK_GAMEDLL
void FetchBombState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void FetchBombState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,7 +1,7 @@
#include "precompiled.h" #include "precompiled.h"
/* <56918b> ../cstrike/dlls/bot/states/cs_bot_follow.cpp:16 */ /* <56918b> ../cstrike/dlls/bot/states/cs_bot_follow.cpp:16 */
NOBODY void FollowState::OnEnter(CCSBot *me) NOBODY void FollowState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// DestroyPath(CCSBot *const this); // 20 // DestroyPath(CCSBot *const this); // 20
// Invalidate(CountdownTimer *const this); // 33 // Invalidate(CountdownTimer *const this); // 33
@ -27,7 +27,7 @@ NOBODY void FollowState::ComputeLeaderMotionState(float leaderSpeed)
} }
/* <569368> ../cstrike/dlls/bot/states/cs_bot_follow.cpp:164 */ /* <569368> ../cstrike/dlls/bot/states/cs_bot_follow.cpp:164 */
NOBODY void FollowState::OnUpdate(CCSBot *me) NOBODY void FollowState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// float leaderSpeed; // 194 // float leaderSpeed; // 194
@ -98,6 +98,25 @@ NOBODY void FollowState::OnUpdate(CCSBot *me)
} }
/* <569231> ../cstrike/dlls/bot/states/cs_bot_follow.cpp:353 */ /* <569231> ../cstrike/dlls/bot/states/cs_bot_follow.cpp:353 */
NOBODY void FollowState::OnExit(CCSBot *me) NOBODY void FollowState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
} }
#ifdef HOOK_GAMEDLL
void FollowState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void FollowState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void FollowState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,13 +1,13 @@
#include "precompiled.h" #include "precompiled.h"
/* <57c261> ../cstrike/dlls/bot/states/cs_bot_hide.cpp:22 */ /* <57c261> ../cstrike/dlls/bot/states/cs_bot_hide.cpp:22 */
NOBODY void HideState::OnEnter(CCSBot *me) NOBODY void HideState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// GetFollowLeader(CCSBot *const this); // 50 // GetFollowLeader(CCSBot *const this); // 50
} }
/* <57c35e> ../cstrike/dlls/bot/states/cs_bot_hide.cpp:59 */ /* <57c35e> ../cstrike/dlls/bot/states/cs_bot_hide.cpp:59 */
NOBODY void HideState::OnUpdate(CCSBot *me) NOBODY void HideState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// class CCSBotManager *ctrl; // 61 // class CCSBotManager *ctrl; // 61
@ -110,7 +110,7 @@ NOBODY void HideState::OnUpdate(CCSBot *me)
} }
/* <57c2c8> ../cstrike/dlls/bot/states/cs_bot_hide.cpp:450 */ /* <57c2c8> ../cstrike/dlls/bot/states/cs_bot_hide.cpp:450 */
NOBODY void HideState::OnExit(CCSBot *me) NOBODY void HideState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
// ClearLookAt(CCSBot *const this); // 456 // ClearLookAt(CCSBot *const this); // 456
// ClearApproachPoints(CCSBot *const this); // 457 // ClearApproachPoints(CCSBot *const this); // 457
@ -118,3 +118,22 @@ NOBODY void HideState::OnExit(CCSBot *me)
// OnExit(HideState *const this, // OnExit(HideState *const this,
// class CCSBot *me); // 450 // class CCSBot *me); // 450
} }
#ifdef HOOK_GAMEDLL
void HideState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void HideState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void HideState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,7 +1,7 @@
#include "precompiled.h" #include "precompiled.h"
/* <58e6e0> ../cstrike/dlls/bot/states/cs_bot_hunt.cpp:18 */ /* <58e6e0> ../cstrike/dlls/bot/states/cs_bot_hunt.cpp:18 */
NOBODY void HuntState::OnEnter(CCSBot *me) NOBODY void HuntState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// SetTask(CCSBot *const this, // SetTask(CCSBot *const this,
// enum TaskType task, // enum TaskType task,
@ -10,7 +10,7 @@ NOBODY void HuntState::OnEnter(CCSBot *me)
} }
/* <58e452> ../cstrike/dlls/bot/states/cs_bot_hunt.cpp:38 */ /* <58e452> ../cstrike/dlls/bot/states/cs_bot_hunt.cpp:38 */
NOBODY void HuntState::OnUpdate(CCSBot *me) NOBODY void HuntState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// class CCSBotManager *ctrl; // 40 // class CCSBotManager *ctrl; // 40
@ -58,6 +58,25 @@ NOBODY void HuntState::OnUpdate(CCSBot *me)
} }
/* <58e418> ../cstrike/dlls/bot/states/cs_bot_hunt.cpp:211 */ /* <58e418> ../cstrike/dlls/bot/states/cs_bot_hunt.cpp:211 */
NOBODY void HuntState::OnExit(CCSBot *me) NOBODY void HuntState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
} }
#ifdef HOOK_GAMEDLL
void HuntState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void HuntState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void HuntState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,7 +1,7 @@
#include "precompiled.h" #include "precompiled.h"
/* <5a12ee> ../cstrike/dlls/bot/states/cs_bot_idle.cpp:26 */ /* <5a12ee> ../cstrike/dlls/bot/states/cs_bot_idle.cpp:26 */
NOBODY void IdleState::OnEnter(CCSBot *me) NOBODY void IdleState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// DestroyPath(CCSBot *const this); // 28 // DestroyPath(CCSBot *const this); // 28
// SetTask(CCSBot *const this, // SetTask(CCSBot *const this,
@ -10,7 +10,7 @@ NOBODY void IdleState::OnEnter(CCSBot *me)
} }
/* <5a0c66> ../cstrike/dlls/bot/states/cs_bot_idle.cpp:46 */ /* <5a0c66> ../cstrike/dlls/bot/states/cs_bot_idle.cpp:46 */
NOBODY void IdleState::OnUpdate(CCSBot *me) NOBODY void IdleState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// class CCSBotManager *ctrl; // 59 // class CCSBotManager *ctrl; // 59
@ -154,3 +154,17 @@ NOBODY void IdleState::OnUpdate(CCSBot *me)
// } // }
// } // }
} }
#ifdef HOOK_GAMEDLL
void IdleState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void IdleState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -7,14 +7,14 @@ NOBODY void InvestigateNoiseState::AttendCurrentNoise(CCSBot *me)
} }
/* <5b2f37> ../cstrike/dlls/bot/states/cs_bot_investigate_noise.cpp:38 */ /* <5b2f37> ../cstrike/dlls/bot/states/cs_bot_investigate_noise.cpp:38 */
NOBODY void InvestigateNoiseState::OnEnter(CCSBot *me) NOBODY void InvestigateNoiseState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// AttendCurrentNoise(InvestigateNoiseState *const this, // AttendCurrentNoise(InvestigateNoiseState *const this,
// class CCSBot *me); // 40 // class CCSBot *me); // 40
} }
/* <5b2fa2> ../cstrike/dlls/bot/states/cs_bot_investigate_noise.cpp:47 */ /* <5b2fa2> ../cstrike/dlls/bot/states/cs_bot_investigate_noise.cpp:47 */
NOBODY void InvestigateNoiseState::OnUpdate(CCSBot *me) NOBODY void InvestigateNoiseState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// float newNoiseDist; // 50 // float newNoiseDist; // 50
@ -40,6 +40,25 @@ NOBODY void InvestigateNoiseState::OnUpdate(CCSBot *me)
} }
/* <5b2e95> ../cstrike/dlls/bot/states/cs_bot_investigate_noise.cpp:129 */ /* <5b2e95> ../cstrike/dlls/bot/states/cs_bot_investigate_noise.cpp:129 */
NOBODY void InvestigateNoiseState::OnExit(CCSBot *me) NOBODY void InvestigateNoiseState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
} }
#ifdef HOOK_GAMEDLL
void InvestigateNoiseState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void InvestigateNoiseState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void InvestigateNoiseState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,7 +1,7 @@
#include "precompiled.h" #include "precompiled.h"
/* <5c4e91> ../cstrike/dlls/bot/states/cs_bot_move_to.cpp:21 */ /* <5c4e91> ../cstrike/dlls/bot/states/cs_bot_move_to.cpp:21 */
NOBODY void MoveToState::OnEnter(CCSBot *me) NOBODY void MoveToState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// { // {
// enum RouteType route; // 30 // enum RouteType route; // 30
@ -9,7 +9,7 @@ NOBODY void MoveToState::OnEnter(CCSBot *me)
} }
/* <5c4edf> ../cstrike/dlls/bot/states/cs_bot_move_to.cpp:55 */ /* <5c4edf> ../cstrike/dlls/bot/states/cs_bot_move_to.cpp:55 */
NOBODY void MoveToState::OnUpdate(CCSBot *me) NOBODY void MoveToState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // {
// class CCSBotManager *ctrl; // 76 // class CCSBotManager *ctrl; // 76
@ -82,6 +82,25 @@ NOBODY void MoveToState::OnUpdate(CCSBot *me)
} }
/* <5c4e54> ../cstrike/dlls/bot/states/cs_bot_move_to.cpp:320 */ /* <5c4e54> ../cstrike/dlls/bot/states/cs_bot_move_to.cpp:320 */
NOBODY void MoveToState::OnExit(CCSBot *me) NOBODY void MoveToState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
} }
#ifdef HOOK_GAMEDLL
void MoveToState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void MoveToState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void MoveToState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,35 +1,79 @@
#include "precompiled.h" #include "precompiled.h"
// Plant the bomb.
/* <5d4160> ../cstrike/dlls/bot/states/cs_bot_plant_bomb.cpp:17 */ /* <5d4160> ../cstrike/dlls/bot/states/cs_bot_plant_bomb.cpp:17 */
NOBODY void PlantBombState::OnEnter(CCSBot *me) void PlantBombState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
// { me->Crouch();
// float yaw; // 25 me->SetDisposition(CCSBot::SELF_DEFENSE);
// class Vector2D dir; // 26
// Vector down; // 28 float yaw = me->pev->v_angle.y;
// GetFeetZ(const class CCSBot *const this); // 28 Vector2D dir(BotCOS(yaw), BotSIN(yaw));
// Vector(Vector *const this,
// float X, Vector down(me->pev->origin.x + 10.0f * dir.x, me->pev->origin.y + 10.0f * dir.y, me->GetFeetZ());
// float Y, me->SetLookAt("Plant bomb on floor", &down, PRIORITY_HIGH);
// float Z); // 28
// }
} }
// Plant the bomb.
/* <5d40d0> ../cstrike/dlls/bot/states/cs_bot_plant_bomb.cpp:36 */ /* <5d40d0> ../cstrike/dlls/bot/states/cs_bot_plant_bomb.cpp:36 */
NOBODY void PlantBombState::OnUpdate(CCSBot *me) void PlantBombState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { CBasePlayerWeapon *gun = me->GetActiveWeapon();
// class CBasePlayerWeapon *gun; // 38 bool holdingC4 = false;
// bool holdingC4; // 39 if (gun != NULL)
// float const timeout; // 59 {
// SetTask(CCSBot *const this, if (FStrEq(STRING(gun->pev->classname), "weapon_c4"))
// enum TaskType task, holdingC4 = true;
// class CBaseEntity *entity); // 54 }
// }
// if we aren't holding the C4, grab it, otherwise plant it
if (holdingC4)
me->PrimaryAttack();
else
me->SelectItem("weapon_c4");
// if we no longer have the C4, we've successfully planted
if (!me->IsCarryingBomb())
{
// move to a hiding spot and watch the bomb
me->SetTask(CCSBot::GUARD_TICKING_BOMB);
me->Hide();
}
// if we time out, it's because we slipped into a non-plantable area
const float timeout = 5.0f;
if (gpGlobals->time - me->GetStateTimestamp() > timeout)
me->Idle();
} }
/* <5d4088> ../cstrike/dlls/bot/states/cs_bot_plant_bomb.cpp:65 */ /* <5d4088> ../cstrike/dlls/bot/states/cs_bot_plant_bomb.cpp:65 */
NOBODY void PlantBombState::OnExit(CCSBot *me) void PlantBombState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
// ClearLookAt(CCSBot *const this); // 72 // equip our rifle (in case we were interrupted while holding C4)
me->EquipBestWeapon();
me->StandUp();
me->ResetStuckMonitor();
me->SetDisposition(CCSBot::ENGAGE_AND_INVESTIGATE);
me->ClearLookAt();
} }
#ifdef HOOK_GAMEDLL
void PlantBombState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void PlantBombState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void PlantBombState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -1,26 +1,68 @@
#include "precompiled.h" #include "precompiled.h"
// Face the entity and "use" it
// NOTE: This state assumes we are standing in range of the entity to be used, with no obstructions.
/* <5e3017> ../cstrike/dlls/bot/states/cs_bot_use_entity.cpp:17 */ /* <5e3017> ../cstrike/dlls/bot/states/cs_bot_use_entity.cpp:17 */
NOBODY void UseEntityState::OnEnter(CCSBot *me) void UseEntityState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{ {
;
} }
/* <5e308c> ../cstrike/dlls/bot/states/cs_bot_use_entity.cpp:21 */ /* <5e308c> ../cstrike/dlls/bot/states/cs_bot_use_entity.cpp:21 */
NOBODY void UseEntityState::OnUpdate(CCSBot *me) void UseEntityState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{ {
// { // in the very rare situation where two or more bots "used" a hostage at the same time,
// float const useTimeout; // 25 // one bot will fail and needs to time out of this state
// Vector pos; // 33 const float useTimeout = 5.0f;
// { if (me->GetStateTimestamp() - gpGlobals->time > useTimeout)
// class CCSBotManager *ctrl; // 39 {
// } me->Idle();
// } return;
// OnUpdate(UseEntityState *const this, }
// class CCSBot *me); // 21
// look at the entity
Vector pos = m_entity->pev->origin + Vector(0, 0, HumanHeight * 0.5f);
me->SetLookAt("Use entity", &pos, PRIORITY_HIGH);
// if we are looking at the entity, "use" it and exit
if (me->IsLookingAtPosition(&pos))
{
if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_RESCUE_HOSTAGES
&& me->m_iTeam == CT
&& me->GetTask() == CCSBot::COLLECT_HOSTAGES)
{
// we are collecting a hostage, assume we were successful - the update check will correct us if we weren't
me->IncreaseHostageEscortCount();
}
me->UseEnvironment();
me->Idle();
}
} }
/* <5e304a> ../cstrike/dlls/bot/states/cs_bot_use_entity.cpp:54 */ /* <5e304a> ../cstrike/dlls/bot/states/cs_bot_use_entity.cpp:54 */
NOBODY void UseEntityState::OnExit(CCSBot *me) void UseEntityState::__MAKE_VHOOK(OnExit)(CCSBot *me)
{ {
// ClearLookAt(CCSBot *const this); // 56 me->ClearLookAt();
me->ResetStuckMonitor();
} }
#ifdef HOOK_GAMEDLL
void UseEntityState::OnEnter(CCSBot *me)
{
OnEnter_(me);
}
void UseEntityState::OnUpdate(CCSBot *me)
{
OnUpdate_(me);
}
void UseEntityState::OnExit(CCSBot *me)
{
OnExit_(me);
}
#endif // HOOK_GAMEDLL

View File

@ -184,17 +184,12 @@ void CCareerTask::OnWeaponKill(int weaponId, int weaponClassId, bool headshot, b
while ((hostageEntity = UTIL_FindEntityByClassname(hostageEntity, "hostage_entity")) != NULL) while ((hostageEntity = UTIL_FindEntityByClassname(hostageEntity, "hostage_entity")) != NULL)
{ {
CHostage *hostage = (CHostage *)hostageEntity; if (hostageEntity->pev->takedamage != DAMAGE_YES)
if (!hostage || hostage->pev->takedamage != DAMAGE_YES)
continue; continue;
if (hostage->m_improv) CHostage *hostage = static_cast<CHostage *>(hostageEntity);
{
if (!hostage->IsFollowingSomeone()) if (!hostage->IsFollowingSomeone())
continue;
}
else if (!hostage->m_hTargetEnt || hostage->m_State != CHostage::FOLLOW)
continue; continue;
if (hostage->IsValid() && hostage->m_target == pAttacker) if (hostage->IsValid() && hostage->m_target == pAttacker)
@ -274,19 +269,10 @@ void CCareerTask::__MAKE_VHOOK(OnEvent)(GameEventType event, CBasePlayer *pVicti
if (hostageEntity->pev->takedamage != DAMAGE_YES) if (hostageEntity->pev->takedamage != DAMAGE_YES)
continue; continue;
CHostage *hostage = reinterpret_cast<CHostage *>(hostageEntity); CHostage *hostage = static_cast<CHostage *>(hostageEntity);
if (hostage->m_improv) if (!hostage->IsFollowingSomeone())
{
if (!hostage->IsFollowingSomeone())
{
continue;
}
}
else if (hostage->m_hTargetEnt == NULL || hostage->m_State != CHostage::FOLLOW)
{
continue; continue;
}
if (hostage->IsValid() && hostage->m_target == pAttacker) if (hostage->IsValid() && hostage->m_target == pAttacker)
++hostages_; ++hostages_;

View File

@ -43,10 +43,7 @@ public:
public: public:
virtual void OnEvent(GameEventType event, CBasePlayer *pAttacker, CBasePlayer *pVictim); virtual void OnEvent(GameEventType event, CBasePlayer *pAttacker, CBasePlayer *pVictim);
virtual void Reset(void); virtual void Reset(void);
virtual bool IsTaskCompletableThisRound(void) virtual bool IsTaskCompletableThisRound(void) { return true; }
{
return true;
}
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -61,26 +58,13 @@ public:
void OnWeaponKill(int weaponId, int weaponClassId, bool headshot, bool killerHasShield, CBasePlayer *pAttacker, CBasePlayer *pVictim); void OnWeaponKill(int weaponId, int weaponClassId, bool headshot, bool killerHasShield, CBasePlayer *pAttacker, CBasePlayer *pVictim);
void OnWeaponInjury(int weaponId, int weaponClassId, bool attackerHasShield, CBasePlayer *pAttacker); void OnWeaponInjury(int weaponId, int weaponClassId, bool attackerHasShield, CBasePlayer *pAttacker);
bool IsComplete(void) bool IsComplete(void) { return m_isComplete;}
{ const char *GetTaskName(void) { return m_name; }
return m_isComplete;
} int GetWeaponId(void) { return m_weaponId; }
const char *GetTaskName(void) int GetWeaponClassId(void) { return m_weaponClassId; }
{
return m_name; bool IsValidFor(CBasePlayer *pPlayer) { return true; }
}
int GetWeaponId(void)
{
return m_weaponId;
}
int GetWeaponClassId(void)
{
return m_weaponClassId;
}
bool IsValidFor(CBasePlayer *pPlayer)
{
return true;
}
void SendPartialNotification(void); void SendPartialNotification(void);
private: private:
@ -102,10 +86,37 @@ private:
};/* size: 44, cachelines: 1, members: 15 */ };/* size: 44, cachelines: 1, members: 15 */
typedef std::list<CCareerTask *> CareerTaskList; typedef std::STD_LIST<CCareerTask *> CareerTaskList;
typedef CareerTaskList::iterator CareerTaskListIt; typedef CareerTaskList::iterator CareerTaskListIt;
typedef CCareerTask *(*TaskFactoryFunction)(const char *taskName, GameEventType event, const char *weaponName, int eventCount, bool mustLive, bool crossRounds, int nextId, bool isComplete);
/* <1ef56d> ../cstrike/dlls/career_tasks.cpp:139 */
class CPreventDefuseTask: public CCareerTask
{
public:
CPreventDefuseTask(const char *taskName, GameEventType event, const char *weaponName, int n, bool mustLive, bool crossRounds, int id, bool isComplete);
public:
virtual void OnEvent(GameEventType event, CBasePlayer *pAttacker, CBasePlayer *pVictim);
virtual void Reset(void);
virtual bool IsTaskCompletableThisRound(void) { return m_bombPlantedThisRound && !m_defuseStartedThisRound; }
#ifdef HOOK_GAMEDLL
void OnEvent_(GameEventType event, CBasePlayer *pAttacker, CBasePlayer *pVictim);
void Reset_(void);
#endif // HOOK_GAMEDLL
public:
static CCareerTask *NewTask(const char *taskName, GameEventType event, const char *weaponName, int n, bool mustLive, bool crossRounds, int id, bool isComplete);
protected:
bool m_bombPlantedThisRound;
bool m_defuseStartedThisRound;
};/* size: 48, cachelines: 1, members: 3 */
/* <1efed1> ../cstrike/dlls/career_tasks.cpp:636 */ /* <1efed1> ../cstrike/dlls/career_tasks.cpp:636 */
class CCareerTaskManager class CCareerTaskManager
{ {
@ -128,32 +139,15 @@ public:
bool AreAllTasksComplete(void); bool AreAllTasksComplete(void);
int GetNumRemainingTasks(void); int GetNumRemainingTasks(void);
float GetRoundElapsedTime(void); float GetRoundElapsedTime(void);
int GetTaskTime(void) int GetTaskTime(void) { return m_taskTime; }
{
return m_taskTime;
}
void SetFinishedTaskTime(int val); void SetFinishedTaskTime(int val);
int GetFinishedTaskTime(void) int GetFinishedTaskTime(void) { return m_finishedTaskTime; }
{ int GetFinishedTaskRound(void) { return m_finishedTaskRound; }
return m_finishedTaskTime; CareerTaskList *GetTasks(void) { return &m_tasks; }
}
int GetFinishedTaskRound(void)
{
return m_finishedTaskRound;
}
CareerTaskList *GetTasks(void)
{
return &m_tasks;
}
void LatchRoundEndMessage(void); void LatchRoundEndMessage(void);
void UnlatchRoundEndMessage(void); void UnlatchRoundEndMessage(void);
private: private:
#if defined(_WIN32) && defined(HOOK_GAMEDLL)
int unknown_padding1;
#endif // HOOK_GAMEDLL
CareerTaskList m_tasks; CareerTaskList m_tasks;
int m_nextId; int m_nextId;
@ -167,8 +161,6 @@ private:
};/* size: 36, cachelines: 1, members: 8 */ };/* size: 36, cachelines: 1, members: 8 */
typedef CCareerTask *(*TaskFactoryFunction)(const char *taskName, GameEventType event, const char *weaponName, int eventCount, bool mustLive, bool crossRounds, int nextId, bool isComplete);
struct TaskInfo struct TaskInfo
{ {
const char *taskName; const char *taskName;
@ -177,35 +169,6 @@ struct TaskInfo
};/* size: 12, cachelines: 1, members: 3 */ };/* size: 12, cachelines: 1, members: 3 */
/* <1ef56d> ../cstrike/dlls/career_tasks.cpp:139 */
class CPreventDefuseTask: public CCareerTask
{
public:
CPreventDefuseTask(const char *taskName, GameEventType event, const char *weaponName, int n, bool mustLive, bool crossRounds, int id, bool isComplete);
public:
virtual void OnEvent(GameEventType event, CBasePlayer *pAttacker, CBasePlayer *pVictim);
virtual void Reset(void);
virtual bool IsTaskCompletableThisRound(void)
{
return m_bombPlantedThisRound && !m_defuseStartedThisRound;
}
#ifdef HOOK_GAMEDLL
void OnEvent_(GameEventType event, CBasePlayer *pAttacker, CBasePlayer *pVictim);
void Reset_(void);
#endif // HOOK_GAMEDLL
public:
static CCareerTask *NewTask(const char *taskName, GameEventType event, const char *weaponName, int n, bool mustLive, bool crossRounds, int id, bool isComplete);
protected:
bool m_bombPlantedThisRound;
bool m_defuseStartedThisRound;
};/* size: 48, cachelines: 1, members: 3 */
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
#define TheCareerTasks (*pTheCareerTasks) #define TheCareerTasks (*pTheCareerTasks)

View File

@ -277,7 +277,7 @@ public:
operator int(); operator int();
operator CBaseEntity*(); operator CBaseEntity*();
operator CBasePlayer*() { return (CBasePlayer *)GET_PRIVATE(Get()); } // custom operator CBasePlayer*() { return static_cast<CBasePlayer *>(GET_PRIVATE(Get())); } // custom
CBaseEntity *operator=(CBaseEntity *pEntity); CBaseEntity *operator=(CBaseEntity *pEntity);
CBaseEntity *operator->(); CBaseEntity *operator->();

View File

@ -711,6 +711,7 @@ void Host_Say(edict_t *pEntity, int teamonly)
char *pszConsoleFormat = NULL; char *pszConsoleFormat = NULL;
bool consoleUsesPlaceName = false; bool consoleUsesPlaceName = false;
// team only
if (teamonly) if (teamonly)
{ {
if (UTIL_IsGame("czero") && (player->m_iTeam == CT || player->m_iTeam == TERRORIST)) if (UTIL_IsGame("czero") && (player->m_iTeam == CT || player->m_iTeam == TERRORIST))
@ -773,6 +774,7 @@ void Host_Say(edict_t *pEntity, int teamonly)
pszConsoleFormat = "(Spectator) %s : %s"; pszConsoleFormat = "(Spectator) %s : %s";
} }
} }
// everyone
else else
{ {
if (bSenderDead) if (bSenderDead)
@ -2006,14 +2008,17 @@ BOOL HandleMenu_ChooseTeam(CBasePlayer *player, int slot)
break; break;
case MENU_SLOT_TEAM_VIP: case MENU_SLOT_TEAM_VIP:
{ {
if (mp->m_iMapHasVIPSafetyZone != MAP_HAVE_VIP_SAFETYZONE_YES || player->m_iTeam != CT) if (mp->m_iMapHasVIPSafetyZone == MAP_HAVE_VIP_SAFETYZONE_YES && player->m_iTeam == CT)
{
mp->AddToVIPQueue(player);
CLIENT_COMMAND(ENT(player->pev), "slot10\n");
return TRUE;
}
else
{ {
return FALSE; return FALSE;
} }
break;
mp->AddToVIPQueue(player);
CLIENT_COMMAND(ENT(player->pev), "slot10\n");
return TRUE;
} }
case MENU_SLOT_TEAM_RANDOM: case MENU_SLOT_TEAM_RANDOM:
{ {
@ -2198,6 +2203,7 @@ BOOL HandleMenu_ChooseTeam(CBasePlayer *player, int slot)
} }
} }
// If we already died and changed teams once, deny
if (player->m_bTeamChanged) if (player->m_bTeamChanged)
{ {
if (player->pev->deadflag != DEAD_NO) if (player->pev->deadflag != DEAD_NO)
@ -4504,6 +4510,20 @@ void ClientPrecache(void)
PRECACHE_GENERIC("sprites/scope_arc_sw.tga"); PRECACHE_GENERIC("sprites/scope_arc_sw.tga");
m_usResetDecals = g_engfuncs.pfnPrecacheEvent(1, "events/decal_reset.sc"); m_usResetDecals = g_engfuncs.pfnPrecacheEvent(1, "events/decal_reset.sc");
/*Vector temp = g_vecZero;
ENGINE_FORCE_UNMODIFIED(force_exactfile, (float *)&temp, (float *)&temp, "sprites/scope_arc.tga");
ENGINE_FORCE_UNMODIFIED(force_exactfile, (float *)&temp, (float *)&temp, "sprites/scope_arc_nw.tga");
ENGINE_FORCE_UNMODIFIED(force_exactfile, (float *)&temp, (float *)&temp, "sprites/scope_arc_ne.tga");
ENGINE_FORCE_UNMODIFIED(force_exactfile, (float *)&temp, (float *)&temp, "sprites/scope_arc_sw.tga");
PRECACHE_GENERIC("sprites/scope_arc.tga");
PRECACHE_GENERIC("sprites/scope_arc_nw.tga");
PRECACHE_GENERIC("sprites/scope_arc_ne.tga");
PRECACHE_GENERIC("sprites/scope_arc_sw.tga");
m_usResetDecals = g_engfuncs.pfnPrecacheEvent(1, "events/decal_reset.sc");*/
} }
/* <4a6e5> ../cstrike/dlls/client.cpp:4996 */ /* <4a6e5> ../cstrike/dlls/client.cpp:4996 */

View File

@ -362,7 +362,7 @@ Activity CBaseMonster::__MAKE_VHOOK(GetDeathActivity)(void)
} }
// can we perform the prescribed death? // can we perform the prescribed death?
if (LookupActivity(deathActivity) == ACTIVITY_NOT_AVAILABLE) if (LookupActivity(deathActivity) == ACT_INVALID)
{ {
// no! did we fail to perform a directional death? // no! did we fail to perform a directional death?
if (fTriedDirection) if (fTriedDirection)
@ -384,7 +384,7 @@ Activity CBaseMonster::__MAKE_VHOOK(GetDeathActivity)(void)
} }
} }
if (LookupActivity(deathActivity) == ACTIVITY_NOT_AVAILABLE) if (LookupActivity(deathActivity) == ACT_INVALID)
{ {
// if we're still invalid, simple is our only option. // if we're still invalid, simple is our only option.
deathActivity = ACT_DIESIMPLE; deathActivity = ACT_DIESIMPLE;
@ -458,7 +458,7 @@ NOXREF Activity CBaseMonster::GetSmallFlinchActivity(void)
} }
// do we have a sequence for the ideal activity? // do we have a sequence for the ideal activity?
if (LookupActivity(flinchActivity) == ACTIVITY_NOT_AVAILABLE) if (LookupActivity(flinchActivity) == ACT_INVALID)
{ {
flinchActivity = ACT_SMALL_FLINCH; flinchActivity = ACT_SMALL_FLINCH;
} }

View File

@ -38,8 +38,10 @@ BOOL CGameRules::__MAKE_VHOOK(CanHaveAmmo)(CBasePlayer *pPlayer, const char *psz
/* <ad89d> ../cstrike/dlls/gamerules.cpp:59 */ /* <ad89d> ../cstrike/dlls/gamerules.cpp:59 */
edict_t *CGameRules::__MAKE_VHOOK(GetPlayerSpawnSpot)(CBasePlayer *pPlayer) edict_t *CGameRules::__MAKE_VHOOK(GetPlayerSpawnSpot)(CBasePlayer *pPlayer)
{ {
// gat valid spawn point
edict_t *pentSpawnSpot = EntSelectSpawnPoint(pPlayer); edict_t *pentSpawnSpot = EntSelectSpawnPoint(pPlayer);
// Move the player to the place it said.
#ifndef PLAY_GAMEDLL #ifndef PLAY_GAMEDLL
pPlayer->pev->origin = VARS(pentSpawnSpot)->origin + Vector(0, 0, 1); pPlayer->pev->origin = VARS(pentSpawnSpot)->origin + Vector(0, 0, 1);
#else #else

View File

@ -64,6 +64,9 @@
#define MAX_MOTD_LENGTH 1536 // (MAX_MOTD_CHUNK * 4) #define MAX_MOTD_LENGTH 1536 // (MAX_MOTD_CHUNK * 4)
// custom enum // custom enum
#define WINNER_NONE 0
#define WINNER_DRAW 1
enum enum
{ {
WINSTATUS_CTS = 1, WINSTATUS_CTS = 1,
@ -187,10 +190,7 @@ public:
return FALSE; return FALSE;
} }
virtual BOOL IsCoOp(void) = 0; virtual BOOL IsCoOp(void) = 0;
virtual const char *GetGameDescription(void) virtual const char *GetGameDescription(void) { return "Counter-Strike"; } // this is the game name that gets seen in the server browser
{
return "Counter-Strike";
}
virtual BOOL ClientConnected(edict_t *pEntity, const char *pszName, const char *pszAddress, char *szRejectReason) = 0; virtual BOOL ClientConnected(edict_t *pEntity, const char *pszName, const char *pszAddress, char *szRejectReason) = 0;
virtual void InitHUD(CBasePlayer *pl) = 0; virtual void InitHUD(CBasePlayer *pl) = 0;
virtual void ClientDisconnected(edict_t *pClient) = 0; virtual void ClientDisconnected(edict_t *pClient) = 0;
@ -473,6 +473,8 @@ public:
virtual void CleanUpMap(void); virtual void CleanUpMap(void);
virtual void RestartRound(void); virtual void RestartRound(void);
// check if the scenario has been won/lost
virtual void CheckWinConditions(void); virtual void CheckWinConditions(void);
virtual void RemoveGuns(void); virtual void RemoveGuns(void);
virtual void GiveC4(void); virtual void GiveC4(void);

View File

@ -130,6 +130,7 @@ void CGrenade::Explode2(TraceResult *pTrace, int bitsDamageType)
m_bJustBlew = true; m_bJustBlew = true;
mp->CheckWinConditions(); mp->CheckWinConditions();
// Pull out of the wall a bit
if (pTrace->flFraction != 1.0f) if (pTrace->flFraction != 1.0f)
{ {
pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * (pev->dmg - 24) * 0.6); pev->origin = pTrace->vecEndPos + (pTrace->vecPlaneNormal * (pev->dmg - 24) * 0.6);
@ -177,6 +178,7 @@ void CGrenade::Explode2(TraceResult *pTrace, int bitsDamageType)
WRITE_BYTE(17); WRITE_BYTE(17);
MESSAGE_END(); MESSAGE_END();
// Sound! for everyone
EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/c4_explode1.wav", VOL_NORM, 0.25); EMIT_SOUND(ENT(pev), CHAN_WEAPON, "weapons/c4_explode1.wav", VOL_NORM, 0.25);
CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3); CSoundEnt::InsertSound(bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3);
@ -198,14 +200,16 @@ void CGrenade::Explode2(TraceResult *pTrace, int bitsDamageType)
} }
// tell director about it // tell director about it
// send director message, that something important happed here
MESSAGE_BEGIN(MSG_SPEC, SVC_DIRECTOR); MESSAGE_BEGIN(MSG_SPEC, SVC_DIRECTOR);
WRITE_BYTE(9); // command length in bytes WRITE_BYTE(9); // command length in bytes
WRITE_BYTE(DRC_CMD_EVENT); // explode event WRITE_BYTE(DRC_CMD_EVENT); // bomb explode
WRITE_SHORT(ENTINDEX(edict())); // index number of primary entity WRITE_SHORT(ENTINDEX(edict())); // index number of primary entity
WRITE_SHORT(0); // index number of secondary entity WRITE_SHORT(0); // index number of secondary entity
WRITE_LONG(15 | DRC_FLAG_FINAL); // eventflags (priority and flags) WRITE_LONG(15 | DRC_FLAG_FINAL); // eventflags (priority and flags)
MESSAGE_END(); MESSAGE_END();
// Decal!
if (RANDOM_FLOAT(0, 1) < 0.5) if (RANDOM_FLOAT(0, 1) < 0.5)
UTIL_DecalTrace(pTrace, DECAL_SCORCH1); UTIL_DecalTrace(pTrace, DECAL_SCORCH1);
else else
@ -984,6 +988,7 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
CBasePlayer *player = GetClassPtr((CBasePlayer *)pActivator->pev); CBasePlayer *player = GetClassPtr((CBasePlayer *)pActivator->pev);
// For CTs to defuse the c4
if (player->m_iTeam != CT) if (player->m_iTeam != CT)
{ {
return; return;
@ -991,16 +996,18 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
if (m_bStartDefuse) if (m_bStartDefuse)
{ {
m_fNextDefuse = gpGlobals->time + 0.5; m_fNextDefuse = gpGlobals->time + 0.5f;
return; return;
} }
// freeze the player in place while defusing
SET_CLIENT_MAXSPEED(player->edict(), 1); SET_CLIENT_MAXSPEED(player->edict(), 1);
if (TheBots != NULL) if (TheBots != NULL)
{ {
TheBots->OnEvent(EVENT_BOMB_DEFUSING, pActivator); TheBots->OnEvent(EVENT_BOMB_DEFUSING, pActivator);
} }
if (g_pGameRules->IsCareer()) if (g_pGameRules->IsCareer())
{ {
if (TheCareerTasks != NULL) if (TheCareerTasks != NULL)
@ -1011,14 +1018,12 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
if (player->m_bHasDefuser) if (player->m_bHasDefuser)
{ {
UTIL_LogPrintf UTIL_LogPrintf("\"%s<%i><%s><CT>\" triggered \"Begin_Bomb_Defuse_With_Kit\"\n",
(
"\"%s<%i><%s><CT>\" triggered \"Begin_Bomb_Defuse_With_Kit\"\n",
STRING(player->pev->netname), STRING(player->pev->netname),
GETPLAYERUSERID(player->edict()), GETPLAYERUSERID(player->edict()),
GETPLAYERAUTHID(player->edict()) GETPLAYERAUTHID(player->edict()));
);
// TODO show messages on clients on event
ClientPrint(player->pev, HUD_PRINTCENTER, "#Defusing_Bomb_With_Defuse_Kit"); ClientPrint(player->pev, HUD_PRINTCENTER, "#Defusing_Bomb_With_Defuse_Kit");
EMIT_SOUND(ENT(player->pev), CHAN_ITEM, "weapons/c4_disarm.wav", VOL_NORM, ATTN_NORM); EMIT_SOUND(ENT(player->pev), CHAN_ITEM, "weapons/c4_disarm.wav", VOL_NORM, ATTN_NORM);
@ -1027,6 +1032,8 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
m_bStartDefuse = true; m_bStartDefuse = true;
m_flDefuseCountDown = gpGlobals->time + 5; m_flDefuseCountDown = gpGlobals->time + 5;
m_fNextDefuse = gpGlobals->time + 0.5; m_fNextDefuse = gpGlobals->time + 0.5;
// start the progress bar
player->SetProgressBarTime(5); player->SetProgressBarTime(5);
} }
else else
@ -1036,6 +1043,7 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
GETPLAYERUSERID(player->edict()), GETPLAYERUSERID(player->edict()),
GETPLAYERAUTHID(player->edict())); GETPLAYERAUTHID(player->edict()));
// TODO show messages on clients on event
ClientPrint(player->pev, HUD_PRINTCENTER, "#Defusing_Bomb_Without_Defuse_Kit"); ClientPrint(player->pev, HUD_PRINTCENTER, "#Defusing_Bomb_Without_Defuse_Kit");
EMIT_SOUND(ENT(player->pev), CHAN_ITEM, "weapons/c4_disarm.wav", VOL_NORM, ATTN_NORM); EMIT_SOUND(ENT(player->pev), CHAN_ITEM, "weapons/c4_disarm.wav", VOL_NORM, ATTN_NORM);
@ -1044,6 +1052,8 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
m_bStartDefuse = true; m_bStartDefuse = true;
m_flDefuseCountDown = gpGlobals->time + 10; m_flDefuseCountDown = gpGlobals->time + 10;
m_fNextDefuse = gpGlobals->time + 0.5; m_fNextDefuse = gpGlobals->time + 0.5;
// start the progress bar
player->SetProgressBarTime(10); player->SetProgressBarTime(10);
} }
} }
@ -1208,14 +1218,17 @@ void CGrenade::C4Think(void)
AnnounceFlashInterval(20); AnnounceFlashInterval(20);
break; break;
} }
++m_iCurWave; ++m_iCurWave;
} }
if (gpGlobals->time >= m_flNextBeep) if (gpGlobals->time >= m_flNextBeep)
{ {
m_flNextBeep = gpGlobals->time + 1.4; m_flNextBeep = gpGlobals->time + 1.4f;
EMIT_SOUND(ENT(pev), CHAN_VOICE, m_sBeepName, VOL_NORM, m_fAttenu); EMIT_SOUND(ENT(pev), CHAN_VOICE, m_sBeepName, VOL_NORM, m_fAttenu);
// let the bots hear the bomb beeping
// BOTPORT: Emit beep events at same time as client effects
if (TheBots != NULL) if (TheBots != NULL)
{ {
TheBots->OnEvent(EVENT_BOMB_BEEP, this); TheBots->OnEvent(EVENT_BOMB_BEEP, this);
@ -1238,6 +1251,7 @@ void CGrenade::C4Think(void)
MESSAGE_END(); MESSAGE_END();
} }
// If the timer has expired ! blow this bomb up!
if (gpGlobals->time >= m_flC4Blow) if (gpGlobals->time >= m_flC4Blow)
{ {
if (TheBots != NULL) if (TheBots != NULL)
@ -1260,7 +1274,7 @@ void CGrenade::C4Think(void)
} }
CBasePlayer *pBombOwner = (CBasePlayer *)CBaseEntity::Instance(pev->owner); CBasePlayer *pBombOwner = (CBasePlayer *)CBaseEntity::Instance(pev->owner);
if (pBombOwner) if (pBombOwner != NULL)
{ {
pBombOwner->pev->frags += 3; pBombOwner->pev->frags += 3;
} }
@ -1276,14 +1290,17 @@ void CGrenade::C4Think(void)
SetThink(&CGrenade::Detonate2); SetThink(&CGrenade::Detonate2);
} }
if (m_bStartDefuse) // if the defusing process has started
if (m_bStartDefuse && m_pBombDefuser != NULL)
{ {
CBasePlayer *pPlayer = (CBasePlayer *)((CBaseEntity *)m_pBombDefuser); CBasePlayer *pPlayer = (CBasePlayer *)m_pBombDefuser;
if (pPlayer != NULL && gpGlobals->time < m_flDefuseCountDown) // if the defusing process has not ended yet
if (gpGlobals->time < m_flDefuseCountDown)
{ {
int iOnGround = ((m_pBombDefuser->pev->flags & FL_ONGROUND) == FL_ONGROUND); int iOnGround = ((m_pBombDefuser->pev->flags & FL_ONGROUND) == FL_ONGROUND);
// if the bomb defuser has stopped defusing the bomb
if (gpGlobals->time > m_fNextDefuse || !iOnGround) if (gpGlobals->time > m_fNextDefuse || !iOnGround)
{ {
if (!iOnGround) if (!iOnGround)
@ -1291,92 +1308,95 @@ void CGrenade::C4Think(void)
ClientPrint(m_pBombDefuser->pev, HUD_PRINTCENTER, "#C4_Defuse_Must_Be_On_Ground"); ClientPrint(m_pBombDefuser->pev, HUD_PRINTCENTER, "#C4_Defuse_Must_Be_On_Ground");
} }
// release the player from being frozen
pPlayer->ResetMaxSpeed(); pPlayer->ResetMaxSpeed();
pPlayer->m_bIsDefusing = false; pPlayer->m_bIsDefusing = false;
pPlayer->SetProgressBarTime(0);
// cancel the progress bar
pPlayer->SetProgressBarTime(0);
m_pBombDefuser = NULL; m_pBombDefuser = NULL;
m_bStartDefuse = false; m_bStartDefuse = false;
m_flDefuseCountDown = 0; m_flDefuseCountDown = 0;
// tell the bots someone has aborted defusing
if (TheBots != NULL) if (TheBots != NULL)
{ {
TheBots->OnEvent(EVENT_BOMB_DEFUSE_ABORTED); TheBots->OnEvent(EVENT_BOMB_DEFUSE_ABORTED);
} }
} }
} }
// if the defuse process has ended, kill the c4
else if (m_pBombDefuser->pev->deadflag == DEAD_NO)
{
Broadcast("BOMBDEF");
if (TheBots != NULL)
{
TheBots->OnEvent(EVENT_BOMB_DEFUSED, (CBaseEntity *)m_pBombDefuser);
}
MESSAGE_BEGIN(MSG_SPEC, SVC_DIRECTOR);
WRITE_BYTE(9);
WRITE_BYTE(DRC_CMD_EVENT);
WRITE_SHORT(ENTINDEX(m_pBombDefuser->edict()));
WRITE_SHORT(0);
WRITE_LONG(15 | DRC_FLAG_FINAL | DRC_FLAG_FACEPLAYER | DRC_FLAG_DRAMATIC);
MESSAGE_END();
UTIL_LogPrintf("\"%s<%i><%s><CT>\" triggered \"Defused_The_Bomb\"\n",
STRING(m_pBombDefuser->pev->netname),
GETPLAYERUSERID(m_pBombDefuser->edict()),
GETPLAYERAUTHID(m_pBombDefuser->edict()));
UTIL_EmitAmbientSound(ENT(pev), pev->origin, "weapons/c4_beep5.wav", 0, ATTN_NONE, SND_STOP, 0);
EMIT_SOUND(ENT(m_pBombDefuser->pev), CHAN_WEAPON, "weapons/c4_disarmed.wav", VOL_NORM, ATTN_NORM);
UTIL_Remove(this);
m_bJustBlew = true;
// release the player from being frozen
pPlayer->ResetMaxSpeed();
pPlayer->m_bIsDefusing = false;
MESSAGE_BEGIN(MSG_ALL, gmsgScenarioIcon);
WRITE_BYTE(0);
MESSAGE_END();
if (g_pGameRules->IsCareer() && !pPlayer->IsBot())
{
if (TheCareerTasks != NULL)
{
TheCareerTasks->HandleEvent(EVENT_BOMB_DEFUSED, pPlayer);
}
}
g_pGameRules->m_bBombDefused = true;
g_pGameRules->CheckWinConditions();
// give the defuser credit for defusing the bomb
m_pBombDefuser->pev->frags += 3;
MESSAGE_BEGIN(MSG_ALL, gmsgBombPickup);
MESSAGE_END();
g_pGameRules->m_bBombDropped = FALSE;
m_pBombDefuser = NULL;
m_bStartDefuse = false;
}
else else
{ {
if (pPlayer != NULL && m_pBombDefuser->pev->deadflag == DEAD_NO) // if it gets here then the previouse defuser has taken off or been killed
// release the player from being frozen
pPlayer->ResetMaxSpeed();
pPlayer->m_bIsDefusing = false;
m_bStartDefuse = false;
m_pBombDefuser = NULL;
// tell the bots someone has aborted defusing
if (TheBots != NULL)
{ {
Broadcast("BOMBDEF"); TheBots->OnEvent(EVENT_BOMB_DEFUSE_ABORTED);
if (TheBots != NULL)
{
TheBots->OnEvent(EVENT_BOMB_DEFUSED, (CBaseEntity *)m_pBombDefuser);
}
MESSAGE_BEGIN(MSG_SPEC, SVC_DIRECTOR);
WRITE_BYTE(9);
WRITE_BYTE(DRC_CMD_EVENT);
WRITE_SHORT(ENTINDEX(m_pBombDefuser->edict()));
WRITE_SHORT(0);
WRITE_LONG(15 | DRC_FLAG_FINAL | DRC_FLAG_FACEPLAYER | DRC_FLAG_DRAMATIC);
MESSAGE_END();
UTIL_LogPrintf("\"%s<%i><%s><CT>\" triggered \"Defused_The_Bomb\"\n",
STRING(m_pBombDefuser->pev->netname),
GETPLAYERUSERID(m_pBombDefuser->edict()),
GETPLAYERAUTHID(m_pBombDefuser->edict()));
UTIL_EmitAmbientSound(ENT(pev), pev->origin, "weapons/c4_beep5.wav", 0, ATTN_NONE, SND_STOP, 0);
EMIT_SOUND(ENT(m_pBombDefuser->pev), CHAN_WEAPON, "weapons/c4_disarmed.wav", VOL_NORM, ATTN_NORM);
UTIL_Remove(this);
m_bJustBlew = true;
pPlayer->ResetMaxSpeed();
pPlayer->m_bIsDefusing = false;
MESSAGE_BEGIN(MSG_ALL, gmsgScenarioIcon);
WRITE_BYTE(0);
MESSAGE_END();
if (g_pGameRules->IsCareer() && !pPlayer->IsBot())
{
if (TheCareerTasks != NULL)
{
TheCareerTasks->HandleEvent(EVENT_BOMB_DEFUSED, pPlayer);
}
}
g_pGameRules->m_bBombDefused = true;
g_pGameRules->CheckWinConditions();
m_pBombDefuser->pev->frags += 3;
MESSAGE_BEGIN(MSG_ALL, gmsgBombPickup);
MESSAGE_END();
g_pGameRules->m_bBombDropped = FALSE;
m_pBombDefuser = NULL;
m_bStartDefuse = false;
}
else
{
if (pPlayer != NULL)
{
pPlayer->ResetMaxSpeed();
pPlayer->m_bIsDefusing = false;
}
m_bStartDefuse = false;
m_pBombDefuser = NULL;
if (TheBots != NULL)
{
TheBots->OnEvent(EVENT_BOMB_DEFUSE_ABORTED);
}
} }
} }
} }

View File

@ -253,17 +253,13 @@ void CHostage::IdleThink(void)
if (m_improv != NULL) if (m_improv != NULL)
{ {
if (IsFollowingSomeone()) if (m_improv->IsFollowing())
{
player = (CBasePlayer *)m_improv->GetFollowLeader(); player = (CBasePlayer *)m_improv->GetFollowLeader();
}
} }
else else
{
player = GetClassPtr((CBasePlayer *)m_hTargetEnt->pev); player = GetClassPtr((CBasePlayer *)m_hTargetEnt->pev);
}
if (!player || player->m_iTeam == CT) if (player == NULL || player->m_iTeam == CT)
{ {
if (!g_pGameRules->m_bMapHasRescueZone) if (!g_pGameRules->m_bMapHasRescueZone)
{ {
@ -924,18 +920,7 @@ void CHostage::DoFollow(void)
} }
else if (pev->takedamage == DAMAGE_YES) else if (pev->takedamage == DAMAGE_YES)
{ {
if (m_improv != NULL) if (IsFollowingSomeone())
{
if (IsFollowingSomeone())
{
if (!m_bStuck && flDistToDest > 200)
{
m_bStuck = TRUE;
m_flStuckTime = gpGlobals->time;
}
}
}
else if (m_hTargetEnt != NULL && m_State == FOLLOW)
{ {
if (!m_bStuck && flDistToDest > 200) if (!m_bStuck && flDistToDest > 200)
{ {
@ -1498,7 +1483,6 @@ bool CHostageManager::IsNearbyHostageJumping(CHostageImprov *improv)
{ {
for (int i = 0; i < m_hostageCount; i++) for (int i = 0; i < m_hostageCount; i++)
{ {
const float closeRange = 500.0f;
const CHostageImprov *other = m_hostage[i]->m_improv; const CHostageImprov *other = m_hostage[i]->m_improv;
if (other == NULL) if (other == NULL)
@ -1507,6 +1491,7 @@ bool CHostageManager::IsNearbyHostageJumping(CHostageImprov *improv)
if (!other->IsAlive() || other == improv) if (!other->IsAlive() || other == improv)
continue; continue;
const float closeRange = 500.0f;
if (!(improv->GetCentroid() - other->GetCentroid()).IsLengthGreaterThan(closeRange) && other->IsJumping()) if (!(improv->GetCentroid() - other->GetCentroid()).IsLengthGreaterThan(closeRange) && other->IsJumping())
{ {
return true; return true;

View File

@ -95,13 +95,15 @@ extern int g_iHostageNumber;
extern cvar_t cv_hostage_debug; extern cvar_t cv_hostage_debug;
extern cvar_t cv_hostage_stop; extern cvar_t cv_hostage_stop;
// A Counter-Strike Hostage Simple
/* <4858e5> ../cstrike/dlls/hostage/hostage.h:32 */ /* <4858e5> ../cstrike/dlls/hostage/hostage.h:32 */
class CHostage: public CBaseMonster class CHostage: public CBaseMonster
{ {
public: public:
virtual void Spawn(void); virtual void Spawn(void);
virtual void Precache(void); virtual void Precache(void);
virtual int ObjectCaps(void); virtual int ObjectCaps(void); // make hostage "useable"
virtual int Classify(void) virtual int Classify(void)
{ {
return CLASS_HUMAN_PASSIVE; return CLASS_HUMAN_PASSIVE;
@ -152,22 +154,34 @@ public:
void Wiggle(void); void Wiggle(void);
void PreThink(void); void PreThink(void);
// queries
bool IsFollowingSomeone(void) bool IsFollowingSomeone(void)
{ {
return m_improv->IsFollowing(); return IsFollowing();
} }
CBaseEntity *GetLeader(void) CBaseEntity *GetLeader(void) // return our leader, or NULL
{ {
if (m_improv != NULL) if (m_improv != NULL)
{ {
return m_improv->GetFollowLeader(); return m_improv->GetFollowLeader();
} }
return NULL; return m_hTargetEnt;
} }
bool IsFollowing(const CBaseEntity *entity) bool IsFollowing(const CBaseEntity *entity = NULL)
{ {
return (entity == m_hTargetEnt && m_State == FOLLOW); if (m_improv != NULL)
{
return m_improv->IsFollowing();
}
if (entity == NULL && m_hTargetEnt == NULL || (entity != NULL && m_hTargetEnt != entity))
return false;
if (m_State != FOLLOW)
return false;
return true;
} }
bool IsValid(void) bool IsValid(void)
{ {
@ -187,24 +201,6 @@ public:
} }
public: public:
enum state
{
FOLLOW = 0,
STAND,
DUCK,
SCARED,
IDLE,
FOLLOWPATH,
};
enum ModelType
{
REGULAR_GUY = 0,
OLD_GUY,
BLACK_GUY,
GOOFY_GUY,
};
int m_Activity; int m_Activity;
BOOL m_bTouched; BOOL m_bTouched;
BOOL m_bRescueMe; BOOL m_bRescueMe;
@ -214,7 +210,8 @@ public:
int m_iModel; int m_iModel;
int m_iSkin; int m_iSkin;
float m_flNextRadarTime; float m_flNextRadarTime;
state m_State; enum state { FOLLOW, STAND, DUCK, SCARED, IDLE, FOLLOWPATH }
m_State;
Vector m_vStart; Vector m_vStart;
Vector m_vStartAngles; Vector m_vStartAngles;
Vector m_vPathToFollow[20]; Vector m_vPathToFollow[20];
@ -235,7 +232,9 @@ public:
BOOL m_bStuck; BOOL m_bStuck;
float m_flStuckTime; float m_flStuckTime;
CHostageImprov *m_improv; CHostageImprov *m_improv;
ModelType m_whichModel;
enum ModelType { REGULAR_GUY, OLD_GUY, BLACK_GUY, GOOFY_GUY }
m_whichModel;
};/* size: 1988, cachelines: 32, members: 32 */ };/* size: 1988, cachelines: 32, members: 32 */
@ -294,6 +293,25 @@ public:
bool IsNearbyHostageTalking(CHostageImprov *improv); bool IsNearbyHostageTalking(CHostageImprov *improv);
bool IsNearbyHostageJumping(CHostageImprov *improv); bool IsNearbyHostageJumping(CHostageImprov *improv);
void OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other); void OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other);
// Iterate over all active hostages in the game, invoking functor on each.
// If functor returns false, stop iteration and return false.
template<typename Functor>
inline bool ForEachHostage(Functor &func) const
{
for (int i = 0; i < m_hostageCount; i++)
{
CHostage *hostage = m_hostage[i];
if (hostage == NULL || hostage->pev->deadflag == DEAD_DEAD)
continue;
if (func(hostage) == false)
return false;
}
return true;
}
inline CHostage *GetClosestHostage(const Vector &pos, float *resultRange = NULL) inline CHostage *GetClosestHostage(const Vector &pos, float *resultRange = NULL)
{ {
float range; float range;
@ -317,23 +335,6 @@ public:
return close; return close;
} }
template<typename T>
bool ForEachHostage(T &func) const
{
for (int i = 0; i < m_hostageCount; i++)
{
CHostage *pHostage = m_hostage[ i ];
if (pHostage->pev->deadflag == DEAD_DEAD)
continue;
if (func(pHostage) == false)
return false;
}
return true;
}
private: private:
CHostage *m_hostage[ MAX_HOSTAGES ]; CHostage *m_hostage[ MAX_HOSTAGES ];
int m_hostageCount; int m_hostageCount;
@ -341,43 +342,18 @@ private:
};/* size: 5680, cachelines: 89, members: 3 */ };/* size: 5680, cachelines: 89, members: 3 */
///* <470134> ../cstrike/dlls/hostage/hostage.h:293 */
//inline void CHostageManager::ForEachHostage<KeepPersonalSpace>(KeepPersonalSpace &func)
//{
//// {
//// int i; // 295
//// }
//}
//
///* <46fbe8> ../cstrike/dlls/hostage/hostage.h:293 */
//inline void CHostageManager::ForEachHostage<CheckAhead>(CheckAhead &func)
//{
//// {
//// int i; // 295
//// }
//}
//
///* <46fb04> ../cstrike/dlls/hostage/hostage.h:293 */
//inline void CHostageManager::ForEachHostage<CheckWayFunctor>(CheckWayFunctor &func)
//{
//// {
//// int i; // 295
//// }
//}
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
// linked object // linked object
C_DLLEXPORT void hostage_entity(entvars_t *pev); C_DLLEXPORT void hostage_entity(entvars_t *pev);
C_DLLEXPORT void monster_scientist(entvars_t *pev); C_DLLEXPORT void monster_scientist(entvars_t *pev);
// refs
extern void (CBaseEntity::*pCHostage__IdleThink)(void);
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
void Hostage_RegisterCVars(void); void Hostage_RegisterCVars(void);
void InstallHostageManager(void); void InstallHostageManager(void);
// refs
extern void (CBaseEntity::*pCHostage__IdleThink)(void);
#endif // HOSTAGE_H #endif // HOSTAGE_H

View File

@ -275,7 +275,7 @@ void CHostageImprov::FaceOutwards(void)
float farthestRange = 0.0f; float farthestRange = 0.0f;
int farthest = 0; int farthest = 0;
Vector corner[] = static Vector corner[] =
{ {
Vector(-1000, 1000, 0), Vector(-1000, 1000, 0),
Vector(1000, 1000, 0), Vector(1000, 1000, 0),
@ -1536,7 +1536,7 @@ CBasePlayer *CHostageImprov::GetClosestVisiblePlayer(int team)
for (int i = 0; i < m_visiblePlayerCount; i++) for (int i = 0; i < m_visiblePlayerCount; i++)
{ {
CBasePlayer *player = (CBasePlayer *)((CBaseEntity *)m_visiblePlayer[i]); CBasePlayer *player = (CBasePlayer *)m_visiblePlayer[i];
if (player == NULL || (team > 0 && player->m_iTeam != team)) if (player == NULL || (team > 0 && player->m_iTeam != team))
continue; continue;
@ -1784,6 +1784,8 @@ void CHostageImprov::Wave(void)
m_animateState.AddSequence(this, ACT_WAVE); m_animateState.AddSequence(this, ACT_WAVE);
} }
// Invoked when an improv fails to reach a MoveTo goal
/* <474938> ../cstrike/dlls/hostage/hostage_improv.cpp:2375 */ /* <474938> ../cstrike/dlls/hostage/hostage_improv.cpp:2375 */
void CHostageImprov::__MAKE_VHOOK(OnMoveToFailure)(const Vector &goal, MoveToFailureType reason) void CHostageImprov::__MAKE_VHOOK(OnMoveToFailure)(const Vector &goal, MoveToFailureType reason)
{ {
@ -1798,12 +1800,6 @@ void CHostageImprov::__MAKE_VHOOK(OnMoveToFailure)(const Vector &goal, MoveToFai
/* <4763d7> ../cstrike/dlls/hostage/hostage_improv.cpp:2391 */ /* <4763d7> ../cstrike/dlls/hostage/hostage_improv.cpp:2391 */
void CHostageImprov::Wiggle(void) void CHostageImprov::Wiggle(void)
{ {
Vector dir;
Vector lat;
const float force = 15.0f;
const float minStuckJumpTime = 0.5f;
// for wiggling // for wiggling
if (m_wiggleTimer.IsElapsed()) if (m_wiggleTimer.IsElapsed())
{ {
@ -1811,45 +1807,34 @@ void CHostageImprov::Wiggle(void)
m_wiggleTimer.Start(RANDOM_FLOAT(0.3, 0.5)); m_wiggleTimer.Start(RANDOM_FLOAT(0.3, 0.5));
} }
lat.x = BotCOS(m_moveAngle); const float force = 15.0f;
lat.y = BotSIN(m_moveAngle); Vector dir(BotCOS(m_moveAngle), BotSIN(m_moveAngle), 0.0f);
lat.z = 0; Vector lat(-dir.y, dir.x, 0.0f);
switch (m_wiggleDirection) switch (m_wiggleDirection)
{ {
case FORWARD: case FORWARD:
dir.x = lat.x;
dir.y = lat.y;
ApplyForce(dir * force); ApplyForce(dir * force);
break; break;
case RIGHT:
dir.x = -lat.y;
dir.y = lat.x;
ApplyForce(dir * -force);
break;
case BACKWARD: case BACKWARD:
dir.x = lat.x;
dir.y = lat.y;
ApplyForce(dir * -force); ApplyForce(dir * -force);
break; break;
case LEFT: case LEFT:
dir.x = -lat.y; ApplyForce(lat * force);
dir.y = lat.x; break;
case RIGHT:
ApplyForce(dir * force); ApplyForce(lat * -force);
break; break;
default: default:
break; break;
} }
const float minStuckJumpTime = 0.5f;
if (m_follower.GetStuckDuration() > minStuckJumpTime && m_wiggleJumpTimer.IsElapsed()) if (m_follower.GetStuckDuration() > minStuckJumpTime && m_wiggleJumpTimer.IsElapsed())
{ {
if (Jump()) if (Jump())
{ {
m_wiggleJumpTimer.Start(RANDOM_FLOAT(0.75, 1.2)); m_wiggleJumpTimer.Start(RANDOM_FLOAT(0.75f, 1.2f));
} }
} }
} }

View File

@ -38,21 +38,21 @@
class CHostage; class CHostage;
enum HostageChatterType; enum HostageChatterType;
// A Counter-Strike Hostage improved
class CHostageImprov: public CImprov class CHostageImprov: public CImprov
{ {
public: public:
CHostageImprov(CBaseEntity *entity); CHostageImprov(CBaseEntity *entity);
~CHostageImprov(void) {}; ~CHostageImprov(void) {};
virtual void OnMoveToSuccess(const Vector &goal) // invoked when an improv reaches its MoveTo goal
{ virtual void OnMoveToSuccess(const Vector &goal) { m_behavior.OnMoveToSuccess(goal); }
m_behavior.OnMoveToSuccess(goal);
} // invoked when an improv fails to reach a MoveTo goal
virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason); virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason);
virtual void OnInjury(float amount) virtual void OnInjury(float amount)
{ {
m_behavior.OnInjury(amount); m_behavior.OnInjury(amount);
m_lastInjuryTimer.Start(); m_lastInjuryTimer.Start();
Frighten(TERRIFIED); Frighten(TERRIFIED);
} }
@ -63,122 +63,58 @@ public:
virtual void FaceTo(const Vector &goal); virtual void FaceTo(const Vector &goal);
virtual void ClearFaceTo(void); virtual void ClearFaceTo(void);
virtual bool IsAtMoveGoal(float error = 20.0f) const; virtual bool IsAtMoveGoal(float error = 20.0f) const;
virtual bool HasLookAt(void) const virtual bool HasLookAt(void) const { return m_isLookingAt; }
{ virtual bool HasFaceTo(void) const { return m_isFacingTo; }
return m_isLookingAt;
}
virtual bool HasFaceTo(void) const
{
return m_isFacingTo;
}
virtual bool IsAtFaceGoal(void) const; virtual bool IsAtFaceGoal(void) const;
virtual bool IsFriendInTheWay(const Vector &goalPos) const; virtual bool IsFriendInTheWay(const Vector &goalPos) const;
virtual bool IsFriendInTheWay(CBaseEntity *myFriend, const Vector &goalPos) const; virtual bool IsFriendInTheWay(CBaseEntity *myFriend, const Vector &goalPos) const;
virtual void MoveForward(void) virtual void MoveForward(void) { m_moveFlags |= IN_FORWARD; }
{ virtual void MoveBackward(void) { m_moveFlags |= IN_BACK; }
m_moveFlags |= IN_FORWARD; virtual void StrafeLeft(void) { m_moveFlags |= IN_MOVELEFT; }
} virtual void StrafeRight(void) { m_moveFlags |= IN_MOVERIGHT; }
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 #define HOSTAGE_MUST_JUMP true
virtual bool Jump(void); virtual bool Jump(void);
virtual void Crouch(void); virtual void Crouch(void);
virtual void StandUp(void); virtual void StandUp(void);
virtual void TrackPath(const Vector &pathGoal, float deltaT); virtual void TrackPath(const Vector &pathGoal, float deltaT); // move along path by following "pathGoal"
virtual void StartLadder(const CNavLadder *ladder, NavTraverseType how, const Vector *approachPos, const Vector *departPos); 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 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 bool GetSimpleGroundHeightWithFloor(const Vector *pos, float *height, Vector *normal = NULL);
virtual void Run(void); virtual void Run(void);
virtual void Walk(void); virtual void Walk(void);
virtual void Stop(void); virtual void Stop(void);
virtual float GetMoveAngle(void) const virtual float GetMoveAngle(void) const { return m_moveAngle; }
{ virtual float GetFaceAngle(void) const { return m_moveAngle; }
return m_moveAngle;
}
virtual float GetFaceAngle(void) const
{
return m_moveAngle;
}
virtual const Vector &GetFeet(void) const; virtual const Vector &GetFeet(void) const;
virtual const Vector &GetCentroid(void) const; virtual const Vector &GetCentroid(void) const;
virtual const Vector &GetEyes(void) const; virtual const Vector &GetEyes(void) const;
virtual bool IsRunning(void) const virtual bool IsRunning(void) const { return (m_moveType == Running); }
{ virtual bool IsWalking(void) const { return (m_moveType == Walking); }
return (m_moveType == Running); virtual bool IsStopped(void) const { return (m_moveType == Stopped); }
} virtual bool IsCrouching(void) const { return m_isCrouching; }
virtual bool IsWalking(void) const virtual bool IsJumping(void) const { return (m_jumpTimer.IsElapsed() == false); }
{ virtual bool IsUsingLadder(void) const { return false; }
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 IsOnGround(void) const;
virtual bool IsMoving(void) const; virtual bool IsMoving(void) const;
virtual bool CanRun(void) const virtual bool CanRun(void) const { return true; }
{ virtual bool CanCrouch(void) const { return true; }
return true; virtual bool CanJump(void) const { return true; }
} virtual bool IsVisible(const Vector &pos, bool testFOV = false) const; // return true if hostage can see position
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 bool IsPlayerLookingAtMe(CBasePlayer *other, float cosTolerance = 0.95f) const;
virtual CBasePlayer *IsAnyPlayerLookingAtMe(int team = 0, 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 CBasePlayer *GetClosestPlayerByTravelDistance(int team = 0, float *range = NULL) const;
virtual CNavArea *GetLastKnownArea(void) const virtual CNavArea *GetLastKnownArea(void) const { return m_lastKnownArea; }
{
return m_lastKnownArea;
}
virtual void OnUpdate(float deltaT); virtual void OnUpdate(float deltaT);
virtual void OnUpkeep(float deltaT); virtual void OnUpkeep(float deltaT);
virtual void OnReset(void); virtual void OnReset(void);
virtual void OnGameEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL); virtual void OnGameEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL);
virtual void OnTouch(CBaseEntity *other); virtual void OnTouch(CBaseEntity *other); // in contact with "other"
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
void OnMoveToSuccess_(const Vector &goal)
{
//if (m_behavior.IsState(NULL))
// IImprovEvent::OnMoveToSuccess(goal);
}
void OnMoveToFailure_(const Vector &goal, MoveToFailureType reason); void OnMoveToFailure_(const Vector &goal, MoveToFailureType reason);
void OnInjury_(float amount)
{
//m_behavior.Update();
//m_lastInjuryTimer.Start();
}
bool IsAlive_(void) const; bool IsAlive_(void) const;
void MoveTo_(const Vector &goal); void MoveTo_(const Vector &goal);
void LookAt_(const Vector &target); void LookAt_(const Vector &target);
@ -217,27 +153,13 @@ public:
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
public: public:
enum MoveType enum MoveType { Stopped, Walking, Running };
{ enum ScareType { NERVOUS, SCARED, TERRIFIED };
Stopped = 0,
Walking,
Running,
};
enum ScareType
{
NERVOUS = 0,
SCARED,
TERRIFIED,
};
void FaceOutwards(void); void FaceOutwards(void);
bool IsFriendInTheWay(void) const; bool IsFriendInTheWay(void) const;
void SetKnownGoodPosition(const Vector &pos); void SetKnownGoodPosition(const Vector &pos);
const Vector &GetKnownGoodPosition(void) const const Vector &GetKnownGoodPosition(void) const { return m_knownGoodPos; }
{
return m_knownGoodPos;
}
void ResetToKnownGoodPosition(void); void ResetToKnownGoodPosition(void);
void ResetJump(void) void ResetJump(void)
{ {
@ -253,7 +175,7 @@ public:
m_hasJumpedIntoAir = true; m_hasJumpedIntoAir = true;
} }
} }
void ApplyForce(Vector force); void ApplyForce(Vector force); // apply a force to the hostage
#ifdef PLAY_GAMEDLL #ifdef PLAY_GAMEDLL
void ApplyForce2(float_precision x, float_precision y) void ApplyForce2(float_precision x, float_precision y)
{ {
@ -261,62 +183,32 @@ public:
m_vel.y += y; m_vel.y += y;
} }
#endif // PLAY_GAMEDLL #endif // PLAY_GAMEDLL
const Vector GetActualVelocity(void) const const Vector GetActualVelocity(void) const { return m_actualVel; }
{ void SetMoveLimit(MoveType limit) { m_moveLimit = limit; }
return m_actualVel; MoveType GetMoveLimit(void) const { return m_moveLimit; }
} CNavPath *GetPath(void) { return &m_path; }
void SetMoveLimit(MoveType limit)
{
m_moveLimit = limit;
}
MoveType GetMoveLimit(void) const
{
return m_moveLimit;
}
CNavPath *GetPath(void)
{
return &m_path;
}
CNavPathFollower *GetPathFollower(void); CNavPathFollower *GetPathFollower(void);
void Idle(void)
{ // hostage states
m_behavior.SetState(&m_idleState); // stand idle
} void Idle(void) { m_behavior.SetState(&m_idleState); }
bool IsIdle(void) const bool IsIdle(void) const { return m_behavior.IsState(&m_idleState); }
{
return m_behavior.IsState(&m_idleState); // begin following "leader"
} void Follow(CBasePlayer *leader) { m_followState.SetLeader(leader); m_behavior.SetState(&m_followState); }
void Follow(CBasePlayer *leader) bool IsFollowing(const CBaseEntity *leader = NULL) const { return m_behavior.IsState(&m_followState); }
{
m_followState.SetLeader(leader); // Escape
m_behavior.SetState(&m_followState); void Escape(void) { m_behavior.SetState(&m_escapeState); }
} bool IsEscaping(void) const { return m_behavior.IsState(&m_escapeState); }
bool IsFollowing(const CBaseEntity *leader = NULL) const
{ // Retreat
return m_behavior.IsState(&m_followState); void Retreat(void) { m_behavior.SetState(&m_retreatState); }
} bool IsRetreating(void) const { return m_behavior.IsState(&m_retreatState); }
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 IsAtHome(void) const;
bool CanSeeRescueZone(void) const; bool CanSeeRescueZone(void) const;
CBaseEntity *GetFollowLeader(void) const CBaseEntity *GetFollowLeader(void) const { return m_followState.GetLeader(); }
{
return m_followState.GetLeader();
}
CBasePlayer *GetClosestVisiblePlayer(int team); CBasePlayer *GetClosestVisiblePlayer(int team);
float GetTimeSinceLastSawPlayer(int team); float GetTimeSinceLastSawPlayer(int team);
float GetTimeSinceLastInjury(void); float GetTimeSinceLastInjury(void);
@ -324,25 +216,13 @@ public:
bool IsTerroristNearby(void); bool IsTerroristNearby(void);
void Frighten(ScareType scare); void Frighten(ScareType scare);
bool IsScared(void) const; bool IsScared(void) const;
ScareType GetScareIntensity(void) const ScareType GetScareIntensity(void) const { return m_scareIntensity; }
{ bool IsIgnoringTerrorists(void) const { m_ignoreTerroristTimer.IsElapsed(); }
return m_scareIntensity; float GetAggression(void) const { return m_aggression; }
}
bool IsIgnoringTerrorists(void) const
{
m_ignoreTerroristTimer.IsElapsed();
}
float GetAggression(void) const
{
return m_aggression;
}
void Chatter(HostageChatterType sayType, bool mustSpeak = true); void Chatter(HostageChatterType sayType, bool mustSpeak = true);
void DelayedChatter(float delayTime, HostageChatterType sayType, bool mustSpeak = false); void DelayedChatter(float delayTime, HostageChatterType sayType, bool mustSpeak = false);
NOXREF void UpdateDelayedChatter(void); NOXREF void UpdateDelayedChatter(void);
bool IsTalking(void) const bool IsTalking(void) const { return m_talkingTimer.IsElapsed(); }
{
return m_talkingTimer.IsElapsed();
}
void UpdateGrenadeReactions(void); void UpdateGrenadeReactions(void);
void Afraid(void); void Afraid(void);
void Wave(void); void Wave(void);
@ -352,20 +232,14 @@ public:
void Flinch(Activity activity); void Flinch(Activity activity);
void UpdateIdleActivity(Activity activity, Activity fidget); void UpdateIdleActivity(Activity activity, Activity fidget);
void UpdateStationaryAnimation(void); void UpdateStationaryAnimation(void);
CHostage *GetEntity(void) const CHostage *GetEntity(void) const { return m_hostage; }
{
return m_hostage;
}
void CheckForNearbyTerrorists(void); void CheckForNearbyTerrorists(void);
void UpdatePosition(float); void UpdatePosition(float);
void MoveTowards(const Vector &pos, float deltaT); void MoveTowards(const Vector &pos, float deltaT);
bool FaceTowards(const Vector &target, float deltaT); bool FaceTowards(const Vector &target, float deltaT); // rotate body to face towards "target"
float GetSpeed(void); float GetSpeed(void);
void SetMoveAngle(float angle) void SetMoveAngle(float angle) { m_moveAngle = angle; }
{ void Wiggle(void); // attempt to wiggle-out of begin stuck
m_moveAngle = angle;
}
void Wiggle(void);
void ClearPath(void); void ClearPath(void);
#define HOSTAGE_ONLY_JUMP_DOWN true #define HOSTAGE_ONLY_JUMP_DOWN true
@ -378,7 +252,7 @@ public:
private: private:
CHostage *m_hostage; CHostage *m_hostage;
CNavArea *m_lastKnownArea; CNavArea *m_lastKnownArea; // last area we were in
mutable Vector m_centroid; mutable Vector m_centroid;
mutable Vector m_eye; mutable Vector m_eye;
HostageStateMachine m_behavior; HostageStateMachine m_behavior;
@ -423,25 +297,27 @@ private:
bool m_isLookingAt; bool m_isLookingAt;
Vector m_faceGoal; Vector m_faceGoal;
bool m_isFacingTo; bool m_isFacingTo;
CNavPath m_path; CNavPath m_path; // current path to follow
CNavPathFollower m_follower; CNavPathFollower m_follower;
Vector m_lastPosition; Vector m_lastPosition;
MoveType m_moveType; MoveType m_moveType;
MoveType m_moveLimit; MoveType m_moveLimit;
bool m_isCrouching; bool m_isCrouching; // true if hostage is crouching
CountdownTimer m_minCrouchTimer; CountdownTimer m_minCrouchTimer;
float m_moveAngle; float m_moveAngle;
NavRelativeDirType m_wiggleDirection; NavRelativeDirType m_wiggleDirection;
CountdownTimer m_wiggleTimer;
CountdownTimer m_wiggleTimer; // for wiggling
CountdownTimer m_wiggleJumpTimer; CountdownTimer m_wiggleJumpTimer;
CountdownTimer m_inhibitObstacleAvoidance; CountdownTimer m_inhibitObstacleAvoidance;
CountdownTimer m_jumpTimer; CountdownTimer m_jumpTimer; // if zero, we can jump
bool m_hasJumped; bool m_hasJumped;
bool m_hasJumpedIntoAir; bool m_hasJumpedIntoAir;
Vector m_jumpTarget; Vector m_jumpTarget;
CountdownTimer m_clearPathTimer; CountdownTimer m_clearPathTimer;
bool m_traversingLadder; bool m_traversingLadder;
EHANDLE m_visiblePlayer[32]; EHANDLE m_visiblePlayer[ MAX_CLIENTS ];
int m_visiblePlayerCount; int m_visiblePlayerCount;
CountdownTimer m_visionTimer; CountdownTimer m_visionTimer;
@ -475,6 +351,9 @@ public:
}; /* size: 20, cachelines: 1, members: 3 */ }; /* size: 20, cachelines: 1, members: 3 */
// Functor used with NavAreaBuildPath() for building Hostage paths.
// Once we hook up crouching and ladders, this can be removed and ShortestPathCost() can be used instead.
/* <46f426> ../cstrike/dlls/hostage/hostage_improv.h:400 */ /* <46f426> ../cstrike/dlls/hostage/hostage_improv.h:400 */
class HostagePathCost class HostagePathCost
{ {
@ -496,9 +375,12 @@ public:
const float ladderCost = 10.0f; const float ladderCost = 10.0f;
return ladder->m_length * ladderCost + fromArea->GetCostSoFar(); return ladder->m_length * ladderCost + fromArea->GetCostSoFar();
} }
else
{
dist = (*area->GetCenter() - *fromArea->GetCenter()).Length();
}
dist = (*area->GetCenter() - *fromArea->GetCenter()).Length(); float cost = dist + fromArea->GetCostSoFar();
float cost = fromArea->GetCostSoFar() + dist;
// if this is a "crouch" area, add penalty // if this is a "crouch" area, add penalty
if (area->GetAttributes() & NAV_CROUCH) if (area->GetAttributes() & NAV_CROUCH)
@ -594,12 +476,8 @@ public:
CheckAhead(const CHostageImprov *me) CheckAhead(const CHostageImprov *me)
{ {
m_me = me; m_me = me;
m_dir = Vector(BotCOS(me->GetMoveAngle()), BotSIN(me->GetMoveAngle()), 0.0f);
m_isBlocked = false; 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 */ /* <47046f> ../cstrike/dlls/hostage/hostage_improv.cpp:525 */
bool operator()(CBaseEntity *entity) bool operator()(CBaseEntity *entity)

View File

@ -79,24 +79,11 @@ public:
virtual void OnEnter(CHostageImprov *improv); virtual void OnEnter(CHostageImprov *improv);
virtual void OnUpdate(CHostageImprov *improv); virtual void OnUpdate(CHostageImprov *improv);
virtual void OnExit(CHostageImprov *improv); virtual void OnExit(CHostageImprov *improv);
virtual const char *GetName(void) const virtual const char *GetName(void) const { return "Idle"; }
{
return "Idle";
}
virtual void UpdateStationaryAnimation(CHostageImprov *improv); virtual void UpdateStationaryAnimation(CHostageImprov *improv);
virtual void OnMoveToSuccess(const Vector &goal) virtual void OnMoveToSuccess(const Vector &goal) { m_moveState = MoveDone; }
{ virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason) { m_moveState = MoveFailed; }
m_moveState = MoveDone; virtual void OnInjury(float amount = -1.0f) { m_fleeTimer.Invalidate(); m_mustFlee = true; }
}
virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason)
{
m_moveState = MoveFailed;
}
virtual void OnInjury(float amount = -1.0f)
{
m_fleeTimer.Invalidate();
m_mustFlee = true;
}
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -137,10 +124,7 @@ public:
virtual void OnEnter(CHostageImprov *improv); virtual void OnEnter(CHostageImprov *improv);
virtual void OnUpdate(CHostageImprov *improv); virtual void OnUpdate(CHostageImprov *improv);
virtual void OnExit(CHostageImprov *improv); virtual void OnExit(CHostageImprov *improv);
virtual const char *GetName(void) const virtual const char *GetName(void) const { return "Escape:ToCover"; }
{
return "Escape:ToCover";
}
virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason); virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason);
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -153,10 +137,7 @@ public:
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
public: public:
void SetRescueGoal(const Vector &rescueGoal) void SetRescueGoal(const Vector &rescueGoal) { m_rescueGoal = rescueGoal; }
{
m_rescueGoal = rescueGoal;
}
private: private:
Vector m_rescueGoal; Vector m_rescueGoal;
@ -174,10 +155,7 @@ public:
virtual void OnEnter(CHostageImprov *improv); virtual void OnEnter(CHostageImprov *improv);
virtual void OnUpdate(CHostageImprov *improv); virtual void OnUpdate(CHostageImprov *improv);
virtual void OnExit(CHostageImprov *improv); virtual void OnExit(CHostageImprov *improv);
virtual const char *GetName(void) const virtual const char *GetName(void) const { return "Escape:LookAround"; }
{
return "Escape:LookAround";
}
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -201,14 +179,8 @@ public:
virtual void OnEnter(CHostageImprov *improv); virtual void OnEnter(CHostageImprov *improv);
virtual void OnUpdate(CHostageImprov *improv); virtual void OnUpdate(CHostageImprov *improv);
virtual void OnExit(CHostageImprov *improv); virtual void OnExit(CHostageImprov *improv);
virtual const char *GetName(void) const virtual const char *GetName(void) const { return "Escape"; }
{ virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason) { m_behavior.OnMoveToFailure(goal, reason); }
return "Escape";
}
virtual void OnMoveToFailure(const Vector &goal, MoveToFailureType reason)
{
m_behavior.OnMoveToFailure(goal, reason);
}
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -219,14 +191,8 @@ public:
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
public: public:
void ToCover(void) void ToCover(void) { m_behavior.SetState(&m_toCoverState); }
{ void LookAround(void) { m_behavior.SetState(&m_lookAroundState); }
m_behavior.SetState(&m_toCoverState);
}
void LookAround(void)
{
m_behavior.SetState(&m_lookAroundState);
}
private: private:
HostageEscapeToCoverState m_toCoverState; HostageEscapeToCoverState m_toCoverState;
@ -246,20 +212,13 @@ public:
virtual void OnEnter(CHostageImprov *improv); virtual void OnEnter(CHostageImprov *improv);
virtual void OnUpdate(CHostageImprov *improv); virtual void OnUpdate(CHostageImprov *improv);
virtual void OnExit(CHostageImprov *improv); virtual void OnExit(CHostageImprov *improv);
virtual const char *GetName(void) const virtual const char *GetName(void) const { return "Retreat"; }
{
return "Retreat";
}
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
void OnEnter_(CHostageImprov *improv); void OnEnter_(CHostageImprov *improv);
void OnUpdate_(CHostageImprov *improv); void OnUpdate_(CHostageImprov *improv);
void OnExit_(CHostageImprov *improv); void OnExit_(CHostageImprov *improv);
const char *GetName_(void) const
{
return GetName();
}
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
@ -274,10 +233,7 @@ public:
virtual void OnEnter(CHostageImprov *improv); virtual void OnEnter(CHostageImprov *improv);
virtual void OnUpdate(CHostageImprov *improv); virtual void OnUpdate(CHostageImprov *improv);
virtual void OnExit(CHostageImprov *improv); virtual void OnExit(CHostageImprov *improv);
virtual const char *GetName(void) const virtual const char *GetName(void) const { return "Follow"; }
{
return "Follow";
}
virtual void UpdateStationaryAnimation(CHostageImprov *improv); virtual void UpdateStationaryAnimation(CHostageImprov *improv);
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -290,14 +246,8 @@ public:
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
public: public:
void SetLeader(CBaseEntity *leader) void SetLeader(CBaseEntity *leader) { m_leader = leader; }
{ CBaseEntity *GetLeader(void) const { return m_leader; }
m_leader = leader;
}
CBaseEntity *GetLeader(void) const
{
return m_leader;
}
private: private:
mutable EHANDLE m_leader; mutable EHANDLE m_leader;
@ -321,10 +271,7 @@ public:
virtual void OnEnter(CHostageImprov *improv); virtual void OnEnter(CHostageImprov *improv);
virtual void OnUpdate(CHostageImprov *improv); virtual void OnUpdate(CHostageImprov *improv);
virtual void OnExit(CHostageImprov *improv); virtual void OnExit(CHostageImprov *improv);
virtual const char *GetName(void) const virtual const char *GetName(void) const { return "Animate"; }
{
return "Animate";
}
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -340,8 +287,7 @@ public:
int seqID; int seqID;
float holdTime; float holdTime;
float rate; float rate;
};
};/* size: 12, cachelines: 1, members: 3 */
enum PerformanceType enum PerformanceType
{ {

View File

@ -137,7 +137,7 @@ void HostageFollowState::__MAKE_VHOOK(OnUpdate)(CHostageImprov *improv)
bool makeWay = false; bool makeWay = false;
const float cosTolerance = 0.99f; const float cosTolerance = 0.99f;
if (improv->IsPlayerLookingAtMe((CBasePlayer *)((CBaseEntity *)m_leader), cosTolerance)) if (improv->IsPlayerLookingAtMe((CBasePlayer *)m_leader, cosTolerance))
{ {
if (!m_makeWayTimer.HasStarted()) if (!m_makeWayTimer.HasStarted())
{ {

View File

@ -448,7 +448,7 @@ CHalfLifeMultiplay::CHalfLifeMultiplay(void)
m_iAccountCT = 0; m_iAccountCT = 0;
m_iAccountTerrorist = 0; m_iAccountTerrorist = 0;
m_iHostagesRescued = 0; m_iHostagesRescued = 0;
m_iRoundWinStatus = 0; m_iRoundWinStatus = WINNER_NONE;
m_iNumCTWins = 0; m_iNumCTWins = 0;
m_iNumTerroristWins = 0; m_iNumTerroristWins = 0;
m_pVIP = NULL; m_pVIP = NULL;
@ -949,7 +949,7 @@ void CHalfLifeMultiplay::QueueCareerRoundEndMenu(float tmDelay, int iWinStatus)
{ {
numHostagesInMap++; numHostagesInMap++;
CHostage *pHostage = reinterpret_cast<CHostage *>(hostage); CHostage *pHostage = static_cast<CHostage *>(hostage);
if (pHostage->pev->takedamage != DAMAGE_YES) if (pHostage->pev->takedamage != DAMAGE_YES)
{ {
@ -958,17 +958,8 @@ void CHalfLifeMultiplay::QueueCareerRoundEndMenu(float tmDelay, int iWinStatus)
CBasePlayer *pLeader = NULL; CBasePlayer *pLeader = NULL;
if (pHostage->m_improv != NULL) if (pHostage->IsFollowingSomeone())
{ pLeader = static_cast<CBasePlayer *>(pHostage->GetLeader());
if (pHostage->IsFollowingSomeone())
{
pLeader = reinterpret_cast<CBasePlayer *>(pHostage->GetLeader());
}
}
else if (pHostage->m_hTargetEnt != NULL && pHostage->m_State == CHostage::FOLLOW)
{
pLeader = (CBasePlayer *)((CBaseEntity *)pHostage->m_hTargetEnt);
}
if (pLeader == NULL) if (pLeader == NULL)
{ {
@ -1042,7 +1033,7 @@ void CHalfLifeMultiplay::__MAKE_VHOOK(CheckWinConditions)(void)
#endif // REGAMEDLL_ADD #endif // REGAMEDLL_ADD
// If a winner has already been determined and game of started.. then get the heck out of here // If a winner has already been determined and game of started.. then get the heck out of here
if (m_bFirstConnected && m_iRoundWinStatus != 0) if (m_bFirstConnected && m_iRoundWinStatus != WINNER_NONE)
{ {
return; return;
} }
@ -2091,7 +2082,7 @@ void CHalfLifeMultiplay::__MAKE_VHOOK(RestartRound)(void)
m_iAccountTerrorist = m_iAccountCT = 0; m_iAccountTerrorist = m_iAccountCT = 0;
m_iHostagesRescued = 0; m_iHostagesRescued = 0;
m_iHostagesTouched = 0; m_iHostagesTouched = 0;
m_iRoundWinStatus = 0; m_iRoundWinStatus = WINNER_NONE;
m_bTargetBombed = m_bBombDefused = false; m_bTargetBombed = m_bBombDefused = false;
m_bLevelInitialized = false; m_bLevelInitialized = false;
m_bCompleteReset = false; m_bCompleteReset = false;
@ -3000,7 +2991,7 @@ void CHalfLifeMultiplay::CheckRestartRound(void)
bool CHalfLifeMultiplay::HasRoundTimeExpired(void) bool CHalfLifeMultiplay::HasRoundTimeExpired(void)
{ {
// We haven't completed other objectives, so go for this!. // We haven't completed other objectives, so go for this!.
if (TimeRemaining() > 0 || m_iRoundWinStatus != 0) if (TimeRemaining() > 0 || m_iRoundWinStatus != WINNER_NONE)
{ {
return false; return false;
} }

View File

@ -463,10 +463,7 @@ public:
virtual void Precache(void); virtual void Precache(void);
virtual int Save(CSave &save); virtual int Save(CSave &save);
virtual int Restore(CRestore &restore); virtual int Restore(CRestore &restore);
virtual int ObjectCaps(void) virtual int ObjectCaps(void) { return (CBaseMonster::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); }
{
return (CBaseMonster::ObjectCaps() & ~FCAP_ACROSS_TRANSITION);
}
virtual int Classify(void); virtual int Classify(void);
virtual void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType); virtual void TraceAttack(entvars_t *pevAttacker, float flDamage, Vector vecDir, TraceResult *ptr, int bitsDamageType);
virtual int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType); virtual int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType);
@ -477,60 +474,30 @@ public:
virtual BOOL AddPlayerItem(CBasePlayerItem *pItem); virtual BOOL AddPlayerItem(CBasePlayerItem *pItem);
virtual BOOL RemovePlayerItem(CBasePlayerItem *pItem); virtual BOOL RemovePlayerItem(CBasePlayerItem *pItem);
virtual int GiveAmmo(int iAmount, char *szName, int iMax); virtual int GiveAmmo(int iAmount, char *szName, int iMax);
virtual void StartSneaking(void) virtual void StartSneaking(void) { m_tSneaking = gpGlobals->time - 1; }
{ virtual void StopSneaking(void) { m_tSneaking = gpGlobals->time + 30; }
m_tSneaking = gpGlobals->time - 1; virtual BOOL IsSneaking(void) { return m_tSneaking <= gpGlobals->time; }
} virtual BOOL IsAlive(void) { return (pev->deadflag == DEAD_NO && pev->health > 0.0f); }
virtual void StopSneaking(void) virtual BOOL IsPlayer(void) { return (pev->flags & FL_SPECTATOR) != FL_SPECTATOR; }
{ virtual BOOL IsNetClient(void) { return TRUE; }
m_tSneaking = gpGlobals->time + 30;
}
virtual BOOL IsSneaking(void)
{
return m_tSneaking <= gpGlobals->time;
}
virtual BOOL IsAlive(void)
{
return (pev->deadflag == DEAD_NO && pev->health > 0.0f);
}
virtual BOOL IsPlayer(void)
{
return (pev->flags & FL_SPECTATOR) != FL_SPECTATOR;
}
virtual BOOL IsNetClient(void)
{
return TRUE;
}
virtual const char *TeamID(void); virtual const char *TeamID(void);
virtual BOOL FBecomeProne(void); virtual BOOL FBecomeProne(void);
virtual Vector BodyTarget(const Vector &posSrc) virtual Vector BodyTarget(const Vector &posSrc) { return Center() + pev->view_ofs * RANDOM_FLOAT(0.5, 1.1); }
{
return Center() + pev->view_ofs * RANDOM_FLOAT(0.5, 1.1);
}
virtual int Illumination(void); virtual int Illumination(void);
virtual BOOL ShouldFadeOnDeath(void) virtual BOOL ShouldFadeOnDeath(void) { return FALSE; }
{
return FALSE;
}
virtual void ResetMaxSpeed(void); virtual void ResetMaxSpeed(void);
virtual void Jump(void); virtual void Jump(void);
virtual void Duck(void); virtual void Duck(void);
virtual void PreThink(void); virtual void PreThink(void);
virtual void PostThink(void); virtual void PostThink(void);
virtual Vector GetGunPosition(void); virtual Vector GetGunPosition(void);
virtual BOOL IsBot(void) virtual BOOL IsBot(void) { return FALSE; }
{
return FALSE;
}
virtual void UpdateClientData(void); virtual void UpdateClientData(void);
virtual void ImpulseCommands(void); virtual void ImpulseCommands(void);
virtual void RoundRespawn(void); virtual void RoundRespawn(void);
virtual Vector GetAutoaimVector(float flDelta); virtual Vector GetAutoaimVector(float flDelta);
virtual void Blind(float flUntilTime, float flHoldTime, float flFadeTime, int iAlpha); virtual void Blind(float flUntilTime, float flHoldTime, float flFadeTime, int iAlpha);
virtual void OnTouchingWeapon(CWeaponBox *pWeapon) virtual void OnTouchingWeapon(CWeaponBox *pWeapon) { }
{
;
}
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -573,10 +540,7 @@ public:
void Observer_SetMode(int iMode); void Observer_SetMode(int iMode);
void Observer_CheckTarget(void); void Observer_CheckTarget(void);
void Observer_CheckProperties(void); void Observer_CheckProperties(void);
int IsObserver(void) int IsObserver(void) { return pev->iuser1; }
{
return pev->iuser1;
}
NOXREF void PlantC4(void); NOXREF void PlantC4(void);
void Radio(const char *msg_id, const char *msg_verbose = NULL, short pitch = 100, bool showIcon = true); void Radio(const char *msg_id, const char *msg_verbose = NULL, short pitch = 100, bool showIcon = true);
CBasePlayer *GetNextRadioRecipient(CBasePlayer *pStartPlayer); CBasePlayer *GetNextRadioRecipient(CBasePlayer *pStartPlayer);
@ -623,10 +587,7 @@ public:
void UpdatePlayerSound(void); void UpdatePlayerSound(void);
void DeathSound(void); void DeathSound(void);
void SetAnimation(PLAYER_ANIM playerAnim); void SetAnimation(PLAYER_ANIM playerAnim);
NOXREF void SetWeaponAnimType(const char *szExtention) NOXREF void SetWeaponAnimType(const char *szExtention) { Q_strcpy(m_szAnimExtention, szExtention); }
{
Q_strcpy(m_szAnimExtention, szExtention);
}
void CheatImpulseCommands(int iImpulse); void CheatImpulseCommands(int iImpulse);
void StartDeathCam(void); void StartDeathCam(void);
void StartObserver(Vector vecPosition, Vector vecViewAngle); void StartObserver(Vector vecPosition, Vector vecViewAngle);
@ -685,10 +646,7 @@ public:
void SendWeatherInfo(void); void SendWeatherInfo(void);
void UpdateShieldCrosshair(bool draw); void UpdateShieldCrosshair(bool draw);
bool HasShield(void); bool HasShield(void);
bool IsProtectedByShield(void) bool IsProtectedByShield(void) { return HasShield() && m_bShieldDrawn; }
{
return HasShield() && m_bShieldDrawn;
}
void RemoveShield(void); void RemoveShield(void);
void DropShield(bool bDeploy = true); void DropShield(bool bDeploy = true);
void GiveShield(bool bDeploy = true); void GiveShield(bool bDeploy = true);
@ -696,27 +654,17 @@ public:
bool SelectSpawnSpot(const char *pEntClassName, CBaseEntity* &pSpot); bool SelectSpawnSpot(const char *pEntClassName, CBaseEntity* &pSpot);
bool IsReloading(void) bool IsReloading(void)
{ {
if (m_pActiveItem != NULL && ((CBasePlayerWeapon *)m_pActiveItem)->m_fInReload) CBasePlayerWeapon *weapon = static_cast<CBasePlayerWeapon *>(m_pActiveItem);
if (weapon != NULL && weapon->m_fInReload)
return true; return true;
return false; return false;
} }
bool IsBlind(void) bool IsBlind(void) const { return (m_blindUntilTime > gpGlobals->time); }
{ bool IsAutoFollowAllowed(void) const { return (gpGlobals->time > m_allowAutoFollowTime); }
return (m_blindUntilTime > gpGlobals->time); void InhibitAutoFollow(float duration) { m_allowAutoFollowTime = gpGlobals->time + duration; }
} void AllowAutoFollow(void) { m_allowAutoFollowTime = 0; }
bool IsAutoFollowAllowed(void)
{
return (gpGlobals->time > m_allowAutoFollowTime);
}
void InhibitAutoFollow(float duration)
{
m_allowAutoFollowTime = duration;
}
void AllowAutoFollow(void)
{
m_allowAutoFollowTime = 0;
}
void ClearAutoBuyData(void); void ClearAutoBuyData(void);
void AddAutoBuyData(const char *str); void AddAutoBuyData(const char *str);
void AutoBuy(void); void AutoBuy(void);
@ -744,15 +692,9 @@ public:
void RebuyNightVision(void); void RebuyNightVision(void);
void RebuyArmor(void); void RebuyArmor(void);
void UpdateLocation(bool forceUpdate = false); void UpdateLocation(bool forceUpdate = false);
void SetObserverAutoDirector(bool val) void SetObserverAutoDirector(bool val) { m_bObserverAutoDirector = val; }
{
m_bObserverAutoDirector = val;
}
bool IsObservingPlayer(CBasePlayer *pPlayer); bool IsObservingPlayer(CBasePlayer *pPlayer);
bool CanSwitchObserverModes(void) bool CanSwitchObserverModes(void) const { return m_canSwitchObserverModes; }
{
return m_canSwitchObserverModes;
}
NOXREF void Intense(void) NOXREF void Intense(void)
{ {
//m_musicState = INTENSE; //m_musicState = INTENSE;

View File

@ -2271,7 +2271,7 @@ void CTriggerCamera::FollowTarget(void)
if (m_hPlayer->IsAlive()) if (m_hPlayer->IsAlive())
{ {
SET_VIEW(m_hPlayer->edict(), m_hPlayer->edict()); SET_VIEW(m_hPlayer->edict(), m_hPlayer->edict());
((CBasePlayer *)((CBaseEntity *)m_hPlayer))->EnableControl(TRUE); ((CBasePlayer *)m_hPlayer)->EnableControl(TRUE);
} }
SUB_UseTargets(this, USE_TOGGLE, 0); SUB_UseTargets(this, USE_TOGGLE, 0);

View File

@ -701,7 +701,7 @@ void CCSTutor::ProcessShownDeathsForEvent(TutorMessageEvent *event)
return; return;
} }
for (int i = 0; i < ARRAYSIZE(m_playerDeathInfo); i++) for (int i = 0; i < ARRAYSIZE(m_playerDeathInfo); ++i)
{ {
if (m_playerDeathInfo[i].m_event == event) if (m_playerDeathInfo[i].m_event == event)
{ {
@ -1071,7 +1071,7 @@ void CCSTutor::ClearEventList(void)
/* <213289> ../cstrike/dlls/tutor_cs_tutor.cpp:1175 */ /* <213289> ../cstrike/dlls/tutor_cs_tutor.cpp:1175 */
void CCSTutor::DeleteEvent(TutorMessageEvent *event) void CCSTutor::DeleteEvent(TutorMessageEvent *event)
{ {
for (int i = 0; i < ARRAYSIZE(m_playerDeathInfo); i++) for (int i = 0; i < ARRAYSIZE(m_playerDeathInfo); ++i)
{ {
if (m_playerDeathInfo[i].m_event == event) if (m_playerDeathInfo[i].m_event == event)
{ {
@ -1409,7 +1409,7 @@ void CCSTutor::HandleWeaponFired(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL && localPlayer->IsAlive()) if (localPlayer != NULL && localPlayer->IsAlive())
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player != NULL && player == localPlayer) if (player != NULL && player == localPlayer)
{ {
@ -1425,7 +1425,7 @@ void CCSTutor::HandleWeaponFiredOnEmpty(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player != NULL && player->IsPlayer() && player == localPlayer) if (player != NULL && player->IsPlayer() && player == localPlayer)
{ {
@ -1449,7 +1449,7 @@ void CCSTutor::HandleWeaponFiredOnEmpty(CBaseEntity *entity, CBaseEntity *other)
/* <213817> ../cstrike/dlls/tutor_cs_tutor.cpp:1654 */ /* <213817> ../cstrike/dlls/tutor_cs_tutor.cpp:1654 */
void CCSTutor::HandleWeaponReloaded(CBaseEntity *entity, CBaseEntity *other) void CCSTutor::HandleWeaponReloaded(CBaseEntity *entity, CBaseEntity *other)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player != NULL && player->IsPlayer() && player == UTIL_GetLocalPlayer()) if (player != NULL && player->IsPlayer() && player == UTIL_GetLocalPlayer())
{ {
@ -1467,8 +1467,8 @@ void CCSTutor::HandlePlayerDied(CBaseEntity *entity, CBaseEntity *other)
return; return;
} }
CBasePlayer *victim = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *victim = static_cast<CBasePlayer *>(entity);
CBasePlayer *attacker = reinterpret_cast<CBasePlayer *>(other); CBasePlayer *attacker = static_cast<CBasePlayer *>(other);
if (victim != NULL && !victim->IsPlayer()) if (victim != NULL && !victim->IsPlayer())
{ {
@ -1711,8 +1711,8 @@ void CCSTutor::HandlePlayerTookDamage(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *victim = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *victim = static_cast<CBasePlayer *>(entity);
CBasePlayer *attacker = reinterpret_cast<CBasePlayer *>(other); CBasePlayer *attacker = static_cast<CBasePlayer *>(other);
if (victim != NULL && !victim->IsPlayer()) if (victim != NULL && !victim->IsPlayer())
{ {
@ -1742,7 +1742,7 @@ void CCSTutor::HandlePlayerBlindedByFlashbang(CBaseEntity *entity, CBaseEntity *
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player != NULL && player->IsPlayer() && player == localPlayer) if (player != NULL && player->IsPlayer() && player == localPlayer)
{ {
@ -1754,7 +1754,7 @@ void CCSTutor::HandlePlayerBlindedByFlashbang(CBaseEntity *entity, CBaseEntity *
/* <213ab7> ../cstrike/dlls/tutor_cs_tutor.cpp:2008 */ /* <213ab7> ../cstrike/dlls/tutor_cs_tutor.cpp:2008 */
void CCSTutor::HandlePlayerSpawned(CBaseEntity *entity, CBaseEntity *other) void CCSTutor::HandlePlayerSpawned(CBaseEntity *entity, CBaseEntity *other)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player->IsPlayer() && player == UTIL_GetLocalPlayer()) if (player->IsPlayer() && player == UTIL_GetLocalPlayer())
{ {
@ -1767,7 +1767,7 @@ void CCSTutor::HandlePlayerSpawned(CBaseEntity *entity, CBaseEntity *other)
/* <21868e> ../cstrike/dlls/tutor_cs_tutor.cpp:2033 */ /* <21868e> ../cstrike/dlls/tutor_cs_tutor.cpp:2033 */
NOXREF void CCSTutor::HandleClientCorpseSpawned(CBaseEntity *entity, CBaseEntity *other) NOXREF void CCSTutor::HandleClientCorpseSpawned(CBaseEntity *entity, CBaseEntity *other)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player == NULL || !player->IsPlayer()) if (player == NULL || !player->IsPlayer())
{ {
@ -1850,7 +1850,7 @@ void CCSTutor::HandleBombDefused(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *defuser = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *defuser = static_cast<CBasePlayer *>(entity);
if (defuser != NULL && defuser->IsPlayer() && defuser == localPlayer) if (defuser != NULL && defuser->IsPlayer() && defuser == localPlayer)
{ {
@ -1881,7 +1881,7 @@ void CCSTutor::HandleBombDefusing(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player != NULL && player->IsPlayer() && player == localPlayer && !player->m_bHasDefuser) if (player != NULL && player->IsPlayer() && player == localPlayer && !player->m_bHasDefuser)
{ {
@ -1962,7 +1962,7 @@ void CCSTutor::HandleBeingShotAt(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player != NULL && player->IsPlayer() && player == localPlayer && localPlayer->IsAlive()) if (player != NULL && player->IsPlayer() && player == localPlayer && localPlayer->IsAlive())
{ {
@ -1978,7 +1978,7 @@ void CCSTutor::HandleHostageUsed(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *activator = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *activator = static_cast<CBasePlayer *>(entity);
if (activator != NULL && activator->IsPlayer()) if (activator != NULL && activator->IsPlayer())
{ {
@ -2013,7 +2013,7 @@ void CCSTutor::HandleHostageRescued(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *rescuer = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *rescuer = static_cast<CBasePlayer *>(entity);
if (rescuer != NULL && rescuer->IsPlayer()) if (rescuer != NULL && rescuer->IsPlayer())
{ {
@ -2060,7 +2060,7 @@ void CCSTutor::HandleHostageDamaged(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *attacker = reinterpret_cast<CBasePlayer *>(other); CBasePlayer *attacker = static_cast<CBasePlayer *>(other);
if (entity != NULL && attacker != NULL && attacker->IsPlayer() && localPlayer == attacker) if (entity != NULL && attacker != NULL && attacker->IsPlayer() && localPlayer == attacker)
{ {
@ -2078,7 +2078,7 @@ void CCSTutor::HandleHostageKilled(CBaseEntity *entity, CBaseEntity *other)
{ {
CheckForAllHostagesDead(); CheckForAllHostagesDead();
CBasePlayer *attacker = reinterpret_cast<CBasePlayer *>(other); CBasePlayer *attacker = static_cast<CBasePlayer *>(other);
if (entity != NULL && attacker != NULL && attacker->IsPlayer()) if (entity != NULL && attacker != NULL && attacker->IsPlayer())
{ {
@ -2141,7 +2141,7 @@ void CCSTutor::HandleDeathCameraStart(CBaseEntity *entity, CBaseEntity *other)
if (localPlayer != NULL) if (localPlayer != NULL)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player != NULL && player->IsPlayer() && player == localPlayer) if (player != NULL && player->IsPlayer() && player == localPlayer)
{ {
@ -2362,9 +2362,9 @@ void CCSTutor::GetNumPlayersAliveOnTeams(int &numT, int &numCT)
numT = 0; numT = 0;
numCT = 0; numCT = 0;
for (int i = 1; i <= gpGlobals->maxClients; i++) for (int i = 1; i <= gpGlobals->maxClients; ++i)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(UTIL_PlayerByIndex(i)); CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
if (player == NULL || !player->IsAlive()) if (player == NULL || !player->IsAlive())
{ {
@ -2481,9 +2481,9 @@ void CCSTutor::CheckForBombViewable(void)
{ {
CBasePlayer *bombCarrier = NULL; CBasePlayer *bombCarrier = NULL;
for (int i = 1; i <= gpGlobals->maxClients; i++) for (int i = 1; i <= gpGlobals->maxClients; ++i)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(UTIL_PlayerByIndex(i)); CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
if (player && player->m_bHasC4) if (player && player->m_bHasC4)
{ {
@ -2683,9 +2683,7 @@ void CCSTutor::CheckForHostageViewable(void)
CBasePlayer *localPlayer = UTIL_GetLocalPlayer(); CBasePlayer *localPlayer = UTIL_GetLocalPlayer();
if (localPlayer == NULL) if (localPlayer == NULL)
{
return; return;
}
CBaseEntity *hostageEntity = NULL; CBaseEntity *hostageEntity = NULL;
bool sawFirst = false; bool sawFirst = false;
@ -2693,21 +2691,12 @@ void CCSTutor::CheckForHostageViewable(void)
while ((hostageEntity = UTIL_FindEntityByClassname(hostageEntity, "hostage_entity")) != NULL) while ((hostageEntity = UTIL_FindEntityByClassname(hostageEntity, "hostage_entity")) != NULL)
{ {
bool validHostage = false; bool validHostage = false;
CHostage *hostage = reinterpret_cast<CHostage *>(hostageEntity); CHostage *hostage = static_cast<CHostage *>(hostageEntity);
if (hostage->pev->takedamage == DAMAGE_YES) if (hostage->pev->takedamage == DAMAGE_YES)
{ {
if (hostage->m_improv != NULL) if (!hostage->IsFollowingSomeone())
{
if (!hostage->IsFollowingSomeone())
{
validHostage = true;
}
}
else if (hostage->m_hTargetEnt == NULL || hostage->m_State != CHostage::FOLLOW)
{
validHostage = true; validHostage = true;
}
} }
if (hostage->IsValid() && validHostage && IsEntityInViewOfPlayer(hostage, localPlayer) && !sawFirst) if (hostage->IsValid() && validHostage && IsEntityInViewOfPlayer(hostage, localPlayer) && !sawFirst)
@ -2813,15 +2802,7 @@ bool CCSTutor::CheckForAllHostagesFollowingSomeone(void)
{ {
if (hostage->pev->takedamage == DAMAGE_YES) if (hostage->pev->takedamage == DAMAGE_YES)
{ {
if (hostage->m_improv != NULL) if (!hostage->IsFollowingSomeone())
{
if (!hostage->IsFollowingSomeone())
{
foundUnusedOne = true;
break;
}
}
else if (hostage->m_hTargetEnt == NULL || hostage->m_State != CHostage::FOLLOW)
{ {
foundUnusedOne = true; foundUnusedOne = true;
break; break;
@ -3098,7 +3079,7 @@ void CCSTutor::CheckExamineMessages(float time)
return; return;
} }
for (int i = 0; i < TUTOR_NUM_MESSAGES; i++) for (int i = 0; i < TUTOR_NUM_MESSAGES; ++i)
{ {
//bool sawOne = false; //bool sawOne = false;
@ -3160,48 +3141,33 @@ void CCSTutor::CheckExamineMessages(float time)
if (i == YOU_SEE_FRIEND) if (i == YOU_SEE_FRIEND)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player->IsPlayer() && player->IsAlive() && player->m_iTeam == localPlayer->m_iTeam) if (player->IsPlayer() && player->IsAlive() && player->m_iTeam == localPlayer->m_iTeam)
{
validEntity = true; validEntity = true;
}
} }
else if (i == YOU_SEE_ENEMY) else if (i == YOU_SEE_ENEMY)
{ {
CBasePlayer *player = reinterpret_cast<CBasePlayer *>(entity); CBasePlayer *player = static_cast<CBasePlayer *>(entity);
if (player->IsPlayer() && player->IsAlive() && player->m_iTeam == localPlayer->m_iTeam) if (player->IsPlayer() && player->IsAlive() && player->m_iTeam == localPlayer->m_iTeam)
{ {
if ((player->m_iTeam != CT || localPlayer->m_iTeam == TERRORIST) && (player->m_iTeam != TERRORIST || localPlayer->m_iTeam == CT)) if ((player->m_iTeam != CT || localPlayer->m_iTeam == TERRORIST) && (player->m_iTeam != TERRORIST || localPlayer->m_iTeam == CT))
{
validEntity = true; validEntity = true;
}
} }
} }
else if (i == YOU_SEE_HOSTAGE_CT_EXAMINE) else if (i == YOU_SEE_HOSTAGE_CT_EXAMINE)
{ {
CHostage *hostage = reinterpret_cast<CHostage *>(entity); CHostage *hostage = static_cast<CHostage *>(entity);
if (entity->pev->takedamage == DAMAGE_YES) if (entity->pev->takedamage == DAMAGE_YES)
{ {
if (hostage->m_improv != NULL) if (!hostage->IsFollowingSomeone())
{
if (!hostage->IsFollowingSomeone())
{
validEntity = true;
}
}
else if (hostage->m_hTargetEnt == NULL || hostage->m_State != CHostage::FOLLOW)
{
validEntity = true; validEntity = true;
}
} }
if (!hostage->IsValid() || !validEntity) if (!hostage->IsValid() || !validEntity)
{
continue; continue;
}
} }
if (validEntity) if (validEntity)
@ -3291,7 +3257,7 @@ bool CCSTutor::IsBombMap(void)
/* <216d35> ../cstrike/dlls/tutor_cs_tutor.cpp:3781 */ /* <216d35> ../cstrike/dlls/tutor_cs_tutor.cpp:3781 */
void CCSTutor::ResetPlayerDeathInfo(void) void CCSTutor::ResetPlayerDeathInfo(void)
{ {
for (int i = 0; i < ARRAYSIZE(m_playerDeathInfo); i++) for (int i = 0; i < ARRAYSIZE(m_playerDeathInfo); ++i)
{ {
m_playerDeathInfo[i].m_hasBeenShown = false; m_playerDeathInfo[i].m_hasBeenShown = false;
m_playerDeathInfo[i].m_event = NULL; m_playerDeathInfo[i].m_event = NULL;
@ -3309,9 +3275,9 @@ void CCSTutor::ConstructRecentDeathsList(TeamName team, char *buf, int buflen, T
char scratch[32]; char scratch[32];
buf[0] = '\0'; buf[0] = '\0';
for (int i = 1; i <= gpGlobals->maxClients; i++) for (int i = 1; i <= gpGlobals->maxClients; ++i)
{ {
CBasePlayer *pPlayer = reinterpret_cast<CBasePlayer *>(UTIL_PlayerByIndex(i)); CBasePlayer *pPlayer = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
if (pPlayer == NULL) if (pPlayer == NULL)
continue; continue;
@ -3334,7 +3300,7 @@ void CCSTutor::ConstructRecentDeathsList(TeamName team, char *buf, int buflen, T
/* <216dc2> ../cstrike/dlls/tutor_cs_tutor.cpp:3853 */ /* <216dc2> ../cstrike/dlls/tutor_cs_tutor.cpp:3853 */
void CCSTutor::TransferDeathEvents(TutorMessageEvent *oldEvent, TutorMessageEvent *newEvent) void CCSTutor::TransferDeathEvents(TutorMessageEvent *oldEvent, TutorMessageEvent *newEvent)
{ {
for (int i = 0; i < ARRAYSIZE(m_playerDeathInfo); i++) for (int i = 0; i < ARRAYSIZE(m_playerDeathInfo); ++i)
{ {
if (m_playerDeathInfo[i].m_event == oldEvent) if (m_playerDeathInfo[i].m_event == oldEvent)
{ {

View File

@ -587,7 +587,7 @@ void CBasePlayerItem::CheckRespawn(void)
} }
} }
// Respawn- this item is already in the world, but it is // Respawn - this item is already in the world, but it is
// invisible and intangible. Make it visible and tangible. // invisible and intangible. Make it visible and tangible.
/* <1d1e09> ../cstrike/dlls/weapons.cpp:616 */ /* <1d1e09> ../cstrike/dlls/weapons.cpp:616 */
@ -620,6 +620,9 @@ CBaseEntity *CBasePlayerItem::__MAKE_VHOOK(Respawn)(void)
return pNewWeapon; return pNewWeapon;
} }
// whats going on here is that if the player drops this weapon, they shouldn't take it back themselves
// for a little while. But if they throw it at someone else, the other player should get it immediately.
/* <1d26f0> ../cstrike/dlls/weapons.cpp:642 */ /* <1d26f0> ../cstrike/dlls/weapons.cpp:642 */
void CBasePlayerItem::DefaultTouch(CBaseEntity *pOther) void CBasePlayerItem::DefaultTouch(CBaseEntity *pOther)
{ {
@ -629,7 +632,7 @@ void CBasePlayerItem::DefaultTouch(CBaseEntity *pOther)
return; return;
} }
CBasePlayer *pPlayer = reinterpret_cast<CBasePlayer *>(pOther); CBasePlayer *pPlayer = static_cast<CBasePlayer *>(pOther);
if (pPlayer->m_bIsVIP if (pPlayer->m_bIsVIP
&& m_iId != WEAPON_USP && m_iId != WEAPON_USP
@ -789,6 +792,8 @@ void CBasePlayerWeapon::KickBack(float up_base, float lateral_base, float up_mod
/* <1d242e> ../cstrike/dlls/weapons.cpp:792 */ /* <1d242e> ../cstrike/dlls/weapons.cpp:792 */
void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL bIsGlock) void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL bIsGlock)
{ {
float nexttime = 0.1f;
m_iClip--; m_iClip--;
if (m_iClip < 0) if (m_iClip < 0)
@ -831,16 +836,15 @@ void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL bI
m_pPlayer->pev->effects |= EF_MUZZLEFLASH; m_pPlayer->pev->effects |= EF_MUZZLEFLASH;
m_pPlayer->SetAnimation(PLAYER_ATTACK1); m_pPlayer->SetAnimation(PLAYER_ATTACK1);
shotsFired++;
float nexttime = 0; shotsFired++;
if (shotsFired != 3) if (shotsFired != 3)
{ {
nexttime = gpGlobals->time + 0.1f; shootTime = gpGlobals->time + nexttime;
} }
else
shootTime = nexttime; shootTime = 0;
} }
/* <1d389e> ../cstrike/dlls/weapons.cpp:876 */ /* <1d389e> ../cstrike/dlls/weapons.cpp:876 */
@ -911,6 +915,8 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
FireRemaining(m_iFamasShotsFired, m_flFamasShoot, FALSE); FireRemaining(m_iFamasShotsFired, m_flFamasShoot, FALSE);
} }
// Return zoom level back to previous zoom level before we fired a shot.
// This is used only for the AWP and Scout
if (m_flNextPrimaryAttack <= UTIL_WeaponTimeBase()) if (m_flNextPrimaryAttack <= UTIL_WeaponTimeBase())
{ {
if (m_pPlayer->m_bResumeZoom) if (m_pPlayer->m_bResumeZoom)
@ -920,6 +926,7 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
if (m_pPlayer->m_iFOV == m_pPlayer->m_iLastZoom) if (m_pPlayer->m_iFOV == m_pPlayer->m_iLastZoom)
{ {
// return the fade level in zoom.
m_pPlayer->m_bResumeZoom = false; m_pPlayer->m_bResumeZoom = false;
} }
} }
@ -978,6 +985,8 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
m_pPlayer->TabulateAmmo(); m_pPlayer->TabulateAmmo();
// Can't shoot during the freeze period
// Always allow firing in single player
if ((m_pPlayer->m_bCanShoot && g_pGameRules->IsMultiplayer() && !g_pGameRules->IsFreezePeriod() && !m_pPlayer->m_bIsDefusing) || !g_pGameRules->IsMultiplayer()) if ((m_pPlayer->m_bCanShoot && g_pGameRules->IsMultiplayer() && !g_pGameRules->IsFreezePeriod() && !m_pPlayer->m_bIsDefusing) || !g_pGameRules->IsMultiplayer())
{ {
PrimaryAttack(); PrimaryAttack();
@ -985,6 +994,7 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
} }
else if ((m_pPlayer->pev->button & IN_RELOAD) && iMaxClip() != WEAPON_NOCLIP && !m_fInReload && m_flNextPrimaryAttack < UTIL_WeaponTimeBase()) else if ((m_pPlayer->pev->button & IN_RELOAD) && iMaxClip() != WEAPON_NOCLIP && !m_fInReload && m_flNextPrimaryAttack < UTIL_WeaponTimeBase())
{ {
// reload when reload is pressed, or if no buttons are down and weapon is empty.
if (m_flFamasShoot == 0 && m_flGlock18Shoot == 0) if (m_flFamasShoot == 0 && m_flGlock18Shoot == 0)
{ {
if (!(m_iWeaponState & WPNSTATE_SHIELD_DRAWN)) if (!(m_iWeaponState & WPNSTATE_SHIELD_DRAWN))
@ -997,6 +1007,9 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
else if (!(usableButtons & (IN_ATTACK | IN_ATTACK2))) else if (!(usableButtons & (IN_ATTACK | IN_ATTACK2)))
{ {
// no fire buttons down // no fire buttons down
// The following code prevents the player from tapping the firebutton repeatedly
// to simulate full auto and retaining the single shot accuracy of single fire
if (m_bDelayFire) if (m_bDelayFire)
{ {
m_bDelayFire = false; m_bDelayFire = false;
@ -1011,16 +1024,19 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
m_fFireOnEmpty = FALSE; m_fFireOnEmpty = FALSE;
if (m_iId != WEAPON_USP && m_iId != WEAPON_GLOCK18 && m_iId != WEAPON_P228 && m_iId != WEAPON_DEAGLE && m_iId != WEAPON_ELITE && m_iId != WEAPON_FIVESEVEN) // if it's a pistol then set the shots fired to 0 after the player releases a button
if (IsSecondaryWeapon(m_iId))
{
m_iShotsFired = 0;
}
else
{ {
if (m_iShotsFired > 0 && m_flDecreaseShotsFired < gpGlobals->time) if (m_iShotsFired > 0 && m_flDecreaseShotsFired < gpGlobals->time)
{ {
m_flDecreaseShotsFired = gpGlobals->time + 0.0225f;
m_iShotsFired--; m_iShotsFired--;
m_flDecreaseShotsFired = gpGlobals->time + 0.0225;
} }
} }
else
m_iShotsFired = 0;
if (!IsUseable() && m_flNextPrimaryAttack < UTIL_WeaponTimeBase()) if (!IsUseable() && m_flNextPrimaryAttack < UTIL_WeaponTimeBase())
{ {

View File

@ -489,10 +489,7 @@ public:
float GetNextAttackDelay(float delay); float GetNextAttackDelay(float delay);
float GetNextAttackDelay2(float delay); float GetNextAttackDelay2(float delay);
bool HasSecondaryAttack(void); bool HasSecondaryAttack(void);
BOOL IsPistol(void) BOOL IsPistol(void) { return (m_iId == WEAPON_USP || m_iId == WEAPON_GLOCK18 || m_iId == WEAPON_P228 || m_iId == WEAPON_DEAGLE || m_iId == WEAPON_ELITE || m_iId == WEAPON_FIVESEVEN); }
{
return FALSE;
}
void SetPlayerShieldAnim(void); void SetPlayerShieldAnim(void);
void ResetPlayerShieldAnim(void); void ResetPlayerShieldAnim(void);
bool ShieldSecondaryFire(int iUpAnim, int iDownAnim); bool ShieldSecondaryFire(int iUpAnim, int iDownAnim);
@ -523,8 +520,8 @@ public:
int m_iShotsFired; int m_iShotsFired;
Vector m_vVecAiming; Vector m_vVecAiming;
string_t model_name; string_t model_name;
float m_flGlock18Shoot; float m_flGlock18Shoot; // time to shoot the remaining bullets of the glock18 burst fire
int m_iGlock18ShotsFired; int m_iGlock18ShotsFired; // used to keep track of the shots fired during the Glock18 burst fire mode.
float m_flFamasShoot; float m_flFamasShoot;
int m_iFamasShotsFired; int m_iFamasShotsFired;
float m_fBurstSpread; float m_fBurstSpread;
@ -2224,7 +2221,7 @@ extern int giAmmoIndex;
extern short g_sModelIndexRadio; extern short g_sModelIndexRadio;
extern MULTIDAMAGE gMultiDamage; extern MULTIDAMAGE gMultiDamage;
void FindHullIntersection(Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity); void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity);
void AnnounceFlashInterval(float interval, float offset = 0); void AnnounceFlashInterval(float interval, float offset = 0);
int MaxAmmoCarry(int iszName); int MaxAmmoCarry(int iszName);

View File

@ -7,41 +7,41 @@
AutoBuyInfoStruct g_autoBuyInfo[] = AutoBuyInfoStruct g_autoBuyInfo[] =
{ {
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_RIFLE), "galil", "weapon_galil" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_RIFLE, "galil", "weapon_galil" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_RIFLE), "ak47", "weapon_ak47" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_RIFLE, "ak47", "weapon_ak47" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SNIPERRIFLE), "scout", "weapon_scout" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SNIPERRIFLE, "scout", "weapon_scout" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_RIFLE), "sg552", "weapon_sg552" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_RIFLE, "sg552", "weapon_sg552" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SNIPERRIFLE), "awp", "weapon_awp" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SNIPERRIFLE, "awp", "weapon_awp" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SNIPERRIFLE), "g3sg1", "weapon_g3sg1" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SNIPERRIFLE, "g3sg1", "weapon_g3sg1" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_RIFLE), "famas", "weapon_famas" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_RIFLE, "famas", "weapon_famas" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_RIFLE), "m4a1", "weapon_m4a1" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_RIFLE, "m4a1", "weapon_m4a1" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_RIFLE), "aug", "weapon_aug" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_RIFLE, "aug", "weapon_aug" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SNIPERRIFLE), "sg550", "weapon_sg550" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SNIPERRIFLE, "sg550", "weapon_sg550" },
{ (AutoBuyClassType)(AUTOBUYCLASS_SECONDARY | AUTOBUYCLASS_PISTOL), "glock", "weapon_glock18" }, { AUTOBUYCLASS_SECONDARY|AUTOBUYCLASS_PISTOL, "glock", "weapon_glock18" },
{ (AutoBuyClassType)(AUTOBUYCLASS_SECONDARY | AUTOBUYCLASS_PISTOL), "usp", "weapon_usp" }, { AUTOBUYCLASS_SECONDARY|AUTOBUYCLASS_PISTOL, "usp", "weapon_usp" },
{ (AutoBuyClassType)(AUTOBUYCLASS_SECONDARY | AUTOBUYCLASS_PISTOL), "p228", "weapon_p228" }, { AUTOBUYCLASS_SECONDARY|AUTOBUYCLASS_PISTOL, "p228", "weapon_p228" },
{ (AutoBuyClassType)(AUTOBUYCLASS_SECONDARY | AUTOBUYCLASS_PISTOL), "deagle", "weapon_deagle" }, { AUTOBUYCLASS_SECONDARY|AUTOBUYCLASS_PISTOL, "deagle", "weapon_deagle" },
{ (AutoBuyClassType)(AUTOBUYCLASS_SECONDARY | AUTOBUYCLASS_PISTOL), "elites", "weapon_elite" }, { AUTOBUYCLASS_SECONDARY|AUTOBUYCLASS_PISTOL, "elites", "weapon_elite" },
{ (AutoBuyClassType)(AUTOBUYCLASS_SECONDARY | AUTOBUYCLASS_PISTOL), "fn57", "weapon_fiveseven" }, { AUTOBUYCLASS_SECONDARY|AUTOBUYCLASS_PISTOL, "fn57", "weapon_fiveseven" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SHOTGUN), "m3", "weapon_m3" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SHOTGUN, "m3", "weapon_m3" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SHOTGUN), "xm1014", "weapon_xm1014" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SHOTGUN, "xm1014", "weapon_xm1014" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SMG), "mac10", "weapon_mac10" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SMG, "mac10", "weapon_mac10" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SMG), "tmp", "weapon_tmp" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SMG, "tmp", "weapon_tmp" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SMG), "mp5", "weapon_mp5navy" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SMG, "mp5", "weapon_mp5navy" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SMG), "ump45", "weapon_ump45" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SMG, "ump45", "weapon_ump45" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SMG), "p90", "weapon_p90" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SMG, "p90", "weapon_p90" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_MACHINEGUN), "m249", "weapon_m249" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_MACHINEGUN, "m249", "weapon_m249" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_AMMO), "primammo", "primammo" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_AMMO, "primammo", "primammo" },
{ (AutoBuyClassType)(AUTOBUYCLASS_SECONDARY | AUTOBUYCLASS_AMMO), "secammo", "secammo" }, { AUTOBUYCLASS_SECONDARY|AUTOBUYCLASS_AMMO, "secammo", "secammo" },
{ (AutoBuyClassType)(AUTOBUYCLASS_ARMOR), "vest", "item_kevlar" }, { AUTOBUYCLASS_ARMOR, "vest", "item_kevlar" },
{ (AutoBuyClassType)(AUTOBUYCLASS_ARMOR), "vesthelm", "item_assaultsuit" }, { AUTOBUYCLASS_ARMOR, "vesthelm", "item_assaultsuit" },
{ (AutoBuyClassType)(AUTOBUYCLASS_GRENADE), "flash", "weapon_flashbang" }, { AUTOBUYCLASS_GRENADE, "flash", "weapon_flashbang" },
{ (AutoBuyClassType)(AUTOBUYCLASS_GRENADE), "hegren", "weapon_hegrenade" }, { AUTOBUYCLASS_GRENADE, "hegren", "weapon_hegrenade" },
{ (AutoBuyClassType)(AUTOBUYCLASS_GRENADE), "sgren", "weapon_smokegrenade"}, { AUTOBUYCLASS_GRENADE, "sgren", "weapon_smokegrenade"},
{ (AutoBuyClassType)(AUTOBUYCLASS_NIGHTVISION), "nvgs", "nvgs" }, { AUTOBUYCLASS_NIGHTVISION, "nvgs", "nvgs" },
{ (AutoBuyClassType)(AUTOBUYCLASS_DEFUSER), "defuser", "defuser" }, { AUTOBUYCLASS_DEFUSER, "defuser", "defuser" },
{ (AutoBuyClassType)(AUTOBUYCLASS_PRIMARY | AUTOBUYCLASS_SHIELD), "shield", "shield" }, { AUTOBUYCLASS_PRIMARY|AUTOBUYCLASS_SHIELD, "shield", "shield" },
{ (AutoBuyClassType)0, NULL, NULL } { AUTOBUYCLASS_NONE, NULL, NULL }
}; };
WeaponAliasInfo weaponAliasInfo[] = WeaponAliasInfo weaponAliasInfo[] =
@ -225,12 +225,14 @@ WeaponInfoStruct weaponInfo[27];
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
// Given an alias, return the associated weapon ID
/* <22cd2a> ../cstrike/dlls/weapontype.cpp:208 */ /* <22cd2a> ../cstrike/dlls/weapontype.cpp:208 */
WeaponIdType AliasToWeaponID(const char *alias) WeaponIdType AliasToWeaponID(const char *alias)
{ {
if (alias != NULL) if (alias != NULL)
{ {
for (int i = 0; weaponAliasInfo[i].alias != NULL; i++) for (int i = 0; weaponAliasInfo[i].alias != NULL; ++i)
{ {
if (!Q_stricmp(weaponAliasInfo[i].alias, alias)) if (!Q_stricmp(weaponAliasInfo[i].alias, alias))
return weaponAliasInfo[i].id; return weaponAliasInfo[i].id;
@ -259,6 +261,8 @@ const char *BuyAliasToWeaponID(const char *alias, WeaponIdType &id)
return NULL; return NULL;
} }
// Given a weapon ID, return its alias
/* <22cd03> ../cstrike/dlls/weapontype.cpp:246 */ /* <22cd03> ../cstrike/dlls/weapontype.cpp:246 */
const char *WeaponIDToAlias(int id) const char *WeaponIDToAlias(int id)
{ {
@ -292,6 +296,8 @@ WeaponClassType WeaponIDToWeaponClass(int id)
return AliasToWeaponClass(WeaponIDToAlias(id)); return AliasToWeaponClass(WeaponIDToAlias(id));
} }
// Return true if given weapon ID is a primary weapon
/* <22cee3> ../cstrike/dlls/weapontype.cpp:285 */ /* <22cee3> ../cstrike/dlls/weapontype.cpp:285 */
bool IsPrimaryWeapon(int id) bool IsPrimaryWeapon(int id)
{ {
@ -324,6 +330,8 @@ bool IsPrimaryWeapon(int id)
return false; return false;
} }
// Return true if given weapon ID is a secondary weapon
/* <22cf19> ../cstrike/dlls/weapontype.cpp:318 */ /* <22cf19> ../cstrike/dlls/weapontype.cpp:318 */
NOXREF bool IsSecondaryWeapon(int id) NOXREF bool IsSecondaryWeapon(int id)
{ {

View File

@ -70,6 +70,7 @@ enum WeaponIdType
enum AutoBuyClassType enum AutoBuyClassType
{ {
AUTOBUYCLASS_NONE = 0,
AUTOBUYCLASS_PRIMARY = (1 << 0), AUTOBUYCLASS_PRIMARY = (1 << 0),
AUTOBUYCLASS_SECONDARY = (1 << 1), AUTOBUYCLASS_SECONDARY = (1 << 1),
AUTOBUYCLASS_AMMO = (1 << 2), AUTOBUYCLASS_AMMO = (1 << 2),

View File

@ -129,6 +129,7 @@ void CAWP::AWPFire(float flSpread, float flCycleTime, BOOL fUseAutoAim)
m_pPlayer->m_iFOV = DEFAULT_FOV; m_pPlayer->m_iFOV = DEFAULT_FOV;
m_pPlayer->pev->fov = DEFAULT_FOV; m_pPlayer->pev->fov = DEFAULT_FOV;
} }
// If we are not zoomed in, the bullet diverts more.
else else
{ {
flSpread += 0.08; flSpread += 0.08;
@ -224,7 +225,11 @@ void CAWP::__MAKE_VHOOK(WeaponIdle)(void)
/* <23fa86> ../cstrike/dlls/wpn_shared/wpn_awp.cpp:283 */ /* <23fa86> ../cstrike/dlls/wpn_shared/wpn_awp.cpp:283 */
float CAWP::__MAKE_VHOOK(GetMaxSpeed)(void) float CAWP::__MAKE_VHOOK(GetMaxSpeed)(void)
{ {
return m_pPlayer->m_iFOV == DEFAULT_FOV ? AWP_MAX_SPEED : AWP_MAX_SPEED_ZOOM; if (m_pPlayer->m_iFOV == DEFAULT_FOV)
return AWP_MAX_SPEED;
// Slower speed when zoomed in.
return AWP_MAX_SPEED_ZOOM;
} }
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL

View File

@ -79,7 +79,7 @@ BOOL CC4::__MAKE_VHOOK(Deploy)(void)
void CC4::__MAKE_VHOOK(Holster)(int skiplocal) void CC4::__MAKE_VHOOK(Holster)(int skiplocal)
{ {
m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5; m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.5;
m_bStartedArming = false; m_bStartedArming = false; // stop arming sequence
if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
{ {
@ -98,15 +98,14 @@ void CC4::__MAKE_VHOOK(Holster)(int skiplocal)
void CC4::__MAKE_VHOOK(PrimaryAttack)(void) void CC4::__MAKE_VHOOK(PrimaryAttack)(void)
{ {
BOOL PlaceBomb; BOOL PlaceBomb;
int inBombZone, onGround;
if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
{ {
return; return;
} }
inBombZone = (m_pPlayer->m_signals.GetState() & SIGNAL_BOMB) == SIGNAL_BOMB; int inBombZone = (m_pPlayer->m_signals.GetState() & SIGNAL_BOMB) == SIGNAL_BOMB;
onGround = (m_pPlayer->pev->flags & FL_ONGROUND) == FL_ONGROUND; int onGround = (m_pPlayer->pev->flags & FL_ONGROUND) == FL_ONGROUND;
PlaceBomb = (onGround && inBombZone); PlaceBomb = (onGround && inBombZone);
if (!m_bStartedArming) if (!m_bStartedArming)
@ -121,7 +120,7 @@ void CC4::__MAKE_VHOOK(PrimaryAttack)(void)
if (!onGround) if (!onGround)
{ {
ClientPrint(m_pPlayer->pev, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground"); ClientPrint(m_pPlayer->pev, HUD_PRINTCENTER, "#C4_Plant_Must_Be_On_Ground");
m_flNextPrimaryAttack = GetNextAttackDelay(1); m_flNextPrimaryAttack = GetNextAttackDelay(1.0);
return; return;
} }
@ -129,8 +128,10 @@ void CC4::__MAKE_VHOOK(PrimaryAttack)(void)
m_bBombPlacedAnimation = false; m_bBombPlacedAnimation = false;
m_fArmedTime = gpGlobals->time + C4_ARMING_ON_TIME; m_fArmedTime = gpGlobals->time + C4_ARMING_ON_TIME;
// player "arming bomb" animation
SendWeaponAnim(C4_ARM, UseDecrement() != FALSE); SendWeaponAnim(C4_ARM, UseDecrement() != FALSE);
// freeze the player in place while planting
SET_CLIENT_MAXSPEED(m_pPlayer->edict(), 1.0); SET_CLIENT_MAXSPEED(m_pPlayer->edict(), 1.0);
m_pPlayer->SetAnimation(PLAYER_ATTACK1); m_pPlayer->SetAnimation(PLAYER_ATTACK1);
@ -186,21 +187,24 @@ void CC4::__MAKE_VHOOK(PrimaryAttack)(void)
TheCareerTasks->HandleEvent(EVENT_BOMB_PLANTED, m_pPlayer); TheCareerTasks->HandleEvent(EVENT_BOMB_PLANTED, m_pPlayer);
} }
UTIL_LogPrintf UTIL_LogPrintf("\"%s<%i><%s><TERRORIST>\" triggered \"Planted_The_Bomb\"\n",
(
"\"%s<%i><%s><TERRORIST>\" triggered \"Planted_The_Bomb\"\n",
STRING(m_pPlayer->pev->netname), STRING(m_pPlayer->pev->netname),
GETPLAYERUSERID(m_pPlayer->edict()), GETPLAYERUSERID(m_pPlayer->edict()),
GETPLAYERAUTHID(m_pPlayer->edict()) GETPLAYERAUTHID(m_pPlayer->edict()));
);
g_pGameRules->m_bBombDropped = FALSE; g_pGameRules->m_bBombDropped = FALSE;
// Play the plant sound.
EMIT_SOUND(edict(), CHAN_WEAPON, "weapons/c4_plant.wav", VOL_NORM, ATTN_NORM); EMIT_SOUND(edict(), CHAN_WEAPON, "weapons/c4_plant.wav", VOL_NORM, ATTN_NORM);
// hide the backpack in Terrorist's models.
m_pPlayer->pev->body = 0; m_pPlayer->pev->body = 0;
m_pPlayer->ResetMaxSpeed();
m_pPlayer->SetBombIcon(FALSE);
// release the player from being frozen
m_pPlayer->ResetMaxSpeed();
// No more c4!
m_pPlayer->SetBombIcon(FALSE);
m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--; m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]--;
if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType]) if (!m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType])
@ -214,9 +218,11 @@ void CC4::__MAKE_VHOOK(PrimaryAttack)(void)
{ {
if (m_fArmedTime - 0.75 <= gpGlobals->time && !m_bBombPlacedAnimation) if (m_fArmedTime - 0.75 <= gpGlobals->time && !m_bBombPlacedAnimation)
{ {
// call the c4 Placement animation
m_bBombPlacedAnimation = true; m_bBombPlacedAnimation = true;
SendWeaponAnim(C4_DROP, UseDecrement() != FALSE); SendWeaponAnim(C4_DROP, UseDecrement() != FALSE);
// player "place" animation
m_pPlayer->SetAnimation(PLAYER_HOLDBOMB); m_pPlayer->SetAnimation(PLAYER_HOLDBOMB);
} }
} }
@ -231,11 +237,17 @@ void CC4::__MAKE_VHOOK(PrimaryAttack)(void)
m_bStartedArming = false; m_bStartedArming = false;
m_flNextPrimaryAttack = GetNextAttackDelay(1.5); m_flNextPrimaryAttack = GetNextAttackDelay(1.5);
// release the player from being frozen, we've somehow left the bomb zone
m_pPlayer->ResetMaxSpeed(); m_pPlayer->ResetMaxSpeed();
m_pPlayer->SetProgressBarTime(0); m_pPlayer->SetProgressBarTime(0);
m_pPlayer->SetAnimation(PLAYER_HOLDBOMB); m_pPlayer->SetAnimation(PLAYER_HOLDBOMB);
SendWeaponAnim(m_bBombPlacedAnimation ? C4_DRAW : C4_IDLE1, UseDecrement() != FALSE); // this means the placement animation is canceled
if (m_bBombPlacedAnimation)
SendWeaponAnim(C4_DRAW, UseDecrement() != FALSE);
else
SendWeaponAnim(C4_IDLE1, UseDecrement() != FALSE);
return; return;
} }
} }
@ -249,13 +261,20 @@ void CC4::__MAKE_VHOOK(WeaponIdle)(void)
{ {
if (m_bStartedArming) if (m_bStartedArming)
{ {
// if the player releases the attack button cancel the arming sequence
m_bStartedArming = false; m_bStartedArming = false;
// release the player from being frozen
m_pPlayer->ResetMaxSpeed(); m_pPlayer->ResetMaxSpeed();
m_flNextPrimaryAttack = GetNextAttackDelay(1.0); m_flNextPrimaryAttack = GetNextAttackDelay(1.0);
m_pPlayer->SetProgressBarTime(0); m_pPlayer->SetProgressBarTime(0);
SendWeaponAnim(m_bBombPlacedAnimation ? C4_DRAW : C4_IDLE1, UseDecrement() != FALSE); // this means the placement animation is canceled
if (m_bBombPlacedAnimation)
SendWeaponAnim(C4_DRAW, UseDecrement() != FALSE);
else
SendWeaponAnim(C4_IDLE1, UseDecrement() != FALSE);
} }
if (m_flTimeWeaponIdle <= UTIL_WeaponTimeBase()) if (m_flTimeWeaponIdle <= UTIL_WeaponTimeBase())

View File

@ -175,6 +175,7 @@ void CGLOCK18::GLOCK18Fire(float flSpread, float flCycleTime, BOOL bFireBurst)
if (m_flLastFire) if (m_flLastFire)
{ {
// Mark the time of this shot and determine the accuracy modifier based on the last shot fired...
m_flAccuracy -= (0.325 - (gpGlobals->time - m_flLastFire)) * 0.275; m_flAccuracy -= (0.325 - (gpGlobals->time - m_flLastFire)) * 0.275;
if (m_flAccuracy > 0.9) if (m_flAccuracy > 0.9)
@ -208,10 +209,13 @@ void CGLOCK18::GLOCK18Fire(float flSpread, float flCycleTime, BOOL bFireBurst)
m_iClip--; m_iClip--;
m_pPlayer->pev->effects |= EF_MUZZLEFLASH; m_pPlayer->pev->effects |= EF_MUZZLEFLASH;
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1); m_pPlayer->SetAnimation(PLAYER_ATTACK1);
UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle); UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle);
// non-silenced
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME; m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH; m_pPlayer->m_iWeaponFlash = NORMAL_GUN_FLASH;
@ -233,6 +237,7 @@ void CGLOCK18::GLOCK18Fire(float flSpread, float flCycleTime, BOOL bFireBurst)
if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0) if (!m_iClip && m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] <= 0)
{ {
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, FALSE); m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, FALSE);
} }
@ -240,6 +245,7 @@ void CGLOCK18::GLOCK18Fire(float flSpread, float flCycleTime, BOOL bFireBurst)
if (bFireBurst) if (bFireBurst)
{ {
// Fire off the next two rounds
m_iGlock18ShotsFired++; m_iGlock18ShotsFired++;
m_flGlock18Shoot = gpGlobals->time + 0.1; m_flGlock18Shoot = gpGlobals->time + 0.1;
} }
@ -294,6 +300,7 @@ void CGLOCK18::__MAKE_VHOOK(WeaponIdle)(void)
SendWeaponAnim(GLOCK18_SHIELD_IDLE, UseDecrement() != FALSE); SendWeaponAnim(GLOCK18_SHIELD_IDLE, UseDecrement() != FALSE);
} }
} }
// only idle if the slid isn't back
else if (m_iClip) else if (m_iClip)
{ {
flRand = RANDOM_FLOAT(0, 1); flRand = RANDOM_FLOAT(0, 1);

View File

@ -93,35 +93,26 @@ NOXREF void CKnife::WeaponAnimation(int iAnimation)
flag = 0; flag = 0;
#endif // CLIENT_WEAPONS #endif // CLIENT_WEAPONS
PLAYBACK_EVENT_FULL PLAYBACK_EVENT_FULL(flag, m_pPlayer->edict(), m_usKnife,
( 0.0, (float *)&g_vecZero, (float *)&g_vecZero,
flag, 0.0,
m_pPlayer->edict(), 0.0,
m_usKnife, iAnimation, 2, 3, 4);
0,
(float *)&g_vecZero,
(float *)&g_vecZero,
0,
0,
iAnimation,
2, // param noxref
3, // param noxref
4 // param noxref
);
} }
/* <26f852> ../cstrike/dlls/wpn_shared/wpn_knife.cpp:140 */ /* <26f852> ../cstrike/dlls/wpn_shared/wpn_knife.cpp:140 */
void FindHullIntersection(Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity) void FindHullIntersection(const Vector &vecSrc, TraceResult &tr, float *mins, float *maxs, edict_t *pEntity)
{ {
int i, j, k; int i, j, k;
float distance; float distance;
float *minmaxs[2] = { mins, maxs }; float *minmaxs[2] = { mins, maxs };
TraceResult tmpTrace; TraceResult tmpTrace;
Vector vecHullEnd, vecEnd; Vector vecHullEnd = tr.vecEndPos;
Vector vecEnd;
distance = 1e6f; distance = 1e6f;
vecHullEnd = vecSrc + ((tr.vecEndPos - vecSrc) * 2); vecHullEnd = vecSrc + ((vecHullEnd - vecSrc) * 2);
UTIL_TraceLine(vecSrc, vecHullEnd, dont_ignore_monsters, pEntity, &tmpTrace); UTIL_TraceLine(vecSrc, vecHullEnd, dont_ignore_monsters, pEntity, &tmpTrace);
if (tmpTrace.flFraction < 1.0f) if (tmpTrace.flFraction < 1.0f)
@ -130,11 +121,11 @@ void FindHullIntersection(Vector &vecSrc, TraceResult &tr, float *mins, float *m
return; return;
} }
for (i = 0; i < 2; i++) for (i = 0; i < 2; ++i)
{ {
for (j = 0; j < 2; j++) for (j = 0; j < 2; ++j)
{ {
for (k = 0; k < 2; k++) for (k = 0; k < 2; ++k)
{ {
vecEnd.x = vecHullEnd.x + minmaxs[i][0]; vecEnd.x = vecHullEnd.x + minmaxs[i][0];
vecEnd.y = vecHullEnd.y + minmaxs[j][1]; vecEnd.y = vecHullEnd.y + minmaxs[j][1];
@ -326,10 +317,10 @@ int CKnife::Swing(int fFirst)
SendWeaponAnim(KNIFE_SHIELD_ATTACKHIT, UseDecrement() != FALSE); SendWeaponAnim(KNIFE_SHIELD_ATTACKHIT, UseDecrement() != FALSE);
m_flNextPrimaryAttack = GetNextAttackDelay(1.0); m_flNextPrimaryAttack = GetNextAttackDelay(1.0);
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.2; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.2f;
} }
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0f;
// play wiff or swish sound // play wiff or swish sound
if (RANDOM_LONG(0, 1)) if (RANDOM_LONG(0, 1))
@ -355,17 +346,17 @@ int CKnife::Swing(int fFirst)
} }
m_flNextPrimaryAttack = GetNextAttackDelay(0.4); m_flNextPrimaryAttack = GetNextAttackDelay(0.4);
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5f;
} }
else else
{ {
SendWeaponAnim(KNIFE_SHIELD_ATTACKHIT, UseDecrement() != FALSE); SendWeaponAnim(KNIFE_SHIELD_ATTACKHIT, UseDecrement() != FALSE);
m_flNextPrimaryAttack = GetNextAttackDelay(1.0); m_flNextPrimaryAttack = GetNextAttackDelay(1.0);
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.2; m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 1.2f;
} }
m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0; m_flTimeWeaponIdle = UTIL_WeaponTimeBase() + 2.0f;
// play thwack, smack, or dong sound // play thwack, smack, or dong sound
float flVol = 1.0f; float flVol = 1.0f;
@ -378,7 +369,7 @@ int CKnife::Swing(int fFirst)
m_pPlayer->SetAnimation(PLAYER_ATTACK1); m_pPlayer->SetAnimation(PLAYER_ATTACK1);
ClearMultiDamage(); ClearMultiDamage();
if (m_flNextPrimaryAttack + 0.4 < UTIL_WeaponTimeBase()) if (m_flNextPrimaryAttack + 0.4f < UTIL_WeaponTimeBase())
pEntity->TraceAttack(m_pPlayer->pev, 20, gpGlobals->v_forward, &tr, (DMG_NEVERGIB | DMG_BULLET)); pEntity->TraceAttack(m_pPlayer->pev, 20, gpGlobals->v_forward, &tr, (DMG_NEVERGIB | DMG_BULLET));
else else
pEntity->TraceAttack(m_pPlayer->pev, 15, gpGlobals->v_forward, &tr, (DMG_NEVERGIB | DMG_BULLET)); pEntity->TraceAttack(m_pPlayer->pev, 15, gpGlobals->v_forward, &tr, (DMG_NEVERGIB | DMG_BULLET));
@ -429,7 +420,7 @@ int CKnife::Swing(int fFirst)
m_trHit = tr; m_trHit = tr;
SetThink(&CKnife::Smack); SetThink(&CKnife::Smack);
pev->nextthink = UTIL_WeaponTimeBase() + 0.2; pev->nextthink = UTIL_WeaponTimeBase() + 0.2f;
m_pPlayer->m_iWeaponVolume = (int)(flVol * KNIFE_WALLHIT_VOLUME); m_pPlayer->m_iWeaponVolume = (int)(flVol * KNIFE_WALLHIT_VOLUME);
ResetPlayerShieldAnim(); ResetPlayerShieldAnim();

View File

@ -115,6 +115,7 @@ typedef struct incomingtransfer_s
//#define Q_strtoull strtoull //#define Q_strtoull strtoull
//#define Q_FileNameCmp FileNameCmp //#define Q_FileNameCmp FileNameCmp
#define Q_vsnprintf _vsnprintf #define Q_vsnprintf _vsnprintf
#define Q_vsnwprintf _vsnwprintf
#else // Q_functions #else // Q_functions
void Q_strcpy(char *dest, const char *src); void Q_strcpy(char *dest, const char *src);
int Q_strlen(const char *str); int Q_strlen(const char *str);

View File

@ -11,6 +11,7 @@ float g_flBotCommandInterval = 1.0 / 30.0;
// full AI only 10 times per second // full AI only 10 times per second
float g_flBotFullThinkInterval = 1.0 / 10.0; float g_flBotFullThinkInterval = 1.0 / 10.0;
// Nasty Hack. See client.cpp/ClientCommand()
const char *BotArgs[4] = { NULL }; const char *BotArgs[4] = { NULL };
bool UseBotArgs = false; bool UseBotArgs = false;
@ -25,14 +26,24 @@ bool UseBotArgs;
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
/* <48fed0> ../game_shared/bot/bot.cpp:28 */ /* <48fed0> ../game_shared/bot/bot.cpp:28 */
NOBODY CBot::CBot(void) CBot::CBot(void)
{ {
// CBasePlayer(CBasePlayer *const this); // 28 // the profile will be attached after this instance is constructed
// { m_profile = NULL;
// unsigned int nextID; // 34
// } // assign this bot a unique ID
static unsigned int nextID = 1;
// wraparound (highly unlikely)
if (nextID == 0)
++nextID;
m_id = nextID++;
m_postureStackIndex = 0;
} }
// Prepare bot for action
/* <48f6ef> ../game_shared/bot/bot.cpp:50 */ /* <48f6ef> ../game_shared/bot/bot.cpp:50 */
bool CBot::__MAKE_VHOOK(Initialize)(const BotProfile *profile) bool CBot::__MAKE_VHOOK(Initialize)(const BotProfile *profile)
{ {
@ -41,18 +52,40 @@ bool CBot::__MAKE_VHOOK(Initialize)(const BotProfile *profile)
} }
/* <48fbbd> ../game_shared/bot/bot.cpp:57 */ /* <48fbbd> ../game_shared/bot/bot.cpp:57 */
NOBODY void CBot::__MAKE_VHOOK(Spawn)(void) void CBot::__MAKE_VHOOK(Spawn)(void)
{ {
// ResetCommand(CBot *const this); // 80 // Let CBasePlayer set some things up
CBasePlayer::Spawn();
// Make sure everyone knows we are a bot
pev->flags |= (FL_CLIENT | FL_FAKECLIENT);
// Bots use their own thinking mechanism
SetThink(NULL);
pev->nextthink = -1;
m_flNextBotThink = gpGlobals->time + g_flBotCommandInterval;
m_flNextFullBotThink = gpGlobals->time + g_flBotFullThinkInterval;
m_flPreviousCommandTime = gpGlobals->time;
m_isRunning = true;
m_isCrouching = false;
m_postureStackIndex = 0;
m_jumpTimestamp = 0.0f;
// Command interface variable initialization
ResetCommand();
// Allow derived classes to setup at spawn time
SpawnBot();
} }
/* <48fa37> ../game_shared/bot/bot.cpp:88 */ /* <48fa37> ../game_shared/bot/bot.cpp:88 */
NOBODY Vector CBot::__MAKE_VHOOK(GetAutoaimVector)(float flDelta) Vector CBot::__MAKE_VHOOK(GetAutoaimVector)(float flDelta)
{ {
// operator+(const Vector *const this, UTIL_MakeVectors(pev->v_angle + pev->punchangle);
// const Vector &v); // 90 return gpGlobals->v_forward;
// Vector(Vector *const this,
// const Vector &v); // 92
} }
/* <48ffa8> ../game_shared/bot/bot.cpp:97 */ /* <48ffa8> ../game_shared/bot/bot.cpp:97 */
@ -76,77 +109,125 @@ void CBot::BotThink(void)
} }
/* <48f723> ../game_shared/bot/bot.cpp:119 */ /* <48f723> ../game_shared/bot/bot.cpp:119 */
NOBODY void CBot::__MAKE_VHOOK(MoveForward)(void) void CBot::__MAKE_VHOOK(MoveForward)(void)
{ {
// GetMoveSpeed(CBot *const this); // 121 m_forwardSpeed = GetMoveSpeed();
m_buttonFlags |= IN_FORWARD;
// make mutually exclusive
m_buttonFlags &= ~IN_BACK;
} }
/* <48f761> ../game_shared/bot/bot.cpp:130 */ /* <48f761> ../game_shared/bot/bot.cpp:130 */
NOBODY void CBot::__MAKE_VHOOK(MoveBackward)(void) void CBot::__MAKE_VHOOK(MoveBackward)(void)
{ {
// GetMoveSpeed(CBot *const this); // 132 m_forwardSpeed = -GetMoveSpeed();
m_buttonFlags |= IN_BACK;
// make mutually exclusive
m_buttonFlags &= ~IN_FORWARD;
} }
/* <48f79f> ../game_shared/bot/bot.cpp:140 */ /* <48f79f> ../game_shared/bot/bot.cpp:140 */
NOBODY void CBot::__MAKE_VHOOK(StrafeLeft)(void) void CBot::__MAKE_VHOOK(StrafeLeft)(void)
{ {
// GetMoveSpeed(CBot *const this); // 142 m_strafeSpeed = -GetMoveSpeed();
m_buttonFlags |= IN_MOVELEFT;
// make mutually exclusive
m_buttonFlags &= ~IN_MOVERIGHT;
} }
/* <48f7dd> ../game_shared/bot/bot.cpp:150 */ /* <48f7dd> ../game_shared/bot/bot.cpp:150 */
NOBODY void CBot::__MAKE_VHOOK(StrafeRight)(void) void CBot::__MAKE_VHOOK(StrafeRight)(void)
{ {
// GetMoveSpeed(CBot *const this); // 152 m_strafeSpeed = GetMoveSpeed();
m_buttonFlags |= IN_MOVERIGHT;
// make mutually exclusive
m_buttonFlags &= ~IN_MOVELEFT;
} }
/* <48fe00> ../game_shared/bot/bot.cpp:160 */ /* <48fe00> ../game_shared/bot/bot.cpp:160 */
NOBODY bool CBot::__MAKE_VHOOK(Jump)(bool mustJump) bool CBot::__MAKE_VHOOK(Jump)(bool mustJump)
{ {
// { if (IsJumping() || IsCrouching())
// float const sanityInterval; // 173 return false;
// IsJumping(CBot *const this); // 162
// { if (!mustJump)
// float const minJumpInterval; // 167 {
// } const float minJumpInterval = 0.9f; // 1.5f;
// } if (gpGlobals->time - m_jumpTimestamp < minJumpInterval)
// Jump(CBot *const this, return false;
// bool mustJump); // 160 }
// still need sanity check for jumping frequency
const float sanityInterval = 0.3f;
if (gpGlobals->time - m_jumpTimestamp < sanityInterval)
return false;
// jump
m_buttonFlags |= IN_JUMP;
m_jumpTimestamp = gpGlobals->time;
return true;
} }
// Zero any MoveForward(), Jump(), etc
/* <48f81b> ../game_shared/bot/bot.cpp:187 */ /* <48f81b> ../game_shared/bot/bot.cpp:187 */
NOBODY void CBot::__MAKE_VHOOK(ClearMovement)(void) void CBot::__MAKE_VHOOK(ClearMovement)(void)
{ {
// ResetCommand(CBot *const this); // 189 ResetCommand();
} }
// Returns true if we are in the midst of a jump
/* <48ffe7> ../game_shared/bot/bot.cpp:196 */ /* <48ffe7> ../game_shared/bot/bot.cpp:196 */
NOBODY bool CBot::IsJumping(void) bool CBot::IsJumping(void)
{ {
// if long time after last jump, we can't be jumping
if (gpGlobals->time - m_jumpTimestamp > 3.0f)
return false;
// if we just jumped, we're still jumping
if (gpGlobals->time - m_jumpTimestamp < 1.0f)
return true;
// a little after our jump, we're jumping until we hit the ground
if (pev->flags & FL_ONGROUND)
return false;
return true;
} }
/* <48f859> ../game_shared/bot/bot.cpp:214 */ /* <48f859> ../game_shared/bot/bot.cpp:214 */
NOBODY void CBot::__MAKE_VHOOK(Crouch)(void) void CBot::__MAKE_VHOOK(Crouch)(void)
{ {
m_isCrouching = true;
} }
/* <48f87f> ../game_shared/bot/bot.cpp:220 */ /* <48f87f> ../game_shared/bot/bot.cpp:220 */
NOBODY void CBot::__MAKE_VHOOK(StandUp)(void) void CBot::__MAKE_VHOOK(StandUp)(void)
{ {
m_isCrouching = false;
} }
/* <48f8a5> ../game_shared/bot/bot.cpp:227 */ /* <48f8a5> ../game_shared/bot/bot.cpp:227 */
NOBODY void CBot::__MAKE_VHOOK(UseEnvironment)(void) void CBot::__MAKE_VHOOK(UseEnvironment)(void)
{ {
m_buttonFlags |= IN_USE;
} }
/* <48f8cb> ../game_shared/bot/bot.cpp:234 */ /* <48f8cb> ../game_shared/bot/bot.cpp:234 */
NOBODY void CBot::__MAKE_VHOOK(PrimaryAttack)(void) void CBot::__MAKE_VHOOK(PrimaryAttack)(void)
{ {
m_buttonFlags |= IN_ATTACK;
} }
/* <48f8f1> ../game_shared/bot/bot.cpp:240 */ /* <48f8f1> ../game_shared/bot/bot.cpp:240 */
NOBODY void CBot::__MAKE_VHOOK(ClearPrimaryAttack)(void) void CBot::__MAKE_VHOOK(ClearPrimaryAttack)(void)
{ {
m_buttonFlags &= ~IN_ATTACK;
} }
/* <48f917> ../game_shared/bot/bot.cpp:246 */ /* <48f917> ../game_shared/bot/bot.cpp:246 */
@ -159,40 +240,68 @@ void CBot::__MAKE_VHOOK(TogglePrimaryAttack)(void)
} }
/* <48f93d> ../game_shared/bot/bot.cpp:260 */ /* <48f93d> ../game_shared/bot/bot.cpp:260 */
NOBODY void CBot::__MAKE_VHOOK(SecondaryAttack)(void) void CBot::__MAKE_VHOOK(SecondaryAttack)(void)
{ {
m_buttonFlags |= IN_ATTACK2;
} }
/* <48f963> ../game_shared/bot/bot.cpp:266 */ /* <48f963> ../game_shared/bot/bot.cpp:266 */
NOBODY void CBot::__MAKE_VHOOK(Reload)(void) void CBot::__MAKE_VHOOK(Reload)(void)
{ {
m_buttonFlags |= IN_RELOAD;
} }
// Returns ratio of ammo left to max ammo (1 = full clip, 0 = empty)
/* <490008> ../game_shared/bot/bot.cpp:275 */ /* <490008> ../game_shared/bot/bot.cpp:275 */
NOBODY float CBot::GetActiveWeaponAmmoRatio(void) const float CBot::GetActiveWeaponAmmoRatio(void) const
{ {
// { CBasePlayerWeapon *weapon = GetActiveWeapon();
// class CBasePlayerWeapon *gun; // 277
// iMaxClip(CBasePlayerItem *const this); // 286 if (!weapon)
// } return 0.0f;
// weapons with no ammo are always full
if (weapon->m_iClip < 0)
return 1.0f;
return (float)weapon->m_iClip / (float)weapon->iMaxClip();
} }
// Return true if active weapon has an empty clip
/* <490058> ../game_shared/bot/bot.cpp:293 */ /* <490058> ../game_shared/bot/bot.cpp:293 */
NOBODY bool CBot::IsActiveWeaponClipEmpty(void) const bool CBot::IsActiveWeaponClipEmpty(void) const
{ {
// { CBasePlayerWeapon *weapon = GetActiveWeapon();
// class CBasePlayerWeapon *gun; // 295
// } if (weapon != NULL && weapon->m_iClip == 0)
return true;
return false;
} }
// Return true if active weapon has no ammo at all
/* <490096> ../game_shared/bot/bot.cpp:307 */ /* <490096> ../game_shared/bot/bot.cpp:307 */
NOBODY bool CBot::IsActiveWeaponOutOfAmmo(void) const bool CBot::IsActiveWeaponOutOfAmmo(void) const
{ {
// { CBasePlayerWeapon *gun = GetActiveWeapon();
// class CBasePlayerWeapon *gun; // 309
// } if (gun == NULL)
return true;
if (gun->m_iClip < 0)
return false;
if (gun->m_iClip == 0 && m_rgAmmo[ gun->m_iPrimaryAmmoType ] <= 0)
return true;
return false;
} }
// Return true if looking thru weapon's scope
/* <4900d4> ../game_shared/bot/bot.cpp:327 */ /* <4900d4> ../game_shared/bot/bot.cpp:327 */
bool CBot::IsUsingScope(void) const bool CBot::IsUsingScope(void) const
{ {
@ -252,6 +361,8 @@ byte CBot::ThrottledMsec(void) const
return (byte)iNewMsec; return (byte)iNewMsec;
} }
// Do a "client command" - useful for invoking menu choices, etc.
/* <49016e> ../game_shared/bot/bot.cpp:389 */ /* <49016e> ../game_shared/bot/bot.cpp:389 */
void CBot::ClientCommand(const char *cmd, const char *arg1, const char *arg2, const char *arg3) void CBot::ClientCommand(const char *cmd, const char *arg1, const char *arg2, const char *arg3)
{ {
@ -265,48 +376,94 @@ void CBot::ClientCommand(const char *cmd, const char *arg1, const char *arg2, co
UseBotArgs = false; UseBotArgs = false;
} }
// Returns TRUE if given entity is our enemy
/* <4901ac> ../game_shared/bot/bot.cpp:410 */ /* <4901ac> ../game_shared/bot/bot.cpp:410 */
NOBODY bool CBot::IsEnemy(CBaseEntity *ent) const bool CBot::IsEnemy(CBaseEntity *ent) const
{ {
// { // only Players (real and AI) can be enemies
// class CBasePlayer *player; // 420 if (!ent->IsPlayer())
// } return false;
// IsEnemy(const class CBot *const this,
// class CBaseEntity *ent); // 410 // corpses are no threat
if (!ent->IsAlive())
return false;
CBasePlayer *player = static_cast<CBasePlayer *>(ent);
// if they are on our team, they are our friends
if (player->m_iTeam == m_iTeam)
return false;
// yep, we hate 'em
return true;
} }
// Return number of enemies left alive
/* <49021a> ../game_shared/bot/bot.cpp:434 */ /* <49021a> ../game_shared/bot/bot.cpp:434 */
NOBODY int CBot::GetEnemiesRemaining(void) const int CBot::GetEnemiesRemaining(void) const
{ {
// { int count = 0;
// int count; // 436
// { for (int i = 1; i <= gpGlobals->maxClients; ++i)
// int i; // 438 {
// { CBaseEntity *player = UTIL_PlayerByIndex(i);
// class CBaseEntity *player; // 440
// FNullEnt(entvars_t *pev); // 445 if (player == NULL)
// IsEnemy(const class CBot *const this, continue;
// class CBaseEntity *ent); // 451
// } if (FNullEnt(player->pev))
// } continue;
// }
if (FStrEq(STRING(player->pev->netname), ""))
continue;
if (!IsEnemy(player))
continue;
if (!player->IsAlive())
continue;
count++;
}
return count;
} }
// Return number of friends left alive
/* <490338> ../game_shared/bot/bot.cpp:467 */ /* <490338> ../game_shared/bot/bot.cpp:467 */
NOBODY int CBot::GetFriendsRemaining(void) const int CBot::GetFriendsRemaining(void) const
{ {
// { int count = 0;
// int count; // 469
// { for (int i = 1; i <= gpGlobals->maxClients; ++i)
// int i; // 471 {
// { CBaseEntity *player = UTIL_PlayerByIndex(i);
// class CBaseEntity *player; // 473
// FNullEnt(entvars_t *pev); // 478 if (player == NULL)
// IsEnemy(const class CBot *const this, continue;
// class CBaseEntity *ent); // 484
// } if (FNullEnt(player->pev))
// } continue;
// }
if (FStrEq(STRING(player->pev->netname), ""))
continue;
if (IsEnemy(player))
continue;
if (!player->IsAlive())
continue;
if (player == static_cast<CBaseEntity *>(const_cast<CBot *>(this)))
continue;
count++;
}
return count;
} }
/* <490489> ../game_shared/bot/bot.cpp:503 */ /* <490489> ../game_shared/bot/bot.cpp:503 */
@ -332,6 +489,7 @@ bool CBot::IsLocalPlayerWatchingMe(void) const
return true; return true;
} }
} }
return false; return false;
} }
@ -417,7 +575,7 @@ bool ActiveGrenade::IsValid(void) const
} }
/* <490710> ../game_shared/bot/bot.cpp:622 */ /* <490710> ../game_shared/bot/bot.cpp:622 */
NOXREF const Vector *ActiveGrenade::GetPosition(void) const const Vector *ActiveGrenade::GetPosition(void) const
{ {
return &m_entity->pev->origin; return &m_entity->pev->origin;
} }

View File

@ -50,6 +50,8 @@ extern bool UseBotArgs;
class BotProfile; class BotProfile;
extern bool AreBotsAllowed();
/* <36c175> ../game_shared/bot/bot.h:36 */ /* <36c175> ../game_shared/bot/bot.h:36 */
template <class T> template <class T>
T *CreateBot(const BotProfile *profile) T *CreateBot(const BotProfile *profile)
@ -88,7 +90,7 @@ public:
// constructor initializes all values to zero // constructor initializes all values to zero
CBot(void); CBot(void);
NOBODY virtual void Spawn(void); virtual void Spawn(void);
// invoked when injured by something // invoked when injured by something
virtual int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType) virtual int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType)
@ -100,15 +102,12 @@ public:
{ {
CBasePlayer::Killed(pevAttacker, iGib); CBasePlayer::Killed(pevAttacker, iGib);
} }
NOBODY virtual void Think(void) {}; virtual void Think(void) {};
virtual BOOL IsBot(void) virtual BOOL IsBot(void) { return true; }
{ virtual Vector GetAutoaimVector(float flDelta);
return true;
}
NOBODY virtual Vector GetAutoaimVector(float flDelta);
// invoked when in contact with a CWeaponBox // invoked when in contact with a CWeaponBox
NOBODY virtual void OnTouchingWeapon(CWeaponBox *box) {} virtual void OnTouchingWeapon(CWeaponBox *box) {}
NOBODY virtual bool Initialize(const BotProfile *profile); virtual bool Initialize(const BotProfile *profile);
virtual void SpawnBot(void) = 0; virtual void SpawnBot(void) = 0;
@ -118,28 +117,29 @@ public:
// heavyweight algorithms, invoked less often // heavyweight algorithms, invoked less often
virtual void Update(void) = 0; virtual void Update(void) = 0;
NOBODY virtual void Run(void); virtual void Run(void);
NOBODY virtual void Walk(void); virtual void Walk(void);
NOBODY virtual void Crouch(void); virtual void Crouch(void);
NOBODY virtual void StandUp(void); virtual void StandUp(void);
NOBODY virtual void MoveForward(void); virtual void MoveForward(void);
NOBODY virtual void MoveBackward(void); virtual void MoveBackward(void);
NOBODY virtual void StrafeLeft(void); virtual void StrafeLeft(void);
NOBODY virtual void StrafeRight(void); virtual void StrafeRight(void);
// returns true if jump was started // returns true if jump was started
NOBODY virtual bool Jump(bool mustJump = false); #define MUST_JUMP true
virtual bool Jump(bool mustJump = false);
// zero any MoveForward(), Jump(), etc // zero any MoveForward(), Jump(), etc
NOBODY virtual void ClearMovement(void); virtual void ClearMovement(void);
// Weapon interface // Weapon interface
NOBODY virtual void UseEnvironment(void); virtual void UseEnvironment(void);
NOBODY virtual void PrimaryAttack(void); virtual void PrimaryAttack(void);
NOBODY virtual void ClearPrimaryAttack(void); virtual void ClearPrimaryAttack(void);
virtual void TogglePrimaryAttack(void); virtual void TogglePrimaryAttack(void);
NOBODY virtual void SecondaryAttack(void); virtual void SecondaryAttack(void);
NOBODY virtual void Reload(void); virtual void Reload(void);
// invoked when event occurs in the game (some events have NULL entities) // invoked when event occurs in the game (some events have NULL entities)
virtual void OnEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL) {}; virtual void OnEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL) {};
@ -150,7 +150,7 @@ public:
// return true if we can see any part of the player // return true if we can see any part of the player
virtual bool IsVisible(CBasePlayer *player, bool testFOV = false, unsigned char *visParts = NULL) const = 0; virtual bool IsVisible(CBasePlayer *player, bool testFOV = false, unsigned char *visParts = NULL) const = 0;
enum VisiblePartType enum VisiblePartType:uint8
{ {
NONE = 0x00, NONE = 0x00,
CHEST = 0x01, CHEST = 0x01,
@ -164,12 +164,12 @@ public:
virtual bool IsEnemyPartVisible(VisiblePartType part) const = 0; virtual bool IsEnemyPartVisible(VisiblePartType part) const = 0;
// return true if player is facing towards us // return true if player is facing towards us
NOBODY virtual bool IsPlayerFacingMe(CBasePlayer *other) const; virtual bool IsPlayerFacingMe(CBasePlayer *other) const;
// returns true if other player is pointing right at us // returns true if other player is pointing right at us
NOBODY virtual bool IsPlayerLookingAtMe(CBasePlayer *other) const; virtual bool IsPlayerLookingAtMe(CBasePlayer *other) const;
virtual void ExecuteCommand(void); virtual void ExecuteCommand(void);
NOBODY virtual void SetModel(const char *modelName); virtual void SetModel(const char *modelName);
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
@ -189,45 +189,36 @@ public:
void ClearPrimaryAttack_(void); void ClearPrimaryAttack_(void);
void TogglePrimaryAttack_(void); void TogglePrimaryAttack_(void);
void SecondaryAttack_(void); void SecondaryAttack_(void);
bool IsPlayerFacingMe_(CBasePlayer *other) const;
bool IsPlayerLookingAtMe_(CBasePlayer *other) const;
void Reload_(void); void Reload_(void);
void ExecuteCommand_(void); void ExecuteCommand_(void);
void SetModel_(const char *modelName);
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
public: public:
unsigned int GetID(void) const unsigned int GetID(void) const { return m_id; }
{ bool IsRunning(void) const { return m_isRunning; }
return m_id; bool IsCrouching(void) const { return m_isCrouching; }
}
bool IsRunning(void) const
{
return m_isRunning;
}
bool IsCrouching(void) const
{
return m_isCrouching;
}
// push the current posture context onto the top of the stack // push the current posture context onto the top of the stack
void PushPostureContext(void); void PushPostureContext(void);
// restore the posture context to the next context on the stack // restore the posture context to the next context on the stack
void PopPostureContext(void); void PopPostureContext(void);
NOBODY bool IsJumping(void); bool IsJumping(void);
// return time last jump began // return time last jump began
float GetJumpTimestamp(void) const float GetJumpTimestamp(void) const { return m_jumpTimestamp; }
{
return m_jumpTimestamp;
}
// returns ratio of ammo left to max ammo (1 = full clip, 0 = empty) // returns ratio of ammo left to max ammo (1 = full clip, 0 = empty)
NOBODY float GetActiveWeaponAmmoRatio(void) const; float GetActiveWeaponAmmoRatio(void) const;
// return true if active weapon has any empty clip // return true if active weapon has any empty clip
NOBODY bool IsActiveWeaponClipEmpty(void) const; bool IsActiveWeaponClipEmpty(void) const;
// return true if active weapon has no ammo at all // return true if active weapon has no ammo at all
NOBODY bool IsActiveWeaponOutOfAmmo(void) const; bool IsActiveWeaponOutOfAmmo(void) const;
// is the weapon in the middle of a reload // is the weapon in the middle of a reload
bool IsActiveWeaponReloading(void) const; bool IsActiveWeaponReloading(void) const;
@ -242,13 +233,13 @@ public:
bool IsUsingScope(void) const; bool IsUsingScope(void) const;
// returns TRUE if given entity is our enemy // returns TRUE if given entity is our enemy
NOBODY bool IsEnemy(CBaseEntity *ent) const; bool IsEnemy(CBaseEntity *ent) const;
// return number of enemies left alive // return number of enemies left alive
NOBODY int GetEnemiesRemaining(void) const; int GetEnemiesRemaining(void) const;
// return number of friends left alive // return number of friends left alive
NOBODY int GetFriendsRemaining(void) const; int GetFriendsRemaining(void) const;
// return true if local player is observing this bot // return true if local player is observing this bot
bool IsLocalPlayerWatchingMe(void) const; bool IsLocalPlayerWatchingMe(void) const;
@ -260,18 +251,13 @@ public:
void PrintIfWatched(char *format,...) const; void PrintIfWatched(char *format,...) const;
void BotThink(void); void BotThink(void);
bool IsNetClient(void) const bool IsNetClient(void) const { return false; }
{
return false;
}
int Save(CSave &save) const; int Save(CSave &save) const;
int Restore(CRestore &restor) const; int Restore(CRestore &restor) const;
// return our personality profile // return our personality profile
const BotProfile *GetProfile(void) const const BotProfile *GetProfile(void) const { return m_profile; }
{
return m_profile;
}
#ifndef HOOK_GAMEDLL #ifndef HOOK_GAMEDLL
protected: protected:
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
@ -280,8 +266,8 @@ protected:
// the "personality" profile of this bot // the "personality" profile of this bot
const BotProfile *m_profile; const BotProfile *m_profile;
private:
private:
void ResetCommand(void); void ResetCommand(void);
byte ThrottledMsec(void) const; byte ThrottledMsec(void) const;
@ -329,7 +315,7 @@ private:
};/* size: 2564, cachelines: 41, members: 15 */ };/* size: 2564, cachelines: 41, members: 15 */
/* <48f61d> ../game_shared/bot/bot.h:253 */ /* <48f61d> ../game_shared/bot/bot.h:253 */
inline void CBot::SetModel(const char *modelName) inline void CBot::__MAKE_VHOOK(SetModel)(const char *modelName)
{ {
SET_CLIENT_KEY_VALUE(entindex(), GET_INFO_BUFFER(edict()), "model", (char *)modelName); SET_CLIENT_KEY_VALUE(entindex(), GET_INFO_BUFFER(edict()), "model", (char *)modelName);
} }
@ -364,11 +350,11 @@ inline CBasePlayerWeapon *CBot::GetActiveWeapon(void) const
/* <5c4d70> ../game_shared/bot/bot.h:287 */ /* <5c4d70> ../game_shared/bot/bot.h:287 */
inline bool CBot::IsActiveWeaponReloading(void) const inline bool CBot::IsActiveWeaponReloading(void) const
{ {
CBasePlayerWeapon *gun = GetActiveWeapon(); CBasePlayerWeapon *weapon = GetActiveWeapon();
if (gun == NULL) if (weapon == NULL)
return false; return false;
return (gun->m_fInReload || gun->m_fInSpecialReload) != 0; return (weapon->m_fInReload || weapon->m_fInSpecialReload) != 0;
} }
/* <3c5c5c> ../game_shared/bot/bot.h:297 */ /* <3c5c5c> ../game_shared/bot/bot.h:297 */
@ -392,6 +378,7 @@ inline void CBot::PushPostureContext(void)
PrintIfWatched("PushPostureContext() overflow error!\n"); PrintIfWatched("PushPostureContext() overflow error!\n");
return; return;
} }
m_postureStack[m_postureStackIndex].isRunning = m_isRunning; m_postureStack[m_postureStackIndex].isRunning = m_isRunning;
m_postureStack[m_postureStackIndex].isCrouching = m_isCrouching; m_postureStack[m_postureStackIndex].isCrouching = m_isCrouching;
++m_postureStackIndex; ++m_postureStackIndex;
@ -416,7 +403,7 @@ inline void CBot::PopPostureContext(void)
} }
/* <48fae3> ../game_shared/bot/bot.h:340 */ /* <48fae3> ../game_shared/bot/bot.h:340 */
inline bool CBot::IsPlayerFacingMe(CBasePlayer *other) const inline bool CBot::__MAKE_VHOOK(IsPlayerFacingMe)(CBasePlayer *other) const
{ {
Vector toOther = other->pev->origin - pev->origin; Vector toOther = other->pev->origin - pev->origin;
UTIL_MakeVectors(other->pev->v_angle + other->pev->punchangle); UTIL_MakeVectors(other->pev->v_angle + other->pev->punchangle);
@ -424,11 +411,12 @@ inline bool CBot::IsPlayerFacingMe(CBasePlayer *other) const
if (otherDir.x * toOther.x + otherDir.y * toOther.y < 0.0f) if (otherDir.x * toOther.x + otherDir.y * toOther.y < 0.0f)
return true; return true;
return false; return false;
} }
/* <48fbfc> ../game_shared/bot/bot.h:355 */ /* <48fbfc> ../game_shared/bot/bot.h:355 */
inline bool CBot::IsPlayerLookingAtMe(CBasePlayer *other) const inline bool CBot::__MAKE_VHOOK(IsPlayerLookingAtMe)(CBasePlayer *other) const
{ {
Vector toOther = other->pev->origin - pev->origin; Vector toOther = other->pev->origin - pev->origin;
toOther.NormalizeInPlace(); toOther.NormalizeInPlace();
@ -443,6 +431,7 @@ inline bool CBot::IsPlayerLookingAtMe(CBasePlayer *other) const
if (IsVisible(&vec)) if (IsVisible(&vec))
return true; return true;
} }
return false; return false;
} }
@ -451,6 +440,21 @@ inline bool CBot::IsPlayerLookingAtMe(CBasePlayer *other) const
typedef bool (CBot::*IS_VISIBLE_VECTOR)(const Vector *, bool) const; typedef bool (CBot::*IS_VISIBLE_VECTOR)(const Vector *, bool) const;
typedef bool (CBot::*IS_VISIBLE_CBASE_PLAYER)(CBasePlayer *, bool, unsigned char *) const; typedef bool (CBot::*IS_VISIBLE_CBASE_PLAYER)(CBasePlayer *, bool, unsigned char *) const;
inline bool CBot::IsPlayerFacingMe(CBasePlayer *other) const
{
return IsPlayerFacingMe_(other);
}
inline bool CBot::IsPlayerLookingAtMe(CBasePlayer *other) const
{
return IsPlayerLookingAtMe_(other);
}
inline void CBot::SetModel(const char *modelName)
{
SetModel_(modelName);
}
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
#endif // BOT_H #endif // BOT_H

View File

@ -32,11 +32,15 @@
#pragma once #pragma once
#endif #endif
// We'll define our own version of this, because everyone else does.
// This needs to stay in sync with MAX_CLIENTS, but there's no header with the #define.
#define BOT_MAX_CLIENTS 32 #define BOT_MAX_CLIENTS 32
// version number is MAJOR.MINOR
#define BOT_VERSION_MAJOR 1 #define BOT_VERSION_MAJOR 1
#define BOT_VERSION_MINOR 50 #define BOT_VERSION_MINOR 50
// Difficulty levels
enum BotDifficultyType enum BotDifficultyType
{ {
BOT_EASY = 0, BOT_EASY = 0,
@ -47,22 +51,12 @@ enum BotDifficultyType
NUM_DIFFICULTY_LEVELS NUM_DIFFICULTY_LEVELS
}; };
#ifdef DEFINE_DIFFICULTY_NAMES #ifdef HOOK_GAMEDLL
char *BotDifficultyName[] = #define BotDifficultyName (*pBotDifficultyName)
{
"EASY",
"NORMAL",
"HARD",
"EXPERT",
NULL #endif // HOOK_GAMEDLL
};
#else extern char *BotDifficultyName[5];
extern char *BotDifficultyName[];
#endif // DEFINE_DIFFICULTY_NAMES
#endif // BOT_CONSTANTS_H #endif // BOT_CONSTANTS_H

View File

@ -8,45 +8,74 @@
BotProfileManager *TheBotProfiles = NULL; BotProfileManager *TheBotProfiles = NULL;
char *BotDifficultyName[] =
{
"EASY", "NORMAL", "HARD", "EXPERT", NULL
};
#else // HOOK_GAMEDLL #else // HOOK_GAMEDLL
BotProfileManager *TheBotProfiles; BotProfileManager *TheBotProfiles;
char *BotDifficultyName[5];
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
// Generates a filename-decorated skin name
/* <4a693f> ../game_shared/bot/bot_profile.cpp:52 */ /* <4a693f> ../game_shared/bot/bot_profile.cpp:52 */
NOBODY const char *GetDecoratedSkinName(const char *name, const char *filename) const char *GetDecoratedSkinName(const char *name, const char *filename)
{ {
// { const int BufLen = MAX_PATH + 64;
// int const BufLen; // 57 static char buf[BufLen];
// char buf; // 59 Q_snprintf(buf, BufLen, "%s/%s", filename, name);
// } return buf;
} }
/* <4a7a99> ../game_shared/bot/bot_profile.cpp:65 */ /* <4a7a99> ../game_shared/bot/bot_profile.cpp:65 */
NOBODY const char *BotProfile::GetWeaponPreferenceAsString(int i) const const char *BotProfile::GetWeaponPreferenceAsString(int i) const
{ {
if (i < 0 || i >= m_weaponPreferenceCount)
return NULL;
return WeaponIDToAlias(m_weaponPreference[i]);
} }
// Return true if this profile has a primary weapon preference
/* <4a7acd> ../game_shared/bot/bot_profile.cpp:78 */ /* <4a7acd> ../game_shared/bot/bot_profile.cpp:78 */
NOBODY bool BotProfile::HasPrimaryPreference(void) const bool BotProfile::HasPrimaryPreference(void) const
{ {
// { for (int i = 0; i < m_weaponPreferenceCount; ++i)
// int i; // 80 {
// { int weaponClass = AliasToWeaponClass(WeaponIDToAlias(m_weaponPreference[i]));
// int weaponClass; // 82
// } if (weaponClass == WEAPONCLASS_SUBMACHINEGUN ||
// } weaponClass == WEAPONCLASS_SHOTGUN ||
weaponClass == WEAPONCLASS_MACHINEGUN ||
weaponClass == WEAPONCLASS_RIFLE ||
weaponClass == WEAPONCLASS_SNIPERRIFLE)
return true;
}
return false;
} }
// Return true if this profile has a pistol weapon preference
/* <4a7b22> ../game_shared/bot/bot_profile.cpp:99 */ /* <4a7b22> ../game_shared/bot/bot_profile.cpp:99 */
NOBODY bool BotProfile::HasPistolPreference(void) const bool BotProfile::HasPistolPreference(void) const
{ {
// { for (int i = 0; i < m_weaponPreferenceCount; ++i)
// int i; // 101 {
// } if (AliasToWeaponClass(WeaponIDToAlias(m_weaponPreference[i])) == WEAPONCLASS_PISTOL)
return true;
}
return false;
} }
// Return true if this profile is valid for the specified team
/* <4a7b5e> ../game_shared/bot/bot_profile.cpp:112 */ /* <4a7b5e> ../game_shared/bot/bot_profile.cpp:112 */
bool BotProfile::IsValidForTeam(BotProfileTeamType team) const bool BotProfile::IsValidForTeam(BotProfileTeamType team) const
{ {
@ -54,132 +83,462 @@ bool BotProfile::IsValidForTeam(BotProfileTeamType team) const
} }
/* <4a7bb2> ../game_shared/bot/bot_profile.cpp:122 */ /* <4a7bb2> ../game_shared/bot/bot_profile.cpp:122 */
NOBODY BotProfileManager::BotProfileManager(void) BotProfileManager::BotProfileManager(void)
{ {
// list(list<BotProfile*, std::allocator<BotProfile*>> *const this); // 122 m_nextSkin = 0;
// vector(vector<char*, std::allocator<char*>> *const this); // 122 for (int i = 0; i < NumCustomSkins; ++i)
// { {
// int i; // 125 m_skins[i] = NULL;
// } m_skinFilenames[i] = NULL;
m_skinModelnames[i] = NULL;
}
} }
// Load the bot profile database
/* <4a8acb> ../game_shared/bot/bot_profile.cpp:137 */ /* <4a8acb> ../game_shared/bot/bot_profile.cpp:137 */
NOBODY void BotProfileManager::Init(const char *filename, unsigned int *checksum) void BotProfileManager::Init(const char *filename, unsigned int *checksum)
{ {
// { int dataLength;
// int dataLength; // 139 char *dataPointer = (char *)LOAD_FILE_FOR_ME(const_cast<char *>(filename), &dataLength);
// char *dataPointer; // 140 const char *dataFile = dataPointer;
// const char *dataFile; // 141
// BotProfileList templateList; // 159 if (dataFile == NULL)
// class BotProfile defaultProfile; // 161 {
// ComputeSimpleChecksum(const unsigned char *dataPointer, if (UTIL_IsGame("czero"))
// int dataLength); // 155 {
// BotProfile(BotProfile *const this); // 161 CONSOLE_ECHO("WARNING: Cannot access bot profile database '%s'\n", filename);
// list(list<BotProfile*, std::allocator<BotProfile*>> *const this); // 159 }
// {
// char *token; // 172 return;
// bool isDefault; // 174 }
// bool isTemplate; // 175
// bool isCustomSkin; // 176 // compute simple checksum
// class BotProfile *profile; // 270 if (checksum)
// bool isFirstWeaponPref; // 348 {
// { *checksum = ComputeSimpleChecksum((const unsigned char *)dataPointer, dataLength);
// int const BufLen; // 180 }
// char skinName; // 181
// const char *decoratedName; // 236 // keep list of templates used for inheritance
// bool skinExists; // 237 BotProfileList templateList;
// GetDecoratedSkinName(const char *name, BotProfile defaultProfile;
// const char *filename); // 236
// GetCustomSkinIndex(BotProfileManager *const this, // Parse the BotProfile.db into BotProfile instances
// const char *name, while (true)
// const char *filename); // 237 {
// CloneString(const char *str); // 241 dataFile = SharedParse(dataFile);
// CloneString(const char *str); // 244 if (!dataFile)
// } break;
// {
// const class BotProfile *inherit; // 287 char *token = SharedGetToken();
// {
// char *c; // 292 bool isDefault = (!Q_stricmp(token, "Default"));
// strchr(char *__s, bool isTemplate = (!Q_stricmp(token, "Template"));
// int __c); // 292 bool isCustomSkin = (!Q_stricmp(token, "Skin"));
// {
// iterator iter; // 297 if (isCustomSkin)
// operator++(_List_iterator<BotProfile*> *const this); // 297 {
// } const int BufLen = 64;
// Inherit(BotProfile *const this, char skinName[BufLen];
// const class BotProfile *parent,
// const class BotProfile *baseline); // 314 // get skin name
// } dataFile = SharedParse(dataFile);
// } if (!dataFile)
// { {
// char attributeName; // 366 CONSOLE_ECHO("Error parsing %s - expected skin name\n", filename);
// { FREE_FILE(dataPointer);
// char *c; // 474 return;
// strchr(char *__s, }
// int __c); // 474
// { token = SharedGetToken();
// int i; // 478 Q_snprintf(skinName, BufLen, "%s", token);
// }
// } // get attribute name
// atof(const char *__nptr); // 464 dataFile = SharedParse(dataFile);
// atof(const char *__nptr); // 453 if (!dataFile)
// atoi(const char *__nptr); // 424 {
// atoi(const char *__nptr); // 420 CONSOLE_ECHO("Error parsing %s - expected 'Model'\n", filename);
// atof(const char *__nptr); // 416 FREE_FILE(dataPointer);
// atoi(const char *__nptr); // 407 return;
// GetCustomSkinIndex(BotProfileManager *const this, }
// const char *name,
// const char *filename); // 411 token = SharedGetToken();
// atof(const char *__nptr); // 403 if (Q_stricmp("Model", token))
// atof(const char *__nptr); // 399 {
// } CONSOLE_ECHO("Error parsing %s - expected 'Model'\n", filename);
// BotProfile(BotProfile *const this); // 278 FREE_FILE(dataPointer);
// CloneString(const char *str); // 334 return;
// push_back(list<BotProfile*, std::allocator<BotProfile*>> *const this, }
// const value_type &__x); // 514
// push_back(list<BotProfile*, std::allocator<BotProfile*>> *const this, // eat '='
// const value_type &__x); // 519 dataFile = SharedParse(dataFile);
// } if (!dataFile)
// ~list(list<BotProfile*, std::allocator<BotProfile*>> *const this, {
// int const __in_chrg); // 159 CONSOLE_ECHO("Error parsing %s - expected '='\n", filename);
// { FREE_FILE(dataPointer);
// iterator iter; // 527 return;
// operator++(_List_iterator<BotProfile*> *const this); // 527 }
// }
// ~list(list<BotProfile*, std::allocator<BotProfile*>> *const this, token = SharedGetToken();
// int const __in_chrg); // 159 if (Q_strcmp("=", token))
// } {
CONSOLE_ECHO("Error parsing %s - expected '='\n", filename);
FREE_FILE(dataPointer);
return;
}
// get attribute value
dataFile = SharedParse(dataFile);
if (!dataFile)
{
CONSOLE_ECHO("Error parsing %s - expected attribute value\n", filename);
FREE_FILE(dataPointer);
return;
}
token = SharedGetToken();
const char *decoratedName = GetDecoratedSkinName(skinName, filename);
bool skinExists = GetCustomSkinIndex(decoratedName) > 0;
if (m_nextSkin < NumCustomSkins && !skinExists)
{
// decorate the name
m_skins[ m_nextSkin ] = CloneString(decoratedName);
// construct the model filename
m_skinModelnames[ m_nextSkin ] = CloneString(token);
m_skinFilenames[ m_nextSkin ] = new char[ Q_strlen(token) * 2 + Q_strlen("models/player//.mdl") + 1 ];
Q_sprintf(m_skinFilenames[ m_nextSkin ], "models/player/%s/%s.mdl", token, token);
++m_nextSkin;
}
// eat 'End'
dataFile = SharedParse(dataFile);
if (!dataFile)
{
CONSOLE_ECHO("Error parsing %s - expected 'End'\n", filename);
FREE_FILE(dataPointer);
return;
}
token = SharedGetToken();
if (Q_strcmp("End", token))
{
CONSOLE_ECHO("Error parsing %s - expected 'End'\n", filename);
FREE_FILE(dataPointer);
return;
}
// it's just a custom skin - no need to do inheritance on a bot profile, etc.
continue;
}
// encountered a new profile
BotProfile *profile;
if (isDefault)
{
profile = &defaultProfile;
}
else
{
profile = new BotProfile;
// always inherit from Default
*profile = defaultProfile;
}
// do inheritance in order of appearance
if (!isTemplate && !isDefault)
{
const BotProfile *inherit = NULL;
// template names are separated by "+"
while (true)
{
char *c = Q_strchr(token, '+');
if (c)
*c = '\000';
// find the given template name
for (BotProfileList::iterator iter = templateList.begin(); iter != templateList.end(); ++iter)
{
if (!Q_stricmp((*iter)->GetName(), token))
{
inherit = *iter;
break;
}
}
if (inherit == NULL)
{
CONSOLE_ECHO("Error parsing '%s' - invalid template reference '%s'\n", filename, token);
FREE_FILE(dataPointer);
return;
}
// inherit the data
profile->Inherit(inherit, &defaultProfile);
if (c == NULL)
break;
token = c + 1;
}
}
// get name of this profile
if (!isDefault)
{
dataFile = SharedParse(dataFile);
if (!dataFile)
{
CONSOLE_ECHO("Error parsing '%s' - expected name\n", filename);
FREE_FILE(dataPointer);
return;
}
profile->m_name = CloneString(SharedGetToken());
// HACK HACK
// Until we have a generalized means of storing bot preferences, we're going to hardcode the bot's
// preference towards silencers based on his name.
if (profile->m_name[0] % 2)
{
profile->m_prefersSilencer = true;
}
}
// read attributes for this profile
bool isFirstWeaponPref = true;
while (true)
{
// get next token
dataFile = SharedParse(dataFile);
if (!dataFile)
{
CONSOLE_ECHO("Error parsing %s - expected 'End'\n", filename);
FREE_FILE(dataPointer);
return;
}
token = SharedGetToken();
// check for End delimiter
if (!Q_stricmp(token, "End"))
break;
// found attribute name - keep it
char attributeName[64];
Q_strcpy(attributeName, token);
// eat '='
dataFile = SharedParse(dataFile);
if (!dataFile)
{
CONSOLE_ECHO("Error parsing %s - expected '='\n", filename);
FREE_FILE(dataPointer);
return;
}
token = SharedGetToken();
if (Q_strcmp("=", token))
{
CONSOLE_ECHO("Error parsing %s - expected '='\n", filename);
FREE_FILE(dataPointer);
return;
}
// get attribute value
dataFile = SharedParse(dataFile);
if (!dataFile)
{
CONSOLE_ECHO("Error parsing %s - expected attribute value\n", filename);
FREE_FILE(dataPointer);
return;
}
token = SharedGetToken();
// store value in appropriate attribute
if (!Q_stricmp("Aggression", attributeName))
{
profile->m_aggression = Q_atof(token) / 100.0f;
}
else if (!Q_stricmp("Skill", attributeName))
{
profile->m_skill = Q_atof(token) / 100.0f;
}
else if (!Q_stricmp("Skin", attributeName))
{
profile->m_skin = Q_atoi(token);
if (profile->m_skin == 0)
{
// Q_atoi() failed - try to look up a custom skin by name
profile->m_skin = GetCustomSkinIndex(token, filename);
}
}
else if (!Q_stricmp("Teamwork", attributeName))
{
profile->m_teamwork = Q_atof(token) / 100.0f;
}
else if (!Q_stricmp("Cost", attributeName))
{
profile->m_cost = Q_atoi(token);
}
else if (!Q_stricmp("VoicePitch", attributeName))
{
profile->m_voicePitch = Q_atoi(token);
}
else if (!Q_stricmp("VoiceBank", attributeName))
{
profile->m_voiceBank = FindVoiceBankIndex(token);
}
else if (!Q_stricmp("WeaponPreference", attributeName))
{
// weapon preferences override parent prefs
if (isFirstWeaponPref)
{
isFirstWeaponPref = false;
profile->m_weaponPreferenceCount = 0;
}
if (!Q_stricmp(token, "none"))
{
profile->m_weaponPreferenceCount = 0;
}
else
{
if (profile->m_weaponPreferenceCount < BotProfile::MAX_WEAPON_PREFS)
{
profile->m_weaponPreference[ profile->m_weaponPreferenceCount++ ] = AliasToWeaponID(token);
}
}
}
else if (!Q_stricmp("ReactionTime", attributeName))
{
profile->m_reactionTime = Q_atof(token);
#ifndef GAMEUI_EXPORTS
// subtract off latency due to "think" update rate.
// In GameUI, we don't really care.
profile->m_reactionTime -= g_flBotFullThinkInterval;
#endif // GAMEUI_EXPORTS
}
else if (!Q_stricmp("AttackDelay", attributeName))
{
profile->m_attackDelay = Q_atof(token);
}
else if (!Q_stricmp("Difficulty", attributeName))
{
// override inheritance
profile->m_difficultyFlags = 0;
// parse bit flags
while (true)
{
char *c = Q_strchr(token, '+');
if (c)
*c = '\000';
for (int i = 0; i < NUM_DIFFICULTY_LEVELS; ++i)
{
if (!Q_stricmp(BotDifficultyName[i], token))
profile->m_difficultyFlags |= (1 << i);
}
if (c == NULL)
break;
token = c + 1;
}
}
else if (!Q_stricmp("Team", attributeName))
{
if (!Q_stricmp(token, "T"))
{
profile->m_teams = BOT_TEAM_T;
}
else if (!Q_stricmp(token, "CT"))
{
profile->m_teams = BOT_TEAM_CT;
}
else
{
profile->m_teams = BOT_TEAM_ANY;
}
}
else
{
CONSOLE_ECHO("Error parsing %s - unknown attribute '%s'\n", filename, attributeName);
}
}
if (!isDefault)
{
if (isTemplate)
{
// add to template list
templateList.push_back(profile);
}
else
{
// add profile to the master list
m_profileList.push_back(profile);
}
}
}
FREE_FILE(dataPointer);
// free the templates
for (BotProfileList::iterator iter = templateList.begin(); iter != templateList.end(); ++iter)
delete *iter;
} }
/* <4a7dfd> ../game_shared/bot/bot_profile.cpp:532 */ /* <4a7dfd> ../game_shared/bot/bot_profile.cpp:532 */
NOBODY BotProfileManager::~BotProfileManager(void) BotProfileManager::~BotProfileManager(void)
{ {
// { Reset();
// iterator it; // 536
// begin(vector<char*, std::allocator<char*>> *const this); // 537 for (VoiceBankList::iterator it = m_voiceBanks.begin(); it != m_voiceBanks.end(); ++it)
// end(vector<char*, std::allocator<char*>> *const this); // 537 delete[] *it;
// operator++(__normal_iterator<char**, std::vector<char*, std::allocator<char*>> > *const this); // 537
// clear(vector<char*, std::allocator<char*>> *const this); // 541 m_voiceBanks.clear();
// }
// ~vector(vector<char*, std::allocator<char*>> *const this,
// int const __in_chrg); // 532
// ~list(list<BotProfile*, std::allocator<BotProfile*>> *const this,
// int const __in_chrg); // 532
} }
// Free all bot profiles
/* <4a7c76> ../game_shared/bot/bot_profile.cpp:548 */ /* <4a7c76> ../game_shared/bot/bot_profile.cpp:548 */
NOBODY void BotProfileManager::Reset(void) void BotProfileManager::Reset(void)
{ {
// clear(list<BotProfile*, std::allocator<BotProfile*>> *const this); // 553 for (BotProfileList::iterator iter = m_profileList.begin(); iter != m_profileList.end(); ++iter)
// { delete *iter;
// iterator iter; // 550
// operator++(_List_iterator<BotProfile*> *const this); // 550 m_profileList.clear();
// }
// { for (int i = 0; i < NumCustomSkins; ++i)
// int i; // 555 {
// } if (m_skins[i])
{
delete[] m_skins[i];
m_skins[i] = NULL;
}
if (m_skinFilenames[i])
{
delete[] m_skinFilenames[i];
m_skinFilenames[i] = NULL;
}
if (m_skinModelnames[i])
{
delete[] m_skinModelnames[i];
m_skinModelnames[i] = NULL;
}
}
} }
// Returns custom skin name at a particular index
/* <4a7fdf> ../game_shared/bot/bot_profile.cpp:579 */ /* <4a7fdf> ../game_shared/bot/bot_profile.cpp:579 */
const char *BotProfileManager::GetCustomSkin(int index) const char *BotProfileManager::GetCustomSkin(int index)
{ {
@ -191,6 +550,8 @@ const char *BotProfileManager::GetCustomSkin(int index)
return m_skins[ index - FirstCustomSkin ]; return m_skins[ index - FirstCustomSkin ];
} }
// Returns custom skin filename at a particular index
/* <4a8019> ../game_shared/bot/bot_profile.cpp:593 */ /* <4a8019> ../game_shared/bot/bot_profile.cpp:593 */
const char *BotProfileManager::GetCustomSkinFname(int index) const char *BotProfileManager::GetCustomSkinFname(int index)
{ {
@ -202,6 +563,8 @@ const char *BotProfileManager::GetCustomSkinFname(int index)
return m_skinFilenames[ index - FirstCustomSkin ]; return m_skinFilenames[ index - FirstCustomSkin ];
} }
// Returns custom skin modelname at a particular index
/* <4a8053> ../game_shared/bot/bot_profile.cpp:607 */ /* <4a8053> ../game_shared/bot/bot_profile.cpp:607 */
const char *BotProfileManager::GetCustomSkinModelname(int index) const char *BotProfileManager::GetCustomSkinModelname(int index)
{ {
@ -213,37 +576,55 @@ const char *BotProfileManager::GetCustomSkinModelname(int index)
return m_skinModelnames[ index - FirstCustomSkin ]; return m_skinModelnames[ index - FirstCustomSkin ];
} }
// Looks up a custom skin index by filename-decorated name (will decorate the name if filename is given)
/* <4a80db> ../game_shared/bot/bot_profile.cpp:621 */ /* <4a80db> ../game_shared/bot/bot_profile.cpp:621 */
NOBODY int BotProfileManager::GetCustomSkinIndex(const char *name, const char *filename) int BotProfileManager::GetCustomSkinIndex(const char *name, const char *filename)
{ {
// { const char *skinName = name;
// const char *skinName; // 623 if (filename)
// GetDecoratedSkinName(const char *name, {
// const char *filename); // 626 skinName = GetDecoratedSkinName(name, filename);
// { }
// int i; // 629
// } for (int i = 0; i < NumCustomSkins; ++i)
// } {
if (m_skins[i])
{
if (!Q_stricmp(skinName, m_skins[i]))
{
return FirstCustomSkin + i;
}
}
}
return 0;
} }
// return index of the (custom) bot phrase db, inserting it if needed
/* <4a8916> ../game_shared/bot/bot_profile.cpp:647 */ /* <4a8916> ../game_shared/bot/bot_profile.cpp:647 */
NOBODY int BotProfileManager::FindVoiceBankIndex(const char *filename) int BotProfileManager::FindVoiceBankIndex(const char *filename)
{ {
// { int index = 0;
// int index; // 649 for (VoiceBankList::const_iterator it = m_voiceBanks.begin(); it != m_voiceBanks.end(); ++it, ++index)
// const_iterator it; // 651 {
// begin(vector<char*, std::allocator<char*>> *const this); // 652 if (!Q_stricmp(filename, *it))
// end(vector<char*, std::allocator<char*>> *const this); // 652 {
// operator++(__normal_iterator<char* const*, std::vector<char*, std::allocator<char*>> > *const this); // 652 return index;
// CloneString(const char *str); // 660 }
// push_back(vector<char*, std::allocator<char*>> *const this, }
// const value_type &__x); // 660
// } m_voiceBanks.push_back(CloneString(filename));
return index;
} }
// Return random unused profile that matches the given difficulty level
/* <4a8177> ../game_shared/bot/bot_profile.cpp:669 */ /* <4a8177> ../game_shared/bot/bot_profile.cpp:669 */
const BotProfile *BotProfileManager::GetRandomProfile(BotDifficultyType difficulty, BotProfileTeamType team) const const BotProfile *BotProfileManager::GetRandomProfile(BotDifficultyType difficulty, BotProfileTeamType team) const
{ {
#ifdef RANDOM_LONG
BotProfileList::const_iterator iter; BotProfileList::const_iterator iter;
// count up valid profiles // count up valid profiles
@ -274,4 +655,8 @@ const BotProfile *BotProfileManager::GetRandomProfile(BotDifficultyType difficul
} }
return NULL; return NULL;
#else
// we don't need random profiles when we're not in the game dll
return NULL;
#endif // RANDOM_LONG
} }

View File

@ -83,71 +83,27 @@ public:
m_voiceBank = 0; m_voiceBank = 0;
m_prefersSilencer = false; m_prefersSilencer = false;
} }
const char *GetName(void) const { return m_name; }
const char *GetName(void) const float GetAggression(void) const { return m_aggression; }
{ float GetSkill(void) const { return m_skill; }
return m_name; float GetTeamwork(void) const { return m_teamwork; }
} int GetWeaponPreference(int i) const { return m_weaponPreference[i]; }
float GetAggression(void) const const char *GetWeaponPreferenceAsString(int i) const;
{ int GetWeaponPreferenceCount(void) const { return m_weaponPreferenceCount; }
return m_aggression; bool HasPrimaryPreference(void) const;
} bool HasPistolPreference(void) const;
float GetSkill(void) const int GetCost(void) const { return m_cost; }
{ int GetSkin(void) const { return m_skin; }
return m_skill; bool IsDifficulty(BotDifficultyType diff) const;
} int GetVoicePitch(void) const { return m_voicePitch; }
float GetTeamwork(void) const float GetReactionTime(void) const { return m_reactionTime; }
{ float GetAttackDelay(void) const { return m_attackDelay; }
return m_teamwork; int GetVoiceBank(void) const { return m_voiceBank; }
}
int GetWeaponPreference(int i)
{
return m_weaponPreference[i];
}
NOBODY const char *GetWeaponPreferenceAsString(int i) const;
int GetWeaponPreferenceCount(void) const
{
return m_weaponPreferenceCount;
}
NOBODY bool HasPrimaryPreference(void) const;
NOBODY bool HasPistolPreference(void) const;
int GetCost(void) const
{
return m_cost;
}
int GetSkin(void) const
{
return m_skin;
}
NOBODY bool IsDifficulty(BotDifficultyType diff) const;
int GetVoicePitch(void) const
{
return m_voicePitch;
}
float GetReactionTime(void) const
{
return m_reactionTime;
}
float GetAttackDelay(void) const
{
return m_attackDelay;
}
int GetVoiceBank(void) const
{
return m_voiceBank;
}
bool IsValidForTeam(BotProfileTeamType team) const; bool IsValidForTeam(BotProfileTeamType team) const;
bool PrefersSilencer(void) const bool PrefersSilencer(void) const { return m_prefersSilencer; }
{
return m_prefersSilencer;
}
// TODO: it func private
NOBODY void Inherit(const BotProfile *parent, const BotProfile *baseline);
private: private:
void Inherit(const BotProfile *parent, const BotProfile *baseline);
friend class BotProfileManager; friend class BotProfileManager;
char *m_name; char *m_name;
@ -223,7 +179,7 @@ inline void BotProfile::Inherit(const BotProfile *parent, const BotProfile *base
m_voiceBank = parent->m_voiceBank; m_voiceBank = parent->m_voiceBank;
} }
typedef std::list<BotProfile *> BotProfileList; typedef std::STD_LIST<BotProfile *> BotProfileList;
/* <36a051> ../game_shared/bot/bot_profile.h:180 */ /* <36a051> ../game_shared/bot/bot_profile.h:180 */
class BotProfileManager class BotProfileManager
@ -238,8 +194,10 @@ public:
const BotProfile *GetProfile(const char *name, BotProfileTeamType team) const const BotProfile *GetProfile(const char *name, BotProfileTeamType team) const
{ {
for (BotProfileList::const_iterator iter = m_profileList.begin(); iter != m_profileList.end(); ++iter) for (BotProfileList::const_iterator iter = m_profileList.begin(); iter != m_profileList.end(); ++iter)
{
if (!Q_stricmp(name, (*iter)->GetName()) && (*iter)->IsValidForTeam(team)) if (!Q_stricmp(name, (*iter)->GetName()) && (*iter)->IsValidForTeam(team))
return *iter; return *iter;
}
return NULL; return NULL;
} }
@ -254,7 +212,7 @@ public:
const char *GetCustomSkinFname(int index); const char *GetCustomSkinFname(int index);
int GetCustomSkinIndex(const char *name, const char *filename = NULL); int GetCustomSkinIndex(const char *name, const char *filename = NULL);
typedef std::vector<char *> VoiceBankList; typedef std::STD_VECTOR<char *> VoiceBankList;
const VoiceBankList *GetVoiceBanks() const const VoiceBankList *GetVoiceBanks() const
{ {
@ -263,11 +221,6 @@ public:
int FindVoiceBankIndex(const char *filename); int FindVoiceBankIndex(const char *filename);
protected: protected:
#if defined(_WIN32) && defined(HOOK_GAMEDLL)
int unknown_padding1;
#endif // HOOK_GAMEDLL
BotProfileList m_profileList; BotProfileList m_profileList;
VoiceBankList m_voiceBanks; VoiceBankList m_voiceBanks;

View File

@ -144,7 +144,7 @@ int UTIL_HumansInGame(bool ignoreSpectators)
} }
/* <4ad507> ../game_shared/bot/bot_util.cpp:174 */ /* <4ad507> ../game_shared/bot/bot_util.cpp:174 */
NOBODY int UTIL_HumansOnTeam(int teamID, bool isAlive) int UTIL_HumansOnTeam(int teamID, bool isAlive)
{ {
int iCount = 0; int iCount = 0;
for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex) for (int iIndex = 1; iIndex <= gpGlobals->maxClients; ++iIndex)
@ -178,7 +178,7 @@ NOBODY int UTIL_HumansOnTeam(int teamID, bool isAlive)
} }
/* <4ad5db> ../game_shared/bot/bot_util.cpp:210 */ /* <4ad5db> ../game_shared/bot/bot_util.cpp:210 */
NOBODY int UTIL_BotsInGame(void) int UTIL_BotsInGame(void)
{ {
int iCount = 0; int iCount = 0;
@ -265,7 +265,7 @@ bool UTIL_KickBotFromTeam(TeamName kickTeam)
} }
/* <4ad7ad> ../game_shared/bot/bot_util.cpp:305 */ /* <4ad7ad> ../game_shared/bot/bot_util.cpp:305 */
NOBODY bool UTIL_IsTeamAllBots(int team) bool UTIL_IsTeamAllBots(int team)
{ {
int botCount = 0; int botCount = 0;
for (int i = 1; i <= gpGlobals->maxClients; ++i) for (int i = 1; i <= gpGlobals->maxClients; ++i)
@ -330,7 +330,7 @@ NOBODY bool UTIL_IsTeamAllBots(int team)
// If 'distance' is non-NULL, the distance to the closest player is returned in it. // If 'distance' is non-NULL, the distance to the closest player is returned in it.
/* <4ad86a> ../game_shared/bot/bot_util.cpp:343 */ /* <4ad86a> ../game_shared/bot/bot_util.cpp:343 */
NOBODY /*extern*/ CBasePlayer *UTIL_GetClosestPlayer(const Vector *pos, int team, float *distance) /*extern*/ CBasePlayer *UTIL_GetClosestPlayer(const Vector *pos, int team, float *distance)
{ {
CBasePlayer *closePlayer = NULL; CBasePlayer *closePlayer = NULL;
float closeDistSq = 1.0e12f; // 999999999999.9f float closeDistSq = 1.0e12f; // 999999999999.9f
@ -388,7 +388,7 @@ void UTIL_ConstructBotNetName(char *name, int nameLength, const BotProfile *prof
} }
/* <4adb6c> ../game_shared/bot/bot_util.cpp:440 */ /* <4adb6c> ../game_shared/bot/bot_util.cpp:440 */
NOBODY bool UTIL_IsVisibleToTeam(const Vector &spot, int team, float maxRange) bool UTIL_IsVisibleToTeam(const Vector &spot, int team, float maxRange)
{ {
for (int i = 1; i <= gpGlobals->maxClients; ++i) for (int i = 1; i <= gpGlobals->maxClients; ++i)
{ {
@ -432,26 +432,26 @@ CBasePlayer *UTIL_GetLocalPlayer(void)
} }
/* <4adcab> ../game_shared/bot/bot_util.cpp:491 */ /* <4adcab> ../game_shared/bot/bot_util.cpp:491 */
NOBODY Vector UTIL_ComputeOrigin(entvars_t *pevVars) NOXREF Vector UTIL_ComputeOrigin(entvars_t *pevVars)
{ {
if ((pevVars->origin.x == 0.0) && (pevVars->origin.y == 0.0) && (pevVars->origin.z == 0.0)) if (pevVars->origin.x == 0.0f && pevVars->origin.y == 0.0f && pevVars->origin.z == 0.0f)
return (pevVars->absmax + pevVars->absmin) *0.5; return (pevVars->absmax + pevVars->absmin) * 0.5f;
else else
return pevVars->origin; return pevVars->origin;
} }
NOBODY Vector UTIL_ComputeOrigin(CBaseEntity *pEntity) NOXREF Vector UTIL_ComputeOrigin(CBaseEntity *pEntity)
{ {
return UTIL_ComputeOrigin(pEntity->pev); return UTIL_ComputeOrigin(pEntity->pev);
} }
NOBODY Vector UTIL_ComputeOrigin(edict_t *pentEdict) NOXREF Vector UTIL_ComputeOrigin(edict_t *pentEdict)
{ {
return UTIL_ComputeOrigin(VARS(pentEdict)); return UTIL_ComputeOrigin(VARS(pentEdict));
} }
/* <4adf8a> ../game_shared/bot/bot_util.cpp:513 */ /* <4adf8a> ../game_shared/bot/bot_util.cpp:513 */
NOBODY void UTIL_DrawBeamFromEnt(int iIndex, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue) NOXREF void UTIL_DrawBeamFromEnt(int iIndex, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue)
{ {
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecEnd); MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecEnd);
WRITE_BYTE(TE_BEAMENTPOINT); WRITE_BYTE(TE_BEAMENTPOINT);
@ -474,7 +474,7 @@ NOBODY void UTIL_DrawBeamFromEnt(int iIndex, Vector vecEnd, int iLifetime, byte
} }
/* <4ae02e> ../game_shared/bot/bot_util.cpp:537 */ /* <4ae02e> ../game_shared/bot/bot_util.cpp:537 */
NOBODY void UTIL_DrawBeamPoints(Vector vecStart, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue) void UTIL_DrawBeamPoints(Vector vecStart, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue)
{ {
MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecStart); MESSAGE_BEGIN(MSG_PVS, SVC_TEMPENTITY, vecStart);
WRITE_BYTE(TE_BEAMPOINTS); WRITE_BYTE(TE_BEAMPOINTS);
@ -585,8 +585,8 @@ bool IsGameEventAudible(GameEventType event, CBaseEntity *entity, CBaseEntity *o
switch (event) switch (event)
{ {
/// TODO: Check weapon type (knives are pretty quiet) // TODO: Check weapon type (knives are pretty quiet)
/// TODO: Use actual volume, account for silencers, etc. // TODO: Use actual volume, account for silencers, etc.
case EVENT_WEAPON_FIRED: case EVENT_WEAPON_FIRED:
{ {
if (player->m_pActiveItem == NULL) if (player->m_pActiveItem == NULL)

View File

@ -45,10 +45,7 @@ class BotProfile;
enum PriorityType enum PriorityType
{ {
PRIORITY_LOW, PRIORITY_LOW, PRIORITY_MEDIUM, PRIORITY_HIGH, PRIORITY_UNINTERRUPTABLE
PRIORITY_MEDIUM,
PRIORITY_HIGH,
PRIORITY_UNINTERRUPTABLE
}; };
// Simple class for tracking intervals of game time // Simple class for tracking intervals of game time
@ -97,7 +94,8 @@ public:
{ {
return (gpGlobals->time - m_timestamp > duration) ? true : false; return (gpGlobals->time - m_timestamp > duration) ? true : false;
} }
/*private:*/
private:
float m_timestamp; float m_timestamp;
};/* size: 4, cachelines: 1, members: 1 */ };/* size: 4, cachelines: 1, members: 1 */
@ -179,12 +177,14 @@ inline bool IsIntersecting2D(const Vector &startA, const Vector &endA, const Vec
// parallel // parallel
return false; return false;
} }
float numS = (startA.y - startB.y) * (endB.x - startB.x) - (startA.x - startB.x) * (endB.y - startB.y); float numS = (startA.y - startB.y) * (endB.x - startB.x) - (startA.x - startB.x) * (endB.y - startB.y);
if (numS == 0.0f) if (numS == 0.0f)
{ {
// coincident // coincident
return true; return true;
} }
float numT = (startA.y - startB.y) * (endA.x - startA.x) - (startA.x - startB.x) * (endA.y - startA.y); float numT = (startA.y - startB.y) * (endA.x - startA.x) - (startA.x - startB.x) * (endA.y - startA.y);
float s = numS / denom; float s = numS / denom;
if (s < 0.0f || s > 1.0f) if (s < 0.0f || s > 1.0f)
@ -192,6 +192,7 @@ inline bool IsIntersecting2D(const Vector &startA, const Vector &endA, const Vec
// intersection is not within line segment of startA to endA // intersection is not within line segment of startA to endA
return false; return false;
} }
float t = numT / denom; float t = numT / denom;
if (t < 0.0f || t > 1.0f) if (t < 0.0f || t > 1.0f)
{ {
@ -214,7 +215,7 @@ inline bool IsIntersecting2D(const Vector &startA, const Vector &endA, const Vec
template <typename Functor> template <typename Functor>
bool ForEachPlayer(Functor &func) bool ForEachPlayer(Functor &func)
{ {
for (int i = 1; i <= gpGlobals->maxClients; i++) for (int i = 1; i <= gpGlobals->maxClients; ++i)
{ {
CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i)); CBasePlayer *player = static_cast<CBasePlayer *>(UTIL_PlayerByIndex(i));
if (!IsEntityValid((CBaseEntity *)player)) if (!IsEntityValid((CBaseEntity *)player))
@ -247,38 +248,106 @@ inline bool IsZombieGame(void)
#define s_iBeamSprite (*ps_iBeamSprite) #define s_iBeamSprite (*ps_iBeamSprite)
#define cosTable (*pcosTable) #define cosTable (*pcosTable)
#define cv_bot_traceview (*pcv_bot_traceview)
#define cv_bot_stop (*pcv_bot_stop)
#define cv_bot_show_nav (*pcv_bot_show_nav)
#define cv_bot_show_danger (*pcv_bot_show_danger)
#define cv_bot_nav_edit (*pcv_bot_nav_edit)
#define cv_bot_nav_zdraw (*pcv_bot_nav_zdraw)
#define cv_bot_walk (*pcv_bot_walk)
#define cv_bot_difficulty (*pcv_bot_difficulty)
#define cv_bot_debug (*pcv_bot_debug)
#define cv_bot_quicksave (*pcv_bot_quicksave)
#define cv_bot_quota (*pcv_bot_quota)
#define cv_bot_quota_match (*pcv_bot_quota_match)
#define cv_bot_prefix (*pcv_bot_prefix)
#define cv_bot_allow_rogues (*pcv_bot_allow_rogues)
#define cv_bot_allow_pistols (*pcv_bot_allow_pistols)
#define cv_bot_allow_shotguns (*pcv_bot_allow_shotguns)
#define cv_bot_allow_sub_machine_guns (*pcv_bot_allow_sub_machine_guns)
#define cv_bot_allow_rifles (*pcv_bot_allow_rifles)
#define cv_bot_allow_machine_guns (*pcv_bot_allow_machine_guns)
#define cv_bot_allow_grenades (*pcv_bot_allow_grenades)
#define cv_bot_allow_snipers (*pcv_bot_allow_snipers)
#define cv_bot_allow_shield (*pcv_bot_allow_shield)
#define cv_bot_join_team (*pcv_bot_join_team)
#define cv_bot_join_after_player (*pcv_bot_join_after_player)
#define cv_bot_auto_vacate (*pcv_bot_auto_vacate)
#define cv_bot_zombie (*pcv_bot_zombie)
#define cv_bot_defer_to_human (*pcv_bot_defer_to_human)
#define cv_bot_chatter (*pcv_bot_chatter)
#define cv_bot_profile_db (*pcv_bot_profile_db)
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
extern short s_iBeamSprite; extern short s_iBeamSprite;
extern float cosTable[COS_TABLE_SIZE]; extern float cosTable[COS_TABLE_SIZE];
extern cvar_t cv_bot_traceview;
extern cvar_t cv_bot_stop;
extern cvar_t cv_bot_show_nav;
extern cvar_t cv_bot_show_danger;
extern cvar_t cv_bot_nav_edit;
extern cvar_t cv_bot_nav_zdraw;
extern cvar_t cv_bot_walk;
extern cvar_t cv_bot_difficulty;
extern cvar_t cv_bot_debug;
extern cvar_t cv_bot_quicksave;
extern cvar_t cv_bot_quota;
extern cvar_t cv_bot_quota_match;
extern cvar_t cv_bot_prefix;
extern cvar_t cv_bot_allow_rogues;
extern cvar_t cv_bot_allow_pistols;
extern cvar_t cv_bot_allow_shotguns;
extern cvar_t cv_bot_allow_sub_machine_guns;
extern cvar_t cv_bot_allow_rifles;
extern cvar_t cv_bot_allow_machine_guns;
extern cvar_t cv_bot_allow_grenades;
extern cvar_t cv_bot_allow_snipers;
extern cvar_t cv_bot_allow_shield;
extern cvar_t cv_bot_join_team;
extern cvar_t cv_bot_join_after_player;
extern cvar_t cv_bot_auto_vacate;
extern cvar_t cv_bot_zombie;
extern cvar_t cv_bot_defer_to_human;
extern cvar_t cv_bot_chatter;
extern cvar_t cv_bot_profile_db;
#define IS_ALIVE true
int UTIL_HumansOnTeam(int teamID, bool isAlive = false);
#define IGNORE_SPECTATORS true
int UTIL_HumansInGame(bool ignoreSpectators = false);
bool UTIL_IsNameTaken(const char *name, bool ignoreHumans = false); bool UTIL_IsNameTaken(const char *name, bool ignoreHumans = false);
int UTIL_ClientsInGame(void); int UTIL_ClientsInGame(void);
int UTIL_ActivePlayersInGame(void); int UTIL_ActivePlayersInGame(void);
int UTIL_HumansInGame(bool ignoreSpectators); int UTIL_BotsInGame(void);
NOBODY int UTIL_HumansOnTeam(int teamID, bool isAlive = false);
NOBODY int UTIL_BotsInGame(void);
bool UTIL_KickBotFromTeam(TeamName kickTeam); bool UTIL_KickBotFromTeam(TeamName kickTeam);
NOBODY bool UTIL_IsTeamAllBots(int team); bool UTIL_IsTeamAllBots(int team);
CBasePlayer *UTIL_GetClosestPlayer(const Vector *pos, float *distance = NULL); CBasePlayer *UTIL_GetClosestPlayer(const Vector *pos, float *distance = NULL);
NOBODY CBasePlayer *UTIL_GetClosestPlayer(const Vector *pos, int team, float *distance = NULL); CBasePlayer *UTIL_GetClosestPlayer(const Vector *pos, int team, float *distance = NULL);
const char *UTIL_GetBotPrefix(); const char *UTIL_GetBotPrefix();
void UTIL_ConstructBotNetName(char *name, int nameLength, const BotProfile *profile); void UTIL_ConstructBotNetName(char *name, int nameLength, const BotProfile *profile);
NOBODY bool UTIL_IsVisibleToTeam(const Vector &spot, int team, float maxRange = -1.0f); bool UTIL_IsVisibleToTeam(const Vector &spot, int team, float maxRange = -1.0f);
CBasePlayer *UTIL_GetLocalPlayer(void); CBasePlayer *UTIL_GetLocalPlayer(void);
NOBODY Vector UTIL_ComputeOrigin(entvars_t *pevVars); NOXREF Vector UTIL_ComputeOrigin(entvars_t *pevVars);
NOBODY Vector UTIL_ComputeOrigin(CBaseEntity *pEntity); NOXREF Vector UTIL_ComputeOrigin(CBaseEntity *pEntity);
NOBODY Vector UTIL_ComputeOrigin(edict_t *pentEdict); NOXREF Vector UTIL_ComputeOrigin(edict_t *pentEdict);
NOBODY void UTIL_DrawBeamFromEnt(int iIndex, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue); NOXREF void UTIL_DrawBeamFromEnt(int iIndex, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue);
NOBODY void UTIL_DrawBeamPoints(Vector vecStart, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue); void UTIL_DrawBeamPoints(Vector vecStart, Vector vecEnd, int iLifetime, byte bRed, byte bGreen, byte bBlue);
// Echos text to the console, and prints it on the client's screen. This is NOT tied to the developer cvar.
// If you are adding debugging output in cstrike, use UTIL_DPrintf() (debug.h) instead.
void CONSOLE_ECHO(char *pszMsg, ...); void CONSOLE_ECHO(char *pszMsg, ...);
void CONSOLE_ECHO_LOGGED(char *pszMsg, ...); void CONSOLE_ECHO_LOGGED(char *pszMsg, ...);
void BotPrecache(void); void BotPrecache(void);
void InitBotTrig(void); void InitBotTrig(void);
float BotCOS(float angle); float BotCOS(float angle);
float BotSIN(float angle); float BotSIN(float angle);
bool IsGameEventAudible(enum GameEventType event, CBaseEntity *entity, CBaseEntity *other, float *range, PriorityType *priority, bool *isHostile); bool IsGameEventAudible(enum GameEventType event, CBaseEntity *entity, CBaseEntity *other, float *range, PriorityType *priority, bool *isHostile);
NOBODY void HintMessageToAllPlayers(const char *message); void HintMessageToAllPlayers(const char *message);
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL

View File

@ -36,7 +36,7 @@
#pragma warning(disable : 4530) #pragma warning(disable : 4530)
// to help identify nav files // to help identify nav files
#define NAV_MAGIC_NUMBER 0xFEEDFACE #define NAV_MAGIC_NUMBER 0xFEEDFACE
// A place is a named group of navigation areas // A place is a named group of navigation areas
typedef unsigned int Place; typedef unsigned int Place;
@ -47,6 +47,7 @@ typedef unsigned int Place;
#define WALK_THRU_DOORS 0x01 #define WALK_THRU_DOORS 0x01
#define WALK_THRU_BREAKABLES 0x02 #define WALK_THRU_BREAKABLES 0x02
#define WALK_THRU_EVERYTHING (WALK_THRU_DOORS | WALK_THRU_BREAKABLES)
//class CNavArea; //class CNavArea;
//class CNavNode; //class CNavNode;
@ -141,24 +142,13 @@ struct Extent
Vector lo; Vector lo;
Vector hi; Vector hi;
UNTESTED float SizeX(void) const float SizeX(void) const { return hi.x - lo.x; }
{ float SizeY(void) const { return hi.y - lo.y;}
return hi.x - lo.x; float SizeZ(void) const { return hi.z - lo.z; }
} float Area(void) const { return SizeX() * SizeY(); }
UNTESTED float SizeY(void) const
{
return hi.y - lo.y;
}
UNTESTED float SizeZ(void) const
{
return hi.z - lo.z;
}
UNTESTED float Area(void) const
{
return SizeX() * SizeY();
}
// return true if 'pos' is inside of this extent // return true if 'pos' is inside of this extent
UNTESTED bool Contains(const Vector *pos) const bool Contains(const Vector *pos) const
{ {
return (pos->x >= lo.x && pos->x <= hi.x && return (pos->x >= lo.x && pos->x <= hi.x &&
pos->y >= lo.y && pos->y <= hi.y && pos->y >= lo.y && pos->y <= hi.y &&
@ -236,12 +226,12 @@ inline void AddDirectionVector(Vector *v, NavDirType dir, float amount)
case NORTH: case NORTH:
v->y -= amount; v->y -= amount;
return; return;
case EAST:
v->x += amount;
return;
case SOUTH: case SOUTH:
v->y += amount; v->y += amount;
return; return;
case EAST:
v->x += amount;
return;
case WEST: case WEST:
v->x -= amount; v->x -= amount;
return; return;
@ -267,7 +257,7 @@ inline float DirectionToAngle(NavDirType dir)
} }
/* <3d8335> ../game_shared/bot/nav.h:202 */ /* <3d8335> ../game_shared/bot/nav.h:202 */
inline NavDirType AngleToDirection(float angle) inline NavDirType AngleToDirection(float_precision angle)
{ {
while (angle < 0.0f) while (angle < 0.0f)
angle += 360.0f; angle += 360.0f;
@ -327,6 +317,13 @@ inline void SnapToGrid(float *value)
*value = c * GenerationStepSize; *value = c * GenerationStepSize;
} }
// custom
inline float SnapToGrid(float v)
{
int c = v / GenerationStepSize;
return c;
}
/* <14ea2f> ../game_shared/bot/nav.h:251 */ /* <14ea2f> ../game_shared/bot/nav.h:251 */
inline float_precision NormalizeAngle(float_precision angle) inline float_precision NormalizeAngle(float_precision angle)
{ {
@ -368,7 +365,7 @@ inline float AngleDifference(float a, float b)
/* <38cac9> ../game_shared/bot/nav.h:288 */ /* <38cac9> ../game_shared/bot/nav.h:288 */
inline bool AnglesAreEqual(float a, float b, float tolerance = 5.0f) inline bool AnglesAreEqual(float a, float b, float tolerance = 5.0f)
{ {
if (abs(AngleDifference(a, b)) < tolerance) if (abs(int64(AngleDifference(a, b))) < tolerance)
return true; return true;
return false; return false;

View File

@ -3631,7 +3631,7 @@ int CNavArea::GetPlayerCount(int teamID, CBasePlayer *ignore) const
if (!player->IsAlive()) if (!player->IsAlive())
continue; continue;
if (teamID == 0 || player->m_iTeam == teamID) if (teamID == UNASSIGNED || player->m_iTeam == teamID)
if (Contains(&player->pev->origin)) if (Contains(&player->pev->origin))
++count; ++count;
} }
@ -3697,7 +3697,7 @@ void CNavArea::DrawConnectedAreas(void)
if (player == NULL) if (player == NULL)
return; return;
CCSBotManager *ctrl = static_cast<CCSBotManager *>(TheBots); CCSBotManager *ctrl = TheCSBots();
const float maxRange = 500.0f; const float maxRange = 500.0f;
// draw self // draw self
@ -3868,10 +3868,9 @@ public:
{ {
m_initialPlace = area->GetPlace(); m_initialPlace = area->GetPlace();
} }
bool operator()(CNavArea *area) bool operator()(CNavArea *area)
{ {
CCSBotManager *ctrl = static_cast<CCSBotManager *>(TheBots); CCSBotManager *ctrl = TheCSBots();
if (area->GetPlace() != m_initialPlace) if (area->GetPlace() != m_initialPlace)
return false; return false;
@ -3891,8 +3890,7 @@ private:
/* <4d76ef> ../game_shared/bot/nav_area.cpp:4002 */ /* <4d76ef> ../game_shared/bot/nav_area.cpp:4002 */
void EditNavAreas(NavEditCmdType cmd) void EditNavAreas(NavEditCmdType cmd)
{ {
CCSBotManager *ctrl = static_cast<CCSBotManager *>(TheBots); CCSBotManager *ctrl = TheCSBots();
CBasePlayer *player = UTIL_GetLocalPlayer(); CBasePlayer *player = UTIL_GetLocalPlayer();
if (player == NULL) if (player == NULL)
return; return;
@ -3912,7 +3910,6 @@ void EditNavAreas(NavEditCmdType cmd)
lastDrawTimestamp = drawTimestamp; lastDrawTimestamp = drawTimestamp;
} }
const float maxRange = 1000.0f; const float maxRange = 1000.0f;
int beamTime = 1; int beamTime = 1;
@ -4034,7 +4031,7 @@ void EditNavAreas(NavEditCmdType cmd)
// find the area the player is pointing at // find the area the player is pointing at
CNavArea *area = TheNavAreaGrid.GetNearestNavArea(&result.vecEndPos); CNavArea *area = TheNavAreaGrid.GetNearestNavArea(&result.vecEndPos);
if (area) if (area != NULL)
{ {
// if area changed, print its ID // if area changed, print its ID
if (area != lastSelectedArea) if (area != lastSelectedArea)
@ -4048,10 +4045,10 @@ void EditNavAreas(NavEditCmdType cmd)
if (area->GetPlace()) if (area->GetPlace())
{ {
const char *name = TheBotPhrases->IDToName(area->GetPlace()); const char *name = TheBotPhrases->IDToName(area->GetPlace());
if (name) if (name != NULL)
strcpy(locName, name); Q_strcpy(locName, name);
else else
strcpy(locName, "ERROR"); Q_strcpy(locName, "ERROR");
} }
else else
{ {
@ -4064,14 +4061,14 @@ void EditNavAreas(NavEditCmdType cmd)
} }
else else
{ {
sprintf(attrib, "%s%s%s%s", Q_sprintf(attrib, "%s%s%s%s",
(area->GetAttributes() & NAV_CROUCH) ? "CROUCH " : "", (area->GetAttributes() & NAV_CROUCH) ? "CROUCH " : "",
(area->GetAttributes() & NAV_JUMP) ? "JUMP " : "", (area->GetAttributes() & NAV_JUMP) ? "JUMP " : "",
(area->GetAttributes() & NAV_PRECISE) ? "PRECISE " : "", (area->GetAttributes() & NAV_PRECISE) ? "PRECISE " : "",
(area->GetAttributes() & NAV_NO_JUMP) ? "NO_JUMP " : ""); (area->GetAttributes() & NAV_NO_JUMP) ? "NO_JUMP " : "");
} }
sprintf(buffer, "Area #%d %s %s\n", area->GetID(), locName, attrib); Q_sprintf(buffer, "Area #%d %s %s\n", area->GetID(), locName, attrib);
UTIL_SayTextAll(buffer, player); UTIL_SayTextAll(buffer, player);
// do "place painting" // do "place painting"
@ -4255,7 +4252,7 @@ void EditNavAreas(NavEditCmdType cmd)
connected += markedArea->GetAdjacentCount(WEST); connected += markedArea->GetAdjacentCount(WEST);
char buffer[80]; char buffer[80];
sprintf(buffer, "Marked Area is connected to %d other Areas\n", connected); Q_sprintf(buffer, "Marked Area is connected to %d other Areas\n", connected);
UTIL_SayTextAll(buffer, player); UTIL_SayTextAll(buffer, player);
} }
break; break;
@ -4302,7 +4299,7 @@ void EditNavAreas(NavEditCmdType cmd)
} }
char buffer[80]; char buffer[80];
sprintf(buffer, "Marked Area is connected to %d other Areas - there are %d total unnamed areas\n", connected, totalUnnamedAreas); Q_sprintf(buffer, "Marked Area is connected to %d other Areas - there are %d total unnamed areas\n", connected, totalUnnamedAreas);
UTIL_SayTextAll(buffer, player); UTIL_SayTextAll(buffer, player);
} }
} }

View File

@ -125,7 +125,6 @@ enum LadderDirectionType
NUM_LADDER_DIRECTIONS NUM_LADDER_DIRECTIONS
}; };
/* <4c2fda> ../game_shared/bot/nav_area.h:63 */ /* <4c2fda> ../game_shared/bot/nav_area.h:63 */
class CNavLadder class CNavLadder
{ {
@ -232,10 +231,12 @@ public:
} }
static void ChangeMasterMarker(void) static void ChangeMasterMarker(void)
{ {
IMPL(m_masterMarker)++; ++IMPL(m_masterMarker);
} }
#ifndef HOOK_GAMEDLL
private: private:
#endif // HOOK_GAMEDLL
friend void DestroyHidingSpots(void); friend void DestroyHidingSpots(void);
Vector m_pos; Vector m_pos;
@ -243,9 +244,6 @@ private:
unsigned int m_marker; unsigned int m_marker;
unsigned char m_flags; unsigned char m_flags;
#ifdef HOOK_GAMEDLL
public:
#endif // HOOK_GAMEDLL
static unsigned int IMPL(m_nextID); static unsigned int IMPL(m_nextID);
static unsigned int IMPL(m_masterMarker); static unsigned int IMPL(m_masterMarker);
@ -303,77 +301,45 @@ public:
void Load(SteamFile *file, unsigned int version); void Load(SteamFile *file, unsigned int version);
NavErrorType PostLoad(void); NavErrorType PostLoad(void);
unsigned int GetID(void) const unsigned int GetID(void) const { return m_id; }
{ void SetAttributes(unsigned char bits) { m_attributeFlags = bits; }
return m_id; unsigned char GetAttributes(void) const { return m_attributeFlags; }
} void SetPlace(Place place) { m_place = place; } // set place descriptor
void SetAttributes(unsigned char bits) Place GetPlace(void) const { return m_place; } // get place descriptor
{
m_attributeFlags = bits;
}
unsigned char GetAttributes(void) const
{
return m_attributeFlags;
}
void SetPlace(Place place) // set place descriptor
{
m_place = place;
}
Place GetPlace(void) const // get place descriptor
{
return m_place;
}
bool IsOverlapping(const Vector *pos) const; // return true if 'pos' is within 2D extents of area 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 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 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 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) 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(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' 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 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 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' 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 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 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 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 int GetAdjacentCount(NavDirType dir) const { return m_connect[dir].size(); } // return number of connected areas in given direction
{ CNavArea *GetAdjacentArea(NavDirType dir, int i) const; // return the i'th adjacent area in the given direction
return m_connect[dir].size();
}
CNavArea *GetAdjacentArea(NavDirType dir, int i) const; // return the i'th adjacent area in the given direction
CNavArea *GetRandomAdjacentArea(NavDirType dir) const; CNavArea *GetRandomAdjacentArea(NavDirType dir) const;
const NavConnectList *GetAdjacentList(NavDirType dir) const const NavConnectList *GetAdjacentList(NavDirType dir) const { return &m_connect[dir]; }
{ bool IsConnected(const CNavArea *area, NavDirType dir) const; // return true if given area is connected in given direction
return &m_connect[dir]; float ComputeHeightChange(const CNavArea *area); // compute change in height from this area to given 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 const NavLadderList *GetLadderList(LadderDirectionType dir) const { return &m_ladder[dir]; }
{
return &m_ladder[dir];
}
void ComputePortal(const CNavArea *to, NavDirType dir, Vector *center, float *halfWidth) const; // compute portal to adjacent area 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 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 NavDirType ComputeDirection(Vector *point) const; // return direction from this area to the given point
// for hunting algorithm // for hunting algorithm
void SetClearedTimestamp(int teamID) // set this area's "clear" timestamp to now void SetClearedTimestamp(int teamID) { m_clearedTimestamp[teamID] = gpGlobals->time; } // set this area's "clear" timestamp to now
{ float GetClearedTimestamp(int teamID) { return m_clearedTimestamp[teamID]; } // get time this area was marked "clear"
m_clearedTimestamp[teamID] = gpGlobals->time;
}
float GetClearedTimestamp(int teamID) // get time this area was marked "clear"
{
return m_clearedTimestamp[teamID];
}
// hiding spots // hiding spots
const HidingSpotList *GetHidingSpotList(void) const const HidingSpotList *GetHidingSpotList(void) const { return &m_hidingSpotList; }
{
return &m_hidingSpotList;
}
void ComputeHidingSpots(void); // analyze local area neighborhood to find "hiding spots" in this area - for map learning 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 void ComputeSniperSpots(void); // analyze local area neighborhood to find "sniper spots" in this area - for map learning
@ -383,22 +349,12 @@ public:
// danger // danger
void IncreaseDanger(int teamID, float amount); // increase the danger of this area for the given team 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 GetDanger(int teamID); // return the danger of this area (decays over time)
float GetSizeX(void) const
{ float GetSizeX(void) const { return m_extent.hi.x - m_extent.lo.x; }
return m_extent.hi.x - m_extent.lo.x; float GetSizeY(void) const { return m_extent.hi.y - m_extent.lo.y; }
}
float GetSizeY(void) const const Extent *GetExtent(void) const { return &m_extent; }
{ const Vector *GetCenter(void) const { return &m_center; }
return m_extent.hi.y - m_extent.lo.y;
}
const Extent *GetExtent(void) const
{
return &m_extent;
}
const Vector *GetCenter(void) const
{
return &m_center;
}
const Vector *GetCorner(NavCornerType corner) const; const Vector *GetCorner(NavCornerType corner) const;
// approach areas // approach areas
@ -411,44 +367,22 @@ public:
NavTraverseType hereToNextHow; NavTraverseType hereToNextHow;
}; };
const ApproachInfo *GetApproachInfo(int i) const const ApproachInfo *GetApproachInfo(int i) const { return &m_approach[i]; }
{ int GetApproachInfoCount(void) const { return m_approachCount; }
return &m_approach[i]; void ComputeApproachAreas(void); // determine the set of "approach areas" - for map learning
}
int GetApproachInfoCount(void) const
{
return m_approachCount;
}
void ComputeApproachAreas(void); // determine the set of "approach areas" - for map learning
// A* pathfinding algorithm // A* pathfinding algorithm
static void MakeNewMarker(void) static void MakeNewMarker(void)
{ {
IMPL(m_masterMarker)++; ++IMPL(m_masterMarker);
if (IMPL(m_masterMarker) == 0) if (IMPL(m_masterMarker) == 0)
IMPL(m_masterMarker) = 1; IMPL(m_masterMarker) = 1;
} }
void Mark(void) void Mark(void) { m_marker = IMPL(m_masterMarker); }
{ BOOL IsMarked(void) const { return (m_marker == IMPL(m_masterMarker)) ? true : false; }
m_marker = IMPL(m_masterMarker); void SetParent(CNavArea *parent, NavTraverseType how = NUM_TRAVERSE_TYPES) { m_parent = parent; m_parentHow = how; }
} CNavArea *GetParent(void) const { return m_parent; }
BOOL IsMarked(void) const NavTraverseType GetParentHow(void) const { return m_parentHow; }
{
return (m_marker == IMPL(m_masterMarker)) ? true : false;
}
void SetParent(CNavArea *parent, NavTraverseType how = NUM_TRAVERSE_TYPES)
{
m_parent = parent;
m_parentHow = how;
}
CNavArea *GetParent(void) const
{
return m_parent;
}
NavTraverseType GetParentHow(void) const
{
return m_parentHow;
}
bool IsOpen(void) const; // true if on "open list" bool IsOpen(void) const; // true if on "open list"
void AddToOpenList(void); // add to open list in decreasing value order void AddToOpenList(void); // add to open list in decreasing value order
@ -463,22 +397,10 @@ public:
static void ClearSearchLists(void); // clears the open and closed lists for a new search static void ClearSearchLists(void); // clears the open and closed lists for a new search
void SetTotalCost(float value) void SetTotalCost(float value) { m_totalCost = value; }
{ float GetTotalCost(void) const { return m_totalCost; }
m_totalCost = value; void SetCostSoFar(float value) { m_costSoFar = value; }
} float GetCostSoFar(void) const { return m_costSoFar; }
float GetTotalCost(void) const
{
return m_totalCost;
}
void SetCostSoFar(float value)
{
m_costSoFar = value;
}
float GetCostSoFar(void) const
{
return m_costSoFar;
}
// editing // editing
void Draw(byte red, byte green, byte blue, int duration = 50); // draw area for debugging & editing void Draw(byte red, byte green, byte blue, int duration = 50); // draw area for debugging & editing
@ -490,18 +412,10 @@ public:
void RaiseCorner(NavCornerType corner, int amount); // raise/lower a corner (or all corners if corner == NUM_CORNERS) void RaiseCorner(NavCornerType corner, int amount); // raise/lower a corner (or all corners if corner == NUM_CORNERS)
// ladders // ladders
void AddLadderUp(CNavLadder *ladder) void AddLadderUp(CNavLadder *ladder) { m_ladder[LADDER_UP].push_back(ladder); }
{ void AddLadderDown(CNavLadder *ladder) { m_ladder[LADDER_DOWN].push_back(ladder); }
m_ladder[LADDER_UP].push_back(ladder);
}
void AddLadderDown(CNavLadder *ladder)
{
m_ladder[LADDER_DOWN].push_back(ladder);
}
#ifdef HOOK_GAMEDLL #ifndef HOOK_GAMEDLL
public:
#else
private: private:
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
friend void ConnectGeneratedAreas(void); friend void ConnectGeneratedAreas(void);
@ -602,6 +516,7 @@ inline CNavArea *CNavArea::GetAdjacentArea(NavDirType dir, int i) const
return (*iter).area; return (*iter).area;
--i; --i;
} }
return NULL; return NULL;
} }
@ -1151,7 +1066,7 @@ void SearchSurroundingAreas(CNavArea *startArea, const Vector *startPos, Functor
// check up ladders // check up ladders
const NavLadderList *ladderList = area->GetLadderList(LADDER_UP); const NavLadderList *ladderList = area->GetLadderList(LADDER_UP);
if (ladderList) if (ladderList != NULL)
{ {
for (ladderIt = ladderList->begin(); ladderIt != ladderList->end(); ++ladderIt) for (ladderIt = ladderList->begin(); ladderIt != ladderList->end(); ++ladderIt)
{ {
@ -1172,7 +1087,7 @@ void SearchSurroundingAreas(CNavArea *startArea, const Vector *startPos, Functor
// check down ladders // check down ladders
ladderList = area->GetLadderList(LADDER_DOWN); ladderList = area->GetLadderList(LADDER_DOWN);
if (ladderList) if (ladderList != NULL)
{ {
for (ladderIt = ladderList->begin(); ladderIt != ladderList->end(); ++ladderIt) for (ladderIt = ladderList->begin(); ladderIt != ladderList->end(); ++ladderIt)
{ {
@ -1185,23 +1100,26 @@ void SearchSurroundingAreas(CNavArea *startArea, const Vector *startPos, Functor
} }
// Apply the functor to all navigation areas // Apply the functor to all navigation areas
// If functor returns false, stop processing and return false.
/* <4c4137> ../game_shared/bot/nav_area.h:1109 */ /* <4c4137> ../game_shared/bot/nav_area.h:1109 */
template <typename Functor> template <typename Functor>
void ForAllAreas(Functor &func) bool ForAllAreas(Functor &func)
{ {
NavAreaList::iterator iter; NavAreaList::iterator iter;
for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter) for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
{ {
CNavArea *area = *iter; CNavArea *area = *iter;
func(area); if (func(area) == false)
return false;
} }
return true;
} }
// Fuctor that returns lowest cost for farthest away areas // Fuctor that returns lowest cost for farthest away areas
// For use with FindMinimumCostArea() // For use with FindMinimumCostArea()
NOXREF class FarAwayFunctor
class FarAwayFunctor NOXREF
{ {
public: public:
float operator()(CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder) float operator()(CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder)
@ -1209,7 +1127,7 @@ public:
if (area == fromArea) if (area == fromArea)
return 9999999.9f; return 9999999.9f;
return 1.0f/(*fromArea->GetCenter() - *area->GetCenter()).Length(); return 1.0f / (*fromArea->GetCenter() - *area->GetCenter()).Length();
} }
}; };
@ -1275,9 +1193,11 @@ CNavArea *FindMinimumCostArea(CNavArea *startArea, CostFunctor &costFunc)
{ {
// replace most expensive cost if this is cheaper // replace most expensive cost if this is cheaper
int expensive = 0; int expensive = 0;
for (int i = 1; i < NUM_CHEAP_AREAS; i++) for (int i = 1; i < NUM_CHEAP_AREAS; ++i)
{
if (cheapAreaSet[i].cost > cheapAreaSet[expensive].cost) if (cheapAreaSet[i].cost > cheapAreaSet[expensive].cost)
expensive = i; expensive = i;
}
if (cheapAreaSet[expensive].cost > cost) if (cheapAreaSet[expensive].cost > cost)
{ {
@ -1299,8 +1219,10 @@ CNavArea *FindMinimumCostArea(CNavArea *startArea, CostFunctor &costFunc)
NavAreaList::iterator iter; NavAreaList::iterator iter;
for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter) for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
{
if (which-- == 0) if (which-- == 0)
break; break;
}
return *iter; return *iter;
} }
@ -1386,9 +1308,4 @@ void BuildLadders(void);
void MarkJumpAreas(void); void MarkJumpAreas(void);
void GenerateNavigationAreaMesh(void); void GenerateNavigationAreaMesh(void);
//refs
extern float (*pGetZ__Vector)(const Vector *pos);
extern CNavArea *(*pGetNearestNavArea)(const Vector *pos, bool anyZ);
extern CNavArea *(*pGetNavArea)(const Vector *pos, float beneathLimit);
#endif // NAV_AREA_H #endif // NAV_AREA_H

View File

@ -16,15 +16,21 @@ char s_shared_quote;
#endif // HOOK_GAMEDLL #endif // HOOK_GAMEDLL
/* <2d4a66> ../game_shared/shared_util.cpp:50 */ /* <2d4a66> ../game_shared/shared_util.cpp:50 */
NOBODY uchar32 *SharedWVarArgs(uchar32 *format, ...) NOXREF wchar_t *SharedWVarArgs(wchar_t *format, ...)
{ {
// { va_list argptr;
// va_list argptr; // 52 const int BufLen = 1024;
// intconst BufLen; // 53 const int NumBuffers = 4;
// intconst NumBuffers; // 54 static wchar_t string[NumBuffers][BufLen];
// wchar_t string; // 55 static int curstring = 0;
// int curstring; // 56
// } curstring = (curstring + 1) % NumBuffers;
va_start(argptr, format);
Q_vsnwprintf(string[curstring], BufLen, format, argptr);
va_end(argptr);
return string[curstring];
} }
/* <2d4b0a> ../game_shared/shared_util.cpp:68 */ /* <2d4b0a> ../game_shared/shared_util.cpp:68 */
@ -59,27 +65,39 @@ char *BufPrintf(char *buf, int &len, const char *fmt, ...)
len -= Q_strlen(buf); len -= Q_strlen(buf);
return buf + Q_strlen(buf); return buf + Q_strlen(buf);
} }
return NULL; return NULL;
} }
/* <2d4c0d> ../game_shared/shared_util.cpp:106 */ /* <2d4c0d> ../game_shared/shared_util.cpp:106 */
NOBODY uchar32 *BufWPrintf(uchar32 *buf, int &len, const uchar32 *fmt, ...) wchar_t *BufWPrintf(wchar_t *buf, int &len, const wchar_t *fmt, ...)
{ {
// { if (len <= 0)
// va_list argptr; // 111 return NULL;
// }
va_list argptr;
va_start(argptr, fmt);
Q_vsnwprintf(buf, len, fmt, argptr);
va_end(argptr);
len -= wcslen(buf);
return buf + wcslen(buf);
} }
/* <2d4c7e> ../game_shared/shared_util.cpp:122 */ /* <2d4c7e> ../game_shared/shared_util.cpp:122 */
NOBODY const uchar32 *NumAsWString(int val) NOXREF const wchar_t *NumAsWString(int val)
{ {
// { const int BufLen = 16;
// intconst BufLen; // 124 const int NumBuffers = 4;
// intconst NumBuffers; // 125 static wchar_t string[NumBuffers][BufLen];
// wchar_t string; // 126 static int curstring = 0;
// int curstring; // 127
// int len; // 131 curstring = (curstring + 1) % NumBuffers;
// }
int len = BufLen;
BufWPrintf(string[curstring], len, L"%d", val);
return string[curstring];
} }
/* <2d4d11> ../game_shared/shared_util.cpp:137 */ /* <2d4d11> ../game_shared/shared_util.cpp:137 */
@ -118,22 +136,99 @@ NOXREF void SharedSetQuoteChar(char c)
// Parse a token out of a string // Parse a token out of a string
/* <2d4de7> ../game_shared/shared_util.cpp:173 */ /* <2d4de7> ../game_shared/shared_util.cpp:173 */
NOBODY const char *SharedParse(const char *data) const char *SharedParse(const char *data)
{ {
// int c;
//skipwhite: // 185 int len;
// {
// int c; // 175 len = 0;
// int len; // 176 s_shared_token[0] = '\0';
// }
if (!data)
return NULL;
// skip whitespace
skipwhite:
while ((c = *data) <= ' ')
{
if (c == 0)
{
// end of file;
return NULL;
}
data++;
}
// skip // comments
if (c == '/' && data[1] == '/')
{
while (*data && *data != '\n')
data++;
goto skipwhite;
}
// handle quoted strings specially
if (c == s_shared_quote)
{
data++;
while (true)
{
c = *data++;
if (c == s_shared_quote || !c)
{
s_shared_token[len] = '\0';
return data;
}
s_shared_token[len] = c;
len++;
}
}
// parse single characters
if (c == '{' || c == '}'|| c == ')'|| c == '(' || c == '\'' || c == ',')
{
s_shared_token[len] = c;
len++;
s_shared_token[len] = '\0';
return data + 1;
}
// parse a regular word
do
{
s_shared_token[len] = c;
data++;
len++;
c = *data;
if (c == '{' || c == '}'|| c == ')'|| c == '(' || c == '\'' || c == ',')
break;
} while (c > 32);
s_shared_token[len] = '\0';
return data;
} }
// Returns true if additional data is waiting to be processed on this line // Returns true if additional data is waiting to be processed on this line
/* <2d4e40> ../game_shared/shared_util.cpp:247 */ /* <2d4e40> ../game_shared/shared_util.cpp:247 */
NOBODY bool SharedTokenWaiting(const char *buffer) NOXREF bool SharedTokenWaiting(const char *buffer)
{ {
// { const char *p;
// const char *p; // 249
// } p = buffer;
while (*p && *p!='\n')
{
if (!isspace(*p) || isalnum(*p))
return true;
p++;
}
return false;
} }

View File

@ -32,6 +32,11 @@
#pragma once #pragma once
#endif #endif
#ifndef _WIN32
#include <string.h>
#include <wchar.h>
#endif // _WIN32
#ifdef HOOK_GAMEDLL #ifdef HOOK_GAMEDLL
#define s_shared_token (*ps_shared_token) #define s_shared_token (*ps_shared_token)
@ -42,16 +47,18 @@
extern char s_shared_token[ 1500 ]; extern char s_shared_token[ 1500 ];
extern char s_shared_quote; extern char s_shared_quote;
NOBODY uchar32 *SharedWVarArgs(uchar32 *format, ...); NOXREF wchar_t *SharedWVarArgs(wchar_t *format, ...);
char *SharedVarArgs(char *format, ...); char *SharedVarArgs(char *format, ...);
char *BufPrintf(char *buf, int &len, const char *fmt, ...); char *BufPrintf(char *buf, int &len, const char *fmt, ...);
NOBODY uchar32 *BufWPrintf(uchar32 *buf, int &len, const uchar32 *fmt, ...); NOXREF wchar_t *BufWPrintf(wchar_t *buf, int &len, const wchar_t *fmt, ...);
NOBODY const uchar32 *NumAsWString(int val); NOXREF const wchar_t *NumAsWString(int val);
const char *NumAsString(int val); const char *NumAsString(int val);
char *SharedGetToken(void); char *SharedGetToken(void);
NOXREF void SharedSetQuoteChar(char c); NOXREF void SharedSetQuoteChar(char c);
NOBODY const char *SharedParse(const char *data); const char *SharedParse(const char *data);
NOBODY bool SharedTokenWaiting(const char *buffer); NOXREF bool SharedTokenWaiting(const char *buffer);
// Simple utility function to allocate memory and duplicate a string
/* <db469> ../game_shared/shared_util.h:46 */ /* <db469> ../game_shared/shared_util.h:46 */
inline char *CloneString(const char *str) inline char *CloneString(const char *str)
@ -62,20 +69,26 @@ inline char *CloneString(const char *str)
cloneStr[0] = '\0'; cloneStr[0] = '\0';
return cloneStr; return cloneStr;
} }
char *cloneStr = new char [Q_strlen(str) + 1]; char *cloneStr = new char [Q_strlen(str) + 1];
Q_strcpy(cloneStr, str); Q_strcpy(cloneStr, str);
return cloneStr; return cloneStr;
} }
#ifdef _WIN32 // Simple utility function to allocate memory and duplicate a wide string
inline wchar_t *CloneWString(const wchar_t *str) inline wchar_t *CloneWString(const wchar_t *str)
{ {
if (!str)
{
wchar_t *cloneStr = new wchar_t[1];
cloneStr[0] = L'\0';
return cloneStr;
}
wchar_t *cloneStr = new wchar_t [wcslen(str) + 1]; wchar_t *cloneStr = new wchar_t [wcslen(str) + 1];
wcscpy(cloneStr, str); wcscpy(cloneStr, str);
return cloneStr; return cloneStr;
} }
#endif // _WIN32
#endif // SHARED_UTIL #endif // SHARED_UTIL

View File

@ -131,7 +131,7 @@ bool CVoiceGameMgr::ClientCommand(CBasePlayer *pPlayer, const char *cmd)
bool bBan = Q_stricmp(cmd, "vban") == 0; bool bBan = Q_stricmp(cmd, "vban") == 0;
if (bBan && CMD_ARGC() >= 2) if (bBan && CMD_ARGC() >= 2)
{ {
for (int i = 1; i < CMD_ARGC(); i++) for (int i = 1; i < CMD_ARGC(); ++i)
{ {
uint32 mask = 0; uint32 mask = 0;
sscanf(CMD_ARGV(i), "%x", &mask); sscanf(CMD_ARGV(i), "%x", &mask);
@ -145,6 +145,8 @@ bool CVoiceGameMgr::ClientCommand(CBasePlayer *pPlayer, const char *cmd)
VoiceServerDebug("CVoiceGameMgr::ClientCommand: invalid index (%d)\n", i); VoiceServerDebug("CVoiceGameMgr::ClientCommand: invalid index (%d)\n", i);
} }
// Force it to update the masks now.
//UpdateMasks();
return true; return true;
} }
else if (Q_stricmp(cmd, "VModEnable") == 0 && CMD_ARGC() >= 2) else if (Q_stricmp(cmd, "VModEnable") == 0 && CMD_ARGC() >= 2)
@ -153,7 +155,7 @@ bool CVoiceGameMgr::ClientCommand(CBasePlayer *pPlayer, const char *cmd)
g_PlayerModEnable[ playerClientIndex ] = !!Q_atoi(CMD_ARGV(1)); g_PlayerModEnable[ playerClientIndex ] = !!Q_atoi(CMD_ARGV(1));
g_bWantModEnable[ playerClientIndex ] = false; g_bWantModEnable[ playerClientIndex ] = false;
//UpdateMasks();
return true; return true;
} }
@ -167,7 +169,7 @@ void CVoiceGameMgr::UpdateMasks(void)
bool bAllTalk = !!(sv_alltalk.value); bool bAllTalk = !!(sv_alltalk.value);
for (int iClient = 0; iClient < m_nMaxPlayers; iClient++) for (int iClient = 0; iClient < m_nMaxPlayers; ++iClient)
{ {
CBaseEntity *pEnt = UTIL_PlayerByIndex(iClient + 1); CBaseEntity *pEnt = UTIL_PlayerByIndex(iClient + 1);
@ -191,7 +193,7 @@ void CVoiceGameMgr::UpdateMasks(void)
if (g_PlayerModEnable[ iClient ]) if (g_PlayerModEnable[ iClient ])
{ {
// Build a mask of who they can hear based on the game rules. // Build a mask of who they can hear based on the game rules.
for (int iOtherClient = 0; iOtherClient < m_nMaxPlayers; iOtherClient++) for (int iOtherClient = 0; iOtherClient < m_nMaxPlayers; ++iOtherClient)
{ {
CBaseEntity *pEnt = UTIL_PlayerByIndex(iOtherClient + 1); CBaseEntity *pEnt = UTIL_PlayerByIndex(iOtherClient + 1);
@ -209,7 +211,7 @@ void CVoiceGameMgr::UpdateMasks(void)
g_SentBanMasks[ iClient ] = g_BanMasks[ iClient ]; g_SentBanMasks[ iClient ] = g_BanMasks[ iClient ];
MESSAGE_BEGIN(MSG_ONE, m_msgPlayerVoiceMask, NULL, pPlayer->pev); MESSAGE_BEGIN(MSG_ONE, m_msgPlayerVoiceMask, NULL, pPlayer->pev);
for (int dw = 0; dw < VOICE_MAX_PLAYERS_DW; dw++) for (int dw = 0; dw < VOICE_MAX_PLAYERS_DW; ++dw)
{ {
WRITE_LONG(gameRulesMask.GetDWord(dw)); WRITE_LONG(gameRulesMask.GetDWord(dw));
WRITE_LONG(g_BanMasks[ iClient ].GetDWord(dw)); WRITE_LONG(g_BanMasks[ iClient ].GetDWord(dw));
@ -218,7 +220,7 @@ void CVoiceGameMgr::UpdateMasks(void)
} }
// Tell the engine. // Tell the engine.
for (int iOtherClient = 0; iOtherClient < m_nMaxPlayers; iOtherClient++) for (int iOtherClient = 0; iOtherClient < m_nMaxPlayers; ++iOtherClient)
{ {
bool bCanHear = gameRulesMask[ iOtherClient ] && !g_BanMasks[ iClient ][ iOtherClient ]; bool bCanHear = gameRulesMask[ iOtherClient ] && !g_BanMasks[ iClient ][ iOtherClient ];
SET_CLIENT_LISTENING(iClient + 1, iOtherClient + 1, bCanHear); SET_CLIENT_LISTENING(iClient + 1, iOtherClient + 1, bCanHear);

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "iterator" #include "iterator"
#include "xutility"
#include "memory" #include "memory"
#ifdef _MSC_VER #ifdef _MSC_VER
@ -142,14 +143,14 @@ public:
{erase(begin(), end()); {erase(begin(), end());
insert(begin(), _N, _X); } insert(begin(), _N, _X); }
iterator insert(iterator _P, const _Ty& _X = _Ty()) iterator insert(iterator _P, const _Ty& _X = _Ty())
{size_type _O = _P - begin(); {size_type _O = size_type(_P - begin());
insert(_P, 1, _X); insert(_P, 1, _X);
return (begin() + _O); } return (begin() + _O); }
void insert(iterator _P, size_type _M, const _Ty& _X) void insert(iterator _P, size_type _M, const _Ty& _X)
{if (_End - _Last < _M) {if (size_type(_End - _Last) < _M)
{size_type _N = size() + (_M < size() ? size() : _M); {size_type _N = size() + (_M < size() ? size() : _M);
iterator_ _S = allocator.allocate(_N, (void *)0); iterator _S = allocator.allocate(_N, (void *)0);
iterator_ _Q = _Ucopy(_First, _P, _S); iterator _Q = _Ucopy(_First, _P, _S);
_Ufill(_Q, _M, _X); _Ufill(_Q, _M, _X);
_Ucopy(_P, _Last, _Q + _M); _Ucopy(_P, _Last, _Q + _M);
__Destroy(_First, _Last); __Destroy(_First, _Last);
@ -157,7 +158,7 @@ public:
_End = _S + _N; _End = _S + _N;
_Last = _S + size() + _M; _Last = _S + size() + _M;
_First = _S; } _First = _S; }
else if (_Last - _P < _M) else if (size_type(_Last - _P) < _M)
{_Ucopy(_P, _Last, _P + _M); {_Ucopy(_P, _Last, _P + _M);
_Ufill(_Last, _M - (_Last - _P), _X); _Ufill(_Last, _M - (_Last - _P), _X);
fill_(_P, _Last, _X); fill_(_P, _Last, _X);
@ -172,8 +173,8 @@ public:
__Distance(_F, _L, _M); __Distance(_F, _L, _M);
if (_End - _Last < _M) if (_End - _Last < _M)
{size_type _N = size() + (_M < size() ? size() : _M); {size_type _N = size() + (_M < size() ? size() : _M);
iterator_ _S = allocator.allocate(_N, (void *)0); iterator _S = allocator.allocate(_N, (void *)0);
iterator_ _Q = _Ucopy(_First, _P, _S); iterator _Q = _Ucopy(_First, _P, _S);
_Q = _Ucopy(_F, _L, _Q); _Q = _Ucopy(_F, _L, _Q);
_Ucopy(_P, _Last, _Q); _Ucopy(_P, _Last, _Q);
__Destroy(_First, _Last); __Destroy(_First, _Last);
@ -197,7 +198,7 @@ public:
--_Last; --_Last;
return (_P); } return (_P); }
iterator erase(iterator _F, iterator _L) iterator erase(iterator _F, iterator _L)
{iterator_ _S = copy_(_L, end(), _F); {iterator _S = copy_(_L, end(), _F);
__Destroy(_S, end()); __Destroy(_S, end());
_Last = _S; _Last = _S;
return (_F); } return (_F); }

View File

@ -838,6 +838,7 @@
<ClInclude Include="..\extra\IDA structures\goldsource.h" /> <ClInclude Include="..\extra\IDA structures\goldsource.h" />
<ClInclude Include="..\game_shared\bitvec.h" /> <ClInclude Include="..\game_shared\bitvec.h" />
<ClInclude Include="..\game_shared\bot\bot.h" /> <ClInclude Include="..\game_shared\bot\bot.h" />
<ClInclude Include="..\game_shared\bot\bot_constants.h" />
<ClInclude Include="..\game_shared\bot\bot_manager.h" /> <ClInclude Include="..\game_shared\bot\bot_manager.h" />
<ClInclude Include="..\game_shared\bot\bot_profile.h" /> <ClInclude Include="..\game_shared\bot\bot_profile.h" />
<ClInclude Include="..\game_shared\bot\bot_util.h" /> <ClInclude Include="..\game_shared\bot\bot_util.h" />
@ -1168,7 +1169,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>CSTRIKE;REGAMEDLL_SELF;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;_DEBUG;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>CSTRIKE;REGAMEDLL_ADD;REGAMEDLL_FIXES;REGAMEDLL_SELF;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;_DEBUG;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FloatingPointModel>Precise</FloatingPointModel> <FloatingPointModel>Precise</FloatingPointModel>
<AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -1204,7 +1205,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>REGAMEDLL_SELF;PLAY_GAMEDLL;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;_DEBUG;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>CSTRIKE;REGAMEDLL_SELF;PLAY_GAMEDLL;REGAMEDLL_CHECKS;CLIENT_WEAPONS;USE_BREAKPAD_HANDLER;DEDICATED;_CRT_SECURE_NO_WARNINGS;_DEBUG;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<FloatingPointModel>Precise</FloatingPointModel> <FloatingPointModel>Precise</FloatingPointModel>
<AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions> <AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

View File

@ -1136,6 +1136,9 @@
<ClInclude Include="..\public\tier0\platform.h"> <ClInclude Include="..\public\tier0\platform.h">
<Filter>public\tier0</Filter> <Filter>public\tier0</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\game_shared\bot\bot_constants.h">
<Filter>game_shared\bot</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\linux\appversion.sh"> <None Include="..\linux\appversion.sh">

View File

@ -43,4 +43,9 @@ char *_strdup_mhook_(const char *s)
return ptr; return ptr;
} }
int __cdecl _rand_mhook_()
{
return CRegamedllPlatformHolder::get()->rand();
}
#endif // _WIN32 #endif // _WIN32

View File

@ -12,6 +12,7 @@ void _free_mhook_(void *p);
void *_calloc_mhook_(size_t n, size_t s); void *_calloc_mhook_(size_t n, size_t s);
void *__nh_malloc_mhook_(size_t n); void *__nh_malloc_mhook_(size_t n);
char *_strdup_mhook_(const char *s); char *_strdup_mhook_(const char *s);
int __cdecl _rand_mhook_();
#endif // _WIN32 #endif // _WIN32

View File

@ -63,6 +63,8 @@ TEST(StructOffsets, ReversingChecks, 5000)
REPEAT_SIZEOF_PRINT(CCareerTask); REPEAT_SIZEOF_PRINT(CCareerTask);
REPEAT_SIZEOF_PRINT(CPreventDefuseTask); REPEAT_SIZEOF_PRINT(CPreventDefuseTask);
REPEAT_SIZEOF_PRINT(BotStatement);
// offset the members // offset the members
REPEAT_OFFSETOF_PRINT(CBaseEntity, pev); REPEAT_OFFSETOF_PRINT(CBaseEntity, pev);
REPEAT_OFFSETOF_PRINT(CBaseEntity, has_disconnected); REPEAT_OFFSETOF_PRINT(CBaseEntity, has_disconnected);
@ -100,6 +102,7 @@ TEST(StructOffsets, ReversingChecks, 5000)
CHECK_CLASS_SIZE(CCSBot, 11404, 11424); CHECK_CLASS_SIZE(CCSBot, 11404, 11424);
//CHECK_CLASS_SIZE(CCSBotManager, 740, 0x2E0u);//0x2E4u | 0x2E0u //CHECK_CLASS_SIZE(CCSBotManager, 740, 0x2E0u);//0x2E4u | 0x2E0u
CHECK_CLASS_SIZE(BotStatement, 0x70u, 0x70u);
//CHECK_CLASS_SIZE(HostageStateMachine, 0x10, 0x10); //CHECK_CLASS_SIZE(HostageStateMachine, 0x10, 0x10);
//CHECK_CLASS_SIZE(HostageFollowState, 0x4C, 0x4C); //CHECK_CLASS_SIZE(HostageFollowState, 0x4C, 0x4C);
//CHECK_CLASS_SIZE(CCSBot, 0x2CA0, 0x2CA0); //CHECK_CLASS_SIZE(CCSBot, 0x2CA0, 0x2CA0);