fix: hostage code (#269)
fix: hostage code add: yb_random_knife_attacks cvar
This commit is contained in:
parent
0b5658c065
commit
f55ac6c5c4
5 changed files with 100 additions and 8 deletions
|
|
@ -35,6 +35,7 @@ ConVar cv_restricted_weapons ("yb_restricted_weapons", "", "Specifies semicolon
|
|||
ConVar cv_attack_monsters ("yb_attack_monsters", "0", "Allows or disallows bots to attack monsters.");
|
||||
ConVar cv_pickup_custom_items ("yb_pickup_custom_items", "0", "Allows or disallows bots to pickup custom items.");
|
||||
ConVar cv_ignore_objectives ("yb_ignore_objectives", "0", "Allows or disallows bots to do map objectives, i.e. plant/defuse bombs, and saves hostages.");
|
||||
ConVar cv_random_knife_attacks ("yb_random_knife_attacks", "1", "Allows or disallows the ability for random knife attacks when bot is rushing and no enemy is nearby.");
|
||||
|
||||
// game console variables
|
||||
ConVar mp_c4timer ("mp_c4timer", nullptr, Var::GameRef);
|
||||
|
|
@ -95,7 +96,7 @@ bool Bot::seesItem (const Vector &destination, const char *classname) {
|
|||
game.testLine (getEyesPos (), destination, TraceIgnore::None, ent (), &tr);
|
||||
|
||||
// check if line of sight to object is not blocked (i.e. visible)
|
||||
if (tr.flFraction >= 0.95f && tr.pHit && tr.pHit != game.getStartEntity ()) {
|
||||
if (tr.flFraction < 1.0f && tr.pHit) {
|
||||
return strcmp (tr.pHit->v.classname.chars (), classname) == 0;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -557,7 +558,7 @@ void Bot::updatePickups () {
|
|||
|
||||
// check if line of sight to object is not blocked (i.e. visible)
|
||||
if (seesItem (origin, classname)) {
|
||||
if (strncmp ("hostage_entity", classname, 14) == 0) {
|
||||
if (strncmp ("hostage_entity", classname, 14) == 0 || strncmp ("monster_scientist", classname, 17) == 0) {
|
||||
allowPickup = true;
|
||||
pickupType = Pickup::Hostage;
|
||||
}
|
||||
|
|
@ -735,6 +736,17 @@ void Bot::updatePickups () {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// don't steal hostage from human teammate (hack)
|
||||
if (allowPickup) {
|
||||
for (auto &client : util.getClients ()) {
|
||||
if ((client.flags & ClientFlags::Used) && !(client.ent->v.flags & FL_FAKECLIENT) && (client.flags & ClientFlags::Alive) &&
|
||||
client.team == m_team && client.ent->v.origin.distanceSq (ent->v.origin) <= cr::square (240.0f)) {
|
||||
allowPickup = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pickupType == Pickup::PlantedC4) {
|
||||
|
|
@ -3057,7 +3069,7 @@ void Bot::normal_ () {
|
|||
}
|
||||
|
||||
// bots rushing with knife, when have no enemy (thanks for idea to nicebot project)
|
||||
if (usesKnife () && (game.isNullEntity (m_lastEnemy) || !util.isAlive (m_lastEnemy)) && game.isNullEntity (m_enemy) && m_knifeAttackTime < game.time () && !hasShield () && numFriendsNear (pev->origin, 96.0f) == 0) {
|
||||
if (cv_random_knife_attacks.bool_ () && usesKnife () && (game.isNullEntity (m_lastEnemy) || !util.isAlive (m_lastEnemy)) && game.isNullEntity (m_enemy) && m_knifeAttackTime < game.time () && !hasShield () && numFriendsNear (pev->origin, 96.0f) == 0) {
|
||||
if (rg.chance (40)) {
|
||||
pev->button |= IN_ATTACK;
|
||||
}
|
||||
|
|
@ -4588,6 +4600,61 @@ void Bot::pickupItem_ () {
|
|||
}
|
||||
m_hostages.push (m_pickupItem);
|
||||
m_pickupItem = nullptr;
|
||||
completeTask ();
|
||||
|
||||
float minDistance = kInfiniteDistance;
|
||||
int nearestHostageNodeIndex = kInvalidNodeIndex;
|
||||
|
||||
// find the nearest 'unused' hostage within the area
|
||||
game.searchEntities (pev->origin, 768.0f, [&] (edict_t *ent) {
|
||||
auto classname = ent->v.classname.chars ();
|
||||
|
||||
if (strncmp ("hostage_entity", classname, 14) != 0 && strncmp ("monster_scientist", classname, 17) != 0) {
|
||||
return EntitySearchResult::Continue;
|
||||
}
|
||||
|
||||
// check if hostage is dead
|
||||
if (game.isNullEntity (ent) || ent->v.health <= 0) {
|
||||
return EntitySearchResult::Continue;
|
||||
}
|
||||
|
||||
// check if hostage is with a bot
|
||||
for (const auto &other : bots) {
|
||||
if (other->m_notKilled) {
|
||||
for (const auto &hostage : other->m_hostages) {
|
||||
if (hostage == ent) {
|
||||
return EntitySearchResult::Continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if hostage is with a human teammate (hack)
|
||||
for (auto &client : util.getClients ()) {
|
||||
if ((client.flags & ClientFlags::Used) && !(client.ent->v.flags & FL_FAKECLIENT) && (client.flags & ClientFlags::Alive) &&
|
||||
client.team == m_team && client.ent->v.origin.distanceSq (ent->v.origin) <= cr::square (240.0f)) {
|
||||
return EntitySearchResult::Continue;
|
||||
}
|
||||
}
|
||||
|
||||
int hostageNodeIndex = graph.getNearest (ent->v.origin);
|
||||
|
||||
if (graph.exists (hostageNodeIndex)) {
|
||||
float distance = graph[hostageNodeIndex].origin.distanceSq (pev->origin);
|
||||
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance;
|
||||
nearestHostageNodeIndex = hostageNodeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return EntitySearchResult::Continue;
|
||||
});
|
||||
|
||||
if (nearestHostageNodeIndex != kInvalidNodeIndex) {
|
||||
clearTask (Task::MoveToPosition); // remove any move tasks
|
||||
startTask (Task::MoveToPosition, TaskPri::MoveToPosition, nearestHostageNodeIndex, 0.0f, true);
|
||||
}
|
||||
}
|
||||
ignoreCollision (); // also don't consider being stuck
|
||||
}
|
||||
|
|
@ -5074,7 +5141,7 @@ bool Bot::hasHostage () {
|
|||
return false;
|
||||
}
|
||||
|
||||
for (auto hostage : m_hostages) {
|
||||
for (auto &hostage : m_hostages) {
|
||||
if (!game.isNullEntity (hostage)) {
|
||||
|
||||
// don't care about dead hostages
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ void Game::levelInitialize (edict_t *entities, int max) {
|
|||
else if (strcmp (classname, "func_vip_safetyzone") == 0 || strcmp (classname, "info_vip_safetyzone") == 0) {
|
||||
m_mapFlags |= MapFlags::Assassination; // assassination map
|
||||
}
|
||||
else if (strcmp (classname, "hostage_entity") == 0) {
|
||||
else if (strcmp (classname, "hostage_entity") == 0 || strcmp (classname, "monster_scientist") == 0) {
|
||||
m_mapFlags |= MapFlags::HostageRescue; // rescue map
|
||||
}
|
||||
else if (strcmp (classname, "func_bomb_target") == 0 || strcmp (classname, "info_bomb_target") == 0) {
|
||||
|
|
|
|||
|
|
@ -2751,6 +2751,7 @@ void BotGraph::addBasic () {
|
|||
autoCreateForEntity (NodeAddFlag::Goal, "func_bomb_target"); // bombspot zone
|
||||
autoCreateForEntity (NodeAddFlag::Goal, "info_bomb_target"); // bombspot zone (same as above)
|
||||
autoCreateForEntity (NodeAddFlag::Goal, "hostage_entity"); // hostage entities
|
||||
autoCreateForEntity (NodeAddFlag::Goal, "monster_scientist"); // hostage entities (same as above)
|
||||
autoCreateForEntity (NodeAddFlag::Goal, "func_vip_safetyzone"); // vip rescue (safety) zone
|
||||
autoCreateForEntity (NodeAddFlag::Goal, "func_escapezone"); // terrorist escape zone
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,9 +79,7 @@ int Bot::findBestGoal () {
|
|||
return findGoalPost (tactic, defensiveNodes, offensiveNodes);
|
||||
}
|
||||
else if (m_team == Team::CT && hasHostage ()) {
|
||||
tactic = 2;
|
||||
offensiveNodes = &graph.m_rescuePoints;
|
||||
|
||||
tactic = 4;
|
||||
return findGoalPost (tactic, defensiveNodes, offensiveNodes);
|
||||
}
|
||||
|
||||
|
|
@ -208,6 +206,31 @@ int Bot::findGoalPost (int tactic, IntArray *defensive, IntArray *offsensive) {
|
|||
postprocessGoals (graph.m_goalPoints, goalChoices);
|
||||
}
|
||||
}
|
||||
else if (tactic == 4 && !graph.m_rescuePoints.empty ()) // rescue goal
|
||||
{
|
||||
// force ct with hostage(s) to select closest rescue goal
|
||||
float minDist = kInfiniteDistance;
|
||||
int count = 0;
|
||||
|
||||
for (auto &point : graph.m_rescuePoints) {
|
||||
float distance = graph[point].origin.distanceSq (pev->origin);
|
||||
|
||||
if (distance < minDist) {
|
||||
goalChoices[count] = point;
|
||||
|
||||
if (++count > 3) {
|
||||
count = 0;
|
||||
}
|
||||
minDist = distance;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &choice : goalChoices) {
|
||||
if (choice == kInvalidNodeIndex) {
|
||||
choice = graph.m_rescuePoints.random ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!graph.exists (m_currentNodeIndex)) {
|
||||
m_currentNodeIndex = changePointIndex (findNearestNode ());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue