diff --git a/Libraries/Core/Core.csproj b/Libraries/Core/Core.csproj index b3ff2b83..f23d1684 100644 --- a/Libraries/Core/Core.csproj +++ b/Libraries/Core/Core.csproj @@ -7,10 +7,6 @@ Library - - - - diff --git a/Libraries/Core/Generators/BotWeaponGenerator.cs b/Libraries/Core/Generators/BotWeaponGenerator.cs index 7a625bda..7746a9dd 100644 --- a/Libraries/Core/Generators/BotWeaponGenerator.cs +++ b/Libraries/Core/Generators/BotWeaponGenerator.cs @@ -33,7 +33,7 @@ public class BotWeaponGenerator( IEnumerable inventoryMagGenComponents ) { - protected List _inventoryMagGenComponents = MagGenSetUp(inventoryMagGenComponents); + protected IEnumerable _inventoryMagGenComponents = MagGenSetUp(inventoryMagGenComponents); protected BotConfig _botConfig = _configServer.GetConfig(); protected PmcConfig _pmcConfig = _configServer.GetConfig(); protected RepairConfig _repairConfig = _configServer.GetConfig(); @@ -42,13 +42,8 @@ public class BotWeaponGenerator( private static List MagGenSetUp(IEnumerable components) { var inventoryMagGens = components.ToList(); - inventoryMagGens.ToList() - .Sort( - (a, b) => - a.GetPriority() - - b.GetPriority() - ); - return inventoryMagGens.ToList(); + inventoryMagGens.Sort((a, b) => a.GetPriority() - b.GetPriority()); + return inventoryMagGens; } /// @@ -398,7 +393,7 @@ public class BotWeaponGenerator( return; } - + var isInternalMag = magTemplate.Properties.ReloadMagType == "InternalMagazine"; var ammoTemplate = _itemHelper.GetItem(generatedWeaponResult.ChosenAmmoTemplate).Value; if (ammoTemplate is null) { @@ -722,7 +717,6 @@ public class BotWeaponGenerator( /// Weapon items list to amend /// Magazine item details we're adding cartridges to /// Cartridge to put into the magazine - /// How many cartridges should go into the magazine /// Magazines db template protected void AddOrUpdateMagazinesChildWithAmmo(List weaponWithMods, Item magazine, string chosenAmmoTpl, TemplateItem magazineTemplate) { @@ -736,8 +730,7 @@ public class BotWeaponGenerator( } // Create array with just magazine - List magazineWithCartridges = new(); - magazineWithCartridges.AddRange(magazine); + List magazineWithCartridges = [magazine]; // Add full cartridge child items to above array _itemHelper.FillMagazineWithCartridge(magazineWithCartridges, magazineTemplate, chosenAmmoTpl, 1); diff --git a/Libraries/Core/Helpers/BotGeneratorHelper.cs b/Libraries/Core/Helpers/BotGeneratorHelper.cs index 410bfc86..2da6c971 100644 --- a/Libraries/Core/Helpers/BotGeneratorHelper.cs +++ b/Libraries/Core/Helpers/BotGeneratorHelper.cs @@ -530,13 +530,17 @@ public class BotGeneratorHelper( foreach (var slotGrid in value?.Properties?.Grids ?? []) { // Grid is empty, skip or item size is bigger than grid - if (slotGrid.Props?.CellsH == 0 || slotGrid.Props?.CellsV == 0 || itemSize[0] * itemSize[1] > slotGrid.Props?.CellsV * slotGrid.Props?.CellsH) + if (slotGrid.Props?.CellsH == 0 || + slotGrid.Props?.CellsV == 0 || + itemSize[0] * itemSize[1] > slotGrid.Props?.CellsV * slotGrid.Props?.CellsH) + { continue; + } // Can't put item type in grid, skip all grids as we're assuming they have the same rules if (!ItemAllowedInContainer(slotGrid, rootItemTplId)) { - // Multiple containers, maybe next one allows item, only break out of loop for this containers grids + // Multiple containers, maybe next one allows item, only break out of loop for the containers grids break; } @@ -548,44 +552,22 @@ public class BotGeneratorHelper( // Get root items in container we can iterate over to find out what space is free var containerItemsToCheck = existingContainerItems.Where(x => x.SlotId == slotGrid.Name); - var itemsToRemove = new List(); - var itemsToAdd = new List(); - foreach (var item in containerItemsToCheck) - { - // Check item in contain for children, store for later insertion into `containerItemsToCheck` - // (used later when figuring out how much space weapon takes up) - var itemWithChildItems = _itemHelper.FindAndReturnChildrenAsItems(inventory.Items, item.Id); - if (itemWithChildItems.Count <= 1) continue; + var containerItemsWithChildren = GetContainerItemsWithChildren(containerItemsToCheck, inventory.Items); - - // Store replaced item + new Child items to add later as we can't modify a collecting while looking over it - itemsToRemove.Add(item); - itemsToAdd.AddRange(itemsToAdd); - } - - // Remove the base items flagged above - foreach (var item in itemsToRemove) - { - existingContainerItems.Remove(item); - } - - // Add item back with its child items - existingContainerItems.AddRange(itemsToAdd); - - // Get rid of items free/used spots in current grid if (slotGrid.Props is not null) { + // Get rid of an items free/used spots in current grid var slotGridMap = _inventoryHelper.GetContainerMap( slotGrid.Props.CellsH.GetValueOrDefault(), slotGrid.Props.CellsV.GetValueOrDefault(), - existingContainerItems, + containerItemsWithChildren, container.Id ); // Try to fit item into grid var findSlotResult = _containerHelper.FindSlotForItem(slotGridMap, itemSize[0], itemSize[1]); - // Open slot found, add item to inventory + // Free slot found, add item if (findSlotResult.Success ?? false) { var parentItem = itemWithChildren.FirstOrDefault((i) => i.Id == rootItemId); @@ -633,6 +615,28 @@ public class BotGeneratorHelper( return ItemAddedResult.NO_SPACE; } + /// + /// Take a list of items and check if they need children + add them + /// + /// + /// + /// + protected List GetContainerItemsWithChildren(IEnumerable containerItems, List inventoryItems) + { + var result = new List(); + foreach (var item in containerItems) + { + // Check item in container for children, store for later insertion into `containerItemsToCheck` + // (used later when figuring out how much space weapon takes up) + var itemWithChildItems = _itemHelper.FindAndReturnChildrenAsItems(inventoryItems, item.Id); + + // Item had children, replace existing data with item + its children + result.AddRange(itemWithChildItems); + } + + return result; + } + /// /// Is the provided item allowed inside a container /// diff --git a/Libraries/Core/Helpers/ProfileHelper.cs b/Libraries/Core/Helpers/ProfileHelper.cs index e507e2b4..47b5a085 100644 --- a/Libraries/Core/Helpers/ProfileHelper.cs +++ b/Libraries/Core/Helpers/ProfileHelper.cs @@ -510,7 +510,7 @@ public class ProfileHelper( /// True if account is developer public bool IsDeveloperAccount(string sessionID) { - return GetFullProfile(sessionID)?.ProfileInfo?.Edition?.ToLower().StartsWith("spt developer") == false; + return GetFullProfile(sessionID)?.ProfileInfo?.Edition?.ToLower().StartsWith("spt developer") ?? false; } /// diff --git a/Libraries/Core/Services/CreateProfileService.cs b/Libraries/Core/Services/CreateProfileService.cs index 09c4b116..8681ea4f 100644 --- a/Libraries/Core/Services/CreateProfileService.cs +++ b/Libraries/Core/Services/CreateProfileService.cs @@ -32,13 +32,16 @@ public class CreateProfileService( SaveServer _saveServer, EventOutputHolder _eventOutputHolder, PlayerScavGenerator _playerScavGenerator, - ICloner _cloner + ICloner _cloner, + MailSendService _mailSendService ) { public string CreateProfile(string sessionId, ProfileCreateRequestData request) { var account = _saveServer.GetProfile(sessionId).ProfileInfo; - var profileTemplate = _cloner.Clone(_databaseService.GetProfiles()?.GetByJsonProp(account.Edition)?.GetByJsonProp(request.Side.ToLower())); + var profileTemplate = _cloner.Clone( + _databaseService.GetProfiles()?.GetByJsonProp(account.Edition)?.GetByJsonProp(request.Side.ToLower()) + ); var pmcData = profileTemplate.Character; // Delete existing profile @@ -439,18 +442,17 @@ public class CreateProfileService( QuestStatusEnum.Started, sessionID, response - ); + ).ToList(); - /* TODO: - _mailSendService.sendLocalisedNpcMessageToPlayer( - sessionID, - this.traderHelper.getTraderById(questFromDb.traderId), - MessageType.QUEST_START, - messageId, - itemRewards, - this.timeUtil.getHoursAsSeconds(100), - ); - */ + + _mailSendService.SendLocalisedNpcMessageToPlayer( + sessionID, + questFromDb.TraderId, + MessageType.QUEST_START, + messageId, + itemRewards, + _timeUtil.GetHoursAsSeconds(100) + ); } } } diff --git a/Libraries/Core/Services/InMemoryCacheService.cs b/Libraries/Core/Services/InMemoryCacheService.cs index 8dd02a2a..ebee155c 100644 --- a/Libraries/Core/Services/InMemoryCacheService.cs +++ b/Libraries/Core/Services/InMemoryCacheService.cs @@ -5,9 +5,9 @@ namespace Core.Services; [Injectable(InjectionType.Singleton)] public class InMemoryCacheService( - ICloner _cloner) + ICloner _cloner +) { - protected Dictionary _cacheData = new(); // Store data into an in-memory object diff --git a/Libraries/Core/Services/LegacyLocationLifecycleService.cs b/Libraries/Core/Services/LegacyLocationLifecycleService.cs deleted file mode 100644 index aacea37e..00000000 --- a/Libraries/Core/Services/LegacyLocationLifecycleService.cs +++ /dev/null @@ -1,76 +0,0 @@ -using SptCommon.Annotations; -using Core.Models.Eft.Common; -using Core.Models.Eft.Match; - -namespace Core.Services; - -[Injectable(InjectionType.Singleton)] -public class LegacyLocationLifecycleService -{ - /// - /// Handle client/match/offline/end - /// - public void endOfflineRaid(EndOfflineRaidRequestData info, string sessionId) - { - throw new NotImplementedException(); - } - - /// - /// Handle when a player extracts using a car - Add rep to fence - /// - /// name of the extract used - /// Player profile - /// Session id - protected void handleCarExtract(string extractName, PmcData pmcData, string sessionId) - { - throw new NotImplementedException(); - } - - /// - /// Get the fence rep gain from using a car or coop extract - /// - /// Profile - /// amount gained for the first extract - /// Number of times extract was taken - /// Fence standing after taking extract - protected int getFenceStandingAfterExtract(PmcData pmcData, int baseGain, int extractCount) - { - throw new NotImplementedException(); - } - - /// - /// Was extract by car - /// - /// name of extract - /// true if car extract - protected bool extractWasViaCar(string extractName) - { - throw new NotImplementedException(); - } - - /// - /// Did player take a COOP extract - /// - /// Name of extract player took - /// True if coop extract - protected bool extractWasViaCoop(string extractName) - { - throw new NotImplementedException(); - } - - /// - /// Handle when a player extracts using a coop extract - add rep to fence - /// - /// Session/player id - /// Profile - /// Name of extract taken - protected void handleCoopExtract(string sessionId, PmcData pmcData, string extractName) - { - throw new NotImplementedException(); - } - - protected void sendCoopTakenFenceMessage(string sessionId) - { - throw new NotImplementedException(); - } -} diff --git a/Libraries/Core/Services/NotificationService.cs b/Libraries/Core/Services/NotificationService.cs index 27c25554..b1c91755 100644 --- a/Libraries/Core/Services/NotificationService.cs +++ b/Libraries/Core/Services/NotificationService.cs @@ -8,19 +8,22 @@ public class NotificationService { protected Dictionary> _messageQueue = new(); - public Dictionary> GetMessageQueue() + public Dictionary> GetMessageQueue() { - throw new NotImplementedException(); + return _messageQueue; } - public List GetMessageFromQueue(string sessionId) + public List? GetMessageFromQueue(string sessionId) { - throw new NotImplementedException(); + return _messageQueue.GetValueOrDefault(sessionId); } public void UpdateMessageOnQueue(string sessionId, List value) { - throw new NotImplementedException(); + if (_messageQueue.ContainsKey(sessionId)) + { + _messageQueue[sessionId] = value; + } } public bool Has(string sessionID) @@ -33,7 +36,9 @@ public class NotificationService /// public WsNotificationEvent Pop(string sessionID) { - throw new NotImplementedException(); + var result = Get(sessionID).First(); + Get(sessionID).Remove(result); + return result; } /// diff --git a/Libraries/Core/Services/ProfileFixerService.cs b/Libraries/Core/Services/ProfileFixerService.cs index 616f685d..a16fe39f 100644 --- a/Libraries/Core/Services/ProfileFixerService.cs +++ b/Libraries/Core/Services/ProfileFixerService.cs @@ -93,15 +93,6 @@ public class ProfileFixerService( } } - /// - /// Find issues in the scav profile data that may cause issues - /// - /// profile to check and fix - public void CheckForAndFixScavProfileIssues(PmcData scavProfile) - { - return; - } - /// /// Attempt to fix common item issues that corrupt profiles /// diff --git a/Libraries/Core/Services/RaidWeatherService.cs b/Libraries/Core/Services/RaidWeatherService.cs index 73b4e0c4..bde35e25 100644 --- a/Libraries/Core/Services/RaidWeatherService.cs +++ b/Libraries/Core/Services/RaidWeatherService.cs @@ -12,8 +12,6 @@ namespace Core.Services; [Injectable(InjectionType.Singleton)] public class RaidWeatherService( - ISptLogger _logger, - DatabaseService _databaseService, TimeUtil _timeUtil, WeatherGenerator _weatherGenerator, SeasonalEventService _seasonalEventService, diff --git a/Libraries/Core/Services/SeasonalEventService.cs b/Libraries/Core/Services/SeasonalEventService.cs index 4015da54..74a92196 100644 --- a/Libraries/Core/Services/SeasonalEventService.cs +++ b/Libraries/Core/Services/SeasonalEventService.cs @@ -897,7 +897,21 @@ public class SeasonalEventService( /// protected void EnableDancingTree() { - throw new NotImplementedException(); + var maps = _databaseService.GetLocations(); + List mapsToCheck = ["hideout", "base", "privatearea"]; + foreach (KeyValuePair map in maps.GetAllPropsAsDict()) + { + // Skip maps that have no tree + if (mapsToCheck.Contains(map.Key)) { + continue; + } + + var mapData = map.Value as Location; + if (mapData.Base?.Events?.Khorovod?.Chance is not null) { + mapData.Base.Events.Khorovod.Chance = 100; + mapData.Base.BotLocationModifier.KhorovodChance = 100; + } + } } /// @@ -905,12 +919,69 @@ public class SeasonalEventService( /// protected void AddGifterBotToMaps() { - throw new NotImplementedException(); + var gifterSettings = _seasonalEventConfig.GifterSettings; + var maps = _databaseService.GetLocations().GetAllPropsAsDict(); + foreach (var gifterMapSettings in gifterSettings) { + Location mapData = maps.FirstOrDefault(x => x.Key == gifterMapSettings.Map).Value as Location; + // Dont add gifter to map twice + if (mapData.Base.BossLocationSpawn.Any((boss) => boss.BossName == "gifter")) { + continue; + } + + mapData.Base.BossLocationSpawn.Add(new BossLocationSpawn { + BossName = "gifter", + BossChance = gifterMapSettings.SpawnChance, + BossZone = gifterMapSettings.Zones, + IsBossPlayer = false, + BossDifficulty = "normal", + BossEscortType = "gifter", + BossEscortDifficulty = "normal", + BossEscortAmount = "0", + ForceSpawn = true, + SpawnMode = ["regular", "pve"], + Time = -1, + TriggerId = "", + TriggerName = "", + Delay = 0, + IsRandomTimeSpawn = false, + }); + } } protected void HandleModEvent(SeasonalEvent seasonalEvent, Config globalConfig) { - throw new NotImplementedException(); + if (seasonalEvent.Settings?.EnableChristmasHideout ?? false) { + globalConfig.EventType = globalConfig.EventType.Where((x) => x != "None").ToList(); + globalConfig.EventType.Add("Christmas"); + } + + if (seasonalEvent.Settings?.EnableHalloweenHideout ?? false) { + globalConfig.EventType = globalConfig.EventType.Where((x) => x != "None").ToList(); + globalConfig.EventType.Add("Halloween"); + globalConfig.EventType.Add("HalloweenIllumination"); + } + + if (seasonalEvent.Settings?.AddEventGearToBots ?? false) { + AddEventGearToBots(seasonalEvent.Type); + } + if (seasonalEvent.Settings?.AddEventLootToBots ?? false) { + AddEventLootToBots(seasonalEvent.Type); + } + + if (seasonalEvent.Settings?.EnableSummoning ?? false) { + EnableHalloweenSummonEvent(); + AddEventBossesToMaps("halloweensummon"); + } + if (seasonalEvent.Settings?.ZombieSettings?.Enabled ?? false) { + ConfigureZombies(seasonalEvent.Settings.ZombieSettings); + } + if (seasonalEvent.Settings?.ForceSeason is not null) { + _weatherConfig.OverrideSeason = seasonalEvent.Settings.ForceSeason; + } + + if (seasonalEvent.Settings?.AdjustBotAppearances ?? false) { + AdjustBotAppearanceValues(seasonalEvent.Type); + } } ///