From d5107daad4fe8df7159993e2d39973201b956392 Mon Sep 17 00:00:00 2001 From: Hedgehog Fog Date: Thu, 3 Dec 2020 14:14:22 +0200 Subject: [PATCH] Added custom monsters and custom items support --- cfg/addons/yapb/conf/yapb.cfg | 13 +++++++++++++ inc/support.h | 6 ++++++ inc/yapb.h | 2 ++ src/botlib.cpp | 15 +++++++++++---- src/combat.cpp | 26 +++++++++++++++++++++++++- src/manager.cpp | 6 +++++- src/support.cpp | 20 ++++++++++++++++++++ 7 files changed, 82 insertions(+), 6 deletions(-) diff --git a/cfg/addons/yapb/conf/yapb.cfg b/cfg/addons/yapb/conf/yapb.cfg index bda9f7f..760c7c6 100644 --- a/cfg/addons/yapb/conf/yapb.cfg +++ b/cfg/addons/yapb/conf/yapb.cfg @@ -401,3 +401,16 @@ yb_display_welcome_text "1" // yb_enable_query_hook "0" +// +// Allows or disallows bots to take attack monsters. +// --- +// Default: "0", Min: "0", Max: "1" +// +yb_attack_monsters "0" + +// +// Allows or disallows bots to pickup custom items. +// --- +// Default: "0", Min: "0", Max: "1" +// +yb_pickup_custom_items "0" \ No newline at end of file diff --git a/inc/support.h b/inc/support.h index 1a73f7d..587702d 100644 --- a/inc/support.h +++ b/inc/support.h @@ -55,6 +55,12 @@ public: // check if entitiy is a player bool isPlayer (edict_t *ent); + // check if entitiy is a monster + bool isMonster (edict_t *ent); + + // check if entitiy is a item + bool isItem (edict_t *ent); + // check if entity is a vip bool isPlayerVIP (edict_t *ent); diff --git a/inc/yapb.h b/inc/yapb.h index 5089c4f..cfcc0d2 100644 --- a/inc/yapb.h +++ b/inc/yapb.h @@ -1164,6 +1164,8 @@ extern ConVar cv_whose_your_daddy; extern ConVar cv_chatter_path; extern ConVar cv_quota; extern ConVar cv_difficulty; +extern ConVar cv_attack_monsters; +extern ConVar cv_pickup_custom_items; // execute client command helper template void Bot::issueCommand (const char *fmt, Args &&...args) { diff --git a/src/botlib.cpp b/src/botlib.cpp index 2838f89..b00d88f 100644 --- a/src/botlib.cpp +++ b/src/botlib.cpp @@ -28,6 +28,9 @@ ConVar cv_destroy_breakables_around ("yb_destroy_breakables_around", "1", "Allow ConVar cv_chatter_path ("yb_chatter_path", "sound/radio/bot", "Specifies the paths for the bot chatter sound files.", false); ConVar cv_restricted_weapons ("yb_restricted_weapons", "", "Specifies semicolon separated list of weapons that are not allowed to buy / pickup.", false); +ConVar cv_attack_monsters ("yb_attack_monsters", "0", "Allows or disallows bots to take attack monsters."); +ConVar cv_pickup_custom_items ("yb_pickup_custom_items", "0", "Allows or disallows bots to pickup custom items."); + // game console variables ConVar mp_c4timer ("mp_c4timer", nullptr, Var::GameRef); ConVar mp_flashlight ("mp_flashlight", nullptr, Var::GameRef); @@ -573,6 +576,10 @@ void Bot::updatePickups () { allowPickup = true; pickupType = Pickup::PlantedC4; } + else if (cv_pickup_custom_items.bool_ () && util.isItem(ent) && strncmp ("item_thighpack", classname, 14) != 0) { + allowPickup = true; + pickupType = Pickup::None; + } } // if the bot found something it can pickup... @@ -1690,7 +1697,7 @@ void Bot::overrideConditions () { m_moveToGoal = false; // don't move to goal m_navTimeset = game.time (); - if (util.isPlayer (m_enemy)) { + if (util.isPlayer (m_enemy) || (cv_attack_monsters.bool_ () && util.isMonster (m_enemy))) { attackMovement (); } } @@ -1704,7 +1711,7 @@ void Bot::overrideConditions () { } // special handling, if we have a knife in our hands - if ((bots.getRoundStartTime () + 6.0f > game.time () || !hasAnyWeapons ()) && usesKnife () && util.isPlayer (m_enemy)) { + if ((bots.getRoundStartTime () + 6.0f > game.time () || !hasAnyWeapons ()) && usesKnife () && (util.isPlayer (m_enemy) || (cv_attack_monsters.bool_ () && util.isMonster (m_enemy)))) { float length = (pev->origin - m_enemy->v.origin).length2d (); // do waypoint movement if enemy is not reachable with a knife @@ -5096,8 +5103,8 @@ void Bot::takeDamage (edict_t *inflictor, int damage, int armor, int bits) { m_lastDamageType = bits; updatePracticeValue (damage); - if (util.isPlayer (inflictor)) { - if (cv_tkpunish.bool_ () && game.getTeam (inflictor) == m_team && !util.isFakeClient (inflictor)) { + if (util.isPlayer (inflictor) || (cv_attack_monsters.bool_ () && util.isMonster (inflictor))) { + if (!util.isMonster (inflictor) && cv_tkpunish.bool_ () && game.getTeam (inflictor) == m_team && !util.isFakeClient (inflictor)) { // alright, die you teamkiller!!! m_actualReactionTime = 0.0f; m_seeEnemyTime = game.time (); diff --git a/src/combat.cpp b/src/combat.cpp index ebc05d9..3718855 100644 --- a/src/combat.cpp +++ b/src/combat.cpp @@ -234,6 +234,30 @@ bool Bot::lookupEnemies () { // ignore shielded enemies, while we have real one edict_t *shieldEnemy = nullptr; + if (cv_attack_monsters. bool_()) { + // search the world for monsters... + for (const auto &intresting : bots.getIntrestingEntities ()) { + if (!util.isMonster(intresting)) { + continue; + } + + // check the engine PVS + if (!isEnemyInFrustum (intresting) || !game.checkVisibility (intresting, set)) { + continue; + } + + // see if bot can see the monster... + if (seesEnemy (intresting)) { + float distance = (intresting->v.origin - pev->origin).lengthSq (); + + if (distance * 0.7f < nearestDistance) { + nearestDistance = distance; + newEnemy = intresting; + } + } + } + } + // search the world for players... for (const auto &client : util.getClients ()) { if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team == m_team || client.ent == ent () || !client.ent) { @@ -277,7 +301,7 @@ bool Bot::lookupEnemies () { } } - if (util.isPlayer (newEnemy)) { + if (util.isPlayer (newEnemy) || (cv_attack_monsters.bool_ () && util.isMonster (newEnemy))) { bots.setCanPause (true); m_aimFlags |= AimFlags::Enemy; diff --git a/src/manager.cpp b/src/manager.cpp index bdc0b6a..1d83946 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -1652,7 +1652,7 @@ void BotManager::updateIntrestingEntities () { auto classname = e->v.classname.chars (); // search for grenades, weaponboxes, weapons, items and armoury entities - if (strncmp ("weaponbox", classname, 9) == 0 || strncmp ("grenade", classname, 7) == 0 || strncmp ("item", classname, 4) == 0 || strncmp ("armoury", classname, 7) == 0) { + if (strncmp ("weaponbox", classname, 9) == 0 || strncmp ("grenade", classname, 7) == 0 || util.isItem (e) || strncmp ("armoury", classname, 7) == 0) { m_intrestingEntities.push (e); } @@ -1671,6 +1671,10 @@ void BotManager::updateIntrestingEntities () { m_intrestingEntities.push (e); } + if (cv_attack_monsters.bool_ () && util.isMonster (e)) { + m_intrestingEntities.push (e); + } + // continue iteration return EntitySearchResult::Continue; }); diff --git a/src/support.cpp b/src/support.cpp index 0fb35a6..3584d7a 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -205,6 +205,26 @@ bool BotSupport::isPlayer (edict_t *ent) { return false; } +bool BotSupport::isMonster (edict_t *ent) { + if (game.isNullEntity (ent)) { + return false; + } + + if (~ent->v.flags & FL_MONSTER) { + return false; + } + + if (strncmp ("hostage", ent->v.classname.chars(), 7) == 0) { + return false; + } + + return true; +} + +bool BotSupport::isItem (edict_t *ent) { + return !!(strstr (ent->v.classname.chars(), "item")); +} + bool BotSupport::isPlayerVIP (edict_t *ent) { if (!game.mapIs (MapFlags::Assassination)) { return false;