Added custom monsters and custom items support

This commit is contained in:
Hedgehog Fog 2020-12-03 14:14:22 +02:00
commit d5107daad4
7 changed files with 82 additions and 6 deletions

View file

@ -401,3 +401,16 @@ yb_display_welcome_text "1"
// //
yb_enable_query_hook "0" 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"

View file

@ -55,6 +55,12 @@ public:
// check if entitiy is a player // check if entitiy is a player
bool isPlayer (edict_t *ent); 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 // check if entity is a vip
bool isPlayerVIP (edict_t *ent); bool isPlayerVIP (edict_t *ent);

View file

@ -1164,6 +1164,8 @@ extern ConVar cv_whose_your_daddy;
extern ConVar cv_chatter_path; extern ConVar cv_chatter_path;
extern ConVar cv_quota; extern ConVar cv_quota;
extern ConVar cv_difficulty; extern ConVar cv_difficulty;
extern ConVar cv_attack_monsters;
extern ConVar cv_pickup_custom_items;
// execute client command helper // execute client command helper
template <typename ...Args> void Bot::issueCommand (const char *fmt, Args &&...args) { template <typename ...Args> void Bot::issueCommand (const char *fmt, Args &&...args) {

View file

@ -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_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_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 // game console variables
ConVar mp_c4timer ("mp_c4timer", nullptr, Var::GameRef); ConVar mp_c4timer ("mp_c4timer", nullptr, Var::GameRef);
ConVar mp_flashlight ("mp_flashlight", nullptr, Var::GameRef); ConVar mp_flashlight ("mp_flashlight", nullptr, Var::GameRef);
@ -573,6 +576,10 @@ void Bot::updatePickups () {
allowPickup = true; allowPickup = true;
pickupType = Pickup::PlantedC4; 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... // if the bot found something it can pickup...
@ -1690,7 +1697,7 @@ void Bot::overrideConditions () {
m_moveToGoal = false; // don't move to goal m_moveToGoal = false; // don't move to goal
m_navTimeset = game.time (); m_navTimeset = game.time ();
if (util.isPlayer (m_enemy)) { if (util.isPlayer (m_enemy) || (cv_attack_monsters.bool_ () && util.isMonster (m_enemy))) {
attackMovement (); attackMovement ();
} }
} }
@ -1704,7 +1711,7 @@ void Bot::overrideConditions () {
} }
// special handling, if we have a knife in our hands // 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 (); float length = (pev->origin - m_enemy->v.origin).length2d ();
// do waypoint movement if enemy is not reachable with a knife // 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; m_lastDamageType = bits;
updatePracticeValue (damage); updatePracticeValue (damage);
if (util.isPlayer (inflictor)) { if (util.isPlayer (inflictor) || (cv_attack_monsters.bool_ () && util.isMonster (inflictor))) {
if (cv_tkpunish.bool_ () && game.getTeam (inflictor) == m_team && !util.isFakeClient (inflictor)) { if (!util.isMonster (inflictor) && cv_tkpunish.bool_ () && game.getTeam (inflictor) == m_team && !util.isFakeClient (inflictor)) {
// alright, die you teamkiller!!! // alright, die you teamkiller!!!
m_actualReactionTime = 0.0f; m_actualReactionTime = 0.0f;
m_seeEnemyTime = game.time (); m_seeEnemyTime = game.time ();

View file

@ -234,6 +234,30 @@ bool Bot::lookupEnemies () {
// ignore shielded enemies, while we have real one // ignore shielded enemies, while we have real one
edict_t *shieldEnemy = nullptr; 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... // search the world for players...
for (const auto &client : util.getClients ()) { for (const auto &client : util.getClients ()) {
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team == m_team || client.ent == ent () || !client.ent) { 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); bots.setCanPause (true);
m_aimFlags |= AimFlags::Enemy; m_aimFlags |= AimFlags::Enemy;

View file

@ -1652,7 +1652,7 @@ void BotManager::updateIntrestingEntities () {
auto classname = e->v.classname.chars (); auto classname = e->v.classname.chars ();
// search for grenades, weaponboxes, weapons, items and armoury entities // 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); m_intrestingEntities.push (e);
} }
@ -1671,6 +1671,10 @@ void BotManager::updateIntrestingEntities () {
m_intrestingEntities.push (e); m_intrestingEntities.push (e);
} }
if (cv_attack_monsters.bool_ () && util.isMonster (e)) {
m_intrestingEntities.push (e);
}
// continue iteration // continue iteration
return EntitySearchResult::Continue; return EntitySearchResult::Continue;
}); });

View file

@ -205,6 +205,26 @@ bool BotSupport::isPlayer (edict_t *ent) {
return false; 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) { bool BotSupport::isPlayerVIP (edict_t *ent) {
if (!game.mapIs (MapFlags::Assassination)) { if (!game.mapIs (MapFlags::Assassination)) {
return false; return false;