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
<ul>
<li> Counter-Strike 1.6 - 100%</li>
<li> Counter-Strike: Condition Zero - 63%</li>
<li> Counter-Strike: Condition Zero - 90%</li>
</ul>
## Build instructions

View File

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

View File

@ -32,17 +32,17 @@
#pragma once
#endif
#ifdef PLAY_GAMEDLL
// probably gamedll compiled with flag /fpmath:fasted,
// so we need to use type double, otherwise will be the test failed
typedef double float_precision;
#else // HOOK_GAMEDLL
typedef float float_precision;
#ifdef PLAY_GAMEDLL
// probably gamedll compiled with flag /fpmath:fasted,
// so we need to use type double, otherwise will be the test failed
typedef double float_precision;
#else // PLAY_GAMEDLL
typedef float float_precision;
#endif // PLAY_GAMEDLL
/* <42b7f> ../common/mathlib.h:3 */
@ -76,6 +76,22 @@ T Q_max(T a, T b) { return (a > b) ? a : b; }
template <typename T>
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 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];}

View File

@ -32,12 +32,9 @@
#pragma once
#endif
#define ACTIVITY_NOT_AVAILABLE -1
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_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 */
@ -134,7 +134,7 @@ int LookupActivityHeaviest(void *pmodel, entvars_t *pev, int activity)
mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
int weight = 0;
int seq = ACTIVITY_NOT_AVAILABLE;
int seq = ACT_INVALID;
for (int i = 0; i < pstudiohdr->numseq; i++)
{
@ -179,13 +179,16 @@ int LookupSequence(void *pmodel, const char *label)
return 0;
}
// Look up by sequence name.
mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex);
for (int i = 0; i < pstudiohdr->numseq; i++)
{
if (!Q_stricmp(pseqdesc[i].label, label))
return i;
}
return -1;
// Not found
return ACT_INVALID;
}
/* <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 MAX_PLACES_PER_MAP 64
#define UNDEFINED_SUBJECT (-1)
#define COUNT_MANY 4
#define COUNT_MANY 4 // equal to or greater than this is "many"
class CCSBot;
class BotChatterInterface;
@ -43,27 +43,41 @@ class BotChatterInterface;
typedef unsigned int PlaceCriteria;
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 */
class BotMeme
{
public:
NOBODY void Transmit(CCSBot *sender) const;
NOBODY virtual void Interpret(CCSBot *sender, CCSBot *receiver) const = 0;
void Transmit(CCSBot *sender) const; // transmit meme to other bots
virtual void Interpret(CCSBot *sender, CCSBot *receiver) const = 0; // cause the given bot to act on this meme
};/* size: 4, cachelines: 1, members: 1 */
class BotAllHostagesGoneMeme: public BotMeme
{
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 */
class BotHostageBeingTakenMeme: public BotMeme
{
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 */
@ -75,7 +89,14 @@ public:
{
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:
Place m_place;
@ -85,24 +106,27 @@ private:
class BotBombsiteStatusMeme: public BotMeme
{
public:
enum StatusType
{
CLEAR = 0,
PLANTED
};
enum StatusType { CLEAR, PLANTED };
BotBombsiteStatusMeme(int zoneIndex, StatusType status)
{
m_zoneIndex = zoneIndex;
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:
int m_zoneIndex;
StatusType m_status;
int m_zoneIndex; // the bombsite
StatusType m_status; // whether it is cleared or the bomb is there (planted)
};/* size: 12, cachelines: 1, members: 3 */
/* <2ff6de> ../cstrike/dlls/bot/cs_bot_chatter.h:87 */
class BotBombStatusMeme: public BotMeme
{
@ -112,8 +136,16 @@ public:
m_state = state;
m_pos = pos;
}
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:
CSGameState::BombState m_state;
Vector m_pos;
@ -124,7 +156,13 @@ private:
class BotFollowMeme: public BotMeme
{
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 */
@ -136,7 +174,14 @@ public:
{
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:
Vector m_pos;
@ -146,7 +191,13 @@ private:
class BotWhereBombMeme: public BotMeme
{
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 */
@ -154,13 +205,19 @@ public:
class BotRequestReportMeme: public BotMeme
{
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 */
enum BotStatementType
{
REPORT_VISIBLE_ENEMIES = 0,
REPORT_VISIBLE_ENEMIES,
REPORT_ENEMY_ACTION,
REPORT_MY_CURRENT_TASK,
REPORT_MY_INTENTION,
@ -171,13 +228,17 @@ enum BotStatementType
REPORT_MY_PLAN,
REPORT_INFORMATION,
REPORT_EMOTE,
REPORT_ACKNOWLEDGE,
REPORT_ACKNOWLEDGE, // affirmative or negative
REPORT_ENEMIES_REMAINING,
REPORT_FRIENDLY_FIRE,
REPORT_KILLED_FRIEND,
//REPORT_ENEMY_LOST
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
{
public:
@ -194,53 +255,45 @@ public:
typedef std::STD_VECTOR<BotSpeakable *> BotSpeakableVector;
typedef std::STD_VECTOR<BotSpeakableVector *> BotVoiceBankVector;
// The BotPhrase class is a collection of Speakables associated with a name, ID, and criteria
class BotPhrase
{
public:
NOBODY BotPhrase(unsigned int id, bool isPlace);
NOBODY ~BotPhrase(void);
NOBODY void InitVoiceBank(int bankIndex);
char *GetSpeakable(int bankIndex, float *duration = NULL) const;
char *GetSpeakable(int bankIndex, float *duration = NULL) const; // return a random speakable and its duration in seconds that meets the current criteria
// NOTE: Criteria must be set just before the GetSpeakable() call, since they are shared among all bots
void ClearCriteria(void) const;
void SetPlaceCriteria(PlaceCriteria place) const;
void SetCountCriteria(CountCriteria count) const;
void SetPlaceCriteria(PlaceCriteria place) const; // all returned phrases must have this place criteria
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;
BotPhrase(unsigned int id, bool isPlace);
~BotPhrase(void);
char *m_name;
Place m_id;
bool m_isPlace;
bool m_isPlace; // true if this is a Place phrase
GameEventType m_radioEvent;
bool m_isImportant;
mutable BotVoiceBankVector m_voiceBank;
std::STD_VECTOR<int> m_count;
mutable std::STD_VECTOR< int > m_index;
int m_numVoiceBanks;
bool m_isImportant; // mission-critical statement
mutable BotVoiceBankVector m_voiceBank; // array of voice banks (arrays of speakables)
std::STD_VECTOR<int> m_count; // number of speakables
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 CountCriteria m_countCriteria;
@ -271,33 +324,30 @@ inline void BotPhrase::SetCountCriteria(CountCriteria count) const
class BotPhraseManager
{
public:
NOBODY BotPhraseManager(void);
NOBODY ~BotPhraseManager(void);
BotPhraseManager(void);
~BotPhraseManager(void);
// 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
void OnRoundRestart(void);
// invoked when map changes
NOBODY void OnMapChange(void);
void OnMapChange(void);
Place NameToID(const char *name) const;
const char *IDToName(Place id) const;
// 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
NOBODY const BotPhrase *GetPlace(const char *name) const;
const BotPhrase *GetPlace(const char *name) const;
// 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
{
return &m_placeList;
}
const BotPhraseList *GetPlaceList(void) const { return &m_placeList; }
// return time last statement of given type was emitted by a teammate for the given place
float GetPlaceStatementInterval(Place place) const;
@ -307,8 +357,6 @@ public:
#ifndef HOOK_GAMEDLL
private:
#else
public:
#endif // HOOK_GAMEDLL
int FindPlaceIndex(Place where) const;
@ -338,12 +386,14 @@ inline int BotPhraseManager::FindPlaceIndex(Place where) const
if (m_placeStatementHistory[i].placeID == where)
return i;
}
if (m_placeCount < MAX_PLACES_PER_MAP)
{
m_placeStatementHistory[++m_placeCount].placeID = where;
m_placeStatementHistory[++m_placeCount].timer.Invalidate();
return m_placeCount-1;
return m_placeCount - 1;
}
return -1;
}
@ -365,6 +415,7 @@ inline float BotPhraseManager::GetPlaceStatementInterval(Place place) const
inline void BotPhraseManager::ResetPlaceStatementInterval(Place place) const
{
int index = FindPlaceIndex(place);
if (index < 0)
return;
@ -374,56 +425,38 @@ inline void BotPhraseManager::ResetPlaceStatementInterval(Place place) const
m_placeStatementHistory[index].timer.Reset();
}
// Statements are meaningful collections of phrases
class BotStatement
{
public:
NOBODY BotStatement(BotChatterInterface *chatter, BotStatementType type, float expireDuration);
NOBODY ~BotStatement(void);
BotStatement(BotChatterInterface *chatter, BotStatementType type, float expireDuration);
~BotStatement(void);
public:
BotChatterInterface *GetChatter(void) const
{
return m_chatter;
}
NOBODY CCSBot *GetOwner(void) const;
BotStatementType GetType(void) const
{
return m_type;
}
NOBODY bool IsImportant(void) const;
bool HasSubject(void) const
{
return (m_subject != UNDEFINED_SUBJECT);
}
void SetSubject(int playerID)
{
m_subject = playerID;
}
int GetSubject(void) const
{
return m_subject;
}
bool HasPlace(void) const
{
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;
}
BotChatterInterface *GetChatter(void) const { return m_chatter; }
CCSBot *GetOwner(void) const;
BotStatementType GetType(void) const { return m_type; } // return the type of statement this is
bool IsImportant(void) const; // return true if this statement is "important" and not personality chatter
bool HasSubject(void) const { return (m_subject != UNDEFINED_SUBJECT); }
void SetSubject(int playerID) { m_subject = playerID; } // who this statement is about
int GetSubject(void) const { return m_subject; } // who this statement is about
bool HasPlace(void) const { return (GetPlace()) ? true : false; }
Place GetPlace(void) const; // if this statement refers to a specific place, return that place
void SetPlace(Place where) { m_place = where; } // explicitly set place
bool HasCount(void) const; // return true if this statement has an associated count
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
void Convert(const BotStatement *say); // possibly change what were going to say base on what teammate is saying
void AppendPhrase(const BotPhrase *phrase);
void SetStartTime(float timestamp) { m_startTime = timestamp; } // define the earliest time this statement can be spoken
float GetStartTime(void) const { return m_startTime; }
enum ConditionType
{
@ -433,8 +466,8 @@ public:
NUM_CONDITIONS,
};
NOBODY void AddCondition(ConditionType condition);
NOBODY bool IsValid(void) const;
void AddCondition(ConditionType condition); // conditions must be true for the statement to be spoken
bool IsValid(void) const; // verify all attached conditions
enum ContextType
{
@ -444,34 +477,33 @@ public:
LONG_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:
friend class BotChatterInterface;
BotChatterInterface *m_chatter;
BotStatement *m_next;
BotStatement *m_prev;
BotStatementType m_type;
int m_subject;
Place m_place;
BotMeme *m_meme;
float m_timestamp;
float m_startTime;
float m_expireTime;
float m_speakTimestamp;
bool m_isSpeaking;
float m_nextTime;
BotChatterInterface *m_chatter; // the chatter system this statement is part of
BotStatement *m_next, *m_prev; // linked list hooks
BotStatementType m_type; // what kind of statement this is
int m_subject; // who this subject is about
Place m_place; // explicit place - note some phrases have implicit places as well
BotMeme *m_meme; // a statement can only have a single meme for now
float m_timestamp; // time when message was created
float m_startTime; // the earliest time this statement can be spoken
float m_expireTime; // time when this statement is no longer valid
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 };
struct
@ -482,115 +514,124 @@ public:
const BotPhrase *phrase;
ContextType context;
};
} m_statement[ MAX_BOT_PHRASES ];
}
m_statement[ MAX_BOT_PHRASES ];
enum { MAX_BOT_CONDITIONS = 4 };
ConditionType m_condition[ MAX_BOT_CONDITIONS ];
ConditionType m_condition[ MAX_BOT_CONDITIONS ]; // conditions that must be true for the statement to be said
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;
};/* size: 112, cachelines: 2, members: 18 */
// This class defines the interface to the bot radio chatter system
class BotChatterInterface
{
public:
BotChatterInterface(void) {};
NOBODY BotChatterInterface(CCSBot *me);
NOBODY ~BotChatterInterface();
BotChatterInterface(CCSBot *me);
~BotChatterInterface();
NOBODY void Reset(void);
NOBODY void Update(void);
void Reset(void); // reset to initial state
void Update(void); // process ongoing chatter
NOBODY void OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other);
NOBODY void OnDeath(void);
void OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other); // invoked when event occurs in the game (some events have NULL entities)
void OnDeath(void); // invoked when we die
enum VerbosityType
{
NORMAL,
MINIMAL,
RADIO,
OFF,
NORMAL, // full chatter
MINIMAL, // only scenario-critical events
RADIO, // use the standard radio instead
OFF // no chatter at all
};
VerbosityType GetVerbosity(void) const; // return our current level of verbosity
VerbosityType GetVerbosity(void) const;
NOBODY CCSBot *GetOwner(void) const
{
return m_me;
}
bool IsTalking(void) const;
NOBODY float GetRadioSilenceDuration(void);
NOBODY void ResetRadioSilenceDuration(void);
CCSBot *GetOwner(void) const { return m_me; }
bool IsTalking(void) const; // return true if we are currently talking
float GetRadioSilenceDuration(void); // return time since any teammate said anything
void ResetRadioSilenceDuration(void);
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);
NOBODY void RemoveStatement(BotStatement *statement);
BotStatement *GetActiveStatement(void); // returns the statement that is being spoken, or is next to be spoken if no-one is speaking now
BotStatement *GetStatement(void) const; // returns our current statement, or NULL if we aren't speaking
NOBODY BotStatement *GetActiveStatement(void);
BotStatement *GetStatement(void) const;
int GetPitch(void) const
{
return m_pitch;
}
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);
NOBODY void AnnouncePlan(const char *phraseName, Place place);
NOBODY void Affirmative(void);
NOBODY void Negative(void);
void AnnouncePlan(const char *phraseName, Place place);
void Affirmative(void);
void Negative(void);
NOBODY void EnemySpotted(void);
NOBODY void KilledMyEnemy(int victimID);
NOBODY void EnemiesRemaining(void);
void EnemySpotted(void); // report enemy sightings
void KilledMyEnemy(int victimID);
void EnemiesRemaining(void);
NOBODY 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);
NOXREF void Clear(Place place);
NOBODY void Encourage(const char *phraseName, float repeatInterval = 10.0f, float lifetime = 3.0f);
NOBODY void KilledFriend(void);
NOBODY void FriendlyFire(void);
public:
static CountdownTimer m_encourageTimer;
static IntervalTimer m_radioSilenceInterval[2];
void ReportIn(void); // ask for current situation
void ReportingIn(void); // report current situation
bool NeedBackup(void);
void PinnedDown(void);
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:
#endif // HOOK_GAMEDLL
NOBODY void ReportEnemies(void);
NOBODY bool ShouldSpeak(void) const;
BotStatement *m_statementList; // list of all active/pending messages for this bot
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;
CCSBot *m_me; // the bot this chatter is for
bool m_seeAtLeastOneEnemy;
float m_timeWhenSawFirstEnemy;
bool m_reportedEnemies;
bool m_requestedBombLocation;
bool m_requestedBombLocation; // true if we already asked where the bomb has been planted
int m_pitch;
static IntervalTimer IMPL(m_radioSilenceInterval)[2]; // one timer for each team
IntervalTimer m_needBackupInterval;
IntervalTimer m_spottedBomberInterval;
IntervalTimer m_scaredInterval;
@ -598,6 +639,8 @@ private:
CountdownTimer m_spottedLooseBombTimer;
CountdownTimer m_heardNoiseTimer;
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 */
/* <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 */
inline bool BotChatterInterface::IsTalking(void) const
{
if (m_statementList)
if (m_statementList != NULL)
{
return m_statementList->IsSpeaking();
}
return false;
}
@ -647,14 +693,14 @@ extern CBaseEntity *g_pSelectedZombieSpawn;
/* <5c4dcf> ../cstrike/dlls/bot/cs_bot_chatter.h:604 */
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));
if (delay > 0.0f)
say->SetStartTime(gpGlobals->curtime + delay);
say->SetStartTime(gpGlobals->time + delay);
AddStatement(say);*/
AddStatement(say);
}
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_BOTPHRASE)(const BotPhrase *);
typedef const BotPhraseManager *(BotPhraseManager::*GET_PLACE_NAME)(const char *name) const;
typedef const BotPhraseManager *(BotPhraseManager::*GET_PLACE_PLACE)(PlaceCriteria place) const;
#endif // HOOK_GAMEDLL
typedef const BotPhrase *(BotPhraseManager::*GET_PLACE_NAME)(const char *name) const;
typedef const BotPhrase *(BotPhraseManager::*GET_PLACE_PLACE)(PlaceCriteria place) const;
// refs
extern void (*pBotPhrase__Randomize)(void);
#endif // HOOK_GAMEDLL
#endif // CS_BOT_CHATTER_H

View File

