diff --git a/Core/Services/BotNameService.cs b/Core/Services/BotNameService.cs index 8e118135..fb8e1a86 100644 --- a/Core/Services/BotNameService.cs +++ b/Core/Services/BotNameService.cs @@ -1,12 +1,46 @@ -using Core.Annotations; +using Core.Annotations; using Core.Models.Eft.Common.Tables; using Core.Models.Spt.Bots; +using Core.Helpers; +using Core.Models.Enums; +using Core.Models.Spt.Config; +using Core.Servers; +using ILogger = Core.Models.Utils.ILogger; +using Core.Utils; namespace Core.Services; [Injectable(InjectionType.Singleton)] public class BotNameService { + private readonly ILogger _logger; + private readonly BotHelper _botHelper; + private readonly RandomUtil _randomUtil; + private readonly LocalisationService _localisationService; + private readonly DatabaseService _databaseService; + private readonly ConfigServer _configServer; + private readonly BotConfig _botConfig; + + private readonly HashSet _usedNameCache; + + public BotNameService( + ILogger logger, + BotHelper botHelper, + RandomUtil randomUtil, + LocalisationService localisationService, + DatabaseService databaseService, + ConfigServer configServer) + { + _logger = logger; + _botHelper = botHelper; + _randomUtil = randomUtil; + _localisationService = localisationService; + _databaseService = databaseService; + _configServer = configServer; + + _botConfig = _configServer.GetConfig(ConfigTypes.BOT); + } + /// /// Clear out any entries in Name Set /// @@ -22,7 +56,6 @@ public class BotNameService /// /// role of bot e.g. assault /// Lowercase roles to always make unique - /// OPTIONAL: profile session id /// Nickname for bot public string GenerateUniqueBotNickname( BotType botJsonTemplate, @@ -30,7 +63,68 @@ public class BotNameService string botRole, List uniqueRoles = null) { - throw new NotImplementedException(); + var isPmc = botGenerationDetails.IsPmc; + + // Never show for players + var showTypeInNickname = !botGenerationDetails.IsPlayerScav.GetValueOrDefault(false) && _botConfig.ShowTypeInNickname; + var roleShouldBeUnique = uniqueRoles?.Contains(botRole.ToLower()); + + var isUnique = true; + var attempts = 0; + while (attempts <= 5) + { + // Get bot name with leading/trailing whitespace removed + var name = (isPmc.GetValueOrDefault(false)) // Explicit handling of PMCs, all other bots will get "first_name last_name" + ? _botHelper.GetPmcNicknameOfMaxLength(_botConfig.BotNameLengthLimit, botGenerationDetails.Side) + : $"{ _randomUtil.GetArrayValue(botJsonTemplate.FirstNames)} {_randomUtil.GetArrayValue(botJsonTemplate.LastNames)}"; + + name = name.Trim(); + + // Config is set to add role to end of bot name + if (showTypeInNickname) + { + name += $" { botRole}"; + } + + // Replace pmc bot names with player name + prefix + if (botGenerationDetails.IsPmc.GetValueOrDefault(false) && botGenerationDetails.AllPmcsHaveSameNameAsPlayer.GetValueOrDefault(false)) + { + var prefix = _localisationService.GetRandomTextThatMatchesPartialKey("pmc-name_prefix_"); + name = $"{prefix} { name}"; + } + + // Is this a role that must be unique + if (roleShouldBeUnique.GetValueOrDefault(false)) + { + // Check name in cache + isUnique = _usedNameCache.Contains(name); + if (!isUnique) + { + // Not unique + if (attempts >= 5) + { + // 5 attempts to generate a name, pool probably isn't big enough + var genericName = $"{ botGenerationDetails.Side} { _randomUtil.GetInt(100000, 999999)}"; + _logger.Debug($"Failed to find unique name for: { botRole} ${ botGenerationDetails.Side} after 5 attempts, using: ${ genericName}"); + + return genericName; + } + + attempts++; + + // Try again + continue; + } + } + + // Add bot name to cache to prevent being used again + _usedNameCache.Add(name); + + return name; + } + + // Should never reach here + return $"BOT {botRole} {botGenerationDetails.BotDifficulty}"; } /// @@ -39,15 +133,23 @@ public class BotNameService /// Bot to update public void AddRandomPmcNameToBotMainProfileNicknameProperty(BotBase bot) { - throw new NotImplementedException(); + // Simulate bot looking like a player scav with the PMC name in brackets. + // E.g. "ScavName (PMC Name)" + bot.Info.MainProfileNickname = GetRandomPmcName(); } /// /// Choose a random PMC name from bear or usec bot jsons /// /// PMC name as string - protected string GetRandomPMCName() + protected string GetRandomPmcName() { - throw new NotImplementedException(); + var bots = _databaseService.GetBots().Types; + + var pmcNames = new List(); + pmcNames.AddRange(bots["usec"].FirstNames); + pmcNames.AddRange(bots["bear"].FirstNames); + + return _randomUtil.GetArrayValue(pmcNames); } }