fix: bots at difficulty 0 unable to do anything useful
fix: lang configs unable to parse last translated line (fixes #340) fix: last enemy isn't cleared instantly with dead entity anymore fix: bot weakness in pistol rounds analyzer: improved optimization of useless nodes linkage: make inability to call gamedll player( non-fatal linkage: fixed bot boot on WON engines pre 2000 builds (support for beta 6.5 restored) cvars: added suupport to revert all cvars to defaults via 'yb cvars defaults' cvars: added cv_preferred_personality to select bot default personality refactor: use single function to send hud messages over the bot code bot: added random original podbot welcome message to preserve origins of this bot conf: shuffle bot names and chatter items on conflig load conf: simplified a bit chatter.cfg syntax (old syntax still works build: added support for building with CMake (thanks @Velaron) refactor: rall the memory hooks moved into their one cpp file
This commit is contained in:
parent
01046f7c9a
commit
bf91ef2831
35 changed files with 1256 additions and 734 deletions
|
|
@ -8,7 +8,7 @@
|
|||
#include <yapb.h>
|
||||
|
||||
ConVar cv_autovacate ("autovacate", "1", "Kick bots to automatically make room for human players.");
|
||||
ConVar cv_autovacate_keep_slots ("autovacate_keep_slots", "1", "How many slots autovacate feature should keep for human players", true, 1.0f, 8.0f);
|
||||
ConVar cv_autovacate_keep_slots ("autovacate_keep_slots", "1", "How many slots autovacate feature should keep for human players.", true, 1.0f, 8.0f);
|
||||
ConVar cv_kick_after_player_connect ("kick_after_player_connect", "1", "Kick the bot immediately when a human player joins the server (yb_autovacate must be enabled).");
|
||||
|
||||
ConVar cv_quota ("quota", "9", "Specifies the number bots to be added to the game.", true, 0.0f, static_cast <float> (kGameMaxPlayers));
|
||||
|
|
@ -37,6 +37,7 @@ ConVar cv_save_bots_names ("save_bots_names", "1", "Allows to save bot names upo
|
|||
|
||||
ConVar cv_botskin_t ("botskin_t", "0", "Specifies the bots wanted skin for Terrorist team.", true, 0.0f, 5.0f);
|
||||
ConVar cv_botskin_ct ("botskin_ct", "0", "Specifies the bots wanted skin for CT team.", true, 0.0f, 5.0f);
|
||||
ConVar cv_preferred_personality ("preferred_personality", "none", "Sets the default personality when creating bots with quota management.\nAllowed values: 'none', 'normal', 'careful', 'rusher'.\nIf 'none' is specified personality chosen randomly.", false);
|
||||
|
||||
ConVar cv_ping_base_min ("ping_base_min", "7", "Lower bound for base bot ping shown in scoreboard upon creation.", true, 0.0f, 100.0f);
|
||||
ConVar cv_ping_base_max ("ping_base_max", "34", "Upper bound for base bot ping shown in scoreboard upon creation.", true, 0.0f, 100.0f);
|
||||
|
|
@ -149,7 +150,15 @@ void BotManager::execGameEntity (edict_t *ent) {
|
|||
MUTIL_CallGameEntity (PLID, "player", &ent->v);
|
||||
return;
|
||||
}
|
||||
ents.callPlayerFunction (ent);
|
||||
|
||||
if (!entlink.callPlayerFunction (ent)) {
|
||||
for (const auto &bot : m_bots) {
|
||||
if (bot->ent () == ent) {
|
||||
bot->kick ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BotManager::forEach (ForEachBot handler) {
|
||||
|
|
@ -182,25 +191,42 @@ BotCreateResult BotManager::create (StringRef name, int difficulty, int personal
|
|||
ctrl.msg ("Desired team is stacked. Unable to proceed with bot creation.");
|
||||
return BotCreateResult::TeamStacked;
|
||||
}
|
||||
if (difficulty < 0 || difficulty > 4) {
|
||||
if (difficulty < Difficulty::Noob || difficulty > Difficulty::Expert) {
|
||||
difficulty = cv_difficulty.int_ ();
|
||||
|
||||
if (difficulty < 0 || difficulty > 4) {
|
||||
if (difficulty < Difficulty::Noob || difficulty > Difficulty::Expert) {
|
||||
difficulty = rg.get (3, 4);
|
||||
cv_difficulty.set (difficulty);
|
||||
}
|
||||
}
|
||||
|
||||
// try to set proffered personality
|
||||
static HashMap <String, Personality> personalityMap {
|
||||
{"normal", Personality::Normal },
|
||||
{"careful", Personality::Careful },
|
||||
{"rusher", Personality::Rusher },
|
||||
};
|
||||
|
||||
// set personality if requested
|
||||
if (personality < Personality::Normal || personality > Personality::Careful) {
|
||||
if (rg.chance (50)) {
|
||||
personality = Personality::Normal;
|
||||
|
||||
// assign preferred if we're forced with cvar
|
||||
if (personalityMap.exists (cv_preferred_personality.str ())) {
|
||||
personality = personalityMap[cv_preferred_personality.str ()];
|
||||
}
|
||||
|
||||
// do a holy random
|
||||
else {
|
||||
if (rg.chance (50)) {
|
||||
personality = Personality::Rusher;
|
||||
personality = Personality::Normal;
|
||||
}
|
||||
else {
|
||||
personality = Personality::Careful;
|
||||
if (rg.chance (50)) {
|
||||
personality = Personality::Rusher;
|
||||
}
|
||||
else {
|
||||
personality = Personality::Careful;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -685,8 +711,9 @@ bool BotManager::kickRandom (bool decQuota, Team fromTeam) {
|
|||
|
||||
// first try to kick the bot that is currently dead
|
||||
for (const auto &bot : m_bots) {
|
||||
if (!bot->m_isAlive && belongsTeam (bot.get ())) // is this slot used?
|
||||
{
|
||||
|
||||
// is this slot used?
|
||||
if (!bot->m_isAlive && belongsTeam (bot.get ())) {
|
||||
updateQuota ();
|
||||
bot->kick ();
|
||||
|
||||
|
|
@ -721,8 +748,9 @@ bool BotManager::kickRandom (bool decQuota, Team fromTeam) {
|
|||
|
||||
// worst case, just kick some random bot
|
||||
for (const auto &bot : m_bots) {
|
||||
if (belongsTeam (bot.get ())) // is this slot used?
|
||||
{
|
||||
|
||||
// is this slot used?
|
||||
if (belongsTeam (bot.get ())) {
|
||||
updateQuota ();
|
||||
bot->kick ();
|
||||
|
||||
|
|
@ -824,7 +852,8 @@ void BotManager::listBots () {
|
|||
};
|
||||
|
||||
for (const auto &bot : bots) {
|
||||
ctrl.msg ("[%-3.1d]\t%-19.16s\t%-10.12s\t%-3.4s\t%-3.1d\t%-3.1d\t%-3.4s\t%-3.0f secs", bot->index (), bot->pev->netname.chars (), bot->m_personality == Personality::Rusher ? "rusher" : bot->m_personality == Personality::Normal ? "normal" : "careful", botTeam (bot->m_team), bot->m_difficulty, static_cast <int> (bot->pev->frags), bot->m_isAlive ? "yes" : "no", cv_rotate_bots.bool_ () ? bot->m_stayTime - game.time () : 0.0f);
|
||||
auto timelimitStr = cv_rotate_bots.bool_ () ? strings.format ("%-3.0f secs", bot->m_stayTime - game.time ()) : "unlimited";
|
||||
ctrl.msg ("[%-2.1d]\t%-22.16s\t%-10.12s\t%-3.4s\t%-3.1d\t%-3.1d\t%-3.4s\t%s", bot->index (), bot->pev->netname.chars (), bot->m_personality == Personality::Rusher ? "rusher" : bot->m_personality == Personality::Normal ? "normal" : "careful", botTeam (bot->m_team), bot->m_difficulty, static_cast <int> (bot->pev->frags), bot->m_isAlive ? "yes" : "no", timelimitStr);
|
||||
}
|
||||
ctrl.msg ("%d bots", m_bots.length ());
|
||||
}
|
||||
|
|
@ -1007,7 +1036,9 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int skin) {
|
|||
|
||||
// set all info buffer keys for this bot
|
||||
auto buffer = engfuncs.pfnGetInfoKeyBuffer (bot);
|
||||
|
||||
engfuncs.pfnSetClientKeyValue (clientIndex, buffer, "_vgui_menus", "0");
|
||||
engfuncs.pfnSetClientKeyValue (clientIndex, buffer, "_ah", "0");
|
||||
|
||||
if (!game.is (GameFlags::Legacy)) {
|
||||
if (cv_show_latency.int_ () == 1) {
|
||||
|
|
@ -1260,7 +1291,16 @@ void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
|
|||
|
||||
// notice nearby to victim teammates, that attacker is near
|
||||
for (const auto ¬ify : bots) {
|
||||
if (notify->m_seeEnemyTime + 2.0f < game.time () && notify->m_isAlive && notify->m_team == victimTeam && game.isNullEntity (notify->m_enemy) && killerTeam != victimTeam && util.isVisible (killer->v.origin, notify->ent ())) {
|
||||
if (notify->m_difficulty >= Difficulty::Hard
|
||||
&& killerTeam != victimTeam
|
||||
&& notify->m_seeEnemyTime + 2.0f < game.time ()
|
||||
&& notify->m_isAlive
|
||||
&& notify->m_team == victimTeam
|
||||
&& game.isNullEntity (notify->m_enemy)
|
||||
&& game.isNullEntity (notify->m_lastEnemy)
|
||||
&& util.isVisible (killer->v.origin, notify->ent ())) {
|
||||
|
||||
// make bot look at last e nemy position
|
||||
notify->m_actualReactionTime = 0.0f;
|
||||
notify->m_seeEnemyTime = game.time ();
|
||||
notify->m_enemy = killer;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue