using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common; using SPTarkov.Server.Core.Models.Spt.Presets; using SPTarkov.Server.Core.Services; using SPTarkov.Server.Core.Utils.Cloners; namespace SPTarkov.Server.Core.Helpers; [Injectable(InjectionType.Singleton)] public class PresetHelper(DatabaseService databaseService, ItemHelper itemHelper, ICloner cloner) { protected Dictionary? _defaultEquipmentPresets; protected Dictionary? _defaultWeaponPresets; /// /// Preset cache - key = item tpl, value = preset ids /// protected Dictionary _lookup = new(); public void HydratePresetStore(Dictionary input) { _lookup = input; } /// /// Get weapon and armor default presets, keyed to preset id NOT item tpl /// /// public Dictionary GetDefaultPresets() { var weapons = GetDefaultWeaponPresets(); var equipment = GetDefaultEquipmentPresets(); return weapons.UnionBy(equipment, kvp => kvp.Key).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); } /// /// Get weapon and armor default presets, keyed to root items tpl /// /// dictionary of presets keyed by the root items tpl public Dictionary GetDefaultPresetsByTplKey() { // Weapons and equipment keyed by their preset id var weapons = GetDefaultWeaponPresets().Values; var equipment = GetDefaultEquipmentPresets().Values; return weapons .Concat(equipment) .Where(preset => preset.Items.Count > 0) // Some safety to prevent nullref .ToDictionary(preset => preset.Items.FirstOrDefault().Template); } /// /// Get default weapon presets /// /// public Dictionary GetDefaultWeaponPresets() { if (_defaultWeaponPresets is null) { var tempPresets = databaseService.GetGlobals().ItemPresets; _defaultWeaponPresets = tempPresets .Where(p => p.Value.Encyclopedia != null && itemHelper.IsOfBaseclass(p.Value.Encyclopedia.Value, BaseClasses.WEAPON)) .ToDictionary(); } return _defaultWeaponPresets; } /// /// Get default equipment presets /// /// Dictionary public Dictionary GetDefaultEquipmentPresets() { if (_defaultEquipmentPresets == null) { var tempPresets = databaseService.GetGlobals().ItemPresets; _defaultEquipmentPresets = tempPresets .Where(p => p.Value.Encyclopedia != null && itemHelper.ArmorItemCanHoldMods(p.Value.Encyclopedia.Value)) .ToDictionary(); } return _defaultEquipmentPresets; } /// /// Is the provided id a preset id /// /// Value to check /// True = preset exists for this id public bool IsPreset(MongoId id) { if (id.IsEmpty()) { return false; } return databaseService.GetGlobals().ItemPresets.ContainsKey(id); } /// /// Checks to see if the preset is of the given base class /// /// id of the preset /// BaseClasses enum to check against /// True if the preset is of the given base class, false otherwise public bool IsPresetBaseClass(MongoId id, MongoId baseClass) { return IsPreset(id) && itemHelper.IsOfBaseclass(GetPreset(id).Encyclopedia.Value, baseClass); } /// /// Does the provided tpl have a preset /// /// Tpl id to check /// True if preset exists for tpl public bool HasPreset(MongoId templateId) { return _lookup.ContainsKey(templateId); } public Preset GetPreset(MongoId id) { return cloner.Clone(databaseService.GetGlobals().ItemPresets[id]); } /// /// Get all presets from globals db /// /// List public List GetAllPresets() { return cloner.Clone(databaseService.GetGlobals().ItemPresets.Values.ToList()); } /// /// Get a clone of a tpls presets /// /// Tpl to get presets for /// List public List GetPresets(MongoId templateId) { // Try adn get preset ids from cache if they exist if (!_lookup.TryGetValue(templateId, out var presetDetailsForTpl)) { // None found, early exit return []; } // Use gathered preset ids to get full preset objects, clone and return return cloner.Clone(presetDetailsForTpl.PresetIds.Select(x => databaseService.GetGlobals().ItemPresets[x]).ToList()); } /// /// Get a cloned default preset for passed in item tpl /// /// Items tpl to get preset for /// null if no default preset, otherwise Preset public Preset? GetDefaultPreset(MongoId templateId) { // look in main cache for presets for this tpl if (!_lookup.TryGetValue(templateId, out var presetDetails)) { return null; } if (presetDetails.DefaultId is null) { return null; } // Use default preset id from above cache to find the weapon/equipment preset if (!_defaultWeaponPresets.TryGetValue(presetDetails.DefaultId.Value, out var defaultPreset)) { if (!_defaultEquipmentPresets.TryGetValue(presetDetails.DefaultId.Value, out defaultPreset)) { // Default not found in weapon or equipment, return first preset in list return cloner.Clone(databaseService.GetGlobals().ItemPresets[presetDetails.PresetIds.First()]); } } return cloner.Clone(defaultPreset); } /// /// Get the presets root item tpl /// /// Preset id to look up /// tpl mongoid public MongoId GetBaseItemTpl(MongoId presetId) { if (!databaseService.GetGlobals().ItemPresets.TryGetValue(presetId, out var preset)) { // No preset exists return ""; } var rootItem = preset.Items.FirstOrDefault(x => x.Id == preset.Parent); if (rootItem is null) { // Cant find root item return ""; } return rootItem.Template; } /// /// Return the price of the preset for the given item tpl, or for the tpl itself if no preset exists /// /// The item template to get the price of /// The price of the given item preset, or base item if no preset exists public double GetDefaultPresetOrItemPrice(MongoId tpl) { // Get default preset if it exists var defaultPreset = GetDefaultPreset(tpl); // Bundle up tpls we want price for var tpls = defaultPreset is not null ? defaultPreset.Items.Select(item => item.Template) : [tpl]; // Get price of tpls return itemHelper.GetItemAndChildrenPrice(tpls); } }