Skip to content

Commit

Permalink
Hostage Support
Browse files Browse the repository at this point in the history
Very basic support for hostage mode.
#9
  • Loading branch information
caxanga334 committed Oct 15, 2021
1 parent 100c3d1 commit d4e12ba
Show file tree
Hide file tree
Showing 8 changed files with 313 additions and 12 deletions.
168 changes: 158 additions & 10 deletions utils/RCBot2_meta/bot_css_bot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@

#include "rcbot/logging.h"

extern IServerGameEnts *servergameents; // for accessing the server game entities

void CCSSBot::init(bool bVarInit)
{
CBot::init();// require this
Expand Down Expand Up @@ -577,6 +579,14 @@ void CCSSBot::modThink()
}
}

if(onLadder())
{
setMoveLookPriority(MOVELOOK_OVERRIDE);
setLookAtTask(LOOK_WAYPOINT);
m_pButtons->holdButton(IN_FORWARD,0,1,0);
setMoveLookPriority(MOVELOOK_MODTHINK);
}

// Team Specific thinking
switch (team)
{
Expand All @@ -596,6 +606,19 @@ void CCSSBot::modThink()
{
modThinkSlow();
}

if(getEnemy() != NULL && isVisible(getEnemy()))
{
CBotWeapon *currentweapon = getCurrentWeapon();

if(!hasSomeConditions(CONDITION_OUT_OF_AMMO))
{
if(currentweapon && !currentweapon->isMelee())
{
stopMoving();
}
}
}
}

void CCSSBot::modThinkSlow()
Expand Down Expand Up @@ -642,6 +665,11 @@ void CCSSBot::getTasks(unsigned int iIgnore)
ADD_UTILITY(BOT_UTIL_SEARCH_FOR_BOMB, !CCounterStrikeSourceMod::wasBombFound() && CCounterStrikeSourceMod::isBombPlanted(), 0.81f);
ADD_UTILITY(BOT_UTIL_DEFUSE_BOMB, CCounterStrikeSourceMod::wasBombFound(), 0.85f);
}
else if(CCounterStrikeSourceMod::isMapType(CS_MAP_HOSTAGERESCUE))
{
ADD_UTILITY(BOT_UTIL_GET_HOSTAGE, CCounterStrikeSourceMod::canRescueHostages(), 0.85f);
ADD_UTILITY(BOT_UTIL_RESCUE, IsLeadingHostage(), 0.84f);
}
break;
}
case CS_TEAM_TERRORIST: // TR specific utilities
Expand All @@ -659,13 +687,13 @@ void CCSSBot::getTasks(unsigned int iIgnore)
ADD_UTILITY(BOT_UTIL_SNIPE, IsSniper(), randomFloat(0.7900f, 0.8200f));

// Combat Utilities
ADD_UTILITY(BOT_UTIL_ENGAGE_ENEMY, hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && !hasSomeConditions(CONDITION_OUT_OF_AMMO), 0.98f);
ADD_UTILITY(BOT_UTIL_ENGAGE_ENEMY, hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && !hasSomeConditions(CONDITION_OUT_OF_AMMO), 1.00f);
ADD_UTILITY(BOT_UTIL_WAIT_LAST_ENEMY, hasSomeConditions(CONDITION_ENEMY_OBSCURED), 0.95f);
ADD_UTILITY(BOT_UTIL_HIDE_FROM_ENEMY, hasSomeConditions(CONDITION_SEE_CUR_ENEMY) && hasSomeConditions(CONDITION_OUT_OF_AMMO), 0.98f);

// Generic Utilities
ADD_UTILITY(BOT_UTIL_BUY, m_pBuyManager->wantsToBuy(), 1.0f); // Buy weapons
ADD_UTILITY(BOT_UTIL_ROAM, true, 0.0001f); // Roam around
ADD_UTILITY(BOT_UTIL_ROAM, true, 0.001f); // Roam around

utils.execute();

Expand All @@ -688,13 +716,17 @@ void CCSSBot::getTasks(unsigned int iIgnore)
if(m_fUtilTimes[next->getId()] < engine->Time())
m_fUtilTimes[next->getId()] = engine->Time() + randomFloat(0.1f, 2.0f); // saves problems with consistent failing

