diff --git a/Libraries/Core/Services/PostDbLoadService.cs b/Libraries/Core/Services/PostDbLoadService.cs index 55685123..a9b7c114 100644 --- a/Libraries/Core/Services/PostDbLoadService.cs +++ b/Libraries/Core/Services/PostDbLoadService.cs @@ -100,6 +100,7 @@ public class PostDbLoadService( if (_seasonalEventService.IsAutomaticEventDetectionEnabled()) { + _seasonalEventService.CacheActiveEvents(); _seasonalEventService.EnableSeasonalEvents(); } diff --git a/Libraries/Core/Services/SeasonalEventService.cs b/Libraries/Core/Services/SeasonalEventService.cs index 74a92196..5dd72085 100644 --- a/Libraries/Core/Services/SeasonalEventService.cs +++ b/Libraries/Core/Services/SeasonalEventService.cs @@ -10,6 +10,7 @@ using SptCommon.Extensions; using Core.Models.Spt.Bots; using Core.Utils; using static System.Net.Mime.MediaTypeNames; +using System; namespace Core.Services; @@ -174,7 +175,7 @@ public class SeasonalEventService( /// /// Name of event to get gear changes for /// bots with equipment changes - protected Dictionary>> GetEventBotGear(SeasonalEventType eventType) + protected Dictionary>>? GetEventBotGear(SeasonalEventType eventType) { return _seasonalEventConfig.EventGear.GetValueOrDefault(eventType, null); } @@ -220,7 +221,7 @@ public class SeasonalEventService( /// public void EnableSeasonalEvents() { - if (_currentlyActiveEvents.Count > 0) + if (_currentlyActiveEvents.Any()) { var globalConfig = _databaseService.GetGlobals().Configuration; foreach (var activeEvent in _currentlyActiveEvents) @@ -571,8 +572,8 @@ public class SeasonalEventService( var props = botDb.BotAppearance.GetType().GetProperties(); foreach (var itemKey in weightAdjustments) { - var prop = props.FirstOrDefault(x => x.Name.ToLower() == appearanceKey.Key.ToLower()); - var propValue = (Dictionary)prop.GetValue(botDb.BotAppearance); + var prop = props.FirstOrDefault(x => string.Equals(x.Name, appearanceKey.Key, StringComparison.CurrentCultureIgnoreCase)); + var propValue = (Dictionary)prop.GetValue(botDb.BotAppearance); propValue[itemKey.Key] = weightAdjustments[itemKey.Key]; prop.SetValue(botDb.BotAppearance, propValue); } @@ -595,13 +596,13 @@ public class SeasonalEventService( continue; } - Location location = (Location)locationProp.GetValue(locations); + var location = (Location)locationProp.GetValue(locations); if (location?.Base?.BotLocationModifier?.AdditionalHostilitySettings is null) { continue; } - List newHostilitySettings = useDefault ? new() : hostilitySettings[locationProp.Name]; + var newHostilitySettings = useDefault ? new() : hostilitySettings[locationProp.Name]; if (newHostilitySettings is null) { continue; @@ -648,10 +649,10 @@ public class SeasonalEventService( /// protected void AdjustZryachiyMeleeChance() { - var zyrach = _databaseService.GetBots().Types.FirstOrDefault(x => x.Key.ToLower() == "bosszryachiy"); + var zryachiyKvP = _databaseService.GetBots().Types.FirstOrDefault(x => x.Key.ToLower() == "bosszryachiy"); var value = new Dictionary(); - foreach (var chance in zyrach.Value.BotChances.EquipmentChances) + foreach (var chance in zryachiyKvP.Value.BotChances.EquipmentChances) { if (chance.Key.ToLower() == "Scabbard") { @@ -662,7 +663,7 @@ public class SeasonalEventService( value.Add(chance.Key, chance.Value); } - zyrach.Value.BotChances.EquipmentChances = value; + zryachiyKvP.Value.BotChances.EquipmentChances = value; } /// @@ -849,10 +850,18 @@ public class SeasonalEventService( { var gifterBot = _databaseService.GetBots().Types["gifter"]; var items = gifterBot.BotInventory.Items.Backpack.Keys.ToList(); - gifterBot.BotDifficulty["Easy"].Patrol["ITEMS_TO_DROP"] = items; - gifterBot.BotDifficulty["Normal"].Patrol["ITEMS_TO_DROP"] = items; - gifterBot.BotDifficulty["Hard"].Patrol["ITEMS_TO_DROP"] = items; - gifterBot.BotDifficulty["Impossible"].Patrol["ITEMS_TO_DROP"] = items; + + gifterBot.BotDifficulty["easy"].Patrol.TryAdd("ITEMS_TO_DROP", 0); + gifterBot.BotDifficulty["easy"].Patrol["ITEMS_TO_DROP"] = items; + + gifterBot.BotDifficulty["normal"].Patrol.TryAdd("ITEMS_TO_DROP", 0); + gifterBot.BotDifficulty["normal"].Patrol["ITEMS_TO_DROP"] = items; + + gifterBot.BotDifficulty["hard"].Patrol.TryAdd("ITEMS_TO_DROP", 0); + gifterBot.BotDifficulty["hard"].Patrol["ITEMS_TO_DROP"] = items; + + gifterBot.BotDifficulty["impossible"].Patrol.TryAdd("ITEMS_TO_DROP", 0); + gifterBot.BotDifficulty["impossible"].Patrol["ITEMS_TO_DROP"] = items; } /// @@ -861,7 +870,40 @@ public class SeasonalEventService( /// Name of the event to read equipment in from config protected void AddEventGearToBots(SeasonalEventType eventType) { - throw new NotImplementedException(); + var botGearChanges = GetEventBotGear(eventType); + if (botGearChanges is null) + { + _logger.Warning(_localisationService.GetText("gameevent-no_gear_data", eventType)); + + return; + } + + // Iterate over bots with changes to apply + foreach (var botKvP in botGearChanges) { + var botToUpdate = _databaseService.GetBots().Types[botKvP.Key.ToLower()]; + if (botToUpdate is null) + { + _logger.Warning(_localisationService.GetText("gameevent-bot_not_found", botKvP)); + continue; + } + + // Iterate over each equipment slot change + var gearAmendmentsBySlot = botGearChanges[botKvP.Key]; + foreach (var equipmentKvP in gearAmendmentsBySlot) { + // Adjust slots spawn chance to be at least 75% + botToUpdate.BotChances.EquipmentChances[equipmentKvP.Key] = Math.Max( + botToUpdate.BotChances.EquipmentChances[equipmentKvP.Key], + 75); + + // Grab gear to add and loop over it + foreach (var itemToAddKvP in equipmentKvP.Value) + { + var equipmentSlot = (EquipmentSlots)Enum.Parse(typeof(EquipmentSlots), equipmentKvP.Key); + var equipmentDict = botToUpdate.BotInventory.Equipment[equipmentSlot]; + equipmentDict[itemToAddKvP.Key] = equipmentKvP.Value[itemToAddKvP.Key]; + } + } + } } /// @@ -870,7 +912,35 @@ public class SeasonalEventService( /// Name of the event to read loot in from config protected void AddEventLootToBots(SeasonalEventType eventType) { - throw new NotImplementedException(); + var botLootChanges = GetEventBotLoot(eventType); + if (botLootChanges is null) + { + _logger.Warning(_localisationService.GetText("gameevent-no_gear_data", eventType)); + + return; + } + + // Iterate over bots with changes to apply + foreach (var botKvpP in botLootChanges) { + var botToUpdate = _databaseService.GetBots().Types[botKvpP.Key.ToLower()]; + if (botToUpdate is null) + { + _logger.Warning(_localisationService.GetText("gameevent-bot_not_found", botKvpP)); + continue; + } + + // Iterate over each loot slot change + var lootAmendmentsBySlot = botLootChanges[botKvpP.Key]; + foreach (var slotKvP in lootAmendmentsBySlot) { + // Grab loot to add and loop over it + var itemTplsToAdd = slotKvP.Value; + foreach (var itemKvP in itemTplsToAdd) + { + var dict = botToUpdate.BotInventory.Items.GetAllPropsAsDict(); + dict[itemKvP.Key] = itemTplsToAdd[itemKvP.Key]; + } + } + } } /// @@ -899,14 +969,14 @@ public class SeasonalEventService( { var maps = _databaseService.GetLocations(); List mapsToCheck = ["hideout", "base", "privatearea"]; - foreach (KeyValuePair map in maps.GetAllPropsAsDict()) + foreach (var mapKvP in maps.GetDictionary()) { // Skip maps that have no tree - if (mapsToCheck.Contains(map.Key)) { + if (mapsToCheck.Contains(mapKvP.Key)) { continue; } - var mapData = map.Value as Location; + var mapData = mapKvP.Value; if (mapData.Base?.Events?.Khorovod?.Chance is not null) { mapData.Base.Events.Khorovod.Chance = 100; mapData.Base.BotLocationModifier.KhorovodChance = 100; @@ -920,9 +990,14 @@ public class SeasonalEventService( protected void AddGifterBotToMaps() { 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; + var maps = _databaseService.GetLocations().GetDictionary(); + foreach (var gifterMapSettings in gifterSettings) + { + if (!maps.TryGetValue(gifterMapSettings.Map, out var mapData)) + { + _logger.Warning($"AddGifterBotToMaps() Map not found {gifterMapSettings.Map}"); + continue; + } // Dont add gifter to map twice if (mapData.Base.BossLocationSpawn.Any((boss) => boss.BossName == "gifter")) { continue;