From cb23d26da391a092d4aed9167e4714da6866c251 Mon Sep 17 00:00:00 2001
From: Valens <8889280+VforValens@users.noreply.github.com>
Date: Sat, 25 Jan 2025 12:25:32 -0500
Subject: [PATCH] Fix AirdropService
Implement the AirdropService file, and all associated methods from the node server.
---
.../Core/Helpers/SecureContainerHelper.cs | 16 +-
.../Core/Models/Spt/Services/LootRequest.cs | 2 +-
Libraries/Core/Services/AirdropService.cs | 141 ++++++++++++++++--
3 files changed, 146 insertions(+), 13 deletions(-)
diff --git a/Libraries/Core/Helpers/SecureContainerHelper.cs b/Libraries/Core/Helpers/SecureContainerHelper.cs
index d0273a18..2399c1c2 100644
--- a/Libraries/Core/Helpers/SecureContainerHelper.cs
+++ b/Libraries/Core/Helpers/SecureContainerHelper.cs
@@ -1,10 +1,10 @@
-using SptCommon.Annotations;
+using SptCommon.Annotations;
using Core.Models.Eft.Common.Tables;
namespace Core.Helpers;
[Injectable]
-public class SecureContainerHelper
+public class SecureContainerHelper(ItemHelper _itemHelper)
{
///
/// Get a list of the item IDs (NOT tpls) inside a secure container
@@ -13,6 +13,16 @@ public class SecureContainerHelper
/// List of ids
public List GetSecureContainerItems(List- items)
{
- throw new NotImplementedException();
+ var secureContainer = items.First((x) => x.SlotId == "SecuredContainer");
+
+ // No container found, drop out
+ if (secureContainer is null) {
+ return [];
+ }
+
+ var itemsInSecureContainer = _itemHelper.FindAndReturnChildrenByItems(items, secureContainer.Id);
+
+ // Return all items returned and exclude the secure container item itself
+ return itemsInSecureContainer.Where((x) => x != secureContainer.Id).ToList();
}
}
diff --git a/Libraries/Core/Models/Spt/Services/LootRequest.cs b/Libraries/Core/Models/Spt/Services/LootRequest.cs
index 446e9459..b993932b 100644
--- a/Libraries/Core/Models/Spt/Services/LootRequest.cs
+++ b/Libraries/Core/Models/Spt/Services/LootRequest.cs
@@ -46,7 +46,7 @@ public record LootRequest
/// key: item base type: value: max count
///
[JsonPropertyName("itemLimits")]
- public Dictionary? ItemLimits { get; set; }
+ public Dictionary? ItemLimits { get; set; }
[JsonPropertyName("itemStackLimits")]
public Dictionary? ItemStackLimits { get; set; }
diff --git a/Libraries/Core/Services/AirdropService.cs b/Libraries/Core/Services/AirdropService.cs
index 4a38f5f9..8abe2d67 100644
--- a/Libraries/Core/Services/AirdropService.cs
+++ b/Libraries/Core/Services/AirdropService.cs
@@ -1,17 +1,41 @@
-using SptCommon.Annotations;
+using SptCommon.Annotations;
using Core.Models.Eft.Common.Tables;
using Core.Models.Eft.Location;
using Core.Models.Enums;
using Core.Models.Spt.Services;
+using Core.Servers;
+using Core.Models.Spt.Config;
+using Core.Models.Utils;
+using Core.Generators;
+using Core.Utils;
+using Core.Helpers;
namespace Core.Services;
[Injectable]
-public class AirdropService
+public class AirdropService(
+ ConfigServer configServer,
+ ISptLogger _logger,
+ LootGenerator _lootGenerator,
+ HashUtil _hashUtil,
+ WeightedRandomHelper _weightedRandomHelper,
+ LocalisationService _localisationService,
+ ItemFilterService _itemFilterService,
+ ItemHelper _itemHelper)
{
+ protected AirdropConfig _airdropConfig = configServer.GetConfig();
+
public GetAirdropLootResponse GenerateCustomAirdropLoot(GetAirdropLootRequest request)
{
- throw new NotImplementedException();
+ if (!_airdropConfig.CustomAirdropMapping.TryGetValue(request.ContainerId, out var customAirdropInformation)) {
+ _logger.Warning(
+ $"Unable to find data for custom airdrop {request.ContainerId}, returning random airdrop instead"
+ );
+
+ return GenerateAirdropLoot();
+ }
+
+ return GenerateAirdropLoot(customAirdropInformation);
}
///
@@ -21,9 +45,40 @@ public class AirdropService
///
/// OPTIONAL - Desired airdrop type, randomised when not provided
/// List of LootItem objects
- public GetAirdropLootResponse GenerateAirdropLoot(string forcedAirdropType = null)
+ public GetAirdropLootResponse GenerateAirdropLoot(SptAirdropTypeEnum? forcedAirdropType = null)
{
- throw new NotImplementedException();
+ var airdropType = forcedAirdropType != null ? forcedAirdropType : ChooseAirdropType();
+ _logger.Debug($"Chose: {airdropType} for airdrop loot");
+
+ // Common/weapon/etc
+ var airdropConfig = GetAirdropLootConfigByType((AirdropTypeEnum)airdropType);
+
+ // generate loot to put into airdrop crate
+ var crateLoot = airdropConfig.UseForcedLoot.GetValueOrDefault(false)
+ ? _lootGenerator.CreateForcedLoot(airdropConfig.ForcedLoot)
+ : _lootGenerator.CreateRandomLoot(airdropConfig);
+
+ // Create airdrop crate and add to result in first spot
+ var airdropCrateItem = GetAirdropCrateItem((SptAirdropTypeEnum)airdropType);
+
+ // Add crate to front of list
+ crateLoot.Insert(0, airdropCrateItem);
+
+ // Reparent loot items to crate we added above
+ foreach (var item in crateLoot) {
+ if (item.Id == airdropCrateItem.Id) {
+ // Crate itself, don't alter
+ continue;
+ }
+
+ // no parentId = root item, make item have create as parent
+ if (item.ParentId is null) {
+ item.ParentId = airdropCrateItem.Id;
+ item.SlotId = "main";
+ }
+ }
+
+ return new GetAirdropLootResponse { Icon = airdropConfig.Icon, Container = crateLoot };
}
///
@@ -33,7 +88,38 @@ public class AirdropService
/// Item
protected Item GetAirdropCrateItem(SptAirdropTypeEnum airdropType)
{
- throw new NotImplementedException();
+ var airdropContainer = new Item {
+ Id = _hashUtil.Generate(),
+ Template = "", // picked later
+ Upd = new Upd()
+ {
+ SpawnedInSession = true,
+ StackObjectsCount = 1,
+ },
+ };
+
+ switch (airdropType) {
+ case SptAirdropTypeEnum.foodMedical:
+ airdropContainer.Template = ItemTpl.LOOTCONTAINER_AIRDROP_MEDICAL_CRATE;
+ break;
+ case SptAirdropTypeEnum.barter:
+ airdropContainer.Template = ItemTpl.LOOTCONTAINER_AIRDROP_SUPPLY_CRATE;
+ break;
+ case SptAirdropTypeEnum.weaponArmor:
+ airdropContainer.Template = ItemTpl.LOOTCONTAINER_AIRDROP_WEAPON_CRATE;
+ break;
+ case SptAirdropTypeEnum.mixed:
+ airdropContainer.Template = ItemTpl.LOOTCONTAINER_AIRDROP_COMMON_SUPPLY_CRATE;
+ break;
+ case SptAirdropTypeEnum.radar:
+ airdropContainer.Template = ItemTpl.LOOTCONTAINER_AIRDROP_TECHNICAL_SUPPLY_CRATE_EVENT_1;
+ break;
+ default:
+ airdropContainer.Template = ItemTpl.LOOTCONTAINER_AIRDROP_COMMON_SUPPLY_CRATE;
+ break;
+ }
+
+ return airdropContainer;
}
///
@@ -42,7 +128,9 @@ public class AirdropService
/// airdrop type value
protected SptAirdropTypeEnum ChooseAirdropType()
{
- throw new NotImplementedException();
+ var possibleAirdropTypes = _airdropConfig.AirdropTypeWeightings;
+
+ return _weightedRandomHelper.GetWeightedValue(possibleAirdropTypes);
}
///
@@ -50,8 +138,43 @@ public class AirdropService
///
/// Type of airdrop to get settings for
/// LootRequest
- protected LootRequest GetAirdropLootConfigByType(AirdropTypeEnum airdropType)
+ protected AirdropLootRequest GetAirdropLootConfigByType(AirdropTypeEnum airdropType)
{
- throw new NotImplementedException();
+ var lootSettingsByType = _airdropConfig.Loot[airdropType.ToString()];
+ if (lootSettingsByType is null) {
+ _logger.Error(
+ _localisationService.GetText("location-unable_to_find_airdrop_drop_config_of_type", airdropType)
+ );
+
+ // Default to common
+ lootSettingsByType = _airdropConfig.Loot[AirdropTypeEnum.Common.ToString()];
+ }
+
+ // Get all items that match the blacklisted types and fold into item blacklist
+ var itemTypeBlacklist = _itemFilterService.GetItemRewardBaseTypeBlacklist();
+ var itemsMatchingTypeBlacklist = _itemHelper.GetItems()
+ .Where((templateItem) => _itemHelper.IsOfBaseclasses(templateItem.Parent, itemTypeBlacklist))
+ .Select((templateItem) => templateItem.Id);
+ var itemBlacklist = new HashSet();
+ itemBlacklist.UnionWith(lootSettingsByType.ItemBlacklist);
+ itemBlacklist.UnionWith(_itemFilterService.GetItemRewardBlacklist());
+ itemBlacklist.UnionWith(_itemFilterService.GetBossItems());
+ itemBlacklist.UnionWith(itemsMatchingTypeBlacklist);
+
+ return new AirdropLootRequest {
+ Icon = lootSettingsByType.Icon,
+ WeaponPresetCount = lootSettingsByType.WeaponPresetCount,
+ ArmorPresetCount = lootSettingsByType.ArmorPresetCount,
+ ItemCount = lootSettingsByType.ItemCount,
+ WeaponCrateCount = lootSettingsByType.WeaponCrateCount,
+ ItemBlacklist = itemBlacklist.ToList(),
+ ItemTypeWhitelist = lootSettingsByType.ItemTypeWhitelist,
+ ItemLimits = lootSettingsByType.ItemLimits,
+ ItemStackLimits = lootSettingsByType.ItemStackLimits,
+ ArmorLevelWhitelist = lootSettingsByType.ArmorLevelWhitelist,
+ AllowBossItems = lootSettingsByType.AllowBossItems,
+ UseForcedLoot = lootSettingsByType.UseForcedLoot,
+ ForcedLoot = lootSettingsByType.ForcedLoot,
+ };
}
}