@ -1,7 +1,7 @@
#include "precompiled.h"
/* <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

View File

@ -1,7 +1,76 @@
#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 */
NOBODY void InstallBotControl(void)
void InstallBotControl(void)
{
if (TheBots != NULL)
{
@ -11,6 +80,8 @@ NOBODY void InstallBotControl(void)
TheBots = new CCSBotManager;
}
// Engine callback for custom server commands
/* <333cb3> ../cstrike/dlls/bot/cs_bot_init.cpp:68 */
void Bot_ServerCommand(void)
{
@ -58,52 +129,35 @@ void Bot_RegisterCvars(void)
}
}
// Constructor
/* <333d1e> ../cstrike/dlls/bot/cs_bot_init.cpp:129 */
//CCSBot::CCSBot(void)
//{
// CountdownTimer(CountdownTimer *const this); // 129
// IdleState(IdleState *const this); // 129
// MoveToState(MoveToState *const this); // 129
// HuntState(HuntState *const this); // 129
// 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
//}
CCSBot::CCSBot(void) : m_chatter(this), m_gameState(this)
{
;
}
// Prepare bot for action
/* <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);
// CS bot initialization
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_currentNode = NULL;
m_combatRange = RANDOM_FLOAT(325, 425);
m_name[0] = '\0';
m_safeTime = m_profile->GetAggression() * 5 + 15;
// set initial safe time guess for this map
m_safeTime = 15.0f + 5.0f * GetProfile()->GetAggression();
m_name[0] = '\000';
ResetValues();
StartNormalProcess();
@ -111,18 +165,13 @@ NOBODY bool CCSBot::__MAKE_VHOOK(Initialize)(const BotProfile *profile)
return true;
}
void (*pCCSBot__ResetValues)(void);
// Reset internal data to initial state
/* <3341dc> ../cstrike/dlls/bot/cs_bot_init.cpp:167 */
NOBODY void __declspec(naked) CCSBot::ResetValues(void)
void CCSBot::ResetValues(void)
{
__asm
{
jmp pCCSBot__ResetValues
}
/*
m_chatter.Reset();//TODO: Reverse me
m_gameState.Reset();//TODO: Reverse me
m_chatter.Reset();
m_gameState.Reset();
m_avoid = NULL;
m_avoidTimestamp = 0.0f;
@ -136,28 +185,28 @@ NOBODY void __declspec(naked) CCSBot::ResetValues(void)
m_pathLength = 0;
m_pathIndex = 0;
m_areaEnteredTimestamp = 0.0f;
m_currentArea = NULL;
m_lastKnownArea = NULL;
m_avoidFriendTimer.Invalidate();
m_isFriendInTheWay = false;
m_isWaitingBehindFriend = false;
m_disposition = ENGAGE_AND_INVESTIGATE;
m_enemy = NULL;
m_isWaitingToTossGrenade = false;
m_wasSafe = true;
m_nearbyEnemyCount = 0;
m_enemyPlace = 0;
m_nearbyFriendCount = 0;
m_closestVisibleFriend = 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].isEnemy = false;
@ -165,24 +214,20 @@ NOBODY void __declspec(naked) CCSBot::ResetValues(void)
m_isEnemyVisible = false;
m_visibleEnemyParts = NONE;
m_lastSawEnemyTimestamp = 0.0f;
m_firstSawEnemyTimestamp = 0.0f;
m_currentEnemyAcquireTimestamp = 0.0f;
m_isLastEnemyDead = true;
m_attacker = NULL;
m_attackedTimestamp = 0.0f;
m_enemyDeathTimestamp = 0.0f;
m_lastVictimID = 0;
m_isAimingAtEnemy = false;
m_fireWeaponTimestamp = 0.0f;
m_equipTimer.Invalidate();
m_isFollowing = false;
m_leader = NULL;
m_followTimestamp = 0.0f;
m_allowAutoFollowTime = 0.0f;
@ -193,47 +238,40 @@ NOBODY void __declspec(naked) CCSBot::ResetValues(void)
m_lookAroundStateTimestamp = 0.0f;
m_inhibitLookAroundTimestamp = 0.0f;
m_lookPitch = 0.0f;
m_lookPitchVel = 0.0f;
m_lookYaw = 0.0f;
m_lookYawVel = 0.0f;
m_aimOffsetTimestamp = 0.0f;
m_aimSpreadTimestamp = 0.0f;
m_lookAtSpotState = NOT_LOOKING_AT_SPOT;
m_spotEncounter = NULL;
m_spotEncounter = NULL;
m_spotCheckTimestamp = 0.0f;
m_peripheralTimestamp = 0.0f;
m_avgVelIndex = 0;
m_avgVelCount = 0;
if (pev)
{
m_lastOrigin = pev->origin;
}
else
m_lastOrigin = Vector(0, 0, 0);
m_lastOrigin = (pev != NULL) ? pev->origin : Vector(0, 0, 0);
m_lastRadioCommand = EVENT_INVALID;
m_lastRadioRecievedTimestamp = 0.0f;
m_lastRadioSentTimestamp = 0.0f;
m_radioSubject = NULL;
m_noisePosition = Vector(0, 0, 0);
m_noiseTimestamp = 0.0f;
m_noiseCheckTimestamp = 0.0f;
m_voiceFeedbackEndTimestamp = 0.0f;
m_hostageEscortCount = 0;
m_hostageEscortCountTimestamp = 0.0f;
m_noisePosition = Vector(0, 0, 0);
m_noiseTimestamp = 0.0f;
m_noiseCheckTimestamp = 0.0f;
m_isNoiseTravelRangeChecked = false;
m_stateTimestamp = 0.0f;
m_stateTimestamp = 0.0f;
m_task = SEEK_AND_DESTROY;
m_taskEntity = NULL;
@ -245,38 +283,49 @@ NOBODY void __declspec(naked) CCSBot::ResetValues(void)
StandUp();
Run();
m_pathLadder = NULL;
m_mustRunTimer.Invalidate();
m_repathTimer.Invalidate();
m_pathLadder = NULL;
m_huntState.ClearHuntArea();
// adjust morale - if we died, our morale decreased,
// but if we live, no adjustement (round win/loss also adjusts morale
if (m_diedLastRound)
{
DecreaseMorale();
}
m_diedLastRound = false;
// IsRogue() randomly changes this
m_isRogue = false;
m_surpriseDelay = 0.0f;
m_surpriseTimestamp = 0.0f;
// even though these are EHANDLEs, they need to be NULL-ed
m_goalEntity = NULL;
m_avoid = 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
StopAttacking();//TODO: Reverse me
Idle();//TODO: Reverse me
*/
StopAttacking();
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 */
NOBODY void CCSBot::__MAKE_VHOOK(SpawnBot)(void)
void CCSBot::__MAKE_VHOOK(SpawnBot)(void)
{
CCSBotManager *ctrl = TheCSBots();
@ -288,7 +337,7 @@ NOBODY void CCSBot::__MAKE_VHOOK(SpawnBot)(void)
SetState(&m_buyState);
SetTouch(&CCSBot::BotTouch);
if (!TheNavAreaList.empty() && !ctrl->IsLearningMap())
if (TheNavAreaList.empty() && !ctrl->IsLearningMap())
{
ctrl->SetLearningMapFlag();
StartLearnProcess();
@ -296,8 +345,11 @@ NOBODY void CCSBot::__MAKE_VHOOK(SpawnBot)(void)
}
/* <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 */
@ -305,11 +357,9 @@ void CCSBot::Disconnect(void)
{
EndVoiceFeedback();
if (m_processMode)
if (m_processMode != PROCESS_NORMAL)
{
MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress);
WRITE_BYTE(FLAG_PROGRESS_HIDE);
MESSAGE_END();
hideProgressMeter();
}
}

View File

@ -1,64 +1,126 @@
#include "precompiled.h"
/*
* Globals initialization
*/
#ifndef HOOK_GAMEDLL
const float updateTimesliceDuration = 0.0f;
#else
const float updateTimesliceDuration = 0.0;//TODO: what value?? check it.
#endif // HOOK_GAMEDLL
const float updateTimesliceDuration = 0.5f;
int _navAreaCount;
int _currentIndex;
/* <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; // 97
// {
// int d; // 103
// {
// Vector tryPos; // 105
// Vector tryNormal; // 118
// float const fudge; // 123
// TraceResult result; // 124
// }
// }
// }
Vector center = *pos;
AddDirectionVector(&center, mountDir, HalfHumanWidth);
// Test the ladder dismount point first, then each cardinal direction one and two steps away
for (int d = (-1); d < 2 * NUM_DIRECTIONS; ++d)
{
Vector tryPos = center;
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 */
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)
{
// {
// class CNavNode *node; // 34
// bool useNew; // 37
// float const zTolerance; // 48
// TraceResult result; // 63
// Vector floor; // 64
// Vector ceiling; // 64
// bool crouch; // 65
// MarkAsVisited(CNavNode *const this,
// enum NavDirType dir); // 52
// {
// float y; // 66
// {
// float x; // 68
// }
// }
// SetAttributes(CNavNode *const this,
// unsigned char bits); // 89
// }
// check if a node exists at this location
CNavNode *node = const_cast<CNavNode *>(CNavNode::GetNode(destPos));
// if no node exists, create one
bool useNew = false;
if (node == NULL)
{
node = new CNavNode(destPos, normal, source);
useNew = true;
}
// connect source node to new node
source->ConnectTo(node, dir);
// optimization: if deltaZ changes very little, assume connection is commutative
const float zTolerance = 10.0f; // 50.0f;
if (fabs(source->GetPosition()->z - destPos->z) < zTolerance)
{
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 */
NOXREF void drawProgressMeter(float progress, char *title)
void drawProgressMeter(float progress, char *title)
{
MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress);
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 */
NOXREF void startProgressMeter(const char *title)
void startProgressMeter(const char *title)
{
MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress);
WRITE_BYTE(FLAG_PROGRESS_START);
@ -77,7 +139,7 @@ NOXREF void startProgressMeter(const char *title)
}
/* <3435a8> ../cstrike/dlls/bot/cs_bot_learn.cpp:167 */
NOXREF void hideProgressMeter(void)
void hideProgressMeter(void)
{
MESSAGE_BEGIN(MSG_ALL, gmsgBotProgress);
WRITE_BYTE(FLAG_PROGRESS_HIDE);
@ -85,115 +147,228 @@ NOXREF void hideProgressMeter(void)
}
/* <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");
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 */
NOBODY bool CCSBot::LearnStep(void)
bool CCSBot::LearnStep(void)
{
// {
// int dir; // 249
// {
// float feetOffset; // 256
// Vector pos; // 259
// int cx; // 262
// int cy; // 263
// TraceResult result; // 283
// Vector from; // 284
// Vector to; // 284
// Vector toNormal; // 289
// Vector fromOrigin; // 298
// Vector toOrigin; // 299
// bool walkable; // 303
// IsEntityWalkable(entvars_t *entity,
// unsigned int flags); // 362
// {
// float toGround; // 309
// float fromGround; // 310
// float epsilon; // 312
// {
// Vector delta; // 322
// float const inc; // 323
// float along; // 324
// bool done; // 325
// float ground; // 326
// Vector normal; // 327
// operator-(const Vector *const this,
// const Vector &v); // 322
// {
// Vector p; // 333
// operator*(const Vector *const this,
// float fl); // 343
// operator+(const Vector *const this,
// const Vector &v); // 343
// }
// }
// }
// VARS(edict_t *pent); // 362
// GetFeetZ(const class CCSBot *const this); // 256
// Vector(Vector *const this,
// const Vector &v); // 259
// MarkAsVisited(CNavNode *const this,
// enum NavDirType dir); // 280
// operator+(const Vector *const this,
// const Vector &v); // 294
// operator+(const Vector *const this,
// const Vector &v); // 298
// operator+(const Vector *const this,
// const Vector &v); // 299
// {
// class CNavNode *newNode; // 376
// AddNode(CCSBot *const this,
// const Vector *destPos,
// const Vector *normal,
// enum NavDirType dir,
// class CNavNode *source); // 376
// }
// }
// HasVisited(CNavNode *const this,
// enum NavDirType dir); // 251
// }
// {
// iterator iter; // 225
// {
// class CNavLadder *ladder; // 227
// LadderEndSearch(CBaseEntity *entity,
// const Vector *pos,
// enum NavDirType mountDir); // 230
// LadderEndSearch(CBaseEntity *entity,
// const Vector *pos,
// enum NavDirType mountDir); // 234
// }
// operator++(_List_iterator<CNavLadder*> *const this); // 225
// }
UNTESTED
// take a step
while (true)
{
if (m_currentNode == NULL)
{
// search is exhausted - continue search from ends of ladders
NavLadderList::iterator iter;
for (iter = TheNavLadderList.begin(); iter != TheNavLadderList.end(); ++iter)
{
CNavLadder *ladder = (*iter);
// check ladder bottom
if ((m_currentNode = LadderEndSearch(ladder->m_entity, &ladder->m_bottom, ladder->m_dir)) != 0)
break;
// check ladder top
if ((m_currentNode = LadderEndSearch(ladder->m_entity, &ladder->m_top, ladder->m_dir)) != 0)
break;
}
if (m_currentNode == NULL)
{
// all seeds exhausted, sampling complete
GenerateNavigationAreaMesh();
return false;
}
}
// Take a step from this node
for (int dir = NORTH; dir < NUM_DIRECTIONS; dir++)
{
if (!m_currentNode->HasVisited((NavDirType)dir))
{
float feetOffset = pev->origin.z - GetFeetZ();
// start at current node position
Vector pos = *m_currentNode->GetPosition();
// snap to grid
int cx = SnapToGrid(pos.x);
int cy = SnapToGrid(pos.y);
// attempt to move to adjacent node
switch (dir)
{
case NORTH: cy -= GenerationStepSize; break;
case SOUTH: cy += GenerationStepSize; break;
case EAST: cx += GenerationStepSize; break;
case WEST: cx -= GenerationStepSize; break;
}
pos.x = cx;
pos.y = cy;
m_generationDir = (NavDirType)dir;
// mark direction as visited
m_currentNode->MarkAsVisited(m_generationDir);
// test if we can move to new position
TraceResult result;
Vector from, to;
// modify position to account for change in ground level during step
to.x = pos.x;
to.y = pos.y;
Vector toNormal;
if (GetGroundHeight(&pos, &to.z, &toNormal) == false)
{
return true;
}
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 */
NOBODY void CCSBot::UpdateLearnProcess(void)
void CCSBot::UpdateLearnProcess(void)
{
// {
// float startTime; // 394
// }
float startTime = g_engfuncs.pfnTime();
while (g_engfuncs.pfnTime() - startTime >= updateTimesliceDuration)
{
if (LearnStep() == false)
{
StartAnalyzeAlphaProcess();
break;
}
}
}
/* <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 */
NOBODY inline bool CCSBot::AnalyzeAlphaStep(void)
bool CCSBot::AnalyzeAlphaStep(void)
{
// {
// class CNavArea *area; // 432
// }
if (m_analyzeIter == TheNavAreaList.end())
return false;
CNavArea *area = (*m_analyzeIter);
++_currentIndex;
area->ComputeHidingSpots();
area->ComputeApproachAreas();
++m_analyzeIter;
return true;
}
/* <3448de> ../cstrike/dlls/bot/cs_bot_learn.cpp:443 */
NOBODY void CCSBot::UpdateAnalyzeAlphaProcess(void)
void CCSBot::UpdateAnalyzeAlphaProcess(void)
{
// {
// float startTime; // 445
// float progress; // 462
// AnalyzeAlphaStep(CCSBot *const this); // 451
// drawProgressMeter(float progress,
// char *title); // 454
// StartAnalyzeBetaProcess(CCSBot *const this); // 456
// drawProgressMeter(float progress,
// char *title); // 463
// }
float startTime = g_engfuncs.pfnTime();
float progress = _currentIndex / _navAreaCount * 50.0f;
while (AnalyzeAlphaStep())
{
if (g_engfuncs.pfnTime() - startTime >= updateTimesliceDuration)
{
drawProgressMeter(progress, "#CZero_AnalyzingHidingSpots");
return;
}
}
drawProgressMeter(50, "#CZero_AnalyzingHidingSpots");
CleanupApproachAreaAnalysisPrep();
StartAnalyzeBetaProcess();
}
/* <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 */
NOBODY inline bool CCSBot::AnalyzeBetaStep(void)
bool CCSBot::AnalyzeBetaStep(void)
{
// {
// class CNavArea *area; // 484
// }
if (m_analyzeIter == TheNavAreaList.end())
return false;
CNavArea *area = (*m_analyzeIter);
++_currentIndex;
area->ComputeSpotEncounters();
area->ComputeSniperSpots();
++m_analyzeIter;
return true;
}
/* <344b8d> ../cstrike/dlls/bot/cs_bot_learn.cpp:495 */
NOBODY void CCSBot::UpdateAnalyzeBetaProcess(void)
void CCSBot::UpdateAnalyzeBetaProcess(void)
{
// {
// float startTime; // 497
// float progress; // 512
// AnalyzeBetaStep(CCSBot *const this); // 503
// drawProgressMeter(float progress,
// char *title); // 506
// StartSaveProcess(CCSBot *const this); // 507
// drawProgressMeter(float progress,
// char *title); // 513
// }
float startTime = g_engfuncs.pfnTime();
float progress = (_currentIndex / _navAreaCount + 1.0f) * 50.0f;
while (AnalyzeBetaStep())
{
if (g_engfuncs.pfnTime() - startTime >= updateTimesliceDuration)
{
drawProgressMeter(progress, "#CZero_AnalyzingApproachPoints");
return;
}
}
drawProgressMeter(100, "#CZero_AnalyzingApproachPoints");
StartSaveProcess();
}
/* <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 */
NOBODY void CCSBot::UpdateSaveProcess(void)
void CCSBot::UpdateSaveProcess(void)
{
// {
// char filename; // 530
// char msg; // 538
// char cmd; // 548
// hideProgressMeter(void); // 542
// StartNormalProcess(CCSBot *const this); // 545
// }
char filename[256];
char msg[256];
char cmd[128];
GET_GAME_DIR(filename);
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 */

View File

@ -1,92 +1,214 @@
#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 */
NOBODY bool CCSBot::ShouldInvestigateNoise(float *retNoiseDist)
bool CCSBot::ShouldInvestigateNoise(float *retNoiseDist)
{
// IsNoiseHeard(const class CCSBot *const this); // 32
// {
// float const noiseCheckInterval; // 36
// Vector toNoise; // 44
// float noiseDist; // 45
// float const maxNoiseDist; // 46
// float const oneStoreyHeight; // 49
// float chance; // 72
// operator-(const Vector *const this,
// const Vector &v); // 44
// Length(const Vector *const this); // 45
// {
// class PathCost pc; // 53
// float travelDistToNoise; // 54
// float const tooFar; // 58
// NavAreaTravelDistance<PathCost>(CNavArea *startArea,
// class CNavArea *endArea,
// class PathCost &costFunc); // 54
// }
// {
// float friendFactor; // 78
// }
// }
if (m_isNoiseTravelRangeChecked)
return false;
// don't investigate noises during safe time
if (!IsWellPastSafe())
return false;
// if our disposition is not to investigate, dont investigate
if (GetDisposition() != ENGAGE_AND_INVESTIGATE)
return false;
// listen for enemy noises
if (IsNoiseHeard() && gpGlobals->time - m_noiseCheckTimestamp >= 0.25f)
{
m_noiseCheckTimestamp = gpGlobals->time;
Vector toNoise = m_noisePosition - pev->origin;
float noiseDist = toNoise.Length();
float const oneStoreyHeight = 120.0f;
if (abs(int64(toNoise.z)) > oneStoreyHeight)
{
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 */
NOBODY bool CCSBot::CanHearNearbyEnemyGunfire(float range)
bool CCSBot::CanHearNearbyEnemyGunfire(float range) const
{
// {
// float gunfireDistSq; // 125
// float enemyDistSq; // 126
// float const muchCloserSq; // 127
// operator-(const Vector *const this,
// const Vector &v); // 126
// operator-(const Vector *const this,
// const Vector &v); // 125
// LengthSquared(const Vector *const this); // 125
// LengthSquared(const Vector *const this); // 126
// }
// CanSeeNoisePosition(const class CCSBot *const this); // 119
// operator-(const Vector *const this,
// const Vector &v); // 115
// IsLengthGreaterThan(const Vector *const this,
// float length); // 115
// only attend to noise if it just happened
if (gpGlobals->time - m_noiseTimestamp > 0.5f)
return false;
// gunfire is high priority
if (m_noisePriority < PRIORITY_HIGH)
return false;
// check noise range
if (range > 0.0f && (pev->origin - m_noisePosition).IsLengthGreaterThan(range))
return false;
// if we dont have line of sight, it's not threatening (cant get shot)
if (!CanSeeNoisePosition())
return false;
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 */
NOBODY bool CCSBot::CanSeeNoisePosition(void)
bool CCSBot::CanSeeNoisePosition(void) const
{
// {
// TraceResult result; // 143
// operator+(const Vector *const this,
// const Vector &v); // 144
// GetEyePosition(const class CCSBot *const this); // 144
// }
TraceResult result;
UTIL_TraceLine(GetEyePosition(), m_noisePosition + Vector(0, 0, HalfHumanHeight), ignore_monsters, ignore_glass, ENT(pev), &result);
if (result.flFraction == 1.0f)
{
// 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 */
NOBODY bool CCSBot::UpdateLookAtNoise(void)
bool CCSBot::UpdateLookAtNoise(void)
{
// {
// bool nearbyThreat; // 176
// float const recentThreatTime; // 177
// float const closeThreatRange; // 178
// Vector spot; // 190
// enum PriorityType pri; // 231
// IsNoiseHeard(const class CCSBot *const this); // 163
// operator-(const Vector *const this,
// const Vector &v); // 181
// IsLengthLessThan(const Vector *const this,
// float length); // 181
// CanSeeNoisePosition(const class CCSBot *const this); // 193
// {
// int nearIdx; // 200
// float nearRangeSq; // 201
// {
// int i; // 202
// {
// float distanceSq; // 206
// operator-(const Vector *const this,
// const Vector &v); // 206
// LengthSquared(const Vector *const this); // 206
// }
// }
// }
// }
// make sure a noise exists
if (!IsNoiseHeard() || gpGlobals->time - m_noiseTimestamp > 0.5f)
return false;
bool nearbyThreat = false;
float const recentThreatTime = 5.0f;
if (GetTimeSinceLastSawEnemy() < recentThreatTime)
{
const float closeThreatRange = 750.0f;
if ((pev->origin - m_lastEnemyPosition).IsLengthLessThan(closeThreatRange))
{
nearbyThreat = true;
}
}
Vector spot;
// if we have clear line of sight to noise position, look directly at it
if ((!IsAtHidingSpot() && nearbyThreat) || CanSeeNoisePosition())
{
// TODO: adjust noise Z to keep consistent with current height while fighting
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 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_isMapDataLoaded (*pm_isMapDataLoaded)
//#define m_editCmd (*pm_editCmd)
@ -77,57 +47,28 @@
extern CBotManager *TheBots;
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;
// The manager for Counter-Strike specific bots
class CCSBotManager: public CBotManager
{
public:
CCSBotManager(void);
public:
CCSBotManager();
virtual void ClientDisconnect(CBasePlayer *pPlayer);
virtual BOOL ClientCommand(CBasePlayer *pPlayer, const char *pcmd);
virtual void ServerActivate(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 AddServerCommands(void);
virtual void RestartRound(void);
NOBODY virtual void StartFrame(void);
virtual void RestartRound(void); // (EXTEND) invoked when a new round begins
virtual void StartFrame(void); // (EXTEND) called each frame
virtual void OnEvent(GameEventType event, CBaseEntity *entity = NULL, CBaseEntity *other = NULL);
NOBODY virtual unsigned int GetPlayerPriority(CBasePlayer *player) const;
NOBODY virtual bool IsImportantPlayer(CBasePlayer *player);
virtual unsigned int GetPlayerPriority(CBasePlayer *player) const; // return priority of player (0 = max pri)
virtual bool IsImportantPlayer(CBasePlayer *player) const; // return true if player is important to scenario (VIP, bomb carrier, etc)
#ifdef HOOK_GAMEDLL
@ -142,31 +83,19 @@ public:
void StartFrame_(void);
void OnEvent_(GameEventType event, CBaseEntity *entity, CBaseEntity *other);
unsigned int GetPlayerPriority_(CBasePlayer *player) const;
bool IsImportantPlayer_(CBasePlayer *player);
bool IsImportantPlayer_(CBasePlayer *player) const;
#endif // HOOK_GAMEDLL
public:
void ValidateMapData(void);
bool IsLearningMap(void)
{
return IMPL(m_isLearningMap);
}
void SetLearningMapFlag(void)
{
IMPL(m_isLearningMap) = true;
}
bool IsAnalysisRequested(void)
{
return IMPL(m_isAnalysisRequested);
}
void RequestAnalysis(void)
{
IMPL(m_isAnalysisRequested) = true;
}
void AckAnalysisRequest(void)
{
IMPL(m_isAnalysisRequested) = false;
}
bool IsLearningMap(void) const { return IMPL(m_isLearningMap); }
void SetLearningMapFlag(void) { IMPL(m_isLearningMap) = true;}
bool IsAnalysisRequested(void) const { return IMPL(m_isAnalysisRequested); }
void RequestAnalysis(void) { IMPL(m_isAnalysisRequested) = true; }
void AckAnalysisRequest(void) { IMPL(m_isAnalysisRequested) = false; }
// difficulty levels
static BotDifficultyType GetDifficultyLevel(void)
{
if (cv_bot_difficulty.value < 0.9f)
@ -181,41 +110,42 @@ public:
return BOT_EXPERT;
}
// the supported game scenarios
enum GameScenarioType
{
SCENARIO_DEATHMATCH,
SCENARIO_DEFUSE_BOMB,
SCENARIO_RESCUE_HOSTAGES,
SCENARIO_ESCORT_VIP,
SCENARIO_ESCORT_VIP
};
GameScenarioType GetScenario(void)
{
return m_gameScenario;
}
GameScenarioType GetScenario(void) const { 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
{
CBaseEntity *m_entity;
CNavArea *m_area[MAX_ZONE_NAV_AREAS];
CBaseEntity *m_entity; // the map entity
CNavArea *m_area[MAX_ZONE_NAV_AREAS]; // nav areas that overlap this zone
int m_areaCount;
Vector m_center;
bool m_isLegacy;
bool m_isLegacy; // if true, use pev->origin and 256 unit radius as zone
int m_index;
Extent m_extent;
};/* size: 116, cachelines: 2, members: 7 */
const Zone *GetZone(int i) const
{
return &m_zone[i];
}
NOBODY const Zone *GetZone(const Vector *pos) const;
const Zone *GetClosestZone(const Vector *pos) const;
const Zone *GetClosestZone(const CBaseEntity *entity) const
{
return GetClosestZone(&entity->pev->origin);
}
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
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
int GetZoneCount(void) const { return m_zoneCount; }
const Vector *GetRandomPositionInZone(const Zone *zone) const;
CNavArea *GetRandomAreaInZone(const Zone *zone) const;
// Return the zone closest to the given position, using the given cost heuristic
template<typename CostFunctor>
const Zone *GetClosestZone(CNavArea *startArea, CostFunctor costFunc, float *travelDistance = NULL) const
{
@ -225,7 +155,7 @@ public:
if (startArea == 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)
continue;
@ -233,7 +163,9 @@ public:
if (m_zone[i].m_isBlocked)
continue;
// just use the first overlapping nav area as a reasonable approximation
float dist = NavAreaTravelDistance(startArea, m_zone[i].m_area[0], costFunc);
if (dist >= 0.0f && dist < closeDist)
{
closeZone = &m_zone[i];
@ -241,17 +173,11 @@ public:
}
}
if (travelDistance)
if (travelDistance != NULL)
*travelDistance = closeDist;
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
const Zone *GetRandomZone(void) const
@ -261,172 +187,89 @@ public:
return &m_zone[ RANDOM_LONG(0, m_zoneCount - 1) ];
}
// returns true if bomb has been planted
bool IsBombPlanted(void) const
{
return m_isBombPlanted;
}
// return time bomb was planted
float GetBombPlantTimestamp(void)
{
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;
}
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
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
float GetBombTimeLeft(void) const; // get the time remaining before the planted bomb explodes
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
void SetLooseBomb(CBaseEntity *bomb);
NOBODY float GetRadioMessageTimestamp(GameEventType event, int teamID);
NOBODY float GetRadioMessageInterval(GameEventType event, int teamID);
NOBODY void SetRadioMessageTimestamp(GameEventType event, int teamID);
float GetRadioMessageTimestamp(GameEventType event, int teamID) const; // return the last time the given radio message was sent for given team
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);
// return the last time anyone has seen an enemy
float GetLastSeenEnemyTimestamp(void) const
{
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;
}
float GetLastSeenEnemyTimestamp(void) const { return m_lastSeenEnemyTimestamp; } // return the last time anyone has seen an enemy
void SetLastSeenEnemyTimestamp(void) { m_lastSeenEnemyTimestamp = gpGlobals->time; }
enum SkillType
{
LOW,
AVERAGE,
HIGH,
RANDOM
};
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
bool AllowRogues(void) const { return cv_bot_allow_rogues.value != 0.0f; }
bool AllowPistols(void) const { return cv_bot_allow_pistols.value != 0.0f; }
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);
NOBODY static void MonitorBotCVars(void);
NOBODY static void MaintainBotQuota(void);
static void MonitorBotCVars(void);
static void MaintainBotQuota(void);
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
private:
#else
public:
#endif // HOOK_GAMEDLL
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_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 ];
int m_zoneCount;
bool m_isBombPlanted;
float m_bombPlantTimestamp;
float m_earliestBombPlantTimestamp;
CBasePlayer *m_bombDefuser;
EHANDLE m_looseBomb;
CNavArea *m_looseBombArea;
bool m_isRoundOver;
bool m_isBombPlanted; // true if bomb has been planted
float m_bombPlantTimestamp; // time bomb was planted
float m_earliestBombPlantTimestamp; // don't allow planting until after this time has elapsed
CBasePlayer *m_bombDefuser; // the player currently defusing a bomb
EHANDLE m_looseBomb; // will be non-NULL if bomb is loose on the ground
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_lastSeenEnemyTimestamp;
float m_roundStartTimestamp;
bool m_isDefenseRushing;
float m_roundStartTimestamp; // the time when the current round began
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);
#ifdef HOOK_GAMEDLL
private:
#endif // HOOK_GAMEDLL
unsigned int m_navPlace;
CountdownTimer m_respawnTimer;
bool m_isRespawnStarted;
@ -448,7 +291,7 @@ inline CCSBotManager *TheCSBots(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

View File

@ -1,218 +1,468 @@
#include "precompiled.h"
// Reset the stuck-checker.
/* <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 */
NOBODY void CCSBot::StuckCheck(void)
void CCSBot::StuckCheck(void)
{
// {
// Vector delta; // 42
// float const unstuckRange; // 44
// operator-(const Vector *const this,
// const Vector &v); // 42
// IsLengthGreaterThan(const Vector *const this,
// float length); // 45
// ResetStuckMonitor(CCSBot *const this); // 48
// }
// {
// Vector vel; // 57
// float moveDist; // 64
// float deltaT; // 66
// operator-(const Vector *const this,
// const Vector &v); // 57
// Length(const Vector *const this); // 64
// {
// float avgVel; // 81
// float stuckVel; // 88
// {
// int t; // 82
// }
// }
// }
if (m_isStuck)
{
// we are stuck - see if we have moved far enough to be considered unstuck
Vector delta = pev->origin - m_stuckSpot;
const float unstuckRange = 75.0f;
if (delta.IsLengthGreaterThan(unstuckRange))
{
// we are no longer stuck
ResetStuckMonitor();
PrintIfWatched("UN-STUCK\n");
}
}
else
{
// check if we are stuck
// compute average velocity over a short period (for stuck check)
Vector vel = pev->origin - m_lastOrigin;
// if we are jumping, ignore Z
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 */
NOBODY bool CCSBot::DiscontinuityJump(float ground, bool onlyJumpDown, bool mustJump)
bool CCSBot::DiscontinuityJump(float ground, bool onlyJumpDown, bool mustJump)
{
// {
// float dz; // 119
// }
// don't try to jump again.
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 */
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,
// const Vector *pos,
// float *height,
// Vector *normal); // 154
if (GetSimpleGroundHeight(pos, height, normal))
{
// our current nav area also serves as a ground polygon
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 */
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 */
NOBODY void CCSBot::MoveTowardsPosition(const Vector *pos)
void CCSBot::MoveTowardsPosition(const Vector *pos)
{
// {
// float angle; // 249
// class Vector2D dir; // 251
// class Vector2D lat; // 252
// class Vector2D to; // 255
// float toProj; // 259
// float latProj; // 260
// float const c; // 262
// {
// float ground; // 200
// Vector aheadRay; // 201
// bool jumped; // 207
// NormalizeInPlace(Vector *const this); // 202
// {
// float const farLookAheadRange; // 210
// Vector normal; // 211
// Vector stepAhead; // 212
// operator*(float fl,
// const Vector &v); // 212
// GetSimpleGroundHeightWithFloor(CCSBot *const this,
// const Vector *pos,
// float *height,
// Vector *normal); // 215
// operator+(const Vector *const this,
// const Vector &v); // 212
// DiscontinuityJump(CCSBot *const this,
// float ground,
// bool onlyJumpDown,
// bool mustJump); // 218
// }
// {
// float const lookAheadRange; // 225
// Vector stepAhead; // 226
// operator*(float fl,
// const Vector &v); // 226
// operator+(const Vector *const this,
// const Vector &v); // 226
// GetSimpleGroundHeightWithFloor(CCSBot *const this,
// const Vector *pos,
// float *height,
// Vector *normal); // 228
// DiscontinuityJump(CCSBot *const this,
// float ground,
// bool onlyJumpDown,
// bool mustJump); // 230
// }
// {
// float const lookAheadRange; // 237
// Vector stepAhead; // 238
// operator*(float fl,
// const Vector &v); // 238
// operator+(const Vector *const this,
// const Vector &v); // 238
// GetSimpleGroundHeightWithFloor(CCSBot *const this,
// const Vector *pos,
// float *height,
// Vector *normal); // 240
// DiscontinuityJump(CCSBot *const this,
// float ground,
// bool onlyJumpDown,
// bool mustJump); // 242
// }
// }
// NormalizeInPlace(Vector2D *const this); // 256
// }
// Jump up on ledges
// Because we may not be able to get to our goal position and enter the next
// area because our extent collides with a nearby vertical ledge, make sure
// we look far enough ahead to avoid this situation.
// Can't look too far ahead, or bots will try to jump up slopes.
// NOTE: We need to do this frequently to catch edges at the right time
// TODO: Look ahead *along path* instead of straight line
if ((m_lastKnownArea == NULL || !(m_lastKnownArea->GetAttributes() & NAV_NO_JUMP)) &&
!IsOnLadder() && !m_isJumpCrouching)
{
float ground;
Vector aheadRay(pos->x - pev->origin.x, pos->y - pev->origin.y, 0);
aheadRay.NormalizeInPlace();
// look far ahead to allow us to smoothly jump over gaps, ledges, etc
// only jump if ground is flat at lookahead spot to avoid jumping up slopes
bool jumped = false;
if (IsRunning())
{
const float farLookAheadRange = 80.0f;
Vector normal;
Vector stepAhead = pev->origin + farLookAheadRange * aheadRay;
stepAhead.z += HalfHumanHeight;
if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground, &normal))
{
if (normal.z > 0.9f)
jumped = DiscontinuityJump(ground, ONLY_JUMP_DOWN);
}
}
if (!jumped)
{
// close up jumping
// cant be less or will miss jumps over low walls
const float lookAheadRange = 30.0f;
Vector stepAhead = pev->origin + lookAheadRange * aheadRay;
stepAhead.z += HalfHumanHeight;
if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
{
jumped = DiscontinuityJump(ground);
}
}
if (!jumped)
{
// about to fall gap-jumping
const float lookAheadRange = 10.0f;
Vector stepAhead = pev->origin + lookAheadRange * aheadRay;
stepAhead.z += HalfHumanHeight;
if (GetSimpleGroundHeightWithFloor(&stepAhead, &ground))
{
jumped = DiscontinuityJump(ground, ONLY_JUMP_DOWN, MUST_JUMP);
}
}
}
// compute our current forward and lateral vectors
float angle = pev->v_angle.y;
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 */
NOBODY void CCSBot::MoveAwayFromPosition(const Vector *pos)
NOXREF void CCSBot::MoveAwayFromPosition(const Vector *pos)
{
// {
// float angle; // 285
// class Vector2D dir; // 287
// class Vector2D lat; // 288
// class Vector2D to; // 291
// float toProj; // 295
// float latProj; // 296
// float const c; // 298
// NormalizeInPlace(Vector2D *const this); // 292
// }
// compute our current forward and lateral vectors
float angle = pev->v_angle[ YAW ];
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 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 */
NOBODY void CCSBot::StrafeAwayFromPosition(const Vector *pos)
void CCSBot::StrafeAwayFromPosition(const Vector *pos)
{
// {
// float angle; // 317
// class Vector2D dir; // 319
// class Vector2D lat; // 320
// class Vector2D to; // 323
// float latProj; // 326
// NormalizeInPlace(Vector2D *const this); // 324
// }
// compute our current forward and lateral vectors
float angle = pev->v_angle[ YAW ];
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();
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 */
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 */
NOBODY void CCSBot::ComputeApproachPoints(void)
void CCSBot::ComputeApproachPoints(void)
{
// {
// Vector eye; // 391
// Vector ap; // 393
// float halfWidth; // 394
// Vector(Vector *const this,
// const Vector &v); // 391
// {
// int i; // 395
// {
// const class ApproachInfo *info; // 397
// Vector bendPoint; // 415
// }
// GetApproachInfoCount(const class CNavArea *const this); // 395
// }
// }
m_approachPointCount = 0;
if (m_lastKnownArea == NULL)
{
return;
}
// assume we're crouching for now
Vector eye = pev->origin;
Vector ap;
float halfWidth;
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 */
NOBODY void CCSBot::DrawApproachPoints(void)
void CCSBot::DrawApproachPoints(void)
{
// {
// int i; // 427
// operator+(const Vector *const this,
// const Vector &v); // 428
// Vector(Vector *const this,
// const Vector &v); // 428
// }
for (int i = 0; i < m_approachPointCount; ++i)
{
UTIL_DrawBeamPoints(m_approachPoint[i], m_approachPoint[i] + Vector(0, 0, 50), 3, 0, 255, 255);
}
}
// Find the approach point that is nearest to our current path, ahead of us
/* <37ce12> ../cstrike/dlls/bot/cs_bot_nav.cpp:435 */
NOBODY bool CCSBot::FindApproachPointNearestPath(const Vector *pos)
NOXREF bool CCSBot::FindApproachPointNearestPath(Vector *pos)
{
// {
// Vector target; // 446
// Vector close; // 446
// float targetRangeSq; // 447
// bool found; // 448
// int start; // 450
// int end; // 451
// float const nearPathSq; // 457
// {
// int i; // 459
// {
// float rangeSq; // 464
// operator-(const Vector *const this,
// const Vector &v); // 464
// LengthSquared(const Vector *const this); // 464
// }
// }
// operator+(const Vector *const this,
// const Vector &v); // 478
// }
if (!HasPath())
return false;
// make sure approach points are accurate
ComputeApproachPoints();
if (m_approachPointCount == 0)
return false;
Vector target = Vector(0, 0, 0), close;
float targetRangeSq = 0.0f;
bool found = false;
int start = m_pathIndex;
int end = m_pathLength;
// We dont want the strictly closest point, but the farthest approach point
// from us that is near our path
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,64 +1,334 @@
#include "precompiled.h"
/* <3a397f> ../cstrike/dlls/bot/cs_bot_radio.cpp:220 */
NOBODY void CCSBot::StartVoiceFeedback(float duration)
{
// {
// class CBasePlayer *pPlayer; // 227
// MESSAGE_BEGIN(int msg_dest,
// int msg_type,
// const float *pOrigin,
// entvars_t *ent); // 230
// edict(CBaseEntity *const this); // 232
// ENTINDEX(edict_t *pEdict); // 232
// }
// Returns true if the radio message is an order to do something
// 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
|| event == EVENT_RADIO_NEGATIVE
|| event == EVENT_RADIO_ENEMY_SPOTTED
|| event == EVENT_RADIO_SECTOR_CLEAR
|| event == EVENT_RADIO_REPORTING_IN
|| event == EVENT_RADIO_REPORT_IN_TEAM
|| event == EVENT_RADIO_ENEMY_DOWN)
return false;
return true;
}
/* <3a3a32> ../cstrike/dlls/bot/cs_bot_radio.cpp:241 */
void CCSBot::EndVoiceFeedback(bool force)
{
if (!force && !m_voiceFeedbackEndTimestamp)
return;
m_voiceFeedbackEndTimestamp = 0;
MESSAGE_BEGIN(MSG_ALL, gmsgBotVoice);
WRITE_BYTE(0);
WRITE_BYTE(ENTINDEX(edict()));
MESSAGE_END();
}
// Respond to radio commands from HUMAN players
/* <3a3bcd> ../cstrike/dlls/bot/cs_bot_radio.cpp:259 */
NOBODY bool CCSBot::RespondToHelpRequest(CBasePlayer *them, Place place, float maxRange)
{
// {
// class PathCost pc; // 272
// float travelDistance; // 273
// NavAreaTravelDistance<PathCost>(CNavArea *startArea,
// class CNavArea *endArea,
// class PathCost &costFunc); // 273
// }
// {
// float rangeSq; // 287
// float const close; // 288
// operator-(const Vector *const this,
// const Vector &v); // 287
// LengthSquared(const Vector *const this); // 287
// }
// {
// const Vector *pos; // 301
// }
// Say(BotChatterInterface *const this,
// const char *phraseName,
// float lifetime,
// float delay); // 309
/* <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;
}
/* <3a4316> ../cstrike/dlls/bot/cs_bot_radio.cpp:319 */
NOBODY void CCSBot::SendRadioMessage(GameEventType event)
{
// {
// class CCSBotManager *ctrl; // 328
// char slot; // 333
// }
}
// 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 */
void CCSBot::EndVoiceFeedback(bool force)
{
if (!force && !m_voiceFeedbackEndTimestamp)
return;
m_voiceFeedbackEndTimestamp = 0;
MESSAGE_BEGIN(MSG_ALL, gmsgBotVoice);
WRITE_BYTE(0);
WRITE_BYTE(ENTINDEX(edict()));
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 */
bool CCSBot::RespondToHelpRequest(CBasePlayer *them, Place place, float maxRange)
{
if (IsRogue())
return false;
// if we're busy, ignore
if (IsBusy())
return false;
// if we are too far away, ignore
if (maxRange > 0.0f)
{
// compute actual travel distance
PathCost pc(this);
float_precision travelDistance = NavAreaTravelDistance(m_lastKnownArea, TheNavAreaGrid.GetNearestNavArea(&them->pev->origin), pc);
if (travelDistance < 0.0f)
return false;
if (travelDistance > maxRange)
return false;
}
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 */
void CCSBot::SendRadioMessage(GameEventType event)
{
// make sure this is a radio event
if (event <= EVENT_START_RADIO_1 || event >= EVENT_END_RADIO)
{
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"
// This method is the ONLY legal way to change a bot's current state
/* <3b3a2a> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:16 */
void CCSBot::SetState(BotState *state)
{
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)
{
StopAttacking();
}
if (m_state)
{
if (m_state != NULL)
m_state->OnExit(this);
}
state->OnEnter(this);
@ -29,144 +28,256 @@ void CCSBot::Idle(void)
}
/* <3b3afa> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:41 */
NOBODY void CCSBot::EscapeFromBomb(void)
void CCSBot::EscapeFromBomb(void)
{
// SetTask(CCSBot::EscapeFromBomb(// enum TaskType task,
// class CBaseEntity *entity); // 43
SetTask(ESCAPE_FROM_BOMB);
SetState(&m_escapeFromBombState);
}
/* <3b3b4b> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:48 */
NOBODY void CCSBot::Follow(CBasePlayer *player)
void CCSBot::Follow(CBasePlayer *player)
{
// SetTask(CCSBot *const this,
// enum TaskType task,
// class CBaseEntity *entity); // 60
// SetLeader(FollowState *const this,
// class CBasePlayer *player); // 61
if (player == NULL)
return;
// note when we began following
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 */
NOBODY void CCSBot::ContinueFollowing(void)
void CCSBot::ContinueFollowing(void)
{
// {
// class CBasePlayer *leader; // 73
// SetTask(CCSBot *const this,
// enum TaskType task,
// class CBaseEntity *entity); // 71
// SetLeader(FollowState *const this,
// class CBasePlayer *player); // 74
// }
SetTask(FOLLOW);
m_followState.SetLeader(m_leader);
SetState(&m_followState);
}
// Stop following
/* <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 */
NOBODY void CCSBot::RescueHostages(void)
void CCSBot::RescueHostages(void)
{
// SetTask(CCSBot::RescueHostages(// enum TaskType task,
// class CBaseEntity *entity); // 96
SetTask(RESCUE_HOSTAGES);
}
// Use the entity
/* <3b3cc9> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:103 */
NOBODY void CCSBot::UseEntity(CBaseEntity *entity)
void CCSBot::UseEntity(CBaseEntity *entity)
{
// SetEntity(UseEntityState *const this,
// class CBaseEntity *entity); // 105
m_useEntityState.SetEntity(entity);
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 */
NOBODY void CCSBot::Hide(CNavArea *searchFromArea, float duration, float hideRange, bool holdPosition)
void CCSBot::Hide(CNavArea *searchFromArea, float duration, float hideRange, bool holdPosition)
{
// {
// class CNavArea *source; // 120
// Vector sourcePos; // 121
// const Vector *pos; // 146
// DestroyPath(CCSBot *const this); // 118
// SetDuration(HideState *const this,
// float time); // 142
// SetSearchArea(HideState *const this,
// class CNavArea *area); // 140
// SetSearchRange(HideState *const this,
// float range); // 141
// SetHoldPosition(HideState *const this,
// bool hold); // 143
// SetHidingSpot(HideState *const this,
// const Vector *pos); // 154
// Idle(CCSBot *const this); // 160
// }
DestroyPath();
CNavArea *source;
Vector sourcePos;
if (searchFromArea)
{
source = searchFromArea;
sourcePos = *searchFromArea->GetCenter();
}
else
{
source = m_lastKnownArea;
sourcePos = pev->origin;
}
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 */
NOBODY void CCSBot::Hide(const Vector *hidingSpot, float duration, bool holdPosition)
void CCSBot::Hide(const Vector *hidingSpot, float duration, bool holdPosition)
{
// {
// class CNavArea *hideArea; // 173
// DestroyPath(CCSBot *const this); // 181
// SetHoldPosition(HideState *const this,
// bool hold); // 186
// SetSearchArea(HideState *const this,
// class CNavArea *area); // 183
// SetSearchRange(HideState *const this,
// float range); // 184
// SetDuration(HideState *const this,
// float time); // 185
// SetHidingSpot(HideState *const this,
// const Vector *pos); // 187
// Idle(CCSBot *const this); // 193
// }
CNavArea *hideArea = TheNavAreaGrid.GetNearestNavArea(hidingSpot);
if (hideArea == NULL)
{
PrintIfWatched("Hiding spot off nav mesh\n");
Idle();
return;
}
DestroyPath();
m_hideState.SetSearchArea(hideArea);
m_hideState.SetSearchRange(750.0f);
m_hideState.SetDuration(duration);
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 */
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)
{
// {
// class CNavArea *source; // 207
// Vector sourcePos; // 208
// const Vector *pos; // 232
// SetDuration(HideState *const this,
// float time); // 228
// SetSearchArea(HideState *const this,
// class CNavArea *area); // 226
// SetSearchRange(HideState *const this,
// float range); // 227
// SetHoldPosition(HideState *const this,
// bool hold); // 229
// SetHidingSpot(HideState *const this,
// const Vector *pos); // 239
// }
CNavArea *source;
Vector sourcePos;
if (searchFromArea)
{
source = searchFromArea;
sourcePos = *searchFromArea->GetCenter();
}
else
{
source = m_lastKnownArea;
sourcePos = pev->origin;
}
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 */
NOBODY bool CCSBot::TryToRetreat(void)
bool CCSBot::TryToRetreat(void)
{
// {
// const Vector *spot; // 258
// {
// float holdTime; // 265
// Hide(CCSBot *const this,
// const Vector *hidingSpot,
// float duration,
// bool holdPosition); // 268
// }
// }
const float maxRange = 1000.0f;
const Vector *spot = FindNearbyRetreatSpot(this, maxRange);
if (spot != NULL)
{
// ignore enemies for a second to give us time to hide
// reaching our hiding spot clears our disposition
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 */
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 */
NOBODY void CCSBot::Attack(CBasePlayer *victim)
void CCSBot::Attack(CBasePlayer *victim)
{
if (victim == NULL)
return;
// zombies never attack
if (cv_bot_zombie.value)
if (cv_bot_zombie.value != 0.0f)
return;
// cannot attack if we are reloading
@ -183,11 +294,11 @@ NOBODY void CCSBot::Attack(CBasePlayer *victim)
if (IsAtHidingSpot())
m_attackState.SetCrouchAndHold((RANDOM_FLOAT(0, 100) < 60.0f) != 0);
else
m_attackState.SetCrouchAndHold(0);
m_attackState.SetCrouchAndHold(false);
PrintIfWatched("ATTACK BEGIN (reaction time = %g (+ update time), surprise time = %g, attack delay = %g)\n");
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
m_lastEnemyPosition = victim->pev->origin;
@ -196,18 +307,16 @@ NOBODY void CCSBot::Attack(CBasePlayer *victim)
// compute the angle difference between where are looking, and where we need to look
Vector toEnemy = victim->pev->origin - pev->origin;
Vector idealAngle;
Vector idealAngle = UTIL_VecToAngles(toEnemy);
idealAngle = UTIL_VecToAngles(toEnemy);
float deltaYaw = (float)abs(m_lookYaw - idealAngle.y);
float deltaYaw = abs((int)(m_lookYaw - idealAngle.y));
while (deltaYaw > 180.0f)
deltaYaw -= 360.0f;
if (deltaYaw < 0.0f)
deltaYaw = -deltaYaw;
// immediately aim at enemy - accuracy penalty depending on how far we must turn to aim
// accuracy is halved if we have to turn 180 degrees
float turn = deltaYaw / 180.0f;
@ -220,11 +329,13 @@ NOBODY void CCSBot::Attack(CBasePlayer *victim)
m_aimOffsetTimestamp = gpGlobals->time + RANDOM_FLOAT(0.25f + turn, 1.5f);
}
// Exit the Attack state
/* <3b4416> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:366 */
void CCSBot::StopAttacking(void)
{
PrintIfWatched("ATTACK END\n");
m_attackState.OnExit(this);//TODO: Reverse me
m_attackState.OnExit(this);
m_isAttacking = false;
// 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 true if we are escaping from the bomb
/* <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 */
bool CCSBot::IsDefusingBomb(void) const
{
@ -254,6 +373,8 @@ bool CCSBot::IsDefusingBomb(void) const
return false;
}
// Return true if we are hiding
/* <3b44ed> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:411 */
bool CCSBot::IsHiding(void) const
{
@ -263,6 +384,8 @@ bool CCSBot::IsHiding(void) const
return false;
}
// Return true if we are hiding and at our hiding spot
/* <3b450f> ../cstrike/dlls/bot/cs_bot_statemachine.cpp:423 */
bool CCSBot::IsAtHidingSpot(void) const
{
@ -272,16 +395,30 @@ bool CCSBot::IsAtHidingSpot(void) const
return m_hideState.IsAtSpot();
}
// Return true if we are huting
/* <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 */
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 */
bool CCSBot::IsBuying(void) const
{
@ -291,31 +428,40 @@ bool CCSBot::IsBuying(void) const
return false;
}
// Move to potentially distant position
/* <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,
// const Vector *pos); // 474
// SetRouteType(MoveToState *const this,
// enum RouteType route); // 475
m_moveToState.SetGoalPosition(*pos);
m_moveToState.SetRouteType(route);
SetState(&m_moveToState);
}
/* <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 */
NOBODY void CCSBot::FetchBomb(void)
void CCSBot::FetchBomb(void)
{
SetState(&m_fetchBombState);
}
/* <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 */
NOBODY void CCSBot::InvestigateNoise(void)
void CCSBot::InvestigateNoise(void)
{
SetState(&m_investigateNoiseState);
}

View File

@ -1,5 +1,7 @@
#include "precompiled.h"
// Lightweight maintenance, invoked frequently
/* <3c635f> ../cstrike/dlls/bot/cs_bot_update.cpp:26 */
void CCSBot::__MAKE_VHOOK(Upkeep)(void)
{
@ -11,10 +13,12 @@ void CCSBot::__MAKE_VHOOK(Upkeep)(void)
if (m_isRapidFiring)
TogglePrimaryAttack();
// aiming must be smooth - update often
if (IsAimingAtEnemy())
{
UpdateAimOffset();
// aim at enemy, if he's still alive
if (m_enemy != NULL)
{
float feetOffset = pev->origin.z - GetFeetZ();
@ -30,13 +34,14 @@ void CCSBot::__MAKE_VHOOK(Upkeep)(void)
m_aimSpot = m_enemy->pev->origin;
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()))
{
if (IsEnemyPartVisible(CHEST))
{
// No headshots in this game, go for the chest.
// No headshots, go for the chest.
aimBlocked = true;
}
}
@ -130,11 +135,12 @@ void CCSBot::__MAKE_VHOOK(Upkeep)(void)
}
float driftAmplitude = 2.0f;
const float sharpshooter = 0.5f;
// have view "drift" very slowly, so view looks "alive"
if (IsUsingSniperRifle() && IsUsingScope())
driftAmplitude = sharpshooter;
{
driftAmplitude = 0.5f;
}
m_lookYaw += driftAmplitude * BotCOS(33.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);
/* <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
{
@ -326,6 +332,12 @@ void __declspec(naked) CCSBot::__MAKE_VHOOK(Update)(void)
#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)
{
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"
/* <3fca3c> ../cstrike/dlls/bot/cs_gamestate.cpp:13 */
NOBODY CSGameState::CSGameState(void)
{
}
/* <3fcd6b> ../cstrike/dlls/bot/cs_gamestate.cpp:27 */
NOBODY CSGameState::CSGameState(CCSBot *owner)
CSGameState::CSGameState(CCSBot *owner)
{
// IntervalTimer(IntervalTimer *const this); // 27
// {
// int i; // 41
// }
// IntervalTimer(IntervalTimer *const this); // 27
// CountdownTimer(CountdownTimer *const this); // 27
m_owner = owner;
m_isRoundOver = false;
m_bombState = MOVING;
m_lastSawBomber.Invalidate();
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 */
NOBODY void CSGameState::Reset(void)
void CSGameState::Reset(void)
{
// {
// class CCSBotManager *ctrl; // 66
// int i; // 69
// Invalidate(IntervalTimer *const this); // 61
// Invalidate(IntervalTimer *const this); // 62
// {
// int swap; // 81
// int rnd; // 82
// }
// }
int i;
CCSBotManager *ctrl = TheCSBots();
m_isRoundOver = false;
// bomb
m_bombState = MOVING;
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 */
NOBODY void CSGameState::OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other)
void CSGameState::OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other)
{
// SetBombState(CSGameState *const this,
// enum BombState state); // 104
// UpdatePlantedBomb(CSGameState *const this,
// const Vector *pos); // 109
// SetBombState(CSGameState *const this,
// enum BombState state); // 117
// SetBombState(CSGameState *const this,
// enum BombState state); // 124
switch (event)
{
case EVENT_BOMB_PLANTED:
SetBombState(PLANTED);
if (m_owner->m_iTeam == TERRORIST && other != NULL)
{
UpdatePlantedBomb(&other->pev->origin);
}
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 */
NOBODY bool CSGameState::IsRoundOver(void) const
bool CSGameState::IsRoundOver(void) const
{
return m_isRoundOver;
}
/* <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 */
NOBODY void CSGameState::UpdateLooseBomb(const Vector *pos)
void CSGameState::UpdateLooseBomb(const Vector *pos)
{
// SetBombState(CSGameState *const this,
// enum BombState state); // 166
// Reset(IntervalTimer *const this); // 163
m_looseBombPos = *pos;
m_lastSawLooseBomb.Reset();
// we saw the loose bomb, update our state
SetBombState(LOOSE);
}
/* <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 */
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 */
NOBODY void CSGameState::UpdateBomber(const Vector *pos)
void CSGameState::UpdateBomber(const Vector *pos)
{
// Reset(IntervalTimer *const this); // 188
// SetBombState(CSGameState *const this,
// enum BombState state); // 191
m_bomberPos = *pos;
m_lastSawBomber.Reset();
// we saw the bomber, update our state
SetBombState(MOVING);
}
/* <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 */
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 */
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 */
NOBODY bool CSGameState::IsAtPlantedBombsite(void) const
bool CSGameState::IsAtPlantedBombsite(void) const
{
// {
// class CCSBotManager *ctrl; // 230
// const class Zone *zone; // 231
// }
if (m_bombState != PLANTED)
return false;
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 */
NOBODY int CSGameState::GetNextBombsiteToSearch(void)
int CSGameState::GetNextBombsiteToSearch(void)
{
// {
// int i; // 251
// {
// int z; // 256
// }
// }
if (m_bombsiteCount <= 0)
return 0;
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 */
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 */
NOBODY void CSGameState::UpdatePlantedBomb(const Vector *pos)
void CSGameState::UpdatePlantedBomb(const Vector *pos)
{
// {
// class CCSBotManager *ctrl; // 315
// const class Zone *zone; // 316
// SetBombState(CSGameState *const this,
// enum BombState state); // 330
// }
CCSBotManager *ctrl = TheCSBots();
const CCSBotManager::Zone *zone = ctrl->GetClosestZone(pos);
if (zone == NULL)
{
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 */
NOBODY void CSGameState::MarkBombsiteAsPlanted(int zoneIndex)
void CSGameState::MarkBombsiteAsPlanted(int zoneIndex)
{
// SetBombState(CSGameState *const this,
// enum BombState state); // 340
m_plantedBombsite = zoneIndex;
SetBombState(PLANTED);
}
// Someone told us a bombsite is clear
/* <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 */
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 */
NOBODY void CSGameState::InitializeHostageInfo(void)
void CSGameState::InitializeHostageInfo(void)
{
// {
// class CBaseEntity *hostage; // 373
// }
m_hostageCount = 0;
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 */
NOBODY CHostage *CSGameState::GetNearestFreeHostage(Vector *knowPos)
CHostage *CSGameState::GetNearestFreeHostage(Vector *knowPos) const
{
// {
// class CNavArea *startArea; // 403
// class CHostage *close; // 407
// const Vector *closePos; // 408
// float closeDistance; // 409
// {
// int i; // 411
// {
// const Vector *hostagePos; // 413
// class CNavArea *hostageArea; // 435
// {
// class ShortestPathCost pc; // 438
// float travelDistance; // 439
// NavAreaTravelDistance<ShortestPathCost>(CNavArea *startArea,
// class CNavArea *endArea,
// class ShortestPathCost &costFunc); // 439
// }
// IsValid(CHostage *const this); // 418
// IsFollowingSomeone(CHostage *const this); // 421
// }
// }
// }
if (m_owner == NULL)
return NULL;
CNavArea *startArea = m_owner->GetLastKnownArea();
if (startArea == NULL)
return NULL;
CHostage *close = NULL;
const Vector *closePos = NULL;
float closeDistance = 9999999999.9f;
for (int i = 0; i < m_hostageCount; ++i)
{
CHostage *hostage = m_hostage[i].hostage;
const Vector *hostagePos = NULL;
if (m_owner->m_iTeam == CT)
{
// 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 */
NOBODY const Vector *CSGameState::GetRandomFreeHostagePosition(void)
const Vector *CSGameState::GetRandomFreeHostagePosition(void)
{
// {
// const Vector *freePos; // 466
// int freeCount; // 467
// {
// int i; // 469
// {
// const class HostageInfo *info; // 471
// IsFollowingSomeone(CHostage *const this); // 480
// }
// }
// }
// TODO: use static?
const Vector *freePos[MAX_HOSTAGES];
int freeCount = 0;
if (m_owner == NULL)
return NULL;
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 */
NOBODY unsigned char CSGameState::ValidateHostagePositions(void)
CSGameState::ValidateStatusType CSGameState::ValidateHostagePositions(void)
{
// {
// float const validateInterval; // 515
// TraceResult result; // 520
// unsigned char status; // 521
// int i; // 523
// int startValidCount; // 524
// int endValidCount; // 605
// IsElapsed(const class CountdownTimer *const this); // 512
// Start(CountdownTimer *const this,
// float duration); // 516
// {
// class HostageInfo *info; // 531
// {
// float const tolerance; // 594
// IsValid(CHostage *const this); // 576
// IsFollowingSomeone(CHostage *const this); // 586
// operator-(const Vector *const this,
// const Vector &v); // 595
// IsLengthGreaterThan(const Vector *const this,
// float length); // 595
// }
// IsFollowingSomeone(CHostage *const this); // 541
// }
// }
// limit how often we validate
if (!m_validateInterval.IsElapsed())
return NO_CHANGE;
const float validateInterval = 0.5f;
m_validateInterval.Start(validateInterval);
// check the status of hostages
ValidateStatusType status = NO_CHANGE;
int i;
int startValidCount = 0;
for (i = 0; i < m_hostageCount; ++i)
{
if (m_hostage[i].isValid)
++startValidCount;
}
for (i = 0; i < m_hostageCount; ++i)
{
HostageInfo *info = &m_hostage[i];
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 */
NOBODY CHostage *CSGameState::GetNearestVisibleFreeHostage(void)
CHostage *CSGameState::GetNearestVisibleFreeHostage(void) const
{
// {
// class CHostage *close; // 628
// float closeRangeSq; // 629
// float rangeSq; // 630
// Vector pos; // 632
// {
// int i; // 634
// {
// const class HostageInfo *info; // 636
// IsFollowingSomeone(CHostage *const this); // 643
// operator+(const Vector *const this,
// const Vector &v); // 647
// operator-(const Vector *const this,
// const Vector &v); // 648
// LengthSquared(const Vector *const this); // 648
// }
// }
// }
CHostage *close = NULL;
float closeRangeSq = 999999999.9f;
float rangeSq;
Vector pos;
for (int i = 0; i < m_hostageCount; ++i)
{
const HostageInfo *info = &m_hostage[i];
if (!info->hostage)
continue;
// if the hostage is dead or rescued, its not free
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 */
NOBODY bool CSGameState::AreAllHostagesBeingRescued(void)
bool CSGameState::AreAllHostagesBeingRescued(void) const
{
// {
// bool isAllDead; // 674
// {
// int i; // 676
// {
// const class HostageInfo *info; // 678
// IsValid(CHostage *const this); // 683
// IsFollowingSomeone(CHostage *const this); // 685
// }
// }
// }
// if the hostages have all been rescued, they are not being rescued any longer
if (m_allHostagesRescued)
return false;
bool isAllDead = true;
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 != 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 */
NOBODY bool CSGameState::AreAllHostagesGone(void)
bool CSGameState::AreAllHostagesGone(void) const
{
// {
// int i; // 718
// {
// const class HostageInfo *info; // 720
// }
// }
if (m_allHostagesRescued)
return true;
// 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 */
NOBODY void CSGameState::AllHostagesGone(void)
void CSGameState::AllHostagesGone(void)
{
// {
// int i; // 744
// }
for (int i = 0; i < m_hostageCount; ++i)
m_hostage[i].isValid = false;
}

View File

@ -33,29 +33,19 @@
#endif
class CCSBot;
//class CHostage;
// This class represents the game state as known by a particular bot
class CSGameState
{
public:
CSGameState(void);
CSGameState() {};
CSGameState(CCSBot *owner);
struct HostageInfo
{
CHostage *hostage;
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;
void Reset(void);
void OnEvent(GameEventType event, CBaseEntity *entity, CBaseEntity *other); // Event handling
bool IsRoundOver(void) const; // true if round has been won or lost (but not yet reset)
// bomb defuse scenario
enum BombState
{
MOVING, // being carried by a Terrorist
@ -64,106 +54,101 @@ public:
DEFUSED, // the bomb has been defused
EXPLODED, // the bomb has exploded
};
bool IsBombMoving(void) const
{
return (m_bombState == MOVING);
}
bool IsBombLoose(void) const
{
return (m_bombState == LOOSE);
}
bool IsBombPlanted(void) const
{
return (m_bombState == PLANTED);
}
bool IsBombDefused(void) const
{
return (m_bombState == DEFUSED);
}
bool IsBombExploded(void) const
{
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 };
// return the zone index of the planted bombsite, or UNKNOWN
NOBODY int GetPlantedBombsite(void) const;
// 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;
bool IsBombMoving(void) const { return (m_bombState == MOVING); }
bool IsBombLoose(void) const { return (m_bombState == LOOSE); }
bool IsBombPlanted(void) const { return (m_bombState == PLANTED); }
bool IsBombDefused(void) const { return (m_bombState == DEFUSED); }
bool IsBombExploded(void) const { return (m_bombState == EXPLODED); }
void UpdateLooseBomb(const Vector *pos); // we see the loose bomb
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
NOBODY CHostage *GetNearestFreeHostage(Vector *knowPos);
NOBODY const Vector *GetRandomFreeHostagePosition(void);
NOBODY bool AreAllHostagesBeingRescued(void);
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
void UpdateBomber(const Vector *pos); // we see the bomber
float TimeSinceLastSawBomber(void) const; // how long has is been since we saw the bomber
//CHostage *pHostage = g_pHostages->GetClosestHostage(m_owner->pev->origin);
//return GetClassPtr((CHostage *)pHostage->pev);
}
NOBODY void InitializeHostageInfo(void);
void UpdatePlantedBomb(const Vector *pos); // we see the planted bomb
bool IsPlantedBombLocationKnown(void) const; // do we know where the bomb was planted
void MarkBombsiteAsPlanted(int zoneIndex); // mark bombsite as the location of the planted bomb
enum { UNKNOWN = -1 };
int GetPlantedBombsite(void) const; // return the zone index of the planted bombsite, or UNKNOWN
bool IsAtPlantedBombsite(void) const; // return true if we are currently in the bombsite where the bomb is planted
int GetNextBombsiteToSearch(void); // return the zone index of the next bombsite to search
bool IsBombsiteClear(int zoneIndex) const; // return true if given bombsite has been cleared
void ClearBombsite(int zoneIndex); // mark bombsite as clear
const Vector *GetBombPosition(void) const; // return where we think the bomb is, or NULL if we don't know
// hostage rescue scenario
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:
CCSBot *m_owner;
bool m_isRoundOver;
BombState m_bombState;
#endif // HOOK_GAMEDLL
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;
Vector m_bomberPos;
IntervalTimer m_lastSawLooseBomb;
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_bombsiteSearchIndex;
int m_plantedBombsite;
bool m_isPlantedBombPosKnown;
int m_bombsiteSearchIndex; // the next step in the search
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;
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;
bool m_allHostagesRescued;
bool m_haveSomeHostagesBeenTaken;
NOXREF CBaseEntity *GetNearestHostage(void) const; // return the closest live hostage
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 */

View File

@ -1,7 +1,7 @@
#include "precompiled.h"
/* <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
@ -43,7 +43,7 @@ NOBODY void AttackState::StopAttacking(CCSBot *me)
}
/* <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
@ -149,7 +149,7 @@ NOBODY void AttackState::OnUpdate(CCSBot *me)
}
/* <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
// PopPostureContext(CBot *const this); // 589
@ -157,3 +157,22 @@ NOBODY void AttackState::OnExit(CCSBot *me)
// StopRapidFire(CCSBot *const this); // 597
// 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 */
NOBODY void BuyState::OnEnter(CCSBot *me)
NOBODY void BuyState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{
// {
// 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 */
NOBODY void BuyState::OnUpdate(CCSBot *me)
NOBODY void BuyState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{
// {
// bool inBuyZone; // 273
@ -84,6 +84,25 @@ NOBODY void BuyState::OnUpdate(CCSBot *me)
}
/* <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"
/* <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,
// const char *phraseName,
@ -10,7 +10,7 @@ NOBODY void DefuseBombState::OnEnter(CCSBot *me)
}
/* <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
@ -19,10 +19,29 @@ NOBODY void DefuseBombState::OnUpdate(CCSBot *me)
}
/* <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,
// enum TaskType task,
// class CBaseEntity *entity); // 77
// 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"
/* <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
}
/* <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
@ -21,6 +21,25 @@ NOBODY void EscapeFromBombState::OnUpdate(CCSBot *me)
}
/* <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"
/* <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
}
/* <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
@ -15,3 +15,17 @@ NOBODY void FetchBombState::OnUpdate(CCSBot *me)
// 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"
/* <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
// 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 */
NOBODY void FollowState::OnUpdate(CCSBot *me)
NOBODY void FollowState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{
// {
// float leaderSpeed; // 194
@ -98,6 +98,25 @@ NOBODY void FollowState::OnUpdate(CCSBot *me)
}
/* <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"
/* <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
}
/* <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
@ -110,7 +110,7 @@ NOBODY void HideState::OnUpdate(CCSBot *me)
}
/* <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
// ClearApproachPoints(CCSBot *const this); // 457
@ -118,3 +118,22 @@ NOBODY void HideState::OnExit(CCSBot *me)
// OnExit(HideState *const this,
// 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"
/* <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,
// enum TaskType task,
@ -10,7 +10,7 @@ NOBODY void HuntState::OnEnter(CCSBot *me)
}
/* <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
@ -58,6 +58,25 @@ NOBODY void HuntState::OnUpdate(CCSBot *me)
}
/* <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"
/* <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
// SetTask(CCSBot *const this,
@ -10,7 +10,7 @@ NOBODY void IdleState::OnEnter(CCSBot *me)
}
/* <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
@ -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 */
NOBODY void InvestigateNoiseState::OnEnter(CCSBot *me)
NOBODY void InvestigateNoiseState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{
// AttendCurrentNoise(InvestigateNoiseState *const this,
// class CCSBot *me); // 40
}
/* <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
@ -40,6 +40,25 @@ NOBODY void InvestigateNoiseState::OnUpdate(CCSBot *me)
}
/* <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"
/* <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
@ -9,7 +9,7 @@ NOBODY void MoveToState::OnEnter(CCSBot *me)
}
/* <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
@ -82,6 +82,25 @@ NOBODY void MoveToState::OnUpdate(CCSBot *me)
}
/* <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"
// Plant the bomb.
/* <5d4160> ../cstrike/dlls/bot/states/cs_bot_plant_bomb.cpp:17 */
NOBODY void PlantBombState::OnEnter(CCSBot *me)
void PlantBombState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{
// {
// float yaw; // 25
// class Vector2D dir; // 26
// Vector down; // 28
// GetFeetZ(const class CCSBot *const this); // 28
// Vector(Vector *const this,
// float X,
// float Y,
// float Z); // 28
// }
me->Crouch();
me->SetDisposition(CCSBot::SELF_DEFENSE);
float yaw = me->pev->v_angle.y;
Vector2D dir(BotCOS(yaw), BotSIN(yaw));
Vector down(me->pev->origin.x + 10.0f * dir.x, me->pev->origin.y + 10.0f * dir.y, me->GetFeetZ());
me->SetLookAt("Plant bomb on floor", &down, PRIORITY_HIGH);
}
// Plant the bomb.
/* <5d40d0> ../cstrike/dlls/bot/states/cs_bot_plant_bomb.cpp:36 */
NOBODY void PlantBombState::OnUpdate(CCSBot *me)
void PlantBombState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{
// {
// class CBasePlayerWeapon *gun; // 38
// bool holdingC4; // 39
// float const timeout; // 59
// SetTask(CCSBot *const this,
// enum TaskType task,
// class CBaseEntity *entity); // 54
// }
CBasePlayerWeapon *gun = me->GetActiveWeapon();
bool holdingC4 = false;
if (gun != NULL)
{
if (FStrEq(STRING(gun->pev->classname), "weapon_c4"))
holdingC4 = true;
}
// 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 */
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"
// 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 */
NOBODY void UseEntityState::OnEnter(CCSBot *me)
void UseEntityState::__MAKE_VHOOK(OnEnter)(CCSBot *me)
{
;
}
/* <5e308c> ../cstrike/dlls/bot/states/cs_bot_use_entity.cpp:21 */
NOBODY void UseEntityState::OnUpdate(CCSBot *me)
void UseEntityState::__MAKE_VHOOK(OnUpdate)(CCSBot *me)
{
// {
// float const useTimeout; // 25
// Vector pos; // 33
// {
// class CCSBotManager *ctrl; // 39
// }
// }
// OnUpdate(UseEntityState *const this,
// class CCSBot *me); // 21
// in the very rare situation where two or more bots "used" a hostage at the same time,
// one bot will fail and needs to time out of this state
const float useTimeout = 5.0f;
if (me->GetStateTimestamp() - gpGlobals->time > useTimeout)
{
me->Idle();
return;
}
// 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 */
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)
{
CHostage *hostage = (CHostage *)hostageEntity;
if (!hostage || hostage->pev->takedamage != DAMAGE_YES)
if (hostageEntity->pev->takedamage != DAMAGE_YES)
continue;
if (hostage->m_improv)
{
if (!hostage->IsFollowingSomeone())
continue;
}
else if (!hostage->m_hTargetEnt || hostage->m_State != CHostage::FOLLOW)
CHostage *hostage = static_cast<CHostage *>(hostageEntity);
if (!hostage->IsFollowingSomeone())
continue;
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)
continue;
CHostage *hostage = reinterpret_cast<CHostage *>(hostageEntity);
CHostage *hostage = static_cast<CHostage *>(hostageEntity);
if (hostage->m_improv)
{
if (!hostage->IsFollowingSomeone())
{
continue;
}
}
else if (hostage->m_hTargetEnt == NULL || hostage->m_State != CHostage::FOLLOW)
{
if (!hostage->IsFollowingSomeone())
continue;
}
if (hostage->IsValid() && hostage->m_target == pAttacker)
++hostages_;

View File

@ -43,10 +43,7 @@ public:
public:
virtual void OnEvent(GameEventType event, CBasePlayer *pAttacker, CBasePlayer *pVictim);
virtual void Reset(void);
virtual bool IsTaskCompletableThisRound(void)
{
return true;
}
virtual bool IsTaskCompletableThisRound(void) { return true; }
#ifdef HOOK_GAMEDLL
@ -61,26 +58,13 @@ public:
void OnWeaponKill(int weaponId, int weaponClassId, bool headshot, bool killerHasShield, CBasePlayer *pAttacker, CBasePlayer *pVictim);
void OnWeaponInjury(int weaponId, int weaponClassId, bool attackerHasShield, CBasePlayer *pAttacker);
bool IsComplete(void)
{
return m_isComplete;
}
const char *GetTaskName(void)
{
return m_name;
}
int GetWeaponId(void)
{
return m_weaponId;
}
int GetWeaponClassId(void)
{
return m_weaponClassId;
}
bool IsValidFor(CBasePlayer *pPlayer)
{
return true;
}
bool IsComplete(void) { return m_isComplete;}
const char *GetTaskName(void) { return m_name; }
int GetWeaponId(void) { return m_weaponId; }
int GetWeaponClassId(void) { return m_weaponClassId; }
bool IsValidFor(CBasePlayer *pPlayer) { return true; }
void SendPartialNotification(void);
private:
@ -102,10 +86,37 @@ private:
};/* size: 44, cachelines: 1, members: 15 */
typedef std::list<CCareerTask *> CareerTaskList;
typedef std::STD_LIST<CCareerTask *> CareerTaskList;
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 */
class CCareerTaskManager
{
@ -128,32 +139,15 @@ public:
bool AreAllTasksComplete(void);
int GetNumRemainingTasks(void);
float GetRoundElapsedTime(void);
int GetTaskTime(void)
{
return m_taskTime;
}
int GetTaskTime(void) { return m_taskTime; }
void SetFinishedTaskTime(int val);
int GetFinishedTaskTime(void)
{
return m_finishedTaskTime;
}
int GetFinishedTaskRound(void)
{
return m_finishedTaskRound;
}
CareerTaskList *GetTasks(void)
{
return &m_tasks;
}
int GetFinishedTaskTime(void) { return m_finishedTaskTime; }
int GetFinishedTaskRound(void) { return m_finishedTaskRound; }
CareerTaskList *GetTasks(void) { return &m_tasks; }
void LatchRoundEndMessage(void);
void UnlatchRoundEndMessage(void);
private:
#if defined(_WIN32) && defined(HOOK_GAMEDLL)
int unknown_padding1;
#endif // HOOK_GAMEDLL
CareerTaskList m_tasks;
int m_nextId;
@ -167,8 +161,6 @@ private:
};/* 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
{
const char *taskName;
@ -177,35 +169,6 @@ struct TaskInfo
};/* 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
#define TheCareerTasks (*pTheCareerTasks)

View File

@ -277,7 +277,7 @@ public:
operator int();
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->();

View File

@ -711,6 +711,7 @@ void Host_Say(edict_t *pEntity, int teamonly)
char *pszConsoleFormat = NULL;
bool consoleUsesPlaceName = false;
// team only
if (teamonly)
{
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";
}
}
// everyone
else
{
if (bSenderDead)
@ -2006,14 +2008,17 @@ BOOL HandleMenu_ChooseTeam(CBasePlayer *player, int slot)
break;
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;
}
mp->AddToVIPQueue(player);
CLIENT_COMMAND(ENT(player->pev), "slot10\n");
return TRUE;
break;
}
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->pev->deadflag != DEAD_NO)
@ -4504,6 +4510,20 @@ void ClientPrecache(void)
PRECACHE_GENERIC("sprites/scope_arc_sw.tga");
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 */

View File

@ -362,7 +362,7 @@ Activity CBaseMonster::__MAKE_VHOOK(GetDeathActivity)(void)
}
// 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?
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.
deathActivity = ACT_DIESIMPLE;
@ -458,7 +458,7 @@ NOXREF Activity CBaseMonster::GetSmallFlinchActivity(void)
}
// do we have a sequence for the ideal activity?
if (LookupActivity(flinchActivity) == ACTIVITY_NOT_AVAILABLE)
if (LookupActivity(flinchActivity) == ACT_INVALID)
{
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 */
edict_t *CGameRules::__MAKE_VHOOK(GetPlayerSpawnSpot)(CBasePlayer *pPlayer)
{
// gat valid spawn point
edict_t *pentSpawnSpot = EntSelectSpawnPoint(pPlayer);
// Move the player to the place it said.
#ifndef PLAY_GAMEDLL
pPlayer->pev->origin = VARS(pentSpawnSpot)->origin + Vector(0, 0, 1);
#else

View File

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

View File

@ -130,6 +130,7 @@ void CGrenade::Explode2(TraceResult *pTrace, int bitsDamageType)
m_bJustBlew = true;
mp->CheckWinConditions();
// Pull out of the wall a bit
if (pTrace->flFraction != 1.0f)
{
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);
MESSAGE_END();
// Sound! for everyone
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);
@ -198,14 +200,16 @@ void CGrenade::Explode2(TraceResult *pTrace, int bitsDamageType)
}
// tell director about it
// send director message, that something important happed here
MESSAGE_BEGIN(MSG_SPEC, SVC_DIRECTOR);
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(0); // index number of secondary entity
WRITE_LONG(15 | DRC_FLAG_FINAL); // eventflags (priority and flags)
MESSAGE_END();
// Decal!
if (RANDOM_FLOAT(0, 1) < 0.5)
UTIL_DecalTrace(pTrace, DECAL_SCORCH1);
else
@ -984,6 +988,7 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
CBasePlayer *player = GetClassPtr((CBasePlayer *)pActivator->pev);
// For CTs to defuse the c4
if (player->m_iTeam != CT)
{
return;
@ -991,16 +996,18 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
if (m_bStartDefuse)
{
m_fNextDefuse = gpGlobals->time + 0.5;
m_fNextDefuse = gpGlobals->time + 0.5f;
return;
}
// freeze the player in place while defusing
SET_CLIENT_MAXSPEED(player->edict(), 1);
if (TheBots != NULL)
{
TheBots->OnEvent(EVENT_BOMB_DEFUSING, pActivator);
}
if (g_pGameRules->IsCareer())
{
if (TheCareerTasks != NULL)
@ -1011,14 +1018,12 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
if (player->m_bHasDefuser)
{
UTIL_LogPrintf
(
"\"%s<%i><%s><CT>\" triggered \"Begin_Bomb_Defuse_With_Kit\"\n",
UTIL_LogPrintf("\"%s<%i><%s><CT>\" triggered \"Begin_Bomb_Defuse_With_Kit\"\n",
STRING(player->pev->netname),
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");
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_flDefuseCountDown = gpGlobals->time + 5;
m_fNextDefuse = gpGlobals->time + 0.5;
// start the progress bar
player->SetProgressBarTime(5);
}
else
@ -1036,6 +1043,7 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
GETPLAYERUSERID(player->edict()),
GETPLAYERAUTHID(player->edict()));
// TODO show messages on clients on event
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);
@ -1044,6 +1052,8 @@ void CGrenade::__MAKE_VHOOK(Use)(CBaseEntity *pActivator, CBaseEntity *pCaller,
m_bStartDefuse = true;
m_flDefuseCountDown = gpGlobals->time + 10;
m_fNextDefuse = gpGlobals->time + 0.5;
// start the progress bar
player->SetProgressBarTime(10);
}
}
@ -1208,14 +1218,17 @@ void CGrenade::C4Think(void)
AnnounceFlashInterval(20);
break;
}
++m_iCurWave;
}
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);
// let the bots hear the bomb beeping
// BOTPORT: Emit beep events at same time as client effects
if (TheBots != NULL)
{
TheBots->OnEvent(EVENT_BOMB_BEEP, this);
@ -1238,6 +1251,7 @@ void CGrenade::C4Think(void)
MESSAGE_END();
}
// If the timer has expired ! blow this bomb up!
if (gpGlobals->time >= m_flC4Blow)
{
if (TheBots != NULL)
@ -1260,7 +1274,7 @@ void CGrenade::C4Think(void)
}
CBasePlayer *pBombOwner = (CBasePlayer *)CBaseEntity::Instance(pev->owner);
if (pBombOwner)
if (pBombOwner != NULL)
{
pBombOwner->pev->frags += 3;
}
@ -1276,14 +1290,17 @@ void CGrenade::C4Think(void)
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);
// if the bomb defuser has stopped defusing the bomb
if (gpGlobals->time > m_fNextDefuse || !iOnGround)
{
if (!iOnGround)
@ -1291,92 +1308,95 @@ void CGrenade::C4Think(void)
ClientPrint(m_pBombDefuser->pev, HUD_PRINTCENTER, "#C4_Defuse_Must_Be_On_Ground");
}
// release the player from being frozen
pPlayer->ResetMaxSpeed();
pPlayer->m_bIsDefusing = false;
pPlayer->SetProgressBarTime(0);
// cancel the progress bar
pPlayer->SetProgressBarTime(0);
m_pBombDefuser = NULL;
m_bStartDefuse = false;
m_flDefuseCountDown = 0;
// tell the bots someone has aborted defusing
if (TheBots != NULL)
{
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
{
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");
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);
}
TheBots->OnEvent(EVENT_BOMB_DEFUSE_ABORTED);
}
}
}

View File

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

View File

@ -95,13 +95,15 @@ extern int g_iHostageNumber;
extern cvar_t cv_hostage_debug;
extern cvar_t cv_hostage_stop;
// A Counter-Strike Hostage Simple
/* <4858e5> ../cstrike/dlls/hostage/hostage.h:32 */
class CHostage: public CBaseMonster
{
public:
virtual void Spawn(void);
virtual void Precache(void);
virtual int ObjectCaps(void);
virtual int ObjectCaps(void); // make hostage "useable"
virtual int Classify(void)
{
return CLASS_HUMAN_PASSIVE;
@ -152,22 +154,34 @@ public:
void Wiggle(void);
void PreThink(void);
// queries
bool IsFollowingSomeone(void)
{
return m_improv->IsFollowing();
return IsFollowing();
}
CBaseEntity *GetLeader(void)
CBaseEntity *GetLeader(void) // return our leader, or NULL
{
if (m_improv != NULL)
{
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)
{
@ -187,24 +201,6 @@ 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;
BOOL m_bTouched;
BOOL m_bRescueMe;
@ -214,7 +210,8 @@ public:
int m_iModel;
int m_iSkin;
float m_flNextRadarTime;
state m_State;
enum state { FOLLOW, STAND, DUCK, SCARED, IDLE, FOLLOWPATH }
m_State;
Vector m_vStart;
Vector m_vStartAngles;
Vector m_vPathToFollow[20];
@ -235,7 +232,9 @@ public:
BOOL m_bStuck;
float m_flStuckTime;
CHostageImprov *m_improv;
ModelType m_whichModel;
enum ModelType { REGULAR_GUY, OLD_GUY, BLACK_GUY, GOOFY_GUY }
m_whichModel;
};/* size: 1988, cachelines: 32, members: 32 */
@ -294,6 +293,25 @@ public:
bool IsNearbyHostageTalking(CHostageImprov *improv);
bool IsNearbyHostageJumping(CHostageImprov *improv);
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)
{
float range;
@ -317,23 +335,6 @@ public:
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:
CHostage *m_hostage[ MAX_HOSTAGES ];
int m_hostageCount;
@ -341,43 +342,18 @@ private:
};/* 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
// linked object
C_DLLEXPORT void hostage_entity(entvars_t *pev);
C_DLLEXPORT void monster_scientist(entvars_t *pev);
// refs
extern void (CBaseEntity::*pCHostage__IdleThink)(void);
#endif // HOOK_GAMEDLL
void Hostage_RegisterCVars(void);
void InstallHostageManager(void);
// refs
extern void (CBaseEntity::*pCHostage__IdleThink)(void);
#endif // HOSTAGE_H

View File

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

View File

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

View File

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

View File

@ -448,7 +448,7 @@ CHalfLifeMultiplay::CHalfLifeMultiplay(void)
m_iAccountCT = 0;
m_iAccountTerrorist = 0;
m_iHostagesRescued = 0;
m_iRoundWinStatus = 0;
m_iRoundWinStatus = WINNER_NONE;
m_iNumCTWins = 0;
m_iNumTerroristWins = 0;
m_pVIP = NULL;
@ -949,7 +949,7 @@ void CHalfLifeMultiplay::QueueCareerRoundEndMenu(float tmDelay, int iWinStatus)
{
numHostagesInMap++;
CHostage *pHostage = reinterpret_cast<CHostage *>(hostage);
CHostage *pHostage = static_cast<CHostage *>(hostage);
if (pHostage->pev->takedamage != DAMAGE_YES)
{
@ -958,17 +958,8 @@ void CHalfLifeMultiplay::QueueCareerRoundEndMenu(float tmDelay, int iWinStatus)
CBasePlayer *pLeader = NULL;
if (pHostage->m_improv != NULL)
{
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 (pHostage->IsFollowingSomeone())
pLeader = static_cast<CBasePlayer *>(pHostage->GetLeader());
if (pLeader == NULL)
{
@ -1042,7 +1033,7 @@ void CHalfLifeMultiplay::__MAKE_VHOOK(CheckWinConditions)(void)
#endif // REGAMEDLL_ADD
// 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;
}
@ -2091,7 +2082,7 @@ void CHalfLifeMultiplay::__MAKE_VHOOK(RestartRound)(void)
m_iAccountTerrorist = m_iAccountCT = 0;
m_iHostagesRescued = 0;
m_iHostagesTouched = 0;
m_iRoundWinStatus = 0;
m_iRoundWinStatus = WINNER_NONE;
m_bTargetBombed = m_bBombDefused = false;
m_bLevelInitialized = false;
m_bCompleteReset = false;
@ -3000,7 +2991,7 @@ void CHalfLifeMultiplay::CheckRestartRound(void)
bool CHalfLifeMultiplay::HasRoundTimeExpired(void)
{
// 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;
}

View File

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

View File

@ -2271,7 +2271,7 @@ void CTriggerCamera::FollowTarget(void)
if (m_hPlayer->IsAlive())
{
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);

View File

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

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.
/* <1d1e09> ../cstrike/dlls/weapons.cpp:616 */
@ -620,6 +620,9 @@ CBaseEntity *CBasePlayerItem::__MAKE_VHOOK(Respawn)(void)
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 */
void CBasePlayerItem::DefaultTouch(CBaseEntity *pOther)
{
@ -629,7 +632,7 @@ void CBasePlayerItem::DefaultTouch(CBaseEntity *pOther)
return;
}
CBasePlayer *pPlayer = reinterpret_cast<CBasePlayer *>(pOther);
CBasePlayer *pPlayer = static_cast<CBasePlayer *>(pOther);
if (pPlayer->m_bIsVIP
&& 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 */
void CBasePlayerWeapon::FireRemaining(int &shotsFired, float &shootTime, BOOL bIsGlock)
{
float nexttime = 0.1f;
m_iClip--;
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->SetAnimation(PLAYER_ATTACK1);
shotsFired++;
float nexttime = 0;
shotsFired++;
if (shotsFired != 3)
{
nexttime = gpGlobals->time + 0.1f;
shootTime = gpGlobals->time + nexttime;
}
shootTime = nexttime;
else
shootTime = 0;
}
/* <1d389e> ../cstrike/dlls/weapons.cpp:876 */
@ -911,6 +915,8 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
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_pPlayer->m_bResumeZoom)
@ -920,6 +926,7 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
if (m_pPlayer->m_iFOV == m_pPlayer->m_iLastZoom)
{
// return the fade level in zoom.
m_pPlayer->m_bResumeZoom = false;
}
}
@ -978,6 +985,8 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
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())
{
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())
{
// reload when reload is pressed, or if no buttons are down and weapon is empty.
if (m_flFamasShoot == 0 && m_flGlock18Shoot == 0)
{
if (!(m_iWeaponState & WPNSTATE_SHIELD_DRAWN))
@ -997,6 +1007,9 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
else if (!(usableButtons & (IN_ATTACK | IN_ATTACK2)))
{
// 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)
{
m_bDelayFire = false;
@ -1011,16 +1024,19 @@ void CBasePlayerWeapon::__MAKE_VHOOK(ItemPostFrame)(void)
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)
{
m_flDecreaseShotsFired = gpGlobals->time + 0.0225f;
m_iShotsFired--;
m_flDecreaseShotsFired = gpGlobals->time + 0.0225;
}
}
else
m_iShotsFired = 0;
if (!IsUseable() && m_flNextPrimaryAttack < UTIL_WeaponTimeBase())
{

View File

@ -489,10 +489,7 @@ public:
float GetNextAttackDelay(float delay);
float GetNextAttackDelay2(float delay);
bool HasSecondaryAttack(void);
BOOL IsPistol(void)
{
return FALSE;
}
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); }
void SetPlayerShieldAnim(void);
void ResetPlayerShieldAnim(void);
bool ShieldSecondaryFire(int iUpAnim, int iDownAnim);
@ -523,8 +520,8 @@ public:
int m_iShotsFired;
Vector m_vVecAiming;
string_t model_name;
float m_flGlock18Shoot;
int m_iGlock18ShotsFired;
float m_flGlock18Shoot; // time to shoot the remaining bullets of the glock18 burst fire
int m_iGlock18ShotsFired; // used to keep track of the shots fired during the Glock18 burst fire mode.
float m_flFamasShoot;
int m_iFamasShotsFired;
float m_fBurstSpread;
@ -2224,7 +2221,7 @@ extern int giAmmoIndex;
extern short g_sModelIndexRadio;
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);
int MaxAmmoCarry(int iszName);

View File

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

View File

@ -70,6 +70,7 @@ enum WeaponIdType
enum AutoBuyClassType
{
AUTOBUYCLASS_NONE = 0,
AUTOBUYCLASS_PRIMARY = (1 << 0),
AUTOBUYCLASS_SECONDARY = (1 << 1),
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->pev->fov = DEFAULT_FOV;
}
// If we are not zoomed in, the bullet diverts more.
else
{
flSpread += 0.08;
@ -224,7 +225,11 @@ void CAWP::__MAKE_VHOOK(WeaponIdle)(void)
/* <23fa86> ../cstrike/dlls/wpn_shared/wpn_awp.cpp:283 */
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

View File

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

View File

@ -175,6 +175,7 @@ void CGLOCK18::GLOCK18Fire(float flSpread, float flCycleTime, BOOL bFireBurst)
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;
if (m_flAccuracy > 0.9)
@ -208,10 +209,13 @@ void CGLOCK18::GLOCK18Fire(float flSpread, float flCycleTime, BOOL bFireBurst)
m_iClip--;
m_pPlayer->pev->effects |= EF_MUZZLEFLASH;
// player "shoot" animation
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
UTIL_MakeVectors(m_pPlayer->pev->v_angle + m_pPlayer->pev->punchangle);
// non-silenced
m_pPlayer->m_iWeaponVolume = NORMAL_GUN_VOLUME;
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)
{
// HEV suit - indicate out of ammo condition
m_pPlayer->SetSuitUpdate("!HEV_AMO0", FALSE, FALSE);
}
@ -240,6 +245,7 @@ void CGLOCK18::GLOCK18Fire(float flSpread, float flCycleTime, BOOL bFireBurst)
if (bFireBurst)
{
// Fire off the next two rounds
m_iGlock18ShotsFired++;
m_flGlock18Shoot = gpGlobals->time + 0.1;
}
@ -294,6 +300,7 @@ void CGLOCK18::__MAKE_VHOOK(WeaponIdle)(void)
SendWeaponAnim(GLOCK18_SHIELD_IDLE, UseDecrement() != FALSE);
}
}
// only idle if the slid isn't back
else if (m_iClip)
{
flRand = RANDOM_FLOAT(0, 1);

View File

@ -93,35 +93,26 @@ NOXREF void CKnife::WeaponAnimation(int iAnimation)
flag = 0;
#endif // CLIENT_WEAPONS
PLAYBACK_EVENT_FULL
(
flag,
m_pPlayer->edict(),
m_usKnife,
0,
(float *)&g_vecZero,
(float *)&g_vecZero,
0,
0,
iAnimation,
2, // param noxref
3, // param noxref
4 // param noxref
);
PLAYBACK_EVENT_FULL(flag, m_pPlayer->edict(), m_usKnife,
0.0, (float *)&g_vecZero, (float *)&g_vecZero,
0.0,
0.0,
iAnimation, 2, 3, 4);
}
/* <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;
float distance;
float *minmaxs[2] = { mins, maxs };
TraceResult tmpTrace;
Vector vecHullEnd, vecEnd;
Vector vecHullEnd = tr.vecEndPos;
Vector vecEnd;
distance = 1e6f;
vecHullEnd = vecSrc + ((tr.vecEndPos - vecSrc) * 2);
vecHullEnd = vecSrc + ((vecHullEnd - vecSrc) * 2);
UTIL_TraceLine(vecSrc, vecHullEnd, dont_ignore_monsters, pEntity, &tmpTrace);
if (tmpTrace.flFraction < 1.0f)
@ -130,11 +121,11 @@ void FindHullIntersection(Vector &vecSrc, TraceResult &tr, float *mins, float *m
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.y = vecHullEnd.y + minmaxs[j][1];
@ -326,10 +317,10 @@ int CKnife::Swing(int fFirst)
SendWeaponAnim(KNIFE_SHIELD_ATTACKHIT, UseDecrement() != FALSE);
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
if (RANDOM_LONG(0, 1))
@ -355,17 +346,17 @@ int CKnife::Swing(int fFirst)
}
m_flNextPrimaryAttack = GetNextAttackDelay(0.4);
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5;
m_flNextSecondaryAttack = UTIL_WeaponTimeBase() + 0.5f;
}
else
{
SendWeaponAnim(KNIFE_SHIELD_ATTACKHIT, UseDecrement() != FALSE);
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
float flVol = 1.0f;
@ -378,7 +369,7 @@ int CKnife::Swing(int fFirst)
m_pPlayer->SetAnimation(PLAYER_ATTACK1);
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));
else
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;
SetThink(&CKnife::Smack);
pev->nextthink = UTIL_WeaponTimeBase() + 0.2;
pev->nextthink = UTIL_WeaponTimeBase() + 0.2f;
m_pPlayer->m_iWeaponVolume = (int)(flVol * KNIFE_WALLHIT_VOLUME);
ResetPlayerShieldAnim();

View File

@ -115,6 +115,7 @@ typedef struct incomingtransfer_s
//#define Q_strtoull strtoull
//#define Q_FileNameCmp FileNameCmp
#define Q_vsnprintf _vsnprintf
#define Q_vsnwprintf _vsnwprintf
#else // Q_functions
void Q_strcpy(char *dest, const char *src);
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
float g_flBotFullThinkInterval = 1.0 / 10.0;
// Nasty Hack. See client.cpp/ClientCommand()
const char *BotArgs[4] = { NULL };
bool UseBotArgs = false;
@ -25,14 +26,24 @@ bool UseBotArgs;
#endif // HOOK_GAMEDLL
/* <48fed0> ../game_shared/bot/bot.cpp:28 */
NOBODY CBot::CBot(void)
CBot::CBot(void)
{
// CBasePlayer(CBasePlayer *const this); // 28
// {
// unsigned int nextID; // 34
// }
// the profile will be attached after this instance is constructed
m_profile = NULL;
// 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 */
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 */
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 */
NOBODY Vector CBot::__MAKE_VHOOK(GetAutoaimVector)(float flDelta)
Vector CBot::__MAKE_VHOOK(GetAutoaimVector)(float flDelta)
{
// operator+(const Vector *const this,
// const Vector &v); // 90
// Vector(Vector *const this,
// const Vector &v); // 92
UTIL_MakeVectors(pev->v_angle + pev->punchangle);
return gpGlobals->v_forward;
}
/* <48ffa8> ../game_shared/bot/bot.cpp:97 */
@ -76,77 +109,125 @@ void CBot::BotThink(void)
}
/* <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 */
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 */
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 */
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 */
NOBODY bool CBot::__MAKE_VHOOK(Jump)(bool mustJump)
bool CBot::__MAKE_VHOOK(Jump)(bool mustJump)
{
// {
// float const sanityInterval; // 173
// IsJumping(CBot *const this); // 162
// {
// float const minJumpInterval; // 167
// }
// }
// Jump(CBot *const this,
// bool mustJump); // 160
if (IsJumping() || IsCrouching())
return false;
if (!mustJump)
{
const float minJumpInterval = 0.9f; // 1.5f;
if (gpGlobals->time - m_jumpTimestamp < minJumpInterval)
return false;
}
// 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 */
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 */
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 */
NOBODY void CBot::__MAKE_VHOOK(Crouch)(void)
void CBot::__MAKE_VHOOK(Crouch)(void)
{
m_isCrouching = true;
}
/* <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 */
NOBODY void CBot::__MAKE_VHOOK(UseEnvironment)(void)
void CBot::__MAKE_VHOOK(UseEnvironment)(void)
{
m_buttonFlags |= IN_USE;
}
/* <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 */
NOBODY void CBot::__MAKE_VHOOK(ClearPrimaryAttack)(void)
void CBot::__MAKE_VHOOK(ClearPrimaryAttack)(void)
{
m_buttonFlags &= ~IN_ATTACK;
}
/* <48f917> ../game_shared/bot/bot.cpp:246 */
@ -159,40 +240,68 @@ void CBot::__MAKE_VHOOK(TogglePrimaryAttack)(void)
}
/* <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 */
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 */
NOBODY float CBot::GetActiveWeaponAmmoRatio(void) const
float CBot::GetActiveWeaponAmmoRatio(void) const
{
// {
// class CBasePlayerWeapon *gun; // 277
// iMaxClip(CBasePlayerItem *const this); // 286
// }
CBasePlayerWeapon *weapon = GetActiveWeapon();
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 */
NOBODY bool CBot::IsActiveWeaponClipEmpty(void) const
bool CBot::IsActiveWeaponClipEmpty(void) const
{
// {
// class CBasePlayerWeapon *gun; // 295
// }
CBasePlayerWeapon *weapon = GetActiveWeapon();
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 */
NOBODY bool CBot::IsActiveWeaponOutOfAmmo(void) const
bool CBot::IsActiveWeaponOutOfAmmo(void) const
{
// {
// class CBasePlayerWeapon *gun; // 309
// }
CBasePlayerWeapon *gun = GetActiveWeapon();
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 */
bool CBot::IsUsingScope(void) const
{
@ -252,6 +361,8 @@ byte CBot::ThrottledMsec(void) const
return (byte)iNewMsec;
}
// Do a "client command" - useful for invoking menu choices, etc.
/* <49016e> ../game_shared/bot/bot.cpp:389 */
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;
}
// Returns TRUE if given entity is our enemy
/* <4901ac> ../game_shared/bot/bot.cpp:410 */
NOBODY bool CBot::IsEnemy(CBaseEntity *ent) const
bool CBot::IsEnemy(CBaseEntity *ent) const
{
// {
// class CBasePlayer *player; // 420
// }
// IsEnemy(const class CBot *const this,
// class CBaseEntity *ent); // 410
// only Players (real and AI) can be enemies
if (!ent->IsPlayer())
return false;
// 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 */
NOBODY int CBot::GetEnemiesRemaining(void) const
int CBot::GetEnemiesRemaining(void) const
{
// {
// int count; // 436
// {
// int i; // 438
// {
// class CBaseEntity *player; // 440
// FNullEnt(entvars_t *pev); // 445
// IsEnemy(const class CBot *const this,
// class CBaseEntity *ent); // 451
// }
// }
// }
int count = 0;
for (int i = 1; i <= gpGlobals->maxClients; ++i)
{
CBaseEntity *player = UTIL_PlayerByIndex(i);
if (player == NULL)
continue;
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 */
NOBODY int CBot::GetFriendsRemaining(void) const
int CBot::GetFriendsRemaining(void) const
{
// {
// int count; // 469
// {
// int i; // 471
// {
// class CBaseEntity *player; // 473
// FNullEnt(entvars_t *pev); // 478
// IsEnemy(const class CBot *const this,
// class CBaseEntity *ent); // 484
// }
// }
// }
int count = 0;
for (int i = 1; i <= gpGlobals->maxClients; ++i)
{
CBaseEntity *player = UTIL_PlayerByIndex(i);
if (player == NULL)
continue;
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 */
@ -332,6 +489,7 @@ bool CBot::IsLocalPlayerWatchingMe(void) const
return true;
}
}
return false;
}
@ -417,7 +575,7 @@ bool ActiveGrenade::IsValid(void) const
}
/* <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;
}

View File

@ -50,6 +50,8 @@ extern bool UseBotArgs;
class BotProfile;
extern bool AreBotsAllowed();
/* <36c175> ../game_shared/bot/bot.h:36 */
template <class T>
T *CreateBot(const BotProfile *profile)
@ -88,7 +90,7 @@ public:
// constructor initializes all values to zero
CBot(void);
NOBODY virtual void Spawn(void);
virtual void Spawn(void);
// invoked when injured by something
virtual int TakeDamage(entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int bitsDamageType)
@ -100,15 +102,12 @@ public:
{
CBasePlayer::Killed(pevAttacker, iGib);
}
NOBODY virtual void Think(void) {};
virtual BOOL IsBot(void)
{
return true;
}
NOBODY virtual Vector GetAutoaimVector(float flDelta);
virtual void Think(void) {};
virtual BOOL IsBot(void) { return true; }
virtual Vector GetAutoaimVector(float flDelta);
// invoked when in contact with a CWeaponBox
NOBODY virtual void OnTouchingWeapon(CWeaponBox *box) {}
NOBODY virtual bool Initialize(const BotProfile *profile);
virtual void OnTouchingWeapon(CWeaponBox *box) {}
virtual bool Initialize(const BotProfile *profile);
virtual void SpawnBot(void) = 0;
@ -118,28 +117,29 @@ public:
// heavyweight algorithms, invoked less often
virtual void Update(void) = 0;
NOBODY virtual void Run(void);
NOBODY virtual void Walk(void);
NOBODY virtual void Crouch(void);
NOBODY virtual void StandUp(void);
NOBODY virtual void MoveForward(void);
NOBODY virtual void MoveBackward(void);
NOBODY virtual void StrafeLeft(void);
NOBODY virtual void StrafeRight(void);
virtual void Run(void);
virtual void Walk(void);
virtual void Crouch(void);
virtual void StandUp(void);
virtual void MoveForward(void);
virtual void MoveBackward(void);
virtual void StrafeLeft(void);
virtual void StrafeRight(void);
// 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
NOBODY virtual void ClearMovement(void);
virtual void ClearMovement(void);
// Weapon interface
NOBODY virtual void UseEnvironment(void);
NOBODY virtual void PrimaryAttack(void);
NOBODY virtual void ClearPrimaryAttack(void);
virtual void UseEnvironment(void);
virtual void PrimaryAttack(void);
virtual void ClearPrimaryAttack(void);
virtual void TogglePrimaryAttack(void);
NOBODY virtual void SecondaryAttack(void);
NOBODY virtual void Reload(void);
virtual void SecondaryAttack(void);
virtual void Reload(void);
// invoked when event occurs in the game (some events have NULL entities)
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
virtual bool IsVisible(CBasePlayer *player, bool testFOV = false, unsigned char *visParts = NULL) const = 0;
enum VisiblePartType
enum VisiblePartType:uint8
{
NONE = 0x00,
CHEST = 0x01,
@ -164,12 +164,12 @@ public:
virtual bool IsEnemyPartVisible(VisiblePartType part) const = 0;
// 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
NOBODY virtual bool IsPlayerLookingAtMe(CBasePlayer *other) const;
virtual bool IsPlayerLookingAtMe(CBasePlayer *other) const;
virtual void ExecuteCommand(void);
NOBODY virtual void SetModel(const char *modelName);
virtual void SetModel(const char *modelName);
#ifdef HOOK_GAMEDLL
@ -189,45 +189,36 @@ public:
void ClearPrimaryAttack_(void);
void TogglePrimaryAttack_(void);
void SecondaryAttack_(void);
bool IsPlayerFacingMe_(CBasePlayer *other) const;
bool IsPlayerLookingAtMe_(CBasePlayer *other) const;
void Reload_(void);
void ExecuteCommand_(void);
void SetModel_(const char *modelName);
#endif // HOOK_GAMEDLL
public:
unsigned int GetID(void) const
{
return m_id;
}
bool IsRunning(void) const
{
return m_isRunning;
}
bool IsCrouching(void) const
{
return m_isCrouching;
}
unsigned int GetID(void) const { return m_id; }
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
void PushPostureContext(void);
// restore the posture context to the next context on the stack
void PopPostureContext(void);
NOBODY bool IsJumping(void);
bool IsJumping(void);
// return time last jump began
float GetJumpTimestamp(void) const
{
return m_jumpTimestamp;
}
float GetJumpTimestamp(void) const { return m_jumpTimestamp; }
// 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
NOBODY bool IsActiveWeaponClipEmpty(void) const;
bool IsActiveWeaponClipEmpty(void) const;
// 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
bool IsActiveWeaponReloading(void) const;
@ -242,13 +233,13 @@ public:
bool IsUsingScope(void) const;
// 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
NOBODY int GetEnemiesRemaining(void) const;
int GetEnemiesRemaining(void) const;
// return number of friends left alive
NOBODY int GetFriendsRemaining(void) const;
int GetFriendsRemaining(void) const;
// return true if local player is observing this bot
bool IsLocalPlayerWatchingMe(void) const;
@ -260,18 +251,13 @@ public:
void PrintIfWatched(char *format,...) const;
void BotThink(void);
bool IsNetClient(void) const
{
return false;
}
bool IsNetClient(void) const { return false; }
int Save(CSave &save) const;
int Restore(CRestore &restor) const;
// return our personality profile
const BotProfile *GetProfile(void) const
{
return m_profile;
}
const BotProfile *GetProfile(void) const { return m_profile; }
#ifndef HOOK_GAMEDLL
protected:
#endif // HOOK_GAMEDLL
@ -280,8 +266,8 @@ protected:
// the "personality" profile of this bot
const BotProfile *m_profile;
private:
private:
void ResetCommand(void);
byte ThrottledMsec(void) const;
@ -329,7 +315,7 @@ private:
};/* size: 2564, cachelines: 41, members: 15 */
/* <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);
}
@ -364,11 +350,11 @@ inline CBasePlayerWeapon *CBot::GetActiveWeapon(void) const
/* <5c4d70> ../game_shared/bot/bot.h:287 */
inline bool CBot::IsActiveWeaponReloading(void) const
{
CBasePlayerWeapon *gun = GetActiveWeapon();
if (gun == NULL)
CBasePlayerWeapon *weapon = GetActiveWeapon();
if (weapon == NULL)
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 */
@ -392,6 +378,7 @@ inline void CBot::PushPostureContext(void)
PrintIfWatched("PushPostureContext() overflow error!\n");
return;
}
m_postureStack[m_postureStackIndex].isRunning = m_isRunning;
m_postureStack[m_postureStackIndex].isCrouching = m_isCrouching;
++m_postureStackIndex;
@ -416,7 +403,7 @@ inline void CBot::PopPostureContext(void)
}
/* <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;
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)
return true;
return false;
}
/* <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;
toOther.NormalizeInPlace();
@ -443,6 +431,7 @@ inline bool CBot::IsPlayerLookingAtMe(CBasePlayer *other) const
if (IsVisible(&vec))
return true;
}
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_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 // BOT_H

View File

@ -32,11 +32,15 @@
#pragma once
#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
// version number is MAJOR.MINOR
#define BOT_VERSION_MAJOR 1
#define BOT_VERSION_MINOR 50
// Difficulty levels
enum BotDifficultyType
{
BOT_EASY = 0,
@ -47,22 +51,12 @@ enum BotDifficultyType
NUM_DIFFICULTY_LEVELS
};
#ifdef DEFINE_DIFFICULTY_NAMES
#ifdef HOOK_GAMEDLL
char *BotDifficultyName[] =
{
"EASY",
"NORMAL",
"HARD",
"EXPERT",
#define BotDifficultyName (*pBotDifficultyName)
NULL
};
#endif // HOOK_GAMEDLL
#else
extern char *BotDifficultyName[];
#endif // DEFINE_DIFFICULTY_NAMES
extern char *BotDifficultyName[5];
#endif // BOT_CONSTANTS_H

View File

@ -8,45 +8,74 @@
BotProfileManager *TheBotProfiles = NULL;
char *BotDifficultyName[] =
{
"EASY", "NORMAL", "HARD", "EXPERT", NULL
};
#else // HOOK_GAMEDLL
BotProfileManager *TheBotProfiles;
char *BotDifficultyName[5];
#endif // HOOK_GAMEDLL
// Generates a filename-decorated skin name
/* <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)
{
// {
// int const BufLen; // 57
// char buf; // 59
// }
const int BufLen = MAX_PATH + 64;
static char buf[BufLen];
Q_snprintf(buf, BufLen, "%s/%s", filename, name);
return buf;
}
/* <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 */
NOBODY bool BotProfile::HasPrimaryPreference(void) const
bool BotProfile::HasPrimaryPreference(void) const
{
// {
// int i; // 80
// {
// int weaponClass; // 82
// }
// }
for (int i = 0; i < m_weaponPreferenceCount; ++i)
{
int weaponClass = AliasToWeaponClass(WeaponIDToAlias(m_weaponPreference[i]));
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 */
NOBODY bool BotProfile::HasPistolPreference(void) const
bool BotProfile::HasPistolPreference(void) const
{
// {
// int i; // 101
// }
for (int i = 0; i < m_weaponPreferenceCount; ++i)
{
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 */
bool BotProfile::IsValidForTeam(BotProfileTeamType team) const
{
@ -54,132 +83,462 @@ bool BotProfile::IsValidForTeam(BotProfileTeamType team) const
}
/* <4a7bb2> ../game_shared/bot/bot_profile.cpp:122 */
NOBODY BotProfileManager::BotProfileManager(void)
BotProfileManager::BotProfileManager(void)
{
// list(list<BotProfile*, std::allocator<BotProfile*>> *const this); // 122
// vector(vector<char*, std::allocator<char*>> *const this); // 122
// {
// int i; // 125
// }
m_nextSkin = 0;
for (int i = 0; i < NumCustomSkins; ++i)
{
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 */
NOBODY void BotProfileManager::Init(const char *filename, unsigned int *checksum)
void BotProfileManager::Init(const char *filename, unsigned int *checksum)
{
// {
// int dataLength; // 139
// char *dataPointer; // 140
// const char *dataFile; // 141
// BotProfileList templateList; // 159
// class BotProfile defaultProfile; // 161
// ComputeSimpleChecksum(const unsigned char *dataPointer,
// int dataLength); // 155
// BotProfile(BotProfile *const this); // 161
// list(list<BotProfile*, std::allocator<BotProfile*>> *const this); // 159
// {
// char *token; // 172
// bool isDefault; // 174
// bool isTemplate; // 175
// bool isCustomSkin; // 176
// class BotProfile *profile; // 270
// bool isFirstWeaponPref; // 348
// {
// int const BufLen; // 180
// char skinName; // 181
// const char *decoratedName; // 236
// bool skinExists; // 237
// GetDecoratedSkinName(const char *name,
// const char *filename); // 236
// GetCustomSkinIndex(BotProfileManager *const this,
// const char *name,
// const char *filename); // 237
// CloneString(const char *str); // 241
// CloneString(const char *str); // 244
// }
// {
// const class BotProfile *inherit; // 287
// {
// char *c; // 292
// strchr(char *__s,
// int __c); // 292
// {
// iterator iter; // 297
// operator++(_List_iterator<BotProfile*> *const this); // 297
// }
// Inherit(BotProfile *const this,
// const class BotProfile *parent,
// const class BotProfile *baseline); // 314
// }
// }
// {
// char attributeName; // 366
// {
// char *c; // 474
// strchr(char *__s,
// int __c); // 474
// {
// int i; // 478
// }
// }
// atof(const char *__nptr); // 464
// atof(const char *__nptr); // 453
// atoi(const char *__nptr); // 424
// atoi(const char *__nptr); // 420
// atof(const char *__nptr); // 416
// atoi(const char *__nptr); // 407
// GetCustomSkinIndex(BotProfileManager *const this,
// const char *name,
// const char *filename); // 411
// atof(const char *__nptr); // 403
// atof(const char *__nptr); // 399
// }
// BotProfile(BotProfile *const this); // 278
// CloneString(const char *str); // 334
// push_back(list<BotProfile*, std::allocator<BotProfile*>> *const this,
// const value_type &__x); // 514
// push_back(list<BotProfile*, std::allocator<BotProfile*>> *const this,
// const value_type &__x); // 519
// }
// ~list(list<BotProfile*, std::allocator<BotProfile*>> *const this,
// int const __in_chrg); // 159
// {
// iterator iter; // 527
// operator++(_List_iterator<BotProfile*> *const this); // 527
// }
// ~list(list<BotProfile*, std::allocator<BotProfile*>> *const this,
// int const __in_chrg); // 159
// }
int dataLength;
char *dataPointer = (char *)LOAD_FILE_FOR_ME(const_cast<char *>(filename), &dataLength);
const char *dataFile = dataPointer;
if (dataFile == NULL)
{
if (UTIL_IsGame("czero"))
{
CONSOLE_ECHO("WARNING: Cannot access bot profile database '%s'\n", filename);
}
return;
}
// compute simple checksum
if (checksum)
{
*checksum = ComputeSimpleChecksum((const unsigned char *)dataPointer, dataLength);
}
// keep list of templates used for inheritance
BotProfileList templateList;
BotProfile defaultProfile;
// Parse the BotProfile.db into BotProfile instances
while (true)
{
dataFile = SharedParse(dataFile);
if (!dataFile)
break;
char *token = SharedGetToken();
bool isDefault = (!Q_stricmp(token, "Default"));
bool isTemplate = (!Q_stricmp(token, "Template"));
bool isCustomSkin = (!Q_stricmp(token, "Skin"));
if (isCustomSkin)
{
const int BufLen = 64;
char skinName[BufLen];
// get skin name
dataFile = SharedParse(dataFile);
if (!dataFile)
{
CONSOLE_ECHO("Error parsing %s - expected skin name\n", filename);
FREE_FILE(dataPointer);
return;
}
token = SharedGetToken();
Q_snprintf(skinName, BufLen, "%s", token);
// get attribute name
dataFile = SharedParse(dataFile);
if (!dataFile)
{
CONSOLE_ECHO("Error parsing %s - expected 'Model'\n", filename);
FREE_FILE(dataPointer);
return;
}
token = SharedGetToken();
if (Q_stricmp("Model", token))
{
CONSOLE_ECHO("Error parsing %s - expected 'Model'\n", filename);
FREE_FILE(dataPointer);
return;
}
// 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();
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 */
NOBODY BotProfileManager::~BotProfileManager(void)
BotProfileManager::~BotProfileManager(void)
{
// {
// iterator it; // 536
// begin(vector<char*, std::allocator<char*>> *const this); // 537
// end(vector<char*, std::allocator<char*>> *const this); // 537
// operator++(__normal_iterator<char**, std::vector<char*, std::allocator<char*>> > *const this); // 537
// clear(vector<char*, std::allocator<char*>> *const this); // 541
// }
// ~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
Reset();
for (VoiceBankList::iterator it = m_voiceBanks.begin(); it != m_voiceBanks.end(); ++it)
delete[] *it;
m_voiceBanks.clear();
}
// Free all bot profiles
/* <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
// {
// iterator iter; // 550
// operator++(_List_iterator<BotProfile*> *const this); // 550
// }
// {
// int i; // 555
// }
for (BotProfileList::iterator iter = m_profileList.begin(); iter != m_profileList.end(); ++iter)
delete *iter;
m_profileList.clear();
for (int i = 0; i < NumCustomSkins; ++i)
{
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 */
const char *BotProfileManager::GetCustomSkin(int index)
{
@ -191,6 +550,8 @@ const char *BotProfileManager::GetCustomSkin(int index)
return m_skins[ index - FirstCustomSkin ];
}
// Returns custom skin filename at a particular index
/* <4a8019> ../game_shared/bot/bot_profile.cpp:593 */
const char *BotProfileManager::GetCustomSkinFname(int index)
{
@ -202,6 +563,8 @@ const char *BotProfileManager::GetCustomSkinFname(int index)
return m_skinFilenames[ index - FirstCustomSkin ];
}
// Returns custom skin modelname at a particular index
/* <4a8053> ../game_shared/bot/bot_profile.cpp:607 */
const char *BotProfileManager::GetCustomSkinModelname(int index)
{
@ -213,37 +576,55 @@ const char *BotProfileManager::GetCustomSkinModelname(int index)
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 */
NOBODY int BotProfileManager::GetCustomSkinIndex(const char *name, const char *filename)
int BotProfileManager::GetCustomSkinIndex(const char *name, const char *filename)
{
// {
// const char *skinName; // 623
// GetDecoratedSkinName(const char *name,
// const char *filename); // 626
// {
// int i; // 629
// }
// }
const char *skinName = name;
if (filename)
{
skinName = GetDecoratedSkinName(name, filename);
}
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 */
NOBODY int BotProfileManager::FindVoiceBankIndex(const char *filename)
int BotProfileManager::FindVoiceBankIndex(const char *filename)
{
// {
// int index; // 649
// const_iterator it; // 651
// begin(vector<char*, std::allocator<char*>> *const this); // 652
// end(vector<char*, std::allocator<char*>> *const this); // 652
// operator++(__normal_iterator<char* const*, std::vector<char*, std::allocator<char*>> > *const this); // 652
// CloneString(const char *str); // 660
// push_back(vector<char*, std::allocator<char*>> *const this,
// const value_type &__x); // 660
// }
int index = 0;
for (VoiceBankList::const_iterator it = m_voiceBanks.begin(); it != m_voiceBanks.end(); ++it, ++index)
{
if (!Q_stricmp(filename, *it))
{
return index;
}
}
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 */
const BotProfile *BotProfileManager::GetRandomProfile(BotDifficultyType difficulty, BotProfileTeamType team) const
{
#ifdef RANDOM_LONG
BotProfileList::const_iterator iter;
// count up valid profiles
@ -274,4 +655,8 @@ const BotProfile *BotProfileManager::GetRandomProfile(BotDifficultyType difficul
}
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_prefersSilencer = false;
}
const char *GetName(void) const
{
return m_name;
}
float GetAggression(void) const
{
return m_aggression;
}
float GetSkill(void) const
{
return m_skill;
}
float GetTeamwork(void) const
{
return m_teamwork;
}
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;
}
const char *GetName(void) const { return m_name; }
float GetAggression(void) const { return m_aggression; }
float GetSkill(void) const { return m_skill; }
float GetTeamwork(void) const { return m_teamwork; }
int GetWeaponPreference(int i) const { return m_weaponPreference[i]; }
const char *GetWeaponPreferenceAsString(int i) const;
int GetWeaponPreferenceCount(void) const { return m_weaponPreferenceCount; }
bool HasPrimaryPreference(void) const;
bool HasPistolPreference(void) const;
int GetCost(void) const { return m_cost; }
int GetSkin(void) const { return m_skin; }
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 PrefersSilencer(void) const
{
return m_prefersSilencer;
}
// TODO: it func private
NOBODY void Inherit(const BotProfile *parent, const BotProfile *baseline);
bool PrefersSilencer(void) const { return m_prefersSilencer; }
private:
void Inherit(const BotProfile *parent, const BotProfile *baseline);
friend class BotProfileManager;
char *m_name;
@ -223,7 +179,7 @@ inline void BotProfile::Inherit(const BotProfile *parent, const BotProfile *base
m_voiceBank = parent->m_voiceBank;
}
typedef std::list<BotProfile *> BotProfileList;
typedef std::STD_LIST<BotProfile *> BotProfileList;
/* <36a051> ../game_shared/bot/bot_profile.h:180 */
class BotProfileManager
@ -238,8 +194,10 @@ public:
const BotProfile *GetProfile(const char *name, BotProfileTeamType team) const
{
for (BotProfileList::const_iterator iter = m_profileList.begin(); iter != m_profileList.end(); ++iter)
{
if (!Q_stricmp(name, (*iter)->GetName()) && (*iter)->IsValidForTeam(team))
return *iter;
}
return NULL;
}
@ -254,7 +212,7 @@ public:
const char *GetCustomSkinFname(int index);
int GetCustomSkinIndex(const char *name, const char *filename = NULL);
typedef std::vector<char *> VoiceBankList;
typedef std::STD_VECTOR<char *> VoiceBankList;
const VoiceBankList *GetVoiceBanks() const
{
@ -263,11 +221,6 @@ public:
int FindVoiceBankIndex(const char *filename);
protected:
#if defined(_WIN32) && defined(HOOK_GAMEDLL)
int unknown_padding1;
#endif // HOOK_GAMEDLL
BotProfileList m_profileList;
VoiceBankList m_voiceBanks;

View File

@ -144,7 +144,7 @@ int UTIL_HumansInGame(bool ignoreSpectators)
}
/* <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;
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 */
NOBODY int UTIL_BotsInGame(void)
int UTIL_BotsInGame(void)
{
int iCount = 0;
@ -265,7 +265,7 @@ bool UTIL_KickBotFromTeam(TeamName kickTeam)
}
/* <4ad7ad> ../game_shared/bot/bot_util.cpp:305 */
NOBODY bool UTIL_IsTeamAllBots(int team)
bool UTIL_IsTeamAllBots(int team)
{
int botCount = 0;
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.
/* <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;
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 */
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)
{
@ -432,26 +432,26 @@ CBasePlayer *UTIL_GetLocalPlayer(void)
}
/* <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))
return (pevVars->absmax + pevVars->absmin) *0.5;
if (pevVars->origin.x == 0.0f && pevVars->origin.y == 0.0f && pevVars->origin.z == 0.0f)
return (pevVars->absmax + pevVars->absmin) * 0.5f;
else
return pevVars->origin;
}
NOBODY Vector UTIL_ComputeOrigin(CBaseEntity *pEntity)
NOXREF Vector UTIL_ComputeOrigin(CBaseEntity *pEntity)
{
return UTIL_ComputeOrigin(pEntity->pev);
}
NOBODY Vector UTIL_ComputeOrigin(edict_t *pentEdict)
NOXREF Vector UTIL_ComputeOrigin(edict_t *pentEdict)
{
return UTIL_ComputeOrigin(VARS(pentEdict));
}
/* <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);
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 */
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);
WRITE_BYTE(TE_BEAMPOINTS);
@ -585,8 +585,8 @@ bool IsGameEventAudible(GameEventType event, CBaseEntity *entity, CBaseEntity *o
switch (event)
{
/// TODO: Check weapon type (knives are pretty quiet)
/// TODO: Use actual volume, account for silencers, etc.
// TODO: Check weapon type (knives are pretty quiet)
// TODO: Use actual volume, account for silencers, etc.
case EVENT_WEAPON_FIRED:
{
if (player->m_pActiveItem == NULL)

View File

@ -45,10 +45,7 @@ class BotProfile;
enum PriorityType
{
PRIORITY_LOW,
PRIORITY_MEDIUM,
PRIORITY_HIGH,
PRIORITY_UNINTERRUPTABLE
PRIORITY_LOW, PRIORITY_MEDIUM, PRIORITY_HIGH, PRIORITY_UNINTERRUPTABLE
};
// Simple class for tracking intervals of game time
@ -97,7 +94,8 @@ public:
{
return (gpGlobals->time - m_timestamp > duration) ? true : false;
}
/*private:*/
private:
float m_timestamp;
};/* size: 4, cachelines: 1, members: 1 */
@ -179,12 +177,14 @@ inline bool IsIntersecting2D(const Vector &startA, const Vector &endA, const Vec
// parallel
return false;
}
float numS = (startA.y - startB.y) * (endB.x - startB.x) - (startA.x - startB.x) * (endB.y - startB.y);
if (numS == 0.0f)
{
// coincident
return true;
}
float numT = (startA.y - startB.y) * (endA.x - startA.x) - (startA.x - startB.x) * (endA.y - startA.y);
float s = numS / denom;
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
return false;
}
float t = numT / denom;
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>
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));
if (!IsEntityValid((CBaseEntity *)player))
@ -247,38 +248,106 @@ inline bool IsZombieGame(void)
#define s_iBeamSprite (*ps_iBeamSprite)
#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
extern short s_iBeamSprite;
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);
int UTIL_ClientsInGame(void);
int UTIL_ActivePlayersInGame(void);
int UTIL_HumansInGame(bool ignoreSpectators);
NOBODY int UTIL_HumansOnTeam(int teamID, bool isAlive = false);
NOBODY int UTIL_BotsInGame(void);
int UTIL_BotsInGame(void);
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);
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();
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);
NOBODY Vector UTIL_ComputeOrigin(entvars_t *pevVars);
NOBODY Vector UTIL_ComputeOrigin(CBaseEntity *pEntity);
NOBODY Vector UTIL_ComputeOrigin(edict_t *pentEdict);
NOBODY 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);
NOXREF Vector UTIL_ComputeOrigin(entvars_t *pevVars);
NOXREF Vector UTIL_ComputeOrigin(CBaseEntity *pEntity);
NOXREF Vector UTIL_ComputeOrigin(edict_t *pentEdict);
NOXREF void UTIL_DrawBeamFromEnt(int iIndex, 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_LOGGED(char *pszMsg, ...);
void BotPrecache(void);
void InitBotTrig(void);
float BotCOS(float angle);
float BotSIN(float angle);
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

View File

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

View File

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

View File

@ -125,7 +125,6 @@ enum LadderDirectionType
NUM_LADDER_DIRECTIONS
};
/* <4c2fda> ../game_shared/bot/nav_area.h:63 */
class CNavLadder
{
@ -232,10 +231,12 @@ public:
}
static void ChangeMasterMarker(void)
{
IMPL(m_masterMarker)++;
++IMPL(m_masterMarker);
}
#ifndef HOOK_GAMEDLL
private:
#endif // HOOK_GAMEDLL
friend void DestroyHidingSpots(void);
Vector m_pos;
@ -243,9 +244,6 @@ private:
unsigned int m_marker;
unsigned char m_flags;
#ifdef HOOK_GAMEDLL
public:
#endif // HOOK_GAMEDLL
static unsigned int IMPL(m_nextID);
static unsigned int IMPL(m_masterMarker);
@ -303,77 +301,45 @@ public:
void Load(SteamFile *file, unsigned int version);
NavErrorType PostLoad(void);
unsigned int GetID(void) const
{
return m_id;
}
void SetAttributes(unsigned char bits)
{
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;
}
unsigned int GetID(void) const { return m_id; }
void SetAttributes(unsigned char bits) { m_attributeFlags = bits; }
unsigned char GetAttributes(void) const { return m_attributeFlags; }
void SetPlace(Place place) { m_place = place; } // set place descriptor
Place GetPlace(void) const { return m_place; } // get place descriptor
bool IsOverlapping(const Vector *pos) const; // return true if 'pos' is within 2D extents of area
bool IsOverlapping(const CNavArea *area) const; // return true if 'area' overlaps our 2D extents
bool IsOverlappingX(const CNavArea *area) const; // return true if 'area' overlaps our X extent
bool IsOverlappingY(const CNavArea *area) const; // return true if 'area' overlaps our Y extent
int GetPlayerCount(int teamID = 0, CBasePlayer *ignore = NULL) const; // return number of players with given teamID in this area (teamID == 0 means any/all)
float GetZ(const Vector *pos) const; // return Z of area at (x,y) of 'pos'
float GetZ(float x, float y) const; // return Z of area at (x,y) of 'pos'
bool Contains(const Vector *pos) const; // return true if given point is on or above this area, but no others
bool IsCoplanar(const CNavArea *area) const; // return true if this area and given area are approximately co-planar
void GetClosestPointOnArea(const Vector *pos, Vector *close) const; // return closest point to 'pos' on this area - returned point in 'close'
float GetDistanceSquaredToPoint(const Vector *pos) const; // return shortest distance between point and this area
bool IsDegenerate(void) const; // return true if this area is badly formed
bool IsEdge(NavDirType dir) const; // return true if there are no bi-directional links on the given side
int GetAdjacentCount(NavDirType dir) const // return number of connected areas in given direction
{
return m_connect[dir].size();
}
CNavArea *GetAdjacentArea(NavDirType dir, int i) const; // return the i'th adjacent area in the given direction
bool IsOverlapping(const Vector *pos) const; // return true if 'pos' is within 2D extents of area
bool IsOverlapping(const CNavArea *area) const; // return true if 'area' overlaps our 2D extents
bool IsOverlappingX(const CNavArea *area) const; // return true if 'area' overlaps our X extent
bool IsOverlappingY(const CNavArea *area) const; // return true if 'area' overlaps our Y extent
int GetPlayerCount(int teamID = 0, CBasePlayer *ignore = NULL) const; // return number of players with given teamID in this area (teamID == 0 means any/all)
float GetZ(const Vector *pos) const; // return Z of area at (x,y) of 'pos'
float GetZ(float x, float y) const; // return Z of area at (x,y) of 'pos'
bool Contains(const Vector *pos) const; // return true if given point is on or above this area, but no others
bool IsCoplanar(const CNavArea *area) const; // return true if this area and given area are approximately co-planar
void GetClosestPointOnArea(const Vector *pos, Vector *close) const; // return closest point to 'pos' on this area - returned point in 'close'
float GetDistanceSquaredToPoint(const Vector *pos) const; // return shortest distance between point and this area
bool IsDegenerate(void) const; // return true if this area is badly formed
bool IsEdge(NavDirType dir) const; // return true if there are no bi-directional links on the given side
int GetAdjacentCount(NavDirType dir) const { return 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
CNavArea *GetRandomAdjacentArea(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
float ComputeHeightChange(const CNavArea *area); // compute change in height from this area to given area
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
float ComputeHeightChange(const CNavArea *area); // compute change in height from this area to given area
const NavLadderList *GetLadderList(LadderDirectionType dir) const
{
return &m_ladder[dir];
}
const NavLadderList *GetLadderList(LadderDirectionType dir) const { return &m_ladder[dir]; }
void ComputePortal(const CNavArea *to, NavDirType dir, Vector *center, float *halfWidth) const; // compute portal to adjacent area
void ComputeClosestPointInPortal(const CNavArea *to, NavDirType dir, const Vector *fromPos, Vector *closePos) const; // compute closest point within the "portal" between to adjacent areas
NavDirType ComputeDirection(Vector *point) const; // return direction from this area to the given point
// for hunting algorithm
void SetClearedTimestamp(int teamID) // set this area's "clear" timestamp to now
{
m_clearedTimestamp[teamID] = gpGlobals->time;
}
float GetClearedTimestamp(int teamID) // get time this area was marked "clear"
{
return m_clearedTimestamp[teamID];
}
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"
// hiding spots
const HidingSpotList *GetHidingSpotList(void) const
{
return &m_hidingSpotList;
}
const HidingSpotList *GetHidingSpotList(void) const { return &m_hidingSpotList; }
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
@ -383,22 +349,12 @@ public:
// danger
void IncreaseDanger(int teamID, float amount); // increase the danger of this area for the given team
float GetDanger(int teamID); // return the danger of this area (decays over time)
float GetSizeX(void) const
{
return m_extent.hi.x - m_extent.lo.x;
}
float GetSizeY(void) const
{
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;
}
float GetSizeX(void) const { return m_extent.hi.x - m_extent.lo.x; }
float GetSizeY(void) const { 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;
// approach areas
@ -411,44 +367,22 @@ public:
NavTraverseType hereToNextHow;
};
const ApproachInfo *GetApproachInfo(int i) const
{
return &m_approach[i];
}
int GetApproachInfoCount(void) const
{
return m_approachCount;
}
void ComputeApproachAreas(void); // determine the set of "approach areas" - for map learning
const ApproachInfo *GetApproachInfo(int i) const { return &m_approach[i]; }
int GetApproachInfoCount(void) const { return m_approachCount; }
void ComputeApproachAreas(void); // determine the set of "approach areas" - for map learning
// A* pathfinding algorithm
static void MakeNewMarker(void)
{
IMPL(m_masterMarker)++;
++IMPL(m_masterMarker);
if (IMPL(m_masterMarker) == 0)
IMPL(m_masterMarker) = 1;
}
void Mark(void)
{
m_marker = IMPL(m_masterMarker);
}
BOOL IsMarked(void) const
{
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;
}
void Mark(void) { m_marker = IMPL(m_masterMarker); }
BOOL IsMarked(void) const { 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"
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
void SetTotalCost(float value)
{
m_totalCost = value;
}
float GetTotalCost(void) const
{
return m_totalCost;
}
void SetCostSoFar(float value)
{
m_costSoFar = value;
}
float GetCostSoFar(void) const
{
return m_costSoFar;
}
void SetTotalCost(float value) { m_totalCost = value; }
float GetTotalCost(void) const { return m_totalCost; }
void SetCostSoFar(float value) { m_costSoFar = value; }
float GetCostSoFar(void) const { return m_costSoFar; }
// 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)
// ladders
void AddLadderUp(CNavLadder *ladder)
{
m_ladder[LADDER_UP].push_back(ladder);
}
void AddLadderDown(CNavLadder *ladder)
{
m_ladder[LADDER_DOWN].push_back(ladder);
}
void AddLadderUp(CNavLadder *ladder) { m_ladder[LADDER_UP].push_back(ladder); }
void AddLadderDown(CNavLadder *ladder) { m_ladder[LADDER_DOWN].push_back(ladder); }
#ifdef HOOK_GAMEDLL
public:
#else
#ifndef HOOK_GAMEDLL
private:
#endif // HOOK_GAMEDLL
friend void ConnectGeneratedAreas(void);
@ -602,6 +516,7 @@ inline CNavArea *CNavArea::GetAdjacentArea(NavDirType dir, int i) const
return (*iter).area;
--i;
}
return NULL;
}
@ -1151,7 +1066,7 @@ void SearchSurroundingAreas(CNavArea *startArea, const Vector *startPos, Functor
// check up ladders
const NavLadderList *ladderList = area->GetLadderList(LADDER_UP);
if (ladderList)
if (ladderList != NULL)
{
for (ladderIt = ladderList->begin(); ladderIt != ladderList->end(); ++ladderIt)
{
@ -1172,7 +1087,7 @@ void SearchSurroundingAreas(CNavArea *startArea, const Vector *startPos, Functor
// check down ladders
ladderList = area->GetLadderList(LADDER_DOWN);
if (ladderList)
if (ladderList != NULL)
{
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
// If functor returns false, stop processing and return false.
/* <4c4137> ../game_shared/bot/nav_area.h:1109 */
template <typename Functor>
void ForAllAreas(Functor &func)
bool ForAllAreas(Functor &func)
{
NavAreaList::iterator iter;
for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
{
CNavArea *area = *iter;
func(area);
if (func(area) == false)
return false;
}
return true;
}
// Fuctor that returns lowest cost for farthest away areas
// For use with FindMinimumCostArea()
class FarAwayFunctor NOXREF
NOXREF class FarAwayFunctor
{
public:
float operator()(CNavArea *area, CNavArea *fromArea, const CNavLadder *ladder)
@ -1209,7 +1127,7 @@ public:
if (area == fromArea)
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
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)
expensive = i;
}
if (cheapAreaSet[expensive].cost > cost)
{
@ -1299,8 +1219,10 @@ CNavArea *FindMinimumCostArea(CNavArea *startArea, CostFunctor &costFunc)
NavAreaList::iterator iter;
for (iter = TheNavAreaList.begin(); iter != TheNavAreaList.end(); ++iter)
{
if (which-- == 0)
break;
}
return *iter;
}
@ -1386,9 +1308,4 @@ void BuildLadders(void);
void MarkJumpAreas(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

View File

@ -16,15 +16,21 @@ char s_shared_quote;
#endif // HOOK_GAMEDLL
/* <2d4a66> ../game_shared/shared_util.cpp:50 */
NOBODY uchar32 *SharedWVarArgs(uchar32 *format, ...)
NOXREF wchar_t *SharedWVarArgs(wchar_t *format, ...)
{
// {
// va_list argptr; // 52
// intconst BufLen; // 53
// intconst NumBuffers; // 54
// wchar_t string; // 55
// int curstring; // 56
// }
va_list argptr;
const int BufLen = 1024;
const int NumBuffers = 4;
static wchar_t string[NumBuffers][BufLen];
static int curstring = 0;
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 */
@ -59,27 +65,39 @@ char *BufPrintf(char *buf, int &len, const char *fmt, ...)
len -= Q_strlen(buf);
return buf + Q_strlen(buf);
}
return NULL;
}
/* <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, ...)
{
// {
// va_list argptr; // 111
// }
if (len <= 0)
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 */
NOBODY const uchar32 *NumAsWString(int val)
NOXREF const wchar_t *NumAsWString(int val)
{
// {
// intconst BufLen; // 124
// intconst NumBuffers; // 125
// wchar_t string; // 126
// int curstring; // 127
// int len; // 131
// }
const int BufLen = 16;
const int NumBuffers = 4;
static wchar_t string[NumBuffers][BufLen];
static int curstring = 0;
curstring = (curstring + 1) % NumBuffers;
int len = BufLen;
BufWPrintf(string[curstring], len, L"%d", val);
return string[curstring];
}
/* <2d4d11> ../game_shared/shared_util.cpp:137 */
@ -118,22 +136,99 @@ NOXREF void SharedSetQuoteChar(char c)
// Parse a token out of a string
/* <2d4de7> ../game_shared/shared_util.cpp:173 */
NOBODY const char *SharedParse(const char *data)
const char *SharedParse(const char *data)
{
//
//skipwhite: // 185
// {
// int c; // 175
// int len; // 176
// }
int c;
int len;
len = 0;
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
/* <2d4e40> ../game_shared/shared_util.cpp:247 */
NOBODY bool SharedTokenWaiting(const char *buffer)
NOXREF bool SharedTokenWaiting(const char *buffer)
{
// {
// const char *p; // 249
// }
const char *p;
p = buffer;
while (*p && *p!='\n')
{
if (!isspace(*p) || isalnum(*p))
return true;
p++;
}
return false;
}

View File

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

View File

@ -131,7 +131,7 @@ bool CVoiceGameMgr::ClientCommand(CBasePlayer *pPlayer, const char *cmd)
bool bBan = Q_stricmp(cmd, "vban") == 0;
if (bBan && CMD_ARGC() >= 2)
{
for (int i = 1; i < CMD_ARGC(); i++)
for (int i = 1; i < CMD_ARGC(); ++i)
{
uint32 mask = 0;
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);
}
// Force it to update the masks now.
//UpdateMasks();
return true;
}
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_bWantModEnable[ playerClientIndex ] = false;
//UpdateMasks();
return true;
}
@ -167,7 +169,7 @@ void CVoiceGameMgr::UpdateMasks(void)
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);
@ -191,7 +193,7 @@ void CVoiceGameMgr::UpdateMasks(void)
if (g_PlayerModEnable[ iClient ])
{
// 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);
@ -209,7 +211,7 @@ void CVoiceGameMgr::UpdateMasks(void)
g_SentBanMasks[ iClient ] = g_BanMasks[ iClient ];
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(g_BanMasks[ iClient ].GetDWord(dw));
@ -218,7 +220,7 @@ void CVoiceGameMgr::UpdateMasks(void)
}
// 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 ];
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
#include "iterator"
#include "xutility"
#include "memory"
#ifdef _MSC_VER
@ -142,14 +143,14 @@ public:
{erase(begin(), end());
insert(begin(), _N, _X); }
iterator insert(iterator _P, const _Ty& _X = _Ty())
{size_type _O = _P - begin();
{size_type _O = size_type(_P - begin());
insert(_P, 1, _X);
return (begin() + _O); }
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);
iterator_ _S = allocator.allocate(_N, (void *)0);
iterator_ _Q = _Ucopy(_First, _P, _S);
iterator _S = allocator.allocate(_N, (void *)0);
iterator _Q = _Ucopy(_First, _P, _S);
_Ufill(_Q, _M, _X);
_Ucopy(_P, _Last, _Q + _M);
__Destroy(_First, _Last);
@ -157,7 +158,7 @@ public:
_End = _S + _N;
_Last = _S + size() + _M;
_First = _S; }
else if (_Last - _P < _M)
else if (size_type(_Last - _P) < _M)
{_Ucopy(_P, _Last, _P + _M);
_Ufill(_Last, _M - (_Last - _P), _X);
fill_(_P, _Last, _X);
@ -172,8 +173,8 @@ public:
__Distance(_F, _L, _M);
if (_End - _Last < _M)
{size_type _N = size() + (_M < size() ? size() : _M);
iterator_ _S = allocator.allocate(_N, (void *)0);
iterator_ _Q = _Ucopy(_First, _P, _S);
iterator _S = allocator.allocate(_N, (void *)0);
iterator _Q = _Ucopy(_First, _P, _S);
_Q = _Ucopy(_F, _L, _Q);
_Ucopy(_P, _Last, _Q);
__Destroy(_First, _Last);
@ -197,7 +198,7 @@ public:
--_Last;
return (_P); }
iterator erase(iterator _F, iterator _L)
{iterator_ _S = copy_(_L, end(), _F);
{iterator _S = copy_(_L, end(), _F);
__Destroy(_S, end());
_Last = _S;
return (_F); }

View File

@ -838,6 +838,7 @@
<ClInclude Include="..\extra\IDA structures\goldsource.h" />
<ClInclude Include="..\game_shared\bitvec.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_profile.h" />
<ClInclude Include="..\game_shared\bot\bot_util.h" />
@ -1168,7 +1169,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<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>
<AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -1204,7 +1205,7 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<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>
<AdditionalOptions>/arch:IA32 %(AdditionalOptions)</AdditionalOptions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>

View File

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

View File

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

View File

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

View File

@ -62,6 +62,8 @@ TEST(StructOffsets, ReversingChecks, 5000)
REPEAT_SIZEOF_PRINT(CCareerTaskManager);
REPEAT_SIZEOF_PRINT(CCareerTask);
REPEAT_SIZEOF_PRINT(CPreventDefuseTask);
REPEAT_SIZEOF_PRINT(BotStatement);
// offset the members
REPEAT_OFFSETOF_PRINT(CBaseEntity, pev);
@ -99,7 +101,8 @@ TEST(StructOffsets, ReversingChecks, 5000)
//CHECK_CLASS_SIZE(CBotManager, 12u, 12);
CHECK_CLASS_SIZE(CCSBot, 11404, 11424);
//CHECK_CLASS_SIZE(CCSBotManager, 740, 0x2E0u);//0x2E4u | 0x2E0u
CHECK_CLASS_SIZE(BotStatement, 0x70u, 0x70u);
//CHECK_CLASS_SIZE(HostageStateMachine, 0x10, 0x10);
//CHECK_CLASS_SIZE(HostageFollowState, 0x4C, 0x4C);
//CHECK_CLASS_SIZE(CCSBot, 0x2CA0, 0x2CA0);