mirror of
https://github.com/ENSL/NS.git
synced 2025-02-16 17:11:15 +00:00
Lerk improvements and bot names
* Improved lerk movement when it is not flying (i.e. being cautious) * Users can now optionally add botnames.txt to the NS folder to define custom bot names
This commit is contained in:
parent
e322e52619
commit
27ed51035c
6 changed files with 130 additions and 51 deletions
|
@ -5,6 +5,8 @@
|
|||
#include "AvHServerUtil.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
|
||||
BotFillTiming CurrentBotFillTiming = FILLTIMING_ALLHUMANS;
|
||||
|
||||
|
@ -16,6 +18,43 @@ bot_skill BotSkillLevels[4];
|
|||
|
||||
AvHMessageID ChamberSequence[3] = { ALIEN_BUILD_DEFENSE_CHAMBER, ALIEN_BUILD_MOVEMENT_CHAMBER, ALIEN_BUILD_SENSORY_CHAMBER };
|
||||
|
||||
string DefaultBotNames[MAX_PLAYERS] = { "MrRobot",
|
||||
"Wall-E",
|
||||
"BeepBoop",
|
||||
"Robotnik",
|
||||
"JonnyAutomaton",
|
||||
"Burninator",
|
||||
"SteelDeath",
|
||||
"Meatbag",
|
||||
"Undertaker",
|
||||
"Botini",
|
||||
"Robottle",
|
||||
"Rusty",
|
||||
"HeavyMetal",
|
||||
"Combot",
|
||||
"BagelLover",
|
||||
"Screwdriver",
|
||||
"LoveBug",
|
||||
"iSmash",
|
||||
"Chippy",
|
||||
"Baymax",
|
||||
"BoomerBot",
|
||||
"Jarvis",
|
||||
"Marvin",
|
||||
"Data",
|
||||
"Scrappy",
|
||||
"Mortis",
|
||||
"TerrorHertz",
|
||||
"Omicron",
|
||||
"Herbie",
|
||||
"Robogeddon",
|
||||
"Velociripper",
|
||||
"TerminalFerocity"
|
||||
};
|
||||
|
||||
vector<string> BotNames;
|
||||
int CurrentNameIndex = 0;
|
||||
|
||||
char BotPrefix[32] = "";
|
||||
|
||||
extern cvar_t avh_botskill;
|
||||
|
@ -110,6 +149,69 @@ bot_skill CONFIG_GetBotSkillLevel()
|
|||
return BotSkillLevels[index];
|
||||
}
|
||||
|
||||
void CONFIG_PopulateBotNames()
|
||||
{
|
||||
BotNames.clear();
|
||||
|
||||
string BotConfigFile = string(getModDirectory()) + "/botnames.txt";
|
||||
|
||||
const char* filename = BotConfigFile.c_str();
|
||||
|
||||
std::ifstream cFile(filename);
|
||||
if (cFile.is_open())
|
||||
{
|
||||
std::string line;
|
||||
while (getline(cFile, line))
|
||||
{
|
||||
if (line[0] == '/' || line.empty())
|
||||
continue;
|
||||
|
||||
BotNames.push_back(line);
|
||||
}
|
||||
}
|
||||
|
||||
if (BotNames.size() > 2)
|
||||
{
|
||||
auto rng = std::default_random_engine{};
|
||||
std::shuffle(begin(BotNames), end(BotNames), rng);
|
||||
}
|
||||
|
||||
vector<string> DefaultNames;
|
||||
|
||||
// Ensure we have 32 names for all bots
|
||||
for (int i = BotNames.size(); i < MAX_PLAYERS; i++)
|
||||
{
|
||||
DefaultNames.push_back(DefaultBotNames[i]);
|
||||
}
|
||||
|
||||
if (DefaultNames.size() > 2)
|
||||
{
|
||||
auto rng = std::default_random_engine{};
|
||||
std::shuffle(begin(DefaultNames), end(DefaultNames), rng);
|
||||
}
|
||||
|
||||
BotNames.insert(BotNames.end(), DefaultNames.begin(), DefaultNames.end());
|
||||
|
||||
CurrentNameIndex = 0;
|
||||
|
||||
}
|
||||
|
||||
string CONFIG_GetNextBotName()
|
||||
{
|
||||
if (BotNames.size() == 0) { return "Bot"; }
|
||||
|
||||
string Result = BotNames[CurrentNameIndex];
|
||||
|
||||
CurrentNameIndex++;
|
||||
|
||||
if (CurrentNameIndex >= BotNames.size())
|
||||
{
|
||||
CurrentNameIndex = 0;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void CONFIG_ParseConfigFile()
|
||||
{
|
||||
|
||||
|
|
|
@ -62,4 +62,8 @@ BotFillTiming CONFIG_GetBotFillTiming();
|
|||
|
||||
void CONFIG_RegenerateIniFile();
|
||||
|
||||
void CONFIG_PopulateBotNames();
|
||||
|
||||
string CONFIG_GetNextBotName();
|
||||
|
||||
#endif
|
|
@ -6213,7 +6213,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
|||
{
|
||||
if (bIsFlyingProfile)
|
||||
{
|
||||
BotFollowFlightPath(pBot);
|
||||
BotFollowFlightPath(pBot, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -6351,7 +6351,7 @@ void SkipAheadInFlightPath(AvHAIPlayer* pBot)
|
|||
}
|
||||
}
|
||||
|
||||
void BotFollowFlightPath(AvHAIPlayer* pBot)
|
||||
void BotFollowFlightPath(AvHAIPlayer* pBot, bool bAllowSkip)
|
||||
{
|
||||
if (pBot->BotNavInfo.CurrentPath.size() == 0 || pBot->BotNavInfo.CurrentPathPoint >= pBot->BotNavInfo.CurrentPath.size())
|
||||
{
|
||||
|
@ -6392,7 +6392,7 @@ void BotFollowFlightPath(AvHAIPlayer* pBot)
|
|||
return;
|
||||
}
|
||||
|
||||
if (CurrentPathPoint->area != SAMPLE_POLYAREA_CROUCH && next(CurrentPathPoint) != BotNavInfo->CurrentPath.end() && next(CurrentPathPoint)->area != SAMPLE_POLYAREA_CROUCH)
|
||||
if (bAllowSkip && CurrentPathPoint->area != SAMPLE_POLYAREA_CROUCH && next(CurrentPathPoint) != BotNavInfo->CurrentPath.end() && next(CurrentPathPoint)->area != SAMPLE_POLYAREA_CROUCH)
|
||||
{
|
||||
SkipAheadInFlightPath(pBot);
|
||||
CurrentPathPoint = (BotNavInfo->CurrentPath.begin() + BotNavInfo->CurrentPathPoint);
|
||||
|
@ -6400,7 +6400,7 @@ void BotFollowFlightPath(AvHAIPlayer* pBot)
|
|||
|
||||
ClosestPointToPath = vClosestPointOnLine(CurrentPathPoint->FromLocation, CurrentPathPoint->Location, pEdict->v.origin);
|
||||
|
||||
if (vDist3DSq(pBot->Edict->v.origin, ClosestPointToPath) > sqrf(GetPlayerRadius(pBot->Edict) * 3.0f))
|
||||
if (bAllowSkip && vDist3DSq(pBot->Edict->v.origin, ClosestPointToPath) > sqrf(GetPlayerRadius(pBot->Edict) * 3.0f))
|
||||
{
|
||||
ClearBotPath(pBot);
|
||||
return;
|
||||
|
@ -6561,7 +6561,7 @@ void BotFollowSwimPath(AvHAIPlayer* pBot)
|
|||
// We're at the surface, now tackle the path the usual way
|
||||
if (pBot->BotNavInfo.NavProfile.bFlyingProfile)
|
||||
{
|
||||
BotFollowFlightPath(pBot);
|
||||
BotFollowFlightPath(pBot, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -6633,6 +6633,15 @@ void BotFollowPath(AvHAIPlayer* pBot)
|
|||
}
|
||||
}
|
||||
|
||||
if (IsPlayerLerk(pBot->Edict))
|
||||
{
|
||||
if (CurrentNode.flag != SAMPLE_POLYFLAGS_WALK && CurrentNode.flag != SAMPLE_POLYFLAGS_LIFT)
|
||||
{
|
||||
BotFollowFlightPath(pBot, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsBotOffPath(pBot))
|
||||
{
|
||||
MoveToWithoutNav(pBot, CurrentNode.Location);
|
||||
|
|
|
@ -332,7 +332,7 @@ void UpdateBotStuck(AvHAIPlayer* pBot);
|
|||
|
||||
// Used by the MoveTo command, handles the bot's movement and inputs to follow a path it has calculated for itself
|
||||
void BotFollowPath(AvHAIPlayer* pBot);
|
||||
void BotFollowFlightPath(AvHAIPlayer* pBot);
|
||||
void BotFollowFlightPath(AvHAIPlayer* pBot, bool bAllowSkip);
|
||||
void BotFollowSwimPath(AvHAIPlayer* pBot);
|
||||
|
||||
void SkipAheadInFlightPath(AvHAIPlayer* pBot);
|
||||
|
|
|
@ -4598,7 +4598,7 @@ AvHMessageID GetNextAIPlayerCOAlienUpgrade(AvHAIPlayer* pBot)
|
|||
// As a bombardier, we can still go fade if we can't afford Onos yet, so calculate our points savings accordingly
|
||||
if (pBot->BotRole == BOT_ROLE_BOMBARDIER)
|
||||
{
|
||||
if (NumPointsAvailable <= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FIVE))
|
||||
if (CONFIG_IsOnosAllowed() && NumPointsAvailable <= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FIVE))
|
||||
{
|
||||
return MESSAGE_NULL;
|
||||
}
|
||||
|
@ -5039,7 +5039,7 @@ void AIPlayerSetPrimaryCOAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
if (pBot->BotRole == BOT_ROLE_ASSAULT)
|
||||
{
|
||||
if (!IsPlayerFade(pBot->Edict) && pBot->ExperiencePointsAvailable >= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FOUR))
|
||||
if (CONFIG_IsFadeAllowed() && !IsPlayerFade(pBot->Edict) && pBot->ExperiencePointsAvailable >= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FOUR))
|
||||
{
|
||||
if (Task->TaskType != TASK_EVOLVE)
|
||||
{
|
||||
|
@ -5060,11 +5060,11 @@ void AIPlayerSetPrimaryCOAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
{
|
||||
AvHMessageID DesiredEvolution = MESSAGE_NULL;
|
||||
|
||||
if (pBot->ExperiencePointsAvailable >= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FIVE))
|
||||
if (CONFIG_IsOnosAllowed() && pBot->ExperiencePointsAvailable >= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FIVE))
|
||||
{
|
||||
DesiredEvolution = ALIEN_LIFEFORM_FIVE;
|
||||
}
|
||||
else if (pBot->ExperiencePointsAvailable >= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FOUR))
|
||||
else if (CONFIG_IsFadeAllowed() && pBot->ExperiencePointsAvailable >= GetGameRules()->GetCostForMessageID(ALIEN_LIFEFORM_FOUR))
|
||||
{
|
||||
DesiredEvolution = ALIEN_LIFEFORM_FOUR;
|
||||
}
|
||||
|
@ -5587,8 +5587,6 @@ void AIPlayerReceiveMoveOrder(AvHAIPlayer* pBot, Vector Destination)
|
|||
|
||||
void BotStopCommanderMode(AvHAIPlayer* pBot)
|
||||
{
|
||||
// Thanks EterniumDev (Alien) for logic to allow commander AI to leave the chair and build structures when needed
|
||||
|
||||
if (IsPlayerCommander(pBot->Edict))
|
||||
{
|
||||
pBot->Player->SetUser3(AVH_USER3_MARINE_PLAYER);
|
||||
|
|
|
@ -51,40 +51,6 @@ float CountdownStartedTime = 0.0f;
|
|||
|
||||
bool bBotsEnabled = false;
|
||||
|
||||
string BotNames[MAX_PLAYERS] = { "MrRobot",
|
||||
"Wall-E",
|
||||
"BeepBoop",
|
||||
"Robotnik",
|
||||
"JonnyAutomaton",
|
||||
"Burninator",
|
||||
"SteelDeath",
|
||||
"Meatbag",
|
||||
"Undertaker",
|
||||
"Botini",
|
||||
"Robottle",
|
||||
"Rusty",
|
||||
"HeavyMetal",
|
||||
"Combot",
|
||||
"BagelLover",
|
||||
"Screwdriver",
|
||||
"LoveBug",
|
||||
"iSmash",
|
||||
"Chippy",
|
||||
"Baymax",
|
||||
"BoomerBot",
|
||||
"Jarvis",
|
||||
"Marvin",
|
||||
"Data",
|
||||
"Scrappy",
|
||||
"Mortis",
|
||||
"TerrorHertz",
|
||||
"Omicron",
|
||||
"Herbie",
|
||||
"Robogeddon",
|
||||
"Velociripper",
|
||||
"TerminalFerocity"
|
||||
};
|
||||
|
||||
AvHAICommanderMode AIMGR_GetCommanderMode()
|
||||
{
|
||||
if (avh_botcommandermode.value == 1)
|
||||
|
@ -442,9 +408,8 @@ void AIMGR_AddAIPlayerToTeam(int Team)
|
|||
BotNameIndex = RANDOM_LONG(0, 31);
|
||||
}
|
||||
|
||||
// Retrieve the current bot name and then cycle the index so the names are always unique
|
||||
// Slap a [BOT] tag too so players know they're not human
|
||||
string NewName = CONFIG_GetBotPrefix() + BotNames[BotNameIndex];
|
||||
// Retrieve the next configured bot name from the list
|
||||
string NewName = CONFIG_GetBotPrefix() + CONFIG_GetNextBotName();
|
||||
|
||||
BotEnt = (*g_engfuncs.pfnCreateFakeClient)(NewName.c_str());
|
||||
|
||||
|
@ -1059,6 +1024,9 @@ void AIMGR_NewMap()
|
|||
bHasRoundStarted = false;
|
||||
|
||||
bPlayerSpawned = false;
|
||||
|
||||
CONFIG_ParseConfigFile();
|
||||
CONFIG_PopulateBotNames();
|
||||
}
|
||||
|
||||
bool AIMGR_IsNavmeshLoaded()
|
||||
|
@ -1081,8 +1049,6 @@ void AIMGR_LoadNavigationData()
|
|||
// Don't reload the nav mesh if it's already loaded
|
||||
if (NavmeshLoaded()) { return; }
|
||||
|
||||
CONFIG_ParseConfigFile();
|
||||
|
||||
const char* theCStrLevelName = STRING(gpGlobals->mapname);
|
||||
|
||||
if (!loadNavigationData(theCStrLevelName))
|
||||
|
|
Loading…
Reference in a new issue