if(CClients::clientsDebugging(BOT_DEBUG_UTIL))
if ( CClients::clientsDebugging(BOT_DEBUG_UTIL) )
{
char buffer[128];
sprintf(buffer, "(%.4f) %s\nTeam: %i\nBomb Carrier: %s\nBomb Dropped: %s\nBomb Planted: %s", engine->Time(), g_szUtils[next->getId()], team,
CCounterStrikeSourceMod::isBombCarrier(this) ? "Yes" : "No", CCounterStrikeSourceMod::isBombDropped() ? "Yes" : "No",
CCounterStrikeSourceMod::isBombPlanted() ? "Yes" : "No");
CClients::clientDebugMsg(BOT_DEBUG_UTIL, buffer, this);
int i = 0;
CClients::clientDebugMsg(this,BOT_DEBUG_UTIL,"-------- getTasks(%s) --------",m_szBotName);

do
{
CClients::clientDebugMsg(this,BOT_DEBUG_UTIL,"%s = %0.3f",g_szUtils[next->getId()],next->getUtility(),this);
}while ((++i<20) && ((next = utils.nextBest()) != NULL));

CClients::clientDebugMsg(this,BOT_DEBUG_UTIL,"----END---- getTasks(%s) ----END----",m_szBotName);
}
break;
}
Expand Down Expand Up @@ -876,6 +908,67 @@ bool CCSSBot::executeAction(eBotAction iAction)
}
break;
}
case BOT_UTIL_GET_HOSTAGE:
{
// Select a random hostage to rescue
CWaypoint* pWaypoint = NULL;
CWaypoint* pRoute = NULL;
CBotSchedule* pSched = new CBotSchedule();
edict_t* pHostage = CCounterStrikeSourceMod::getRandomHostage();
pSched->setID(SCHED_GOTONEST);

if(CBotGlobals::entityIsAlive(pHostage))
{
Vector vHostage = CBotGlobals::entityOrigin(pHostage);
pRoute = CWaypoints::randomRouteWaypoint(this, getOrigin(), vHostage, getTeam(), 0);
if((m_fUseRouteTime <= engine->Time()))
{
if(pRoute)
{
int iRoute = CWaypoints::getWaypointIndex(pRoute); // Route waypoint
pSched->addTask(new CFindPathTask(iRoute, LOOK_WAYPOINT));
m_fUseRouteTime = engine->Time() + 30.0f;
}
}

pSched->addTask(new CFindPathTask(pHostage));
pSched->addTask(new CMoveToTask(pHostage));
pSched->addTask(new CBotHL2DMUseButton(pHostage));
pSched->addTask(new CBotWaitTask(1.0f));
m_pSchedules->add(pSched);
}

break;
}
case BOT_UTIL_RESCUE:
{
// Go to a random Rescue Zone waypoint
CWaypoint* pWaypoint = NULL;
CWaypoint* pRoute = NULL;
CBotSchedule* pSched = new CBotSchedule();
pSched->setID(SCHED_GOTO_ORIGIN);

pWaypoint = CWaypoints::randomWaypointGoal(CWaypointTypes::W_FL_RESCUEZONE, getTeam(), 0, false, this, false);

if(pWaypoint)
{
pRoute = CWaypoints::randomRouteWaypoint(this, getOrigin(), pWaypoint->getOrigin(), getTeam(), pWaypoint->getArea());
if((m_fUseRouteTime <= engine->Time()))
{
if(pRoute)
{
int iRoute = CWaypoints::getWaypointIndex(pRoute); // Route waypoint
pSched->addTask(new CFindPathTask(iRoute, LOOK_WAYPOINT));
m_fUseRouteTime = engine->Time() + 30.0f;
}
}

pSched->addTask(new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint)));
pSched->addTask(new CBotWaitTask(3.0f));
m_pSchedules->add(pSched);
}
break;
}
case BOT_UTIL_SNIPE:
{
CWaypoint *pWaypoint = NULL;
Expand All @@ -886,7 +979,7 @@ bool CCSSBot::executeAction(eBotAction iAction)
if(pWaypoint)
{
CFindPathTask *pFindPath = new CFindPathTask(CWaypoints::getWaypointIndex(pWaypoint));
pFindPath->setInterruptFunction(new CBotCSSRoamInterrupt());
//pFindPath->setInterruptFunction(new CBotCSSRoamInterrupt());
CCSSGuardTask *pGuard = new CCSSGuardTask(getPrimaryWeapon(), pWaypoint->getOrigin(), pWaypoint->getAimYaw(), false, 0.0f, pWaypoint->getFlags());
pSched->addTask(pFindPath);
pSched->addTask(pGuard);
Expand All @@ -908,7 +1001,7 @@ bool CCSSBot::executeAction(eBotAction iAction)
{
int iWaypoint = CWaypoints::getWaypointIndex(pWaypoint);
CFindPathTask *pFindPath = new CFindPathTask(iWaypoint);
pFindPath->setInterruptFunction(new CBotCSSRoamInterrupt());
//pFindPath->setInterruptFunction(new CBotCSSRoamInterrupt());
pSched->addTask(pFindPath);
m_pSchedules->add(pSched);

Expand All @@ -925,4 +1018,59 @@ bool CCSSBot::executeAction(eBotAction iAction)
void CCSSBot::onRoundStart()
{
m_pBuyManager->onRoundStart();
}

bool CCSSBot::IsLeadingHostage()
{
std::vector<CBaseHandle> hostages = CCounterStrikeSourceMod::getHostageVector();
edict_t *pHostage = NULL;

if(getTeam() != CS_TEAM_COUNTERTERRORIST)
return false;

if(hostages.size() == 0)
return false;

for(CBaseHandle i : hostages)
{
edict_t *pHostage = INDEXENT(i.GetEntryIndex());

if(CBotGlobals::entityIsValid(pHostage) && CClassInterface::getCSHostageLeader(pHostage) == m_pEdict)
{
return true;
}
}

return false;
}

void CCSSBot::touchedWpt(CWaypoint *pWaypoint, int iNextWaypoint, int iPrevWaypoint)
{
if(iNextWaypoint != -1 && pWaypoint->hasFlag(CWaypointTypes::W_FL_DOOR)) // Use waypoint: Check for door
{
CWaypoint *pNext = CWaypoints::getWaypoint(iNextWaypoint);
if(pNext)
{
/**
* Traces a line between the current waypoint and the next waypoint. If a door is blocking the path, try to open it.
**/
CTraceFilterHitAll filter;
trace_t *tr = CBotGlobals::getTraceResult();
CBotGlobals::traceLine(pWaypoint->getOrigin() + Vector(0,0,CWaypoint::WAYPOINT_HEIGHT/2), pNext->getOrigin() + Vector(0,0,CWaypoint::WAYPOINT_HEIGHT/2), MASK_PLAYERSOLID, &filter);
if(tr->fraction < 1.0f)
{
if(tr->m_pEnt)
{
edict_t *pDoor = servergameents->BaseEntityToEdict(tr->m_pEnt);
const char *szclassname = pDoor->GetClassName();
if(strncmp(szclassname, "prop_door_rotating", 18) == 0 || strncmp(szclassname, "func_door", 9) == 0 || strncmp(szclassname, "func_door_rotating", 18) == 0)
{
m_pSchedules->addFront(new CSynOpenDoorSched(pDoor));
}
}
}
}
}

CBot::touchedWpt(pWaypoint, iNextWaypoint, iPrevWaypoint);
}
2 changes: 2 additions & 0 deletions utils/RCBot2_meta/bot_css_bot.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class CCSSBot : public CBot
void modThink() override;
void listenForPlayers() override;
void freeMapMemory() override;
void touchedWpt(CWaypoint *pWaypoint, int iNextWaypoint = -1, int iPrevWaypoint = -1) override;
virtual void modThinkSlow();
unsigned int maxEntityIndex() override { return gpGlobals->maxEntities; }
void getTasks (unsigned int iIgnore=0) override;
Expand All @@ -77,6 +78,7 @@ class CCSSBot : public CBot
virtual CBotWeapon *getPrimaryWeapon();
virtual bool IsSniper();
virtual void onRoundStart();
virtual bool IsLeadingHostage();
private:
edict_t *m_pCurrentWeapon; // The bot current weapon
float m_fNextAttackTime; // Control timer for bot primary attack
Expand Down
100 changes: 98 additions & 2 deletions utils/RCBot2_meta/bot_css_mod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ float CCounterStrikeSourceMod::m_fBombPlantedTime = 0.0f;
bool CCounterStrikeSourceMod::m_bIsBombPlanted = false;
bool CCounterStrikeSourceMod::m_bBombWasFound = false;
CBaseHandle CCounterStrikeSourceMod::m_hBomb = NULL;
std::vector<CBaseHandle> CCounterStrikeSourceMod::m_hHostages;


void CCounterStrikeSourceMod::initMod()
Expand Down Expand Up @@ -184,6 +185,11 @@ void CCounterStrikeSourceMod::onRoundStart()
pCSBot->onRoundStart();
}
}

if(CCounterStrikeSourceMod::isMapType(CS_MAP_HOSTAGERESCUE))
{
updateHostages();
}
}

