From acb5def10c7f15d99040869d6c7a53a2109adb8d Mon Sep 17 00:00:00 2001 From: Chomp Date: Fri, 24 Jan 2025 22:52:42 +0000 Subject: [PATCH] Implemented `AddLootToContainer` --- .../Core/Controllers/InsuranceController.cs | 1 - .../Core/Generators/LocationLootGenerator.cs | 92 ++++++++++++++++++- Libraries/Core/Models/Eft/Common/Location.cs | 11 ++- 3 files changed, 98 insertions(+), 6 deletions(-) diff --git a/Libraries/Core/Controllers/InsuranceController.cs b/Libraries/Core/Controllers/InsuranceController.cs index b95d36ed..1e269cd3 100644 --- a/Libraries/Core/Controllers/InsuranceController.cs +++ b/Libraries/Core/Controllers/InsuranceController.cs @@ -1,4 +1,3 @@ -using System.Runtime.InteropServices.JavaScript; using Core.Helpers; using Core.Models.Common; using Core.Models.Eft.Common; diff --git a/Libraries/Core/Generators/LocationLootGenerator.cs b/Libraries/Core/Generators/LocationLootGenerator.cs index 564013e8..1cc6c0fe 100644 --- a/Libraries/Core/Generators/LocationLootGenerator.cs +++ b/Libraries/Core/Generators/LocationLootGenerator.cs @@ -18,9 +18,11 @@ public class LocationLootGenerator( ISptLogger _logger, RandomUtil _randomUtil, MathUtil _mathUtil, + HashUtil _hashUtil, ItemHelper _itemHelper, InventoryHelper _inventoryHelper, DatabaseService _databaseService, + ContainerHelper _containerHelper, LocalisationService _localisationService, SeasonalEventService _seasonalEventService, ItemFilterService _itemFilterService, @@ -379,12 +381,94 @@ public class LocationLootGenerator( /// Name of the map to generate static loot for /// StaticContainerData protected StaticContainerData AddLootToContainer(StaticContainerData staticContainer, - List staticForced, + List? staticForced, Dictionary staticLootDist, Dictionary> staticAmmoDist, string locationName ) { - throw new NotImplementedException(); + var containerClone = _cloner.Clone(staticContainer); + var containerTpl = containerClone.Template.Items[0].Template; + + // Create new unique parent id to prevent any collisions + var parentId = _hashUtil.Generate(); + containerClone.Template.Root = parentId; + containerClone.Template.Items[0].Id = parentId; + + var containerMap = GetContainerMapping(containerTpl); + + // Choose count of items to add to container + var itemCountToAdd = GetWeightedCountOfContainerItems(containerTpl, staticLootDist, locationName); + + // Get all possible loot items for container + var containerLootPool = GetPossibleLootItemsForContainer(containerTpl, staticLootDist); + + // Some containers need to have items forced into it (quest keys etc) + var tplsForced = staticForced + .Where((forcedStaticProp) => forcedStaticProp.ContainerId == containerClone.Template.Id) + .Select((x) => x.ItemTpl); + + // Draw random loot + // Allow money to spawn more than once in container + var failedToFitCount = 0; + var locklist = _itemHelper.GetMoneyTpls(); + + // Choose items to add to container, factor in weighting + lock money down + // Filter out items picked that're already in the above `tplsForced` array + var chosenTpls = containerLootPool + .Draw(itemCountToAdd, _locationConfig.AllowDuplicateItemsInStaticContainers, locklist) + .Where((tpl) => !tplsForced.Contains(tpl)); + + // Add forced loot to chosen item pool + var tplsToAddToContainer = tplsForced.Concat(chosenTpls); + foreach (var tplToAdd in tplsToAddToContainer) { + var chosenItemWithChildren = CreateStaticLootItem(tplToAdd, staticAmmoDist, parentId); + if (chosenItemWithChildren is null) + { + continue; + } + + var items = _locationConfig.TplsToStripChildItemsFrom.Contains(tplToAdd) + ? [chosenItemWithChildren.Items[0]] // Strip children from parent + : chosenItemWithChildren.Items; + var width = chosenItemWithChildren.Width; + var height = chosenItemWithChildren.Height; + + // look for open slot to put chosen item into + var result = _containerHelper.FindSlotForItem(containerMap, width, height); + if (!result.Success.GetValueOrDefault(false)) + { + if (failedToFitCount >= _locationConfig.FitLootIntoContainerAttempts) + { + // x attempts to fit an item, container is probably full, stop trying to add more + break; + } + + // Can't fit item, skip + failedToFitCount++; + + continue; + } + + _containerHelper.FillContainerMapWithItem( + containerMap, + result.X.Value, + result.Y.Value, + width, + height, + result.Rotation.GetValueOrDefault(false)); + + var rotation = result.Rotation.GetValueOrDefault(false) ? 1 : 0; + + items[0].SlotId = "main"; + items[0].Location = new { X = result.X, Y = result.Y, R = rotation }; + + // Add loot to container before returning + foreach (var item in items) { + containerClone.Template.Items.Add(item); + } + } + + return containerClone; } /// @@ -452,7 +536,7 @@ public class LocationLootGenerator( /// Container to get possible loot for /// staticLoot.json /// ProbabilityObjectArray of item tpls + probabilty - protected object GetPossibleLootItemsForContainer(string containerTypeId, + protected ProbabilityObjectArray, string, float?> GetPossibleLootItemsForContainer(string containerTypeId, Dictionary staticLootDist) // TODO: Type Fuckery, return type was ProbabilityObjectArray { var seasonalEventActive = _seasonalEventService.SeasonalEventEnabled(); @@ -519,7 +603,7 @@ public class LocationLootGenerator( /// List to add forced loot spawn locations to /// Forced loot locations that must be added /// Name of map currently having force loot created for - protected void addForcedLoot(List lootLocationTemplates, + protected void AddForcedLoot(List lootLocationTemplates, List forcedSpawnPoints, string locationName, Dictionary> staticAmmoDist) { diff --git a/Libraries/Core/Models/Eft/Common/Location.cs b/Libraries/Core/Models/Eft/Common/Location.cs index 77fdc68b..8c04b7a4 100644 --- a/Libraries/Core/Models/Eft/Common/Location.cs +++ b/Libraries/Core/Models/Eft/Common/Location.cs @@ -146,7 +146,16 @@ public record StaticContainerDetails public List StaticContainers { get; set; } [JsonPropertyName("staticForced")] - public List StaticForced { get; set; } + public List StaticForced { get; set; } +} + +public record StaticForced +{ + [JsonPropertyName("containerId")] + public string ContainerId { get; set; } + + [JsonPropertyName("itemTpl")] + public string ItemTpl { get; set; } } public record StaticContainerData