Fixed crash, added more cvars

This commit is contained in:
RGreenlees 2024-03-13 11:08:24 +00:00 committed by pierow
parent 3220533c44
commit b6ac4431ed
10 changed files with 144 additions and 196 deletions

View File

@ -2389,7 +2389,7 @@ dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, const dtPoly* fromPoly,
break; break;
} }
} }
if (!link) if (!link || fromPoly->vertCount == 0)
return DT_FAILURE | DT_INVALID_PARAM; return DT_FAILURE | DT_INVALID_PARAM;
// Handle off-mesh connections. // Handle off-mesh connections.
@ -2672,7 +2672,7 @@ dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, cons
const dtLink* link = &tile->links[i]; const dtLink* link = &tile->links[i];
// Find link which contains this edge. // Find link which contains this edge.
if ((int)link->edge != segMax) if ((int)link->edge != segMax || poly->vertCount == 0)
continue; continue;
// Get pointer to the next polygon. // Get pointer to the next polygon.
@ -3699,7 +3699,7 @@ dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* cen
const dtLink* link = &bestTile->links[i]; const dtLink* link = &bestTile->links[i];
dtPolyRef neighbourRef = link->ref; dtPolyRef neighbourRef = link->ref;
// Skip invalid neighbours and do not follow back to parent. // Skip invalid neighbours and do not follow back to parent.
if (!neighbourRef || neighbourRef == parentRef) if (!neighbourRef || neighbourRef == parentRef || bestPoly->vertCount == 0)
continue; continue;
// Expand to neighbour. // Expand to neighbour.

View File

@ -128,11 +128,16 @@ cvar_t avh_version = {kvVersion, "330", FCVAR_SERVER};
cvar_t avh_botsenabled = { kvBotsEnabled,"0", FCVAR_SERVER }; // Bots can be added to the server Y/N cvar_t avh_botsenabled = { kvBotsEnabled,"0", FCVAR_SERVER }; // Bots can be added to the server Y/N
cvar_t avh_botautomode = { kvBotAutoMode,"0", FCVAR_SERVER }; // Defines automated behaviour for adding/removing bots. 0 = manual (must add via console), 1 = automatic (auto-fills teams), 2 = balance only (only keeps teams even) cvar_t avh_botautomode = { kvBotAutoMode,"0", FCVAR_SERVER }; // Defines automated behaviour for adding/removing bots. 0 = manual (must add via console), 1 = automatic (auto-fills teams), 2 = balance only (only keeps teams even)
cvar_t avh_botminplayers = { kvBotMinPlayers,"0", FCVAR_SERVER }; // If bots are enabled and auto mode == 1 then it will maintain this player count by adding/removing as needed cvar_t avh_botminplayers = { kvBotMinPlayers,"0", FCVAR_SERVER }; // If bots are enabled and auto mode == 1 then it will maintain this player count by adding/removing as needed
cvar_t avh_botskill = { kvBotSkill,"0", FCVAR_SERVER }; // Sets the skill for the bots (0 = easiest, 3 = hardest) cvar_t avh_botskill = { kvBotSkill,"1", FCVAR_SERVER }; // Sets the skill for the bots (0 = easiest, 3 = hardest)
cvar_t avh_botusemapdefaults = { kvBotUseMapDefaults,"0", FCVAR_SERVER }; // If bot auto mode == 1 then the min players will be taken from the config cvar_t avh_botusemapdefaults = { kvBotUseMapDefaults,"0", FCVAR_SERVER }; // If bot auto mode == 1 then the min players will be taken from the config
cvar_t avh_botcommandermode = { kvBotCommanderMode,"0", FCVAR_SERVER }; // 0 = Bots never command, 1 = If nobody takes charge, 2 = Only if no humans on team cvar_t avh_botcommandermode = { kvBotCommanderMode,"0", FCVAR_SERVER }; // 0 = Bots never command, 1 = If nobody takes charge, 2 = Only if no humans on team
cvar_t avh_botdebugmode = { kvBotDebugMode,"0", FCVAR_SERVER }; // 0 = Regular play, 1 = Drone mode, 2 = Test Navigation mode cvar_t avh_botdebugmode = { kvBotDebugMode,"0", FCVAR_SERVER }; // 0 = Regular play, 1 = Drone mode, 2 = Test Navigation mode
cvar_t avh_botallowlerk = { kvBotAllowLerk,"1", FCVAR_SERVER }; // 0 = Bot will never evolve lerk, 1 = Bot will go lerk when appropriate
cvar_t avh_botallowfade = { kvBotAllowFade,"1", FCVAR_SERVER }; // 0 = Bot will never evolve fade, 1 = Bot will go fade when appropriate
cvar_t avh_botallowonos = { kvBotAllowOnos,"1", FCVAR_SERVER }; // 0 = Bot will never evolve onos, 1 = Bot will go onos when appropriate
cvar_t avh_botcommanderwait = { kvBotCommWait,"10", FCVAR_SERVER }; // If mp_botcommandermode == 1 then how long the bot will wait before taking command, to give a human a chance
cvar_t avh_botlerkcooldown = { kvBotLerkCooldown,"60", FCVAR_SERVER }; // If the team's lerk is killed, how long the bot will wait before going lerk again.
cvar_t avh_botmaxstucktime = { kvBotMaxStuckTime,"15", FCVAR_SERVER }; // If the team's lerk is killed, how long the bot will wait before going lerk again.
//playtest cvars //playtest cvars
cvar_t avh_fastjp = {kvfastjp, "0", FCVAR_SERVER}; cvar_t avh_fastjp = {kvfastjp, "0", FCVAR_SERVER};
@ -224,6 +229,12 @@ void GameDLLInit( void )
CVAR_REGISTER(&avh_botskill); CVAR_REGISTER(&avh_botskill);
CVAR_REGISTER(&avh_botcommandermode); CVAR_REGISTER(&avh_botcommandermode);
CVAR_REGISTER(&avh_botdebugmode); CVAR_REGISTER(&avh_botdebugmode);
CVAR_REGISTER(&avh_botallowlerk);
CVAR_REGISTER(&avh_botallowfade);
CVAR_REGISTER(&avh_botallowonos);
CVAR_REGISTER(&avh_botcommanderwait);
CVAR_REGISTER(&avh_botlerkcooldown);
CVAR_REGISTER(&avh_botmaxstucktime);
// Register AvH variables // Register AvH variables
CVAR_REGISTER (&avh_drawdamage); CVAR_REGISTER (&avh_drawdamage);