/**
Expand All @@ -198,7 +204,6 @@ void CCounterStrikeSourceMod::onFreezeTimeEnd()
if(pC4)
{
m_hBomb.Init(engine->IndexOfEdict(pC4), pC4->m_NetworkSerialNumber);
logger->Log(LogLevel::DEBUG, "CSS C4: %i %i %s", m_hBomb.GetEntryIndex(), m_hBomb.GetSerialNumber(), m_hBomb.IsValid() ? "Valid" : "Invalid");
}

for(short int i = 0; i < MAX_PLAYERS; i++)
Expand Down Expand Up @@ -226,7 +231,6 @@ void CCounterStrikeSourceMod::onBombPlanted()
if(pPlantedC4)
{
m_hBomb.Init(engine->IndexOfEdict(pPlantedC4), pPlantedC4->m_NetworkSerialNumber);
logger->Log(LogLevel::DEBUG, "CSS C4: %i %i %s", m_hBomb.GetEntryIndex(), m_hBomb.GetSerialNumber(), m_hBomb.IsValid() ? "Valid" : "Invalid");
}

for(short int i = 0; i < MAX_PLAYERS; i++)
Expand All @@ -241,4 +245,96 @@ void CCounterStrikeSourceMod::onBombPlanted()
}
}
}
}

/**
* Hostage entities needs to be updated on round start since killed hostages gets their entity deleted.
**/
void CCounterStrikeSourceMod::updateHostages()
{
edict_t *current;
CBaseHandle bh;
m_hHostages.clear();

for(int i = gpGlobals->maxClients + 1; i < gpGlobals->maxEntities; i++)
{
bh.Term();
current = engine->PEntityOfEntIndex(i);
if (current == NULL)
{
continue;
}

IServerNetworkable *network = current->GetNetworkable();
if (network == NULL)
{
continue;
}

//const char *classname = current->GetClassName();
ServerClass *sClass = network->GetServerClass();
const char *sname = sClass->GetName();

if(strcmp(sname, "CHostage") == 0)
{
bh.Init(i, current->m_NetworkSerialNumber);
m_hHostages.push_back(bh);
}
}

logger->Log(LogLevel::DEBUG, "Hostage Vector Size %i", m_hHostages.size());

for(CBaseHandle i : m_hHostages)
{
logger->Log(LogLevel::DEBUG, "Stored Hostage: %i - %i", i.GetEntryIndex(), i.GetSerialNumber());
}
}

