Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bot Chatter: Bots will react to enemy snipers presence #1055

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions regamedll/dlls/bot/cs_bot.h
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,11 @@ class CCSBot: public CBot
bool IsAwareOfEnemyDeath() const; // return true if we *noticed* that our enemy died
int GetLastVictimID() const; // return the ID (entindex) of the last victim we killed, or zero

#ifdef REGAMEDLL_ADD
bool CanSeeSniper(void) const; ///< return true if we can see an enemy sniper
bool HasSeenSniperRecently(void) const; ///< return true if we have seen a sniper recently
#endif

// navigation
bool HasPath() const;
void DestroyPath();
Expand Down Expand Up @@ -921,6 +926,11 @@ class CCSBot: public CBot

float m_fireWeaponTimestamp;

#ifdef REGAMEDLL_ADD
bool m_isEnemySniperVisible; ///< do we see an enemy sniper right now
CountdownTimer m_sawEnemySniperTimer; ///< tracking time since saw enemy sniper
#endif

// reaction time system
enum { MAX_ENEMY_QUEUE = 20 };
struct ReactionState
Expand Down Expand Up @@ -1250,6 +1260,18 @@ inline int CCSBot::GetLastVictimID() const
return m_lastVictimID;
}

#ifdef REGAMEDLL_ADD
inline bool CCSBot::CanSeeSniper(void) const
{
return m_isEnemySniperVisible;
}

inline bool CCSBot::HasSeenSniperRecently(void) const
{
return !m_sawEnemySniperTimer.IsElapsed();
}
#endif

inline bool CCSBot::HasPath() const
{
return m_pathLength != 0;
Expand Down
50 changes: 50 additions & 0 deletions regamedll/dlls/bot/cs_bot_chatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,17 @@ void BotHostageBeingTakenMeme::Interpret(CCSBot *pSender, CCSBot *pReceiver) con
pReceiver->GetChatter()->Say("Affirmative");
}

#ifdef REGAMEDLL_ADD
//---------------------------------------------------------------------------------------------------------------
/**
* A teammate warned about snipers, so we shouldn't warn again for awhile
*/
void BotWarnSniperMeme::Interpret(CCSBot* sender, CCSBot* receiver) const
{
receiver->GetChatter()->FriendSpottedSniper();
}
#endif

BotSpeakable::BotSpeakable()
{
m_phrase = nullptr;
Expand Down Expand Up @@ -1270,6 +1281,9 @@ void BotChatterInterface::Reset()
m_planInterval.Invalidate();
m_encourageTimer.Invalidate();
m_escortingHostageTimer.Invalidate();
#ifdef REGAMEDLL_ADD
m_warnSniperTimer.Invalidate();
#endif
}

// Register a statement for speaking
Expand Down Expand Up @@ -1626,6 +1640,42 @@ void BotChatterInterface::EnemySpotted()
AddStatement(say);
}

#ifdef REGAMEDLL_ADD
//---------------------------------------------------------------------------------------------------------------
/**
* If a friend warned of snipers, don't warn again for awhile
*/
void BotChatterInterface::FriendSpottedSniper(void)
{
m_warnSniperTimer.Start(60.0f);
}

//---------------------------------------------------------------------------------------------------------------
/**
* Warn of an enemy sniper
*/
void BotChatterInterface::SpottedSniper(void)
{
if (!m_warnSniperTimer.IsElapsed())
{
return;
}

if (m_me->GetFriendsRemaining() == 0)
{
// no-one to warn
return;
}

BotStatement* say = new BotStatement(this, REPORT_INFORMATION, 10.0f);

say->AppendPhrase(TheBotPhrases->GetPhrase("SniperWarning"));
say->AttachMeme(new BotWarnSniperMeme());

AddStatement(say);
}
#endif

NOXREF void BotChatterInterface::Clear(Place place)
{
BotStatement *say = new BotStatement(this, REPORT_INFORMATION, 10.0f);
Expand Down
15 changes: 15 additions & 0 deletions regamedll/dlls/bot/cs_bot_chatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,14 @@ class BotRequestReportMeme: public BotMeme
virtual void Interpret(CCSBot *pSender, CCSBot *pReceiver) const; // cause the given bot to act on this meme
};

#ifdef REGAMEDLL_ADD
class BotWarnSniperMeme : public BotMeme
{
public:
virtual void Interpret(CCSBot* sender, CCSBot* receiver) const; ///< cause the given bot to act on this meme
};
#endif

enum BotStatementType
{
REPORT_VISIBLE_ENEMIES,
Expand Down Expand Up @@ -531,6 +539,10 @@ class BotChatterInterface
void KilledFriend();
void FriendlyFire();

#ifdef REGAMEDLL_ADD
void SpottedSniper(void);
void FriendSpottedSniper(void);
#endif
bool SeesAtLeastOneEnemy() const { return m_seeAtLeastOneEnemy; }

private:
Expand All @@ -557,6 +569,9 @@ class BotChatterInterface
CountdownTimer m_spottedLooseBombTimer;
CountdownTimer m_heardNoiseTimer;
CountdownTimer m_escortingHostageTimer;
#ifdef REGAMEDLL_ADD
CountdownTimer m_warnSniperTimer;
#endif
};

inline BotChatterInterface::VerbosityType BotChatterInterface::GetVerbosity() const
Expand Down
5 changes: 5 additions & 0 deletions regamedll/dlls/bot/cs_bot_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ void CCSBot::ResetValues()
m_currentArea = nullptr;
m_lastKnownArea = nullptr;

#ifdef REGAMEDLL_ADD
m_isEnemySniperVisible = false;
m_sawEnemySniperTimer.Invalidate();
#endif

m_avoidFriendTimer.Invalidate();
m_isFriendInTheWay = false;
m_isWaitingBehindFriend = false;
Expand Down
23 changes: 20 additions & 3 deletions regamedll/dlls/bot/cs_bot_update.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ void CCSBot::Update()
Vector dir = m_spotEncounter->path.to - m_spotEncounter->path.from;
float length = dir.NormalizeInPlace();

for (auto &order : m_spotEncounter->spotList) {
for (auto& order : m_spotEncounter->spotList) {
UTIL_DrawBeamPoints(m_spotEncounter->path.from + order.t * length * dir, *order.spot->GetPosition(), 3, 0, 255, 255);
}
}
Expand Down Expand Up @@ -339,7 +339,7 @@ void CCSBot::Update()
UpdateReactionQueue();

// "threat" may be the same as our current enemy
CBasePlayer *threat = GetRecognizedEnemy();
CBasePlayer* threat = GetRecognizedEnemy();
if (threat)
{
// adjust our personal "safe" time
Expand Down Expand Up @@ -592,6 +592,10 @@ void CCSBot::Update()
SecondaryAttack();
}

#ifdef REGAMEDLL_ADD
if (!IsBlind())
{
#endif
// check encounter spots
UpdatePeripheralVision();

Expand All @@ -601,11 +605,24 @@ void CCSBot::Update()
GetChatter()->SpottedBomber(GetBomber());
}

#ifdef REGAMEDLL_ADD
// watch for snipers
if (CanSeeSniper() && !HasSeenSniperRecently())
{
GetChatter()->SpottedSniper();

const float sniperRecentInterval = 20.0f;
m_sawEnemySniperTimer.Start(sniperRecentInterval);
}
#endif

if (CanSeeLooseBomb())
{
GetChatter()->SpottedLooseBomb(TheCSBots()->GetLooseBomb());
}

#ifdef REGAMEDLL_ADD
}
#endif
// Scenario interrupts
switch (TheCSBots()->GetScenario())
{
Expand Down
69 changes: 69 additions & 0 deletions regamedll/dlls/bot/cs_bot_vision.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,13 @@ CBasePlayer *CCSBot::FindMostDangerousThreat()
m_closestVisibleFriend = nullptr;
m_closestVisibleHumanFriend = nullptr;

#ifdef REGAMEDLL_ADD
m_isEnemySniperVisible = false;
CBasePlayer* sniperThreat = NULL;
float sniperThreatRange = 99999999999.9f;
bool sniperThreatIsFacingMe = false;
#endif

float closeFriendRange = 99999999999.9f;
float closeHumanFriendRange = 99999999999.9f;

Expand Down Expand Up @@ -789,6 +796,51 @@ CBasePlayer *CCSBot::FindMostDangerousThreat()
Vector d = pev->origin - pPlayer->pev->origin;
float distSq = d.LengthSquared();

#ifdef REGAMEDLL_ADD
if (isSniperRifle(pPlayer->m_pActiveItem)) {
m_isEnemySniperVisible = true;
if (sniperThreat)
{
if (IsPlayerLookingAtMe(pPlayer))
{
if (sniperThreatIsFacingMe)
{
// several snipers are facing us - keep closest
if (distSq < sniperThreatRange)
{
sniperThreat = pPlayer;
sniperThreatRange = distSq;
sniperThreatIsFacingMe = true;
}
}
else
{
// even if this sniper is farther away, keep it because he's aiming at us
sniperThreat = pPlayer;
sniperThreatRange = distSq;
sniperThreatIsFacingMe = true;
}
}
else
{
// this sniper is not looking at us, only consider it if we dont have a sniper facing us
if (!sniperThreatIsFacingMe && distSq < sniperThreatRange)
{
sniperThreat = pPlayer;
sniperThreatRange = distSq;
}
}
}
else
{
// first sniper we see
sniperThreat = pPlayer;
sniperThreatRange = distSq;
sniperThreatIsFacingMe = IsPlayerLookingAtMe(pPlayer);
}
}
#endif

// maintain set of visible threats, sorted by increasing distance
if (threatCount == 0)
{
Expand Down Expand Up @@ -950,6 +1002,23 @@ CBasePlayer *CCSBot::FindMostDangerousThreat()
{
return currentThreat;
}

// if we are a sniper and we see a sniper threat, attack it unless
// there are other close enemies facing me
if (IsSniper() && sniperThreat)
{
const float closeCombatRange = 500.0f;

for (t = 0; t < threatCount; ++t)
{
if (threat[t].range < closeCombatRange && IsPlayerLookingAtMe(threat[t].enemy))
{
return threat[t].enemy;
}
}

return sniperThreat;
}
#endif

// otherwise, find the closest threat that without using shield
Expand Down