View File

@ -6,56 +6,52 @@
#include <unordered_map> #include <unordered_map>
float fCommanderWaitTime = 10.0f; BotFillTiming CurrentBotFillTiming = FILLTIMING_ALLHUMANS;
float fLerkCooldown = 60.0f;
float MaxStuckTime = 30.0f;
bool bLerkAllowed = true;
bool bFadeAllowed = true;
bool bOnosAllowed = true;
BotFillTiming CurrentBotFillTiming = FILLTIMING_MAPLOAD;
std::unordered_map<std::string, TeamSizeDefinitions> TeamSizeMap; std::unordered_map<std::string, TeamSizeDefinitions> TeamSizeMap;
std::unordered_map<std::string, bot_skill> BotSkillLevelsMap; bot_skill BotSkillLevels[4];
std::string CurrentSkillLevel;
std::string GlobalSkillLevel = "default";
AvHMessageID ChamberSequence[3] = { ALIEN_BUILD_DEFENSE_CHAMBER, ALIEN_BUILD_MOVEMENT_CHAMBER, ALIEN_BUILD_SENSORY_CHAMBER }; AvHMessageID ChamberSequence[3] = { ALIEN_BUILD_DEFENSE_CHAMBER, ALIEN_BUILD_MOVEMENT_CHAMBER, ALIEN_BUILD_SENSORY_CHAMBER };
char BotPrefix[32] = ""; char BotPrefix[32] = "";
extern cvar_t avh_botskill;
extern cvar_t avh_botallowlerk;
extern cvar_t avh_botallowfade;
extern cvar_t avh_botallowonos;
extern cvar_t avh_botcommanderwait;
extern cvar_t avh_botlerkcooldown;
extern cvar_t avh_botmaxstucktime;
float CONFIG_GetCommanderWaitTime() float CONFIG_GetCommanderWaitTime()
{ {
return fCommanderWaitTime; return avh_botcommanderwait.value;
} }
float CONFIG_GetLerkCooldown() float CONFIG_GetLerkCooldown()
{ {
return fLerkCooldown; return avh_botlerkcooldown.value;
} }
bool CONFIG_IsLerkAllowed() bool CONFIG_IsLerkAllowed()
{ {
return bLerkAllowed; return avh_botallowlerk.value > 0;
} }
bool CONFIG_IsFadeAllowed() bool CONFIG_IsFadeAllowed()
{ {
return bFadeAllowed; return avh_botallowfade.value > 0;
} }
bool CONFIG_IsOnosAllowed() bool CONFIG_IsOnosAllowed()
{ {
return bOnosAllowed; return avh_botallowonos.value > 0;
} }
float CONFIG_GetMaxStuckTime() float CONFIG_GetMaxStuckTime()
{ {
return MaxStuckTime; return avh_botmaxstucktime.value;
} }
string CONFIG_GetBotPrefix() string CONFIG_GetBotPrefix()
@ -100,52 +96,55 @@ AvHMessageID CONFIG_GetHiveTechAtIndex(const int Index)
return ChamberSequence[Index]; return ChamberSequence[Index];
} }
bot_skill CONFIG_GetBotSkillLevel(const char* SkillName) bot_skill CONFIG_GetBotSkillLevel()
{ {
std::string s = SkillName; int index = clampi((int)avh_botskill.value, 0, 3);
std::unordered_map<std::string, bot_skill>::const_iterator got = BotSkillLevelsMap.find(s);
if (got == BotSkillLevelsMap.end()) return BotSkillLevels[index];
{
return BotSkillLevelsMap["default"];
}
else
{
return got->second;
}
}
bool CONFIG_BotSkillLevelExists(const char* SkillName)
{
std::string s = SkillName;
std::unordered_map<std::string, bot_skill>::const_iterator got = BotSkillLevelsMap.find(s);
return (got != BotSkillLevelsMap.end());
}
bot_skill CONFIG_GetGlobalBotSkillLevel()
{
return BotSkillLevelsMap[GlobalSkillLevel.c_str()];
} }
void CONFIG_ParseConfigFile() void CONFIG_ParseConfigFile()
{ {
TeamSizeMap.clear();
TeamSizeMap["default"].TeamASize = 6;
TeamSizeMap["default"].TeamBSize = 6;
BotSkillLevelsMap.clear(); BotSkillLevels[0].marine_bot_reaction_time = 0.4f;
BotSkillLevels[0].marine_bot_aim_skill = 0.1f;
BotSkillLevels[0].marine_bot_motion_tracking_skill = 0.1f;
BotSkillLevels[0].marine_bot_view_speed = 0.5f;
BotSkillLevelsMap["default"].marine_bot_aim_skill = 0.3f; BotSkillLevels[0].alien_bot_reaction_time = 0.4f;
BotSkillLevelsMap["default"].marine_bot_motion_tracking_skill = 0.3f; BotSkillLevels[0].alien_bot_aim_skill = 0.2f;
BotSkillLevelsMap["default"].marine_bot_reaction_time = 0.3f; BotSkillLevels[0].alien_bot_motion_tracking_skill = 0.2f;
BotSkillLevelsMap["default"].marine_bot_view_speed = 1.0f; BotSkillLevels[0].alien_bot_view_speed = 0.75f;
BotSkillLevelsMap["default"].alien_bot_aim_skill = 0.5f;
BotSkillLevelsMap["default"].alien_bot_motion_tracking_skill = 0.5f;
BotSkillLevelsMap["default"].alien_bot_reaction_time = 0.3f;
BotSkillLevelsMap["default"].alien_bot_view_speed = 1.5f;
CurrentSkillLevel = "default"; BotSkillLevels[1].marine_bot_reaction_time = 0.2f;
BotSkillLevels[1].marine_bot_aim_skill = 0.5f;
BotSkillLevels[1].marine_bot_motion_tracking_skill = 0.4f;
BotSkillLevels[1].marine_bot_view_speed = 1.0f;
BotSkillLevels[1].alien_bot_reaction_time = 0.2f;
BotSkillLevels[1].alien_bot_aim_skill = 0.5f;
BotSkillLevels[1].alien_bot_motion_tracking_skill = 0.5f;
BotSkillLevels[1].alien_bot_view_speed = 1.3f;
BotSkillLevels[2].marine_bot_reaction_time = 0.2f;
BotSkillLevels[2].marine_bot_aim_skill = 0.6f;
BotSkillLevels[2].marine_bot_motion_tracking_skill = 0.6f;
BotSkillLevels[2].marine_bot_view_speed = 1.5f;
BotSkillLevels[2].alien_bot_reaction_time = 0.2f;
BotSkillLevels[2].alien_bot_aim_skill = 0.8f;
BotSkillLevels[2].alien_bot_motion_tracking_skill = 0.8f;
BotSkillLevels[2].alien_bot_view_speed = 1.5f;
BotSkillLevels[3].marine_bot_reaction_time = 0.1f;
BotSkillLevels[3].marine_bot_aim_skill = 1.0f;
BotSkillLevels[3].marine_bot_motion_tracking_skill = 1.0f;
BotSkillLevels[3].marine_bot_view_speed = 2.0f;
BotSkillLevels[3].alien_bot_reaction_time = 0.1f;
BotSkillLevels[3].alien_bot_aim_skill = 1.0f;
BotSkillLevels[3].alien_bot_motion_tracking_skill = 1.0f;
BotSkillLevels[3].alien_bot_view_speed = 2.0f;
string BotConfigFile = string(getModDirectory()) + "/nsbots.cfg"; string BotConfigFile = string(getModDirectory()) + "/nsbots.cfg";
@ -156,6 +155,8 @@ void CONFIG_ParseConfigFile()
if (cFile.is_open()) if (cFile.is_open())
{ {
std::string line; std::string line;
int CurrSkillIndex = 0;
while (getline(cFile, line)) while (getline(cFile, line))
{ {
line.erase(std::remove_if(line.begin(), line.end(), isspace), line.erase(std::remove_if(line.begin(), line.end(), isspace),
@ -204,45 +205,6 @@ void CONFIG_ParseConfigFile()
continue; continue;
} }
if (key.compare("CommanderWaitTime") == 0)
{
fCommanderWaitTime = (float)atoi(value.c_str());
fCommanderWaitTime = fmaxf(0.0f, fCommanderWaitTime);
continue;
}
if (key.compare("LerkCooldown") == 0)
{
fLerkCooldown = (float)atoi(value.c_str());
fLerkCooldown = fmaxf(0.0f, fLerkCooldown);
continue;
}
if (key.compare("AllowLerk") == 0)
{
bLerkAllowed = atoi(value.c_str()) > 0;
continue;
}
if (key.compare("AllowFade") == 0)
{
bFadeAllowed = atoi(value.c_str()) > 0;
continue;
}
if (key.compare("AllowOnos") == 0)
{
bOnosAllowed = atoi(value.c_str()) > 0;
continue;
}
if (key.compare("MaxStuckTime") == 0)
{
MaxStuckTime = (float)atoi(value.c_str());
MaxStuckTime = fmaxf(0.0f, MaxStuckTime);
continue;
}
if (key.compare("BotFillTiming") == 0) if (key.compare("BotFillTiming") == 0)
{ {
int FillSetting = atoi(value.c_str()); int FillSetting = atoi(value.c_str());
@ -251,27 +213,18 @@ void CONFIG_ParseConfigFile()
continue; continue;
} }
if (key.compare("BotSkillName") == 0) if (key.compare("BotSkillLevel") == 0)
{ {
BotSkillLevelsMap[value.c_str()].marine_bot_aim_skill = 0.5f; CurrSkillIndex = std::stoi(value.c_str());
BotSkillLevelsMap[value.c_str()].marine_bot_motion_tracking_skill = 0.5f; CurrSkillIndex = clampi(CurrSkillIndex, 0, 3);
BotSkillLevelsMap[value.c_str()].marine_bot_reaction_time = 0.2f;
BotSkillLevelsMap[value.c_str()].marine_bot_view_speed = 1.0f;
BotSkillLevelsMap[value.c_str()].alien_bot_aim_skill = 0.5f;
BotSkillLevelsMap[value.c_str()].alien_bot_motion_tracking_skill = 0.5f;
BotSkillLevelsMap[value.c_str()].alien_bot_reaction_time = 0.2f;
BotSkillLevelsMap[value.c_str()].alien_bot_view_speed = 1.0f;
CurrentSkillLevel = value;
continue; continue;
} }
if (key.compare("MarineReactionTime") == 0) if (key.compare("MarineReactionTime") == 0)
{ {
float NewValue = std::stof(value.c_str()); float NewValue = std::stof(value.c_str());
BotSkillLevelsMap[CurrentSkillLevel.c_str()].marine_bot_reaction_time = clampf(NewValue, 0.0f, 1.0f); BotSkillLevels[CurrSkillIndex].marine_bot_reaction_time = clampf(NewValue, 0.0f, 1.0f);
continue; continue;
} }
@ -281,7 +234,7 @@ void CONFIG_ParseConfigFile()
float NewValue = std::stof(value.c_str()); float NewValue = std::stof(value.c_str());
BotSkillLevelsMap[CurrentSkillLevel.c_str()].alien_bot_reaction_time = clampf(NewValue, 0.0f, 1.0f); BotSkillLevels[CurrSkillIndex].alien_bot_reaction_time = clampf(NewValue, 0.0f, 1.0f);
continue; continue;
} }
@ -291,7 +244,7 @@ void CONFIG_ParseConfigFile()
float NewValue = std::stof(value.c_str()); float NewValue = std::stof(value.c_str());
BotSkillLevelsMap[CurrentSkillLevel.c_str()].marine_bot_aim_skill = clampf(NewValue, 0.0f, 1.0f); BotSkillLevels[CurrSkillIndex].marine_bot_aim_skill = clampf(NewValue, 0.0f, 1.0f);
continue; continue;
} }
@ -301,7 +254,7 @@ void CONFIG_ParseConfigFile()
float NewValue = std::stof(value.c_str()); float NewValue = std::stof(value.c_str());
BotSkillLevelsMap[CurrentSkillLevel.c_str()].alien_bot_aim_skill = clampf(NewValue, 0.0f, 1.0f); BotSkillLevels[CurrSkillIndex].alien_bot_aim_skill = clampf(NewValue, 0.0f, 1.0f);
continue; continue;
} }
@ -311,7 +264,7 @@ void CONFIG_ParseConfigFile()
float NewValue = std::stof(value.c_str()); float NewValue = std::stof(value.c_str());
BotSkillLevelsMap[CurrentSkillLevel.c_str()].marine_bot_motion_tracking_skill = clampf(NewValue, 0.0f, 1.0f); BotSkillLevels[CurrSkillIndex].marine_bot_motion_tracking_skill = clampf(NewValue, 0.0f, 1.0f);
continue; continue;
} }
@ -321,7 +274,7 @@ void CONFIG_ParseConfigFile()
float NewValue = std::stof(value.c_str()); float NewValue = std::stof(value.c_str());
BotSkillLevelsMap[CurrentSkillLevel.c_str()].alien_bot_motion_tracking_skill = clampf(NewValue, 0.0f, 1.0f); BotSkillLevels[CurrSkillIndex].alien_bot_motion_tracking_skill = clampf(NewValue, 0.0f, 1.0f);
continue; continue;
} }
@ -331,7 +284,7 @@ void CONFIG_ParseConfigFile()
float NewValue = std::stof(value.c_str()); float NewValue = std::stof(value.c_str());
BotSkillLevelsMap[CurrentSkillLevel.c_str()].marine_bot_view_speed = clampf(NewValue, 0.0f, 5.0f); BotSkillLevels[CurrSkillIndex].marine_bot_view_speed = clampf(NewValue, 0.0f, 5.0f);
continue; continue;
} }
@ -341,14 +294,7 @@ void CONFIG_ParseConfigFile()
float NewValue = std::stof(value.c_str()); float NewValue = std::stof(value.c_str());
BotSkillLevelsMap[CurrentSkillLevel.c_str()].alien_bot_view_speed = clampf(NewValue, 0.0f, 5.0f); BotSkillLevels[CurrSkillIndex].alien_bot_view_speed = clampf(NewValue, 0.0f, 5.0f);
continue;
}
if (key.compare("DefaultSkillLevel") == 0)
{
GlobalSkillLevel = value;
continue; continue;
} }
@ -483,11 +429,6 @@ void CONFIG_ParseConfigFile()
} }
} }
} }
if (!CONFIG_BotSkillLevelExists(GlobalSkillLevel.c_str()))
{
GlobalSkillLevel = "default";
}
} }
BotFillTiming CONFIG_GetBotFillTiming() BotFillTiming CONFIG_GetBotFillTiming()