/**
* Checks if there are hostages that can be rescued
**/
bool CCounterStrikeSourceMod::canRescueHostages()
{
if(m_hHostages.size() == 0)
return false;

edict_t *pHostage;

for(CBaseHandle i : m_hHostages)
{
pHostage = INDEXENT(i.GetEntryIndex());

if(CBotGlobals::entityIsValid(pHostage) && !CClassInterface::isCSHostageRescued(pHostage) && CClassInterface::getCSHostageLeader(pHostage) == NULL)
{
return true;
}
}

return false;
}

edict_t *CCounterStrikeSourceMod::getRandomHostage()
{
std::vector<CBaseHandle> temp;
edict_t *pEdict;

// Build a new vector with hostages that are valid to be rescued
for(CBaseHandle i : temp)
{
pEdict = INDEXENT(i.GetEntryIndex());

if(CBotGlobals::entityIsValid(pEdict) && !CClassInterface::isCSHostageRescued(pEdict) && CClassInterface::getCSHostageLeader(pEdict) == NULL && CClassInterface::getCSHostageHealth(pEdict) > 0)
{
temp.push_back(i);
}
}

if(temp.size() > 0)
{
return INDEXENT(temp.at(randomInt(0, temp.size() - 1)).GetEntryIndex());
}
else
{
return NULL;
}
}
Loading

0 comments on commit d4e12ba

Please sign in to comment.