View File

@ -54,13 +54,7 @@ int CONFIG_GetTeamBSizeForMap(const char* MapName);
// Returns the configured hive tech at that index (chamber build sequence) // Returns the configured hive tech at that index (chamber build sequence)
AvHMessageID CONFIG_GetHiveTechAtIndex(const int Index); AvHMessageID CONFIG_GetHiveTechAtIndex(const int Index);
bot_skill CONFIG_GetBotSkillLevel(const char* SkillName); bot_skill CONFIG_GetBotSkillLevel();
bool CONFIG_BotSkillLevelExists(const char* SkillName);
bot_skill CONFIG_GetGlobalBotSkillLevel();
void CONFIG_SetGlobalBotSkillLevel(const char* NewSkillLevel);
BotFillTiming CONFIG_GetBotFillTiming(); BotFillTiming CONFIG_GetBotFillTiming();

View File

@ -14,6 +14,7 @@
#include "AvHAITactical.h" #include "AvHAITactical.h"
#include "AvHAITask.h" #include "AvHAITask.h"
#include "AvHAIWeaponHelper.h" #include "AvHAIWeaponHelper.h"
#include "AvHAIConfig.h"
#include "../AvHWeldable.h" #include "../AvHWeldable.h"
#include "../AvHServerUtil.h" #include "../AvHServerUtil.h"
@ -5452,7 +5453,7 @@ void UpdateBotStuck(AvHAIPlayer* pBot)
if (pBot->BotNavInfo.StuckInfo.TotalStuckTime > 0.25f) if (pBot->BotNavInfo.StuckInfo.TotalStuckTime > 0.25f)
{ {
if (pBot->BotNavInfo.StuckInfo.TotalStuckTime > 15.0f) if (pBot->BotNavInfo.StuckInfo.TotalStuckTime > CONFIG_GetMaxStuckTime())
{ {
BotSuicide(pBot); BotSuicide(pBot);
return; return;

View File

@ -1902,30 +1902,37 @@ void UpdateAIPlayerCORole(AvHAIPlayer* pBot)
return; return;
} }
int NumLerks = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER3, pBot->Edict); if (CONFIG_IsLerkAllowed())
int NumHarassers = AIMGR_GetNumAIPlayersWithRoleOnTeam(BotTeam, BOT_ROLE_HARASS, pBot);
if (NumLerks + NumHarassers == 0)
{ {
float LastSeenTime;
edict_t* PreviousLerk = AITAC_GetLastSeenLerkForTeam(BotTeam, LastSeenTime);
// We only go lerk if the last lerk we had in the match was either us, or we've not had another lerk in 30 seconds int NumLerks = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER3, pBot->Edict);
// This prevents a situation where a human is lerk, gets killed, and a bot immediately takes over. int NumHarassers = AIMGR_GetNumAIPlayersWithRoleOnTeam(BotTeam, BOT_ROLE_HARASS, pBot);
// This is undesireable as it pressures the human to pick something else to avoid too many lerks
if (LastSeenTime > 30.0f || PreviousLerk == pBot->Edict) if (NumLerks + NumHarassers == 0)
{ {
SetNewAIPlayerRole(pBot, BOT_ROLE_HARASS); float LastSeenTime;
return; edict_t* PreviousLerk = AITAC_GetLastSeenLerkForTeam(BotTeam, LastSeenTime);
// We only go lerk if the last lerk we had in the match was either us, or we've not had another lerk in 30 seconds
// This prevents a situation where a human is lerk, gets killed, and a bot immediately takes over.
// This is undesireable as it pressures the human to pick something else to avoid too many lerks
if (FNullEnt(PreviousLerk) || (gpGlobals->time - LastSeenTime > CONFIG_GetLerkCooldown()) || PreviousLerk == pBot->Edict)
{
SetNewAIPlayerRole(pBot, BOT_ROLE_HARASS);
return;
}
} }
} }
int MaxOnos = (int)(ceilf((float)(AIMGR_GetNumPlayersOnTeam(BotTeam) - 2)) * 0.3f); if (CONFIG_IsOnosAllowed())
if (AIMGR_GetNumAIPlayersWithRoleOnTeam(BotTeam, BOT_ROLE_BOMBARDIER, pBot) < MaxOnos)
{ {
SetNewAIPlayerRole(pBot, BOT_ROLE_BOMBARDIER); int MaxOnos = (int)(ceilf((float)(AIMGR_GetNumPlayersOnTeam(BotTeam) - 2)) * 0.3f);
return;
if (AIMGR_GetNumAIPlayersWithRoleOnTeam(BotTeam, BOT_ROLE_BOMBARDIER, pBot) < MaxOnos)
{
SetNewAIPlayerRole(pBot, BOT_ROLE_BOMBARDIER);
return;
}
} }
} }
@ -4329,7 +4336,7 @@ AvHMessageID GetNextAIPlayerCOAlienUpgrade(AvHAIPlayer* pBot)
// If we're going assault then make sure we've saved up enough for fade // If we're going assault then make sure we've saved up enough for fade
if (pBot->BotRole == BOT_ROLE_ASSAULT) if (pBot->BotRole == BOT_ROLE_ASSAULT)
{ {
if (NumPointsAvailable <= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FOUR)) if (CONFIG_IsFadeAllowed() && NumPointsAvailable <= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FOUR))
{ {
return MESSAGE_NULL; return MESSAGE_NULL;
} }
@ -5609,7 +5616,7 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
if (Task->TaskType == TASK_EVOLVE) { return; } if (Task->TaskType == TASK_EVOLVE) { return; }
if (!IsPlayerOnos(pBot->Edict) && pBot->Player->GetResources() >= BALANCE_VAR(kOnosCost)) if (CONFIG_IsOnosAllowed() && !IsPlayerOnos(pBot->Edict) && pBot->Player->GetResources() >= BALANCE_VAR(kOnosCost))
{ {
int NumOnos = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER5, pBot->Edict); int NumOnos = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER5, pBot->Edict);
@ -5625,7 +5632,7 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
} }
} }
if (!IsPlayerFade(pBot->Edict) && pBot->Player->GetResources() >= BALANCE_VAR(kFadeCost)) if (CONFIG_IsFadeAllowed() && !IsPlayerFade(pBot->Edict) && pBot->Player->GetResources() >= BALANCE_VAR(kFadeCost))
{ {
int NumFades = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER4, pBot->Edict); int NumFades = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER4, pBot->Edict);
int NumOnos = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER5, pBot->Edict); int NumOnos = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER5, pBot->Edict);

View File

@ -23,6 +23,7 @@ extern cvar_t avh_botminplayers;
extern cvar_t avh_botusemapdefaults; extern cvar_t avh_botusemapdefaults;
extern cvar_t avh_botcommandermode; extern cvar_t avh_botcommandermode;
extern cvar_t avh_botdebugmode; extern cvar_t avh_botdebugmode;
extern cvar_t avh_botskill;
float LastAIPlayerCountUpdate = 0.0f; float LastAIPlayerCountUpdate = 0.0f;
@ -518,7 +519,7 @@ void AIMGR_AddAIPlayerToTeam(int Team)
NewAIPlayer.WantsAndNeedsTask.TaskType = TASK_NONE; NewAIPlayer.WantsAndNeedsTask.TaskType = TASK_NONE;
NewAIPlayer.CommanderTask.TaskType = TASK_NONE; NewAIPlayer.CommanderTask.TaskType = TASK_NONE;
const bot_skill BotSkillSettings = CONFIG_GetGlobalBotSkillLevel(); const bot_skill BotSkillSettings = CONFIG_GetBotSkillLevel();
memcpy(&NewAIPlayer.BotSkillSettings, &BotSkillSettings, sizeof(bot_skill)); memcpy(&NewAIPlayer.BotSkillSettings, &BotSkillSettings, sizeof(bot_skill));
@ -595,6 +596,8 @@ void AIMGR_UpdateAIPlayers()
static float LastThinkTime = 0.0f; static float LastThinkTime = 0.0f;
static int CurrentBotSkill = 1;
CurrTime = gpGlobals->time; CurrTime = gpGlobals->time;
if (CurrTime < PrevTime) if (CurrTime < PrevTime)
@ -610,6 +613,14 @@ void AIMGR_UpdateAIPlayers()
float FrameDelta = CurrTime - PrevTime; float FrameDelta = CurrTime - PrevTime;
float ThinkDelta = CurrTime - LastThinkTime; float ThinkDelta = CurrTime - LastThinkTime;
int cvarBotSkill = clampi((int)avh_botskill.value, 0, 3);
bool bSkillChanged = (cvarBotSkill != CurrentBotSkill);
if (bSkillChanged)
{
CurrentBotSkill = cvarBotSkill;
}
for (auto BotIt = ActiveAIPlayers.begin(); BotIt != ActiveAIPlayers.end();) for (auto BotIt = ActiveAIPlayers.begin(); BotIt != ActiveAIPlayers.end();)
@ -623,6 +634,12 @@ void AIMGR_UpdateAIPlayers()
AvHAIPlayer* bot = &(*BotIt); AvHAIPlayer* bot = &(*BotIt);
if (bSkillChanged)
{
const bot_skill NewSkillSettings = CONFIG_GetBotSkillLevel();
memcpy(&bot->BotSkillSettings, &NewSkillSettings, sizeof(bot_skill));
}
BotUpdateViewRotation(bot, FrameDelta); BotUpdateViewRotation(bot, FrameDelta);
if (IS_DEDICATED_SERVER() || ThinkDelta >= BOT_MIN_FRAME_TIME) if (IS_DEDICATED_SERVER() || ThinkDelta >= BOT_MIN_FRAME_TIME)
@ -643,37 +660,6 @@ void AIMGR_UpdateAIPlayers()
} }
} }
if (!vIsZero(DebugVector1) && !vIsZero(DebugVector2))
{
UTIL_DrawLine(INDEXENT(1), DebugVector1, DebugVector2);
edict_t* PlayerEdict = INDEXENT(1);
bool bOnGround = (INDEXENT(1)->v.flags & FL_ONGROUND) || IsPlayerOnLadder(PlayerEdict);
bool Result = false;
if (!IsPlayerOnLadder(PlayerEdict))
{
if (IsPlayerClimbingWall(PlayerEdict)) { Result = true; }
if (bOnGround)
{
if (!UTIL_PointIsDirectlyReachable(GetPlayerBottomOfCollisionHull(PlayerEdict), DebugVector1) && !UTIL_PointIsDirectlyReachable(GetPlayerBottomOfCollisionHull(PlayerEdict), DebugVector2)) { Result = true; }
}
}
if (Result)
{
UTIL_DrawHUDText(PlayerEdict, 0, 0.1f, 0.1f, 255, 255, 255, "TRUE");
}
else
{
UTIL_DrawHUDText(PlayerEdict, 0, 0.1f, 0.1f, 255, 255, 255, "FALSE");
}
}
if (bHasRoundStarted) if (bHasRoundStarted)
{ {
AvHTeamNumber TeamANumber = GetGameRules()->GetTeamANumber(); AvHTeamNumber TeamANumber = GetGameRules()->GetTeamANumber();
@ -958,7 +944,7 @@ void AIMGR_RoundStarted()
bHasRoundStarted = true; bHasRoundStarted = true;
AvHTeamNumber TeamANumber = GetGameRules()->GetTeamANumber(); AvHTeamNumber TeamANumber = GetGameRules()->GetTeamANumber();
AvHTeamNumber TeamBNumber = GetGameRules()->GetTeamANumber(); AvHTeamNumber TeamBNumber = GetGameRules()->GetTeamBNumber();
// If our team has no humans on it, then we can take command right away. Otherwise, wait the allotted grace period to allow the human to take command // If our team has no humans on it, then we can take command right away. Otherwise, wait the allotted grace period to allow the human to take command

View File

@ -5,7 +5,7 @@
#include "AvHAIPlayer.h" #include "AvHAIPlayer.h"
// Max rate bot can run its logic, default is 1/60th second. WARNING: Increasing the rate past 100hz causes bots to move and turn slowly due to GoldSrc limits! // Max rate bot can run its logic, default is 1/60th second. WARNING: Increasing the rate past 100hz causes bots to move and turn slowly due to GoldSrc limits!
static const double BOT_MIN_FRAME_TIME = (1.0 / 60.0); static const double BOT_MIN_FRAME_TIME = 0;// (1.0 / 60.0);
// Once the first human player has joined the game, how long to wait before adding bots // Once the first human player has joined the game, how long to wait before adding bots
static const float AI_GRACE_PERIOD = 5.0f; static const float AI_GRACE_PERIOD = 5.0f;
// Max time to wait before spawning players if none connect (e.g. empty dedicated server) // Max time to wait before spawning players if none connect (e.g. empty dedicated server)

View File

@ -4195,11 +4195,13 @@ bool AITAC_IsAlienHarasserNeeded(AvHAIPlayer* pBot)
{ {
if (IsPlayerLerk(pBot->Edict)) { return true; } if (IsPlayerLerk(pBot->Edict)) { return true; }
if (!CONFIG_IsLerkAllowed()) { return false; }
if (pBot->Player->GetResources() < BALANCE_VAR(kLerkCost)) { return false; } if (pBot->Player->GetResources() < BALANCE_VAR(kLerkCost)) { return false; }
AvHTeamNumber BotTeam = pBot->Player->GetTeam(); AvHTeamNumber BotTeam = pBot->Player->GetTeam();
if (pBot->BotRole == BOT_ROLE_ASSAULT) if (pBot->BotRole == BOT_ROLE_ASSAULT && pBot->Player->GetResources() > (BALANCE_VAR(kFadeCost) * 0.8f))
{ {
int NumFades = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER4, pBot->Edict); int NumFades = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER4, pBot->Edict);
int NumOnos = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER5, pBot->Edict); int NumOnos = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER5, pBot->Edict);
@ -4223,7 +4225,7 @@ bool AITAC_IsAlienHarasserNeeded(AvHAIPlayer* pBot)
// We only go lerk if the last lerk we had in the match was either us, or we've not had another lerk in 60 seconds // We only go lerk if the last lerk we had in the match was either us, or we've not had another lerk in 60 seconds
// It avoids aliens spending all their resources on evolving lerks if they keep dying // It avoids aliens spending all their resources on evolving lerks if they keep dying
// It also means that if a human was playing lerk and died, a bot doesn't immediately take over that role, and lets the human try again if they want // It also means that if a human was playing lerk and died, a bot doesn't immediately take over that role, and lets the human try again if they want
return (LastSeenTime > 60.0f || PreviousLerk == pBot->Edict); return (FNullEnt(PreviousLerk) || (gpGlobals->time - LastSeenTime > CONFIG_GetLerkCooldown()) || PreviousLerk == pBot->Edict);
} }
return false; return false;

View File

@ -149,6 +149,12 @@ float ns_cvar_float(const cvar_t *cvar);
#define kvBotAutoMode "mp_botautomode" #define kvBotAutoMode "mp_botautomode"
#define kvBotCommanderMode "mp_botcommandermode" #define kvBotCommanderMode "mp_botcommandermode"
#define kvBotDebugMode "mp_botdebugmode" #define kvBotDebugMode "mp_botdebugmode"
#define kvBotAllowLerk "mp_botallowlerk"
#define kvBotAllowFade "mp_botallowfade"
#define kvBotAllowOnos "mp_botallowonos"
#define kvBotCommWait "mp_botcommanderwait"
#define kvBotLerkCooldown "mp_botlerkcooldown"
#define kvBotMaxStuckTime "mp_botmaxstucktime"
#define kvEasterEggChance "mp_eastereggchance" #define kvEasterEggChance "mp_eastereggchance"
#define kvUplink "mp_uplink" #define kvUplink "mp_uplink"