Added item extensions
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
using SPTarkov.Server.Core.DI;
|
using SPTarkov.Server.Core.DI;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Profile;
|
using SPTarkov.Server.Core.Models.Eft.Profile;
|
||||||
using SPTarkov.Server.Core.Models.Spt.Config;
|
using SPTarkov.Server.Core.Models.Spt.Config;
|
||||||
@@ -114,7 +115,7 @@ public class BtrDeliveryCallbacks(
|
|||||||
var rootItemParentId = _hashUtil.Generate();
|
var rootItemParentId = _hashUtil.Generate();
|
||||||
|
|
||||||
// Update the delivery items to have the new root parent ID for root/orphaned items
|
// Update the delivery items to have the new root parent ID for root/orphaned items
|
||||||
package.Items = _itemHelper.AdoptOrphanedItems(rootItemParentId, package.Items);
|
package.Items = package.Items.AdoptOrphanedItems(rootItemParentId);
|
||||||
|
|
||||||
_btrDeliveryService.SendBTRDelivery(sessionId, package.Items);
|
_btrDeliveryService.SendBTRDelivery(sessionId, package.Items);
|
||||||
|
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ public class GameController(
|
|||||||
/// <param name="pmcProfile">Player profile</param>
|
/// <param name="pmcProfile">Player profile</param>
|
||||||
protected void WarnOnActiveBotReloadSkill(PmcData pmcProfile)
|
protected void WarnOnActiveBotReloadSkill(PmcData pmcProfile)
|
||||||
{
|
{
|
||||||
var botReloadSkill = _profileHelper.GetSkillFromProfile(pmcProfile, SkillTypes.BotReload);
|
var botReloadSkill = pmcProfile.GetSkillFromProfile(SkillTypes.BotReload);
|
||||||
if (botReloadSkill?.Progress > 0)
|
if (botReloadSkill?.Progress > 0)
|
||||||
{
|
{
|
||||||
_logger.Warning(
|
_logger.Warning(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Common;
|
using SPTarkov.Server.Core.Models.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
@@ -123,7 +124,7 @@ public class InsuranceController(
|
|||||||
var rootItemParentId = _hashUtil.Generate();
|
var rootItemParentId = _hashUtil.Generate();
|
||||||
|
|
||||||
// Update the insured items to have the new root parent ID for root/orphaned items
|
// Update the insured items to have the new root parent ID for root/orphaned items
|
||||||
insured.Items = _itemHelper.AdoptOrphanedItems(rootItemParentId, insured.Items);
|
insured.Items = insured.Items.AdoptOrphanedItems(rootItemParentId);
|
||||||
|
|
||||||
var simulateItemsBeingTaken = _insuranceConfig.SimulateItemsBeingTaken;
|
var simulateItemsBeingTaken = _insuranceConfig.SimulateItemsBeingTaken;
|
||||||
if (simulateItemsBeingTaken)
|
if (simulateItemsBeingTaken)
|
||||||
@@ -135,7 +136,7 @@ public class InsuranceController(
|
|||||||
RemoveItemsFromInsurance(insured, itemsToDelete);
|
RemoveItemsFromInsurance(insured, itemsToDelete);
|
||||||
|
|
||||||
// There's a chance we've orphaned weapon attachments, so adopt any orphaned items again
|
// There's a chance we've orphaned weapon attachments, so adopt any orphaned items again
|
||||||
insured.Items = _itemHelper.AdoptOrphanedItems(rootItemParentId, insured.Items);
|
insured.Items = insured.Items.AdoptOrphanedItems(rootItemParentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
SendMail(sessionId, insured);
|
SendMail(sessionId, insured);
|
||||||
@@ -192,7 +193,7 @@ public class InsuranceController(
|
|||||||
|
|
||||||
// Populate a Map object of items for quick lookup by their ID and use it to populate a Map of main-parent items
|
// Populate a Map object of items for quick lookup by their ID and use it to populate a Map of main-parent items
|
||||||
// and each of their attachments. For example, a gun mapped to each of its attachments.
|
// and each of their attachments. For example, a gun mapped to each of its attachments.
|
||||||
var itemsMap = _itemHelper.GenerateItemsMap(insured.Items);
|
var itemsMap = insured.Items.GenerateItemsMap();
|
||||||
var parentAttachmentsMap = PopulateParentAttachmentsMap(
|
var parentAttachmentsMap = PopulateParentAttachmentsMap(
|
||||||
rootItemParentId,
|
rootItemParentId,
|
||||||
insured,
|
insured,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Generators.RepeatableQuestGeneration;
|
using SPTarkov.Server.Core.Generators.RepeatableQuestGeneration;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
@@ -222,8 +223,7 @@ public class RepeatableQuestController(
|
|||||||
var traderOfReplacedQuest = pmcData.TradersInfo[replacedQuestTraderId];
|
var traderOfReplacedQuest = pmcData.TradersInfo[replacedQuestTraderId];
|
||||||
traderOfReplacedQuest.Standing -= previousChangeRequirement.ChangeStandingCost;
|
traderOfReplacedQuest.Standing -= previousChangeRequirement.ChangeStandingCost;
|
||||||
|
|
||||||
var charismaBonus =
|
var charismaBonus = pmcData.GetSkillFromProfile(SkillTypes.Charisma)?.Progress ?? 0;
|
||||||
_profileHelper.GetSkillFromProfile(pmcData, SkillTypes.Charisma)?.Progress ?? 0;
|
|
||||||
foreach (var cost in previousChangeRequirement.ChangeCost)
|
foreach (var cost in previousChangeRequirement.ChangeCost)
|
||||||
{
|
{
|
||||||
// Not free, Charge player + apply charisma bonus to cost of replacement
|
// Not free, Charge player + apply charisma bonus to cost of replacement
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
|
|
||||||
|
namespace SPTarkov.Server.Core.Extensions
|
||||||
|
{
|
||||||
|
public static class ItemExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This method will compare two items and see if they are equivalent
|
||||||
|
/// This method will NOT compare IDs on the items
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item1">first item to compare</param>
|
||||||
|
/// <param name="item2">second item to compare</param>
|
||||||
|
/// <param name="compareUpdProperties">Upd properties to compare between the items</param>
|
||||||
|
/// <returns>true if they are the same</returns>
|
||||||
|
public static bool IsSameItem(
|
||||||
|
this Item item1,
|
||||||
|
Item item2,
|
||||||
|
HashSet<string>? compareUpdProperties = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Different tpl == different item
|
||||||
|
if (item1.Template != item2.Template)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both lack upd object + same tpl = same
|
||||||
|
if (item1.Upd is null && item2.Upd is null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// item1 lacks upd, item2 has one
|
||||||
|
if (item1.Upd is null && item2.Upd is not null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// item1 has upd, item2 lacks one
|
||||||
|
if (item1.Upd is not null && item2.Upd is null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// key = Upd property Type as string, value = comparison function that returns bool
|
||||||
|
var comparers = new Dictionary<string, Func<Upd, Upd, bool>>
|
||||||
|
{
|
||||||
|
{ "Key", (upd1, upd2) => upd1.Key?.NumberOfUsages == upd2.Key?.NumberOfUsages },
|
||||||
|
{
|
||||||
|
"Buff",
|
||||||
|
(upd1, upd2) =>
|
||||||
|
upd1.Buff?.Value == upd2.Buff?.Value
|
||||||
|
&& upd1.Buff?.BuffType == upd2.Buff?.BuffType
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"CultistAmulet",
|
||||||
|
(upd1, upd2) =>
|
||||||
|
upd1.CultistAmulet?.NumberOfUsages == upd2.CultistAmulet?.NumberOfUsages
|
||||||
|
},
|
||||||
|
{ "Dogtag", (upd1, upd2) => upd1.Dogtag?.ProfileId == upd2.Dogtag?.ProfileId },
|
||||||
|
{ "FaceShield", (upd1, upd2) => upd1.FaceShield?.Hits == upd2.FaceShield?.Hits },
|
||||||
|
{
|
||||||
|
"Foldable",
|
||||||
|
(upd1, upd2) =>
|
||||||
|
upd1.Foldable?.Folded.GetValueOrDefault(false)
|
||||||
|
== upd2.Foldable?.Folded.GetValueOrDefault(false)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"FoodDrink",
|
||||||
|
(upd1, upd2) => upd1.FoodDrink?.HpPercent == upd2.FoodDrink?.HpPercent
|
||||||
|
},
|
||||||
|
{ "MedKit", (upd1, upd2) => upd1.MedKit?.HpResource == upd2.MedKit?.HpResource },
|
||||||
|
{
|
||||||
|
"RecodableComponent",
|
||||||
|
(upd1, upd2) =>
|
||||||
|
upd1.RecodableComponent?.IsEncoded == upd2.RecodableComponent?.IsEncoded
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"RepairKit",
|
||||||
|
(upd1, upd2) => upd1.RepairKit?.Resource == upd2.RepairKit?.Resource
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Resource",
|
||||||
|
(upd1, upd2) => upd1.Resource?.UnitsConsumed == upd2.Resource?.UnitsConsumed
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Choose above keys or passed in keys to compare items with
|
||||||
|
var valuesToCompare =
|
||||||
|
compareUpdProperties?.Count > 0 ? compareUpdProperties : comparers.Keys.ToHashSet();
|
||||||
|
foreach (var propertyName in valuesToCompare)
|
||||||
|
{
|
||||||
|
if (!comparers.TryGetValue(propertyName, out var comparer))
|
||||||
|
// Key not found, skip
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!comparer(item1.Upd, item2.Upd))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if item is stored inside a container
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemToCheck">Item to check is inside of container</param>
|
||||||
|
/// <param name="desiredContainerSlotId">Name of slot to check item is in e.g. SecuredContainer/Backpack</param>
|
||||||
|
/// <param name="items">Inventory with child parent items to check</param>
|
||||||
|
/// <returns>True when item is in container</returns>
|
||||||
|
public static bool ItemIsInsideContainer(
|
||||||
|
this Item itemToCheck,
|
||||||
|
string desiredContainerSlotId,
|
||||||
|
IEnumerable<Item> items
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Get items parent
|
||||||
|
var parent = items.FirstOrDefault(item =>
|
||||||
|
item.Id.Equals(itemToCheck.ParentId, StringComparison.OrdinalIgnoreCase)
|
||||||
|
);
|
||||||
|
if (parent is null)
|
||||||
|
// No parent, end of line, not inside container
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent.SlotId == desiredContainerSlotId)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent.ItemIsInsideContainer(desiredContainerSlotId, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the size of a stack, return 1 if no stack object count property found
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">Item to get stack size of</param>
|
||||||
|
/// <returns>size of stack</returns>
|
||||||
|
public static int GetItemStackSize(this Item item)
|
||||||
|
{
|
||||||
|
if (item.Upd?.StackObjectsCount is not null)
|
||||||
|
{
|
||||||
|
return (int)item.Upd.StackObjectsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a dictionary from a collection of items, keyed by item id
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items">Collection of items</param>
|
||||||
|
/// <returns>Dictionary of items</returns>
|
||||||
|
public static Dictionary<string, Item> GenerateItemsMap(this IEnumerable<Item> items)
|
||||||
|
{
|
||||||
|
// Convert list to dictionary, keyed by items Id
|
||||||
|
return items.ToDictionary(item => item.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adopts orphaned items by resetting them as root "hideout" items. Helpful in situations where a parent has been
|
||||||
|
/// deleted from a group of items and there are children still referencing the missing parent. This method will
|
||||||
|
/// remove the reference from the children to the parent and set item properties to root values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rootId">The ID of the "root" of the container</param>
|
||||||
|
/// <param name="items">Array of Items that should be adjusted</param>
|
||||||
|
/// <returns>Returns Array of Items that have been adopted</returns>
|
||||||
|
public static List<Item> AdoptOrphanedItems(this List<Item> items, string rootId)
|
||||||
|
{
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
// Check if the item's parent exists.
|
||||||
|
var parentExists = items.Any(parentItem =>
|
||||||
|
parentItem.Id.Equals(item.ParentId, StringComparison.OrdinalIgnoreCase)
|
||||||
|
);
|
||||||
|
|
||||||
|
// If the parent does not exist and the item is not already a 'hideout' item, adopt the orphaned item by
|
||||||
|
// setting the parent ID to the PMCs inventory equipment ID, the slot ID to 'hideout', and remove the location.
|
||||||
|
if (!parentExists && item.ParentId != rootId && item.SlotId != "hideout")
|
||||||
|
{
|
||||||
|
item.ParentId = rootId;
|
||||||
|
item.SlotId = "hideout";
|
||||||
|
item.Location = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,5 +62,16 @@ namespace SPTarkov.Server.Core.Extensions
|
|||||||
|
|
||||||
return profile.TaskConditionCounters.Count > 0;
|
return profile.TaskConditionCounters.Count > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a specific common skill from supplied profile
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="profile">Player profile</param>
|
||||||
|
/// <param name="skill">Skill to look up and return value from</param>
|
||||||
|
/// <returns>Common skill object from desired profile</returns>
|
||||||
|
public static CommonSkill? GetSkillFromProfile(this PmcData profile, SkillTypes skill)
|
||||||
|
{
|
||||||
|
return profile?.Skills?.Common?.FirstOrDefault(s => s.Id == skill);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Hideout;
|
using SPTarkov.Server.Core.Models.Eft.Hideout;
|
||||||
@@ -1349,10 +1350,7 @@ public class HideoutHelper(
|
|||||||
/// <returns>Consumption bonus</returns>
|
/// <returns>Consumption bonus</returns>
|
||||||
protected double? GetHideoutManagementConsumptionBonus(PmcData pmcData)
|
protected double? GetHideoutManagementConsumptionBonus(PmcData pmcData)
|
||||||
{
|
{
|
||||||
var hideoutManagementSkill = _profileHelper.GetSkillFromProfile(
|
var hideoutManagementSkill = pmcData.GetSkillFromProfile(SkillTypes.HideoutManagement);
|
||||||
pmcData,
|
|
||||||
SkillTypes.HideoutManagement
|
|
||||||
);
|
|
||||||
if (hideoutManagementSkill is null || hideoutManagementSkill.Progress == 0)
|
if (hideoutManagementSkill is null || hideoutManagementSkill.Progress == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1384,7 +1382,7 @@ public class HideoutHelper(
|
|||||||
double valuePerLevel
|
double valuePerLevel
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var profileSkill = _profileHelper.GetSkillFromProfile(pmcData, skill);
|
var profileSkill = pmcData.GetSkillFromProfile(skill);
|
||||||
if (profileSkill is null || profileSkill.Progress == 0)
|
if (profileSkill is null || profileSkill.Progress == 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1563,10 +1561,7 @@ public class HideoutHelper(
|
|||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// Calculate bonus percent (apply hideoutManagement bonus)
|
// Calculate bonus percent (apply hideoutManagement bonus)
|
||||||
var hideoutManagementSkill = _profileHelper.GetSkillFromProfile(
|
var hideoutManagementSkill = pmcData.GetSkillFromProfile(SkillTypes.HideoutManagement);
|
||||||
pmcData,
|
|
||||||
SkillTypes.HideoutManagement
|
|
||||||
);
|
|
||||||
var hideoutManagementSkillBonusPercent = 1 + hideoutManagementSkill.Progress / 10000; // 5100 becomes 0.51, add 1 to it, 1.51
|
var hideoutManagementSkillBonusPercent = 1 + hideoutManagementSkill.Progress / 10000; // 5100 becomes 0.51, add 1 to it, 1.51
|
||||||
var bonus =
|
var bonus =
|
||||||
GetDogtagCombatSkillBonusPercent(pmcData, activeDogtags)
|
GetDogtagCombatSkillBonusPercent(pmcData, activeDogtags)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using SPTarkov.Common.Extensions;
|
using SPTarkov.Common.Extensions;
|
||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
using SPTarkov.Server.Core.Models.Spt.Config;
|
using SPTarkov.Server.Core.Models.Spt.Config;
|
||||||
@@ -25,8 +26,9 @@ public class InRaidHelper(
|
|||||||
"pocket3",
|
"pocket3",
|
||||||
"pocket4",
|
"pocket4",
|
||||||
];
|
];
|
||||||
protected InRaidConfig _inRaidConfig = _configServer.GetConfig<InRaidConfig>();
|
protected readonly InRaidConfig _inRaidConfig = _configServer.GetConfig<InRaidConfig>();
|
||||||
protected LostOnDeathConfig _lostOnDeathConfig = _configServer.GetConfig<LostOnDeathConfig>();
|
protected readonly LostOnDeathConfig _lostOnDeathConfig =
|
||||||
|
_configServer.GetConfig<LostOnDeathConfig>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deprecated. Reset the skill points earned in a raid to 0, ready for next raid.
|
/// Deprecated. Reset the skill points earned in a raid to 0, ready for next raid.
|
||||||
@@ -116,7 +118,7 @@ public class InRaidHelper(
|
|||||||
&& !(dbItems[item.Template].Properties.QuestItem ?? false)
|
&& !(dbItems[item.Template].Properties.QuestItem ?? false)
|
||||||
&& !(
|
&& !(
|
||||||
_inRaidConfig.KeepFiRSecureContainerOnDeath
|
_inRaidConfig.KeepFiRSecureContainerOnDeath
|
||||||
&& _itemHelper.ItemIsInsideContainer(item, "SecuredContainer", items)
|
&& item.ItemIsInsideContainer("SecuredContainer", items)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -201,13 +203,7 @@ public class InRaidHelper(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (
|
if (inventoryItem.ItemIsInsideContainer(secureContainerSlotId, pmcData.Inventory.Items))
|
||||||
_itemHelper.ItemIsInsideContainer(
|
|
||||||
inventoryItem,
|
|
||||||
secureContainerSlotId,
|
|
||||||
pmcData.Inventory.Items
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
itemsInsideContainer.Add(inventoryItem);
|
itemsInsideContainer.Add(inventoryItem);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Text.Json;
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using SPTarkov.Common.Extensions;
|
using SPTarkov.Common.Extensions;
|
||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Inventory;
|
using SPTarkov.Server.Core.Models.Eft.Inventory;
|
||||||
@@ -27,7 +28,6 @@ public class InventoryHelper(
|
|||||||
HttpResponseUtil _httpResponseUtil,
|
HttpResponseUtil _httpResponseUtil,
|
||||||
DialogueHelper _dialogueHelper,
|
DialogueHelper _dialogueHelper,
|
||||||
ContainerHelper _containerHelper,
|
ContainerHelper _containerHelper,
|
||||||
DatabaseServer _databaseServer,
|
|
||||||
EventOutputHolder _eventOutputHolder,
|
EventOutputHolder _eventOutputHolder,
|
||||||
ProfileHelper _profileHelper,
|
ProfileHelper _profileHelper,
|
||||||
ItemHelper _itemHelper,
|
ItemHelper _itemHelper,
|
||||||
@@ -42,7 +42,8 @@ public class InventoryHelper(
|
|||||||
BaseClasses.FUNCTIONAL_MOD,
|
BaseClasses.FUNCTIONAL_MOD,
|
||||||
BaseClasses.MOD,
|
BaseClasses.MOD,
|
||||||
];
|
];
|
||||||
protected InventoryConfig _inventoryConfig = _configServer.GetConfig<InventoryConfig>();
|
protected readonly InventoryConfig _inventoryConfig =
|
||||||
|
_configServer.GetConfig<InventoryConfig>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add multiple items to player stash (assuming they all fit)
|
/// Add multiple items to player stash (assuming they all fit)
|
||||||
@@ -655,7 +656,7 @@ public class InventoryHelper(
|
|||||||
var remainingCount = countToRemove;
|
var remainingCount = countToRemove;
|
||||||
foreach (var itemToReduce in itemsToReduce)
|
foreach (var itemToReduce in itemsToReduce)
|
||||||
{
|
{
|
||||||
var itemStackSize = _itemHelper.GetItemStackSize(itemToReduce);
|
var itemStackSize = itemToReduce.GetItemStackSize();
|
||||||
|
|
||||||
// Remove whole stack
|
// Remove whole stack
|
||||||
if (remainingCount >= itemStackSize)
|
if (remainingCount >= itemStackSize)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
using SPTarkov.Server.Core.Models.Enums;
|
using SPTarkov.Server.Core.Models.Enums;
|
||||||
@@ -178,98 +179,7 @@ public class ItemHelper(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsSameItem(itemOf1, itemOf2, compareUpdProperties))
|
if (!itemOf1.IsSameItem(itemOf2, compareUpdProperties))
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This method will compare two items and see if they are equivalent
|
|
||||||
/// This method will NOT compare IDs on the items
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item1">first item to compare</param>
|
|
||||||
/// <param name="item2">second item to compare</param>
|
|
||||||
/// <param name="compareUpdProperties">Upd properties to compare between the items</param>
|
|
||||||
/// <returns>true if they are the same</returns>
|
|
||||||
public bool IsSameItem(Item item1, Item item2, HashSet<string>? compareUpdProperties = null)
|
|
||||||
{
|
|
||||||
// Different tpl == different item
|
|
||||||
if (item1.Template != item2.Template)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Both lack upd object + same tpl = same
|
|
||||||
if (item1.Upd is null && item2.Upd is null)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// item1 lacks upd, item2 has one
|
|
||||||
if (item1.Upd is null && item2.Upd is not null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// item1 has upd, item2 lacks one
|
|
||||||
if (item1.Upd is not null && item2.Upd is null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// key = Upd property Type as string, value = comparison function that returns bool
|
|
||||||
var comparers = new Dictionary<string, Func<Upd, Upd, bool>>
|
|
||||||
{
|
|
||||||
{ "Key", (upd1, upd2) => upd1.Key?.NumberOfUsages == upd2.Key?.NumberOfUsages },
|
|
||||||
{
|
|
||||||
"Buff",
|
|
||||||
(upd1, upd2) =>
|
|
||||||
upd1.Buff?.Value == upd2.Buff?.Value
|
|
||||||
&& upd1.Buff?.BuffType == upd2.Buff?.BuffType
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"CultistAmulet",
|
|
||||||
(upd1, upd2) =>
|
|
||||||
upd1.CultistAmulet?.NumberOfUsages == upd2.CultistAmulet?.NumberOfUsages
|
|
||||||
},
|
|
||||||
{ "Dogtag", (upd1, upd2) => upd1.Dogtag?.ProfileId == upd2.Dogtag?.ProfileId },
|
|
||||||
{ "FaceShield", (upd1, upd2) => upd1.FaceShield?.Hits == upd2.FaceShield?.Hits },
|
|
||||||
{
|
|
||||||
"Foldable",
|
|
||||||
(upd1, upd2) =>
|
|
||||||
upd1.Foldable?.Folded.GetValueOrDefault(false)
|
|
||||||
== upd2.Foldable?.Folded.GetValueOrDefault(false)
|
|
||||||
},
|
|
||||||
{ "FoodDrink", (upd1, upd2) => upd1.FoodDrink?.HpPercent == upd2.FoodDrink?.HpPercent },
|
|
||||||
{ "MedKit", (upd1, upd2) => upd1.MedKit?.HpResource == upd2.MedKit?.HpResource },
|
|
||||||
{
|
|
||||||
"RecodableComponent",
|
|
||||||
(upd1, upd2) =>
|
|
||||||
upd1.RecodableComponent?.IsEncoded == upd2.RecodableComponent?.IsEncoded
|
|
||||||
},
|
|
||||||
{ "RepairKit", (upd1, upd2) => upd1.RepairKit?.Resource == upd2.RepairKit?.Resource },
|
|
||||||
{
|
|
||||||
"Resource",
|
|
||||||
(upd1, upd2) => upd1.Resource?.UnitsConsumed == upd2.Resource?.UnitsConsumed
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Choose above keys or passed in keys to compare items with
|
|
||||||
var valuesToCompare =
|
|
||||||
compareUpdProperties?.Count > 0 ? compareUpdProperties : comparers.Keys.ToHashSet();
|
|
||||||
foreach (var propertyName in valuesToCompare)
|
|
||||||
{
|
|
||||||
if (!comparers.TryGetValue(propertyName, out var comparer))
|
|
||||||
// Key not found, skip
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!comparer(item1.Upd, item2.Upd))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1709,37 +1619,6 @@ public class ItemHelper(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Check if item is stored inside a container
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="itemToCheck">Item to check is inside of container</param>
|
|
||||||
/// <param name="desiredContainerSlotId">Name of slot to check item is in e.g. SecuredContainer/Backpack</param>
|
|
||||||
/// <param name="items">Inventory with child parent items to check</param>
|
|
||||||
/// <returns>True when item is in container</returns>
|
|
||||||
public bool ItemIsInsideContainer(
|
|
||||||
Item itemToCheck,
|
|
||||||
string desiredContainerSlotId,
|
|
||||||
List<Item> items
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Get items parent
|
|
||||||
var parent = items.FirstOrDefault(item =>
|
|
||||||
item.Id.Equals(itemToCheck.ParentId, StringComparison.OrdinalIgnoreCase)
|
|
||||||
);
|
|
||||||
if (parent is null)
|
|
||||||
// No parent, end of line, not inside container
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent.SlotId == desiredContainerSlotId)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ItemIsInsideContainer(parent, desiredContainerSlotId, items);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add child items (cartridges) to a magazine
|
/// Add child items (cartridges) to a magazine
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1987,21 +1866,6 @@ public class ItemHelper(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get the size of a stack, return 1 if no stack object count property found
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="item">Item to get stack size of</param>
|
|
||||||
/// <returns>size of stack</returns>
|
|
||||||
public int GetItemStackSize(Item item)
|
|
||||||
{
|
|
||||||
if (item.Upd?.StackObjectsCount is not null)
|
|
||||||
{
|
|
||||||
return (int)item.Upd.StackObjectsCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the name of an item from the locale file using the item tpl
|
/// Get the name of an item from the locale file using the item tpl
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -2256,45 +2120,6 @@ public class ItemHelper(
|
|||||||
return newId;
|
return newId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adopts orphaned items by resetting them as root "hideout" items. Helpful in situations where a parent has been
|
|
||||||
// deleted from a group of items and there are children still referencing the missing parent. This method will
|
|
||||||
// remove the reference from the children to the parent and set item properties to root values.
|
|
||||||
//
|
|
||||||
// The ID of the "root" of the container.
|
|
||||||
// Array of Items that should be adjusted.
|
|
||||||
// Returns Array of Items that have been adopted.
|
|
||||||
public List<Item> AdoptOrphanedItems(string rootId, List<Item> items)
|
|
||||||
{
|
|
||||||
foreach (var item in items)
|
|
||||||
{
|
|
||||||
// Check if the item's parent exists.
|
|
||||||
var parentExists = items.Any(parentItem =>
|
|
||||||
parentItem.Id.Equals(item.ParentId, StringComparison.OrdinalIgnoreCase)
|
|
||||||
);
|
|
||||||
|
|
||||||
// If the parent does not exist and the item is not already a 'hideout' item, adopt the orphaned item by
|
|
||||||
// setting the parent ID to the PMCs inventory equipment ID, the slot ID to 'hideout', and remove the location.
|
|
||||||
if (!parentExists && item.ParentId != rootId && item.SlotId != "hideout")
|
|
||||||
{
|
|
||||||
item.ParentId = rootId;
|
|
||||||
item.SlotId = "hideout";
|
|
||||||
item.Location = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate a Map object of items for quick lookup using their ID.
|
|
||||||
//
|
|
||||||
// An array of Items that should be added to a Map.
|
|
||||||
// Returns A Map where the keys are the item IDs and the values are the corresponding Item objects.
|
|
||||||
public Dictionary<string, Item> GenerateItemsMap(List<Item> items)
|
|
||||||
{
|
|
||||||
// Convert list to dictionary, keyed by items Id
|
|
||||||
return items.ToDictionary(item => item.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a blank upd object to passed in item if it does not exist already
|
// Add a blank upd object to passed in item if it does not exist already
|
||||||
// item to add upd to
|
// item to add upd to
|
||||||
// text to write to log when upd object was not found
|
// text to write to log when upd object was not found
|
||||||
@@ -2372,19 +2197,6 @@ public class ItemHelper(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove FiR status from passed in items
|
|
||||||
// Items to update FiR status of
|
|
||||||
public void RemoveSpawnedInSessionPropertyFromItems(List<Item> items)
|
|
||||||
{
|
|
||||||
foreach (var item in items)
|
|
||||||
{
|
|
||||||
if (item.Upd is not null)
|
|
||||||
{
|
|
||||||
item.Upd.SpawnedInSession = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a 2D grid of a container's item slots
|
/// Get a 2D grid of a container's item slots
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -565,25 +565,6 @@ public class ProfileHelper(
|
|||||||
profileSkill.LastAccess = _timeUtil.GetTimeStamp();
|
profileSkill.LastAccess = _timeUtil.GetTimeStamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get a specific common skill from supplied profile
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pmcData">Player profile</param>
|
|
||||||
/// <param name="skill">Skill to look up and return value from</param>
|
|
||||||
/// <returns>Common skill object from desired profile</returns>
|
|
||||||
public CommonSkill? GetSkillFromProfile(PmcData pmcData, SkillTypes skill)
|
|
||||||
{
|
|
||||||
var skillToReturn = pmcData?.Skills?.Common.FirstOrDefault(s => s.Id == skill);
|
|
||||||
if (skillToReturn == null)
|
|
||||||
{
|
|
||||||
_logger.Warning(
|
|
||||||
$"Profile {pmcData.SessionId} does not have a skill named: {skill.ToString()}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return skillToReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the provided session id for a developer account
|
/// Is the provided session id for a developer account
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
using SPTarkov.Common.Extensions;
|
using SPTarkov.Common.Extensions;
|
||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
using SPTarkov.Server.Core.Models.Eft.ItemEvent;
|
using SPTarkov.Server.Core.Models.Eft.ItemEvent;
|
||||||
using SPTarkov.Server.Core.Models.Enums;
|
using SPTarkov.Server.Core.Models.Enums;
|
||||||
using SPTarkov.Server.Core.Models.Spt.Config;
|
|
||||||
using SPTarkov.Server.Core.Models.Utils;
|
using SPTarkov.Server.Core.Models.Utils;
|
||||||
using SPTarkov.Server.Core.Servers;
|
|
||||||
using SPTarkov.Server.Core.Services;
|
using SPTarkov.Server.Core.Services;
|
||||||
using SPTarkov.Server.Core.Utils;
|
|
||||||
using SPTarkov.Server.Core.Utils.Cloners;
|
using SPTarkov.Server.Core.Utils.Cloners;
|
||||||
|
|
||||||
namespace SPTarkov.Server.Core.Helpers;
|
namespace SPTarkov.Server.Core.Helpers;
|
||||||
@@ -16,23 +14,14 @@ namespace SPTarkov.Server.Core.Helpers;
|
|||||||
[Injectable]
|
[Injectable]
|
||||||
public class QuestRewardHelper(
|
public class QuestRewardHelper(
|
||||||
ISptLogger<QuestRewardHelper> _logger,
|
ISptLogger<QuestRewardHelper> _logger,
|
||||||
HashUtil _hashUtil,
|
|
||||||
TimeUtil _timeUtil,
|
|
||||||
ItemHelper _itemHelper,
|
|
||||||
PaymentHelper _paymentHelper,
|
PaymentHelper _paymentHelper,
|
||||||
TraderHelper _traderHelper,
|
|
||||||
DatabaseService _databaseService,
|
DatabaseService _databaseService,
|
||||||
QuestConditionHelper _questConditionHelper,
|
|
||||||
ProfileHelper _profileHelper,
|
ProfileHelper _profileHelper,
|
||||||
PresetHelper _presetHelper,
|
|
||||||
RewardHelper _rewardHelper,
|
RewardHelper _rewardHelper,
|
||||||
LocalisationService _localisationService,
|
LocalisationService _localisationService,
|
||||||
ICloner _cloner,
|
ICloner _cloner
|
||||||
ConfigServer _configServer
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected QuestConfig _questConfig = _configServer.GetConfig<QuestConfig>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Value for in game reward traders to not duplicate quest rewards.
|
/// Value for in game reward traders to not duplicate quest rewards.
|
||||||
/// Value can be modified by modders by overriding this value with new traders.
|
/// Value can be modified by modders by overriding this value with new traders.
|
||||||
@@ -161,10 +150,7 @@ public class QuestRewardHelper(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Calculate hideout management bonus as a percentage (up to 51% bonus)
|
// Calculate hideout management bonus as a percentage (up to 51% bonus)
|
||||||
var hideoutManagementSkill = _profileHelper.GetSkillFromProfile(
|
var hideoutManagementSkill = pmcData.GetSkillFromProfile(SkillTypes.HideoutManagement);
|
||||||
pmcData,
|
|
||||||
SkillTypes.HideoutManagement
|
|
||||||
);
|
|
||||||
|
|
||||||
// 5100 becomes 0.51, add 1 to it, 1.51
|
// 5100 becomes 0.51, add 1 to it, 1.51
|
||||||
// We multiply the money reward bonuses by the hideout management skill multiplier, giving the new result
|
// We multiply the money reward bonuses by the hideout management skill multiplier, giving the new result
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using SPTarkov.Common.Extensions;
|
using SPTarkov.Common.Extensions;
|
||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
@@ -42,7 +43,7 @@ public class CircleOfCultistService(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected const string CircleOfCultistSlotId = "CircleOfCultistsGrid1";
|
protected const string CircleOfCultistSlotId = "CircleOfCultistsGrid1";
|
||||||
protected HideoutConfig _hideoutConfig = _configServer.GetConfig<HideoutConfig>();
|
protected readonly HideoutConfig _hideoutConfig = _configServer.GetConfig<HideoutConfig>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start a sacrifice event
|
/// Start a sacrifice event
|
||||||
@@ -176,10 +177,7 @@ public class CircleOfCultistService(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Adjust value generated by the players hideout management skill
|
// Adjust value generated by the players hideout management skill
|
||||||
var hideoutManagementSkill = _profileHelper.GetSkillFromProfile(
|
var hideoutManagementSkill = pmcData.GetSkillFromProfile(SkillTypes.HideoutManagement);
|
||||||
pmcData,
|
|
||||||
SkillTypes.HideoutManagement
|
|
||||||
);
|
|
||||||
if (hideoutManagementSkill is not null)
|
if (hideoutManagementSkill is not null)
|
||||||
{
|
{
|
||||||
rewardAmountMultiplier *= (float)(1 + hideoutManagementSkill.Progress / 10000); // 5100 becomes 0.51, add 1 to it, 1.51, multiply the bonus by it (e.g. 1.2 x 1.51)
|
rewardAmountMultiplier *= (float)(1 + hideoutManagementSkill.Progress / 10000); // 5100 becomes 0.51, add 1 to it, 1.51, multiply the bonus by it (e.g. 1.2 x 1.51)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
@@ -21,7 +22,6 @@ public class InsuranceService(
|
|||||||
DatabaseService _databaseService,
|
DatabaseService _databaseService,
|
||||||
RandomUtil _randomUtil,
|
RandomUtil _randomUtil,
|
||||||
ItemHelper _itemHelper,
|
ItemHelper _itemHelper,
|
||||||
HashUtil _hashUtil,
|
|
||||||
TimeUtil _timeUtil,
|
TimeUtil _timeUtil,
|
||||||
SaveServer _saveServer,
|
SaveServer _saveServer,
|
||||||
TraderHelper _traderHelper,
|
TraderHelper _traderHelper,
|
||||||
@@ -32,7 +32,8 @@ public class InsuranceService(
|
|||||||
ICloner _cloner
|
ICloner _cloner
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
protected InsuranceConfig _insuranceConfig = _configServer.GetConfig<InsuranceConfig>();
|
protected readonly InsuranceConfig _insuranceConfig =
|
||||||
|
_configServer.GetConfig<InsuranceConfig>();
|
||||||
protected Dictionary<string, Dictionary<string, List<Item>>?> _insured = new();
|
protected Dictionary<string, Dictionary<string, List<Item>>?> _insured = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -302,13 +303,13 @@ public class InsuranceService(
|
|||||||
/// <returns>True if item</returns>
|
/// <returns>True if item</returns>
|
||||||
protected bool ItemCannotBeLostOnDeath(Item lostItem, List<Item> inventoryItems)
|
protected bool ItemCannotBeLostOnDeath(Item lostItem, List<Item> inventoryItems)
|
||||||
{
|
{
|
||||||
if (lostItem.SlotId?.ToLower().StartsWith("specialslot") ?? false)
|
if (lostItem.SlotId?.StartsWith("specialslot", StringComparison.OrdinalIgnoreCase) ?? false)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We check secure container items even tho they are omitted from lostInsuredItems, just in case
|
// We check secure container items even tho they are omitted from lostInsuredItems, just in case
|
||||||
if (_itemHelper.ItemIsInsideContainer(lostItem, "SecuredContainer", inventoryItems))
|
if (lostItem.ItemIsInsideContainer("SecuredContainer", inventoryItems))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Profile;
|
using SPTarkov.Server.Core.Models.Eft.Profile;
|
||||||
@@ -195,7 +196,7 @@ public class MailSendService(
|
|||||||
{
|
{
|
||||||
var rootItemParentId = _hashUtil.Generate();
|
var rootItemParentId = _hashUtil.Generate();
|
||||||
|
|
||||||
details.Items.AddRange(_itemHelper.AdoptOrphanedItems(rootItemParentId, items));
|
details.Items.AddRange(items.AdoptOrphanedItems(rootItemParentId));
|
||||||
details.ItemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds;
|
details.ItemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
||||||
@@ -88,10 +89,7 @@ public class ProfileFixerService(
|
|||||||
|
|
||||||
// Otherwise we need to generate a new unique stash ID for this message's attachments
|
// Otherwise we need to generate a new unique stash ID for this message's attachments
|
||||||
message.Items.Stash = _hashUtil.Generate();
|
message.Items.Stash = _hashUtil.Generate();
|
||||||
message.Items.Data = _itemHelper.AdoptOrphanedItems(
|
message.Items.Data = message.Items.Data.AdoptOrphanedItems(message.Items.Stash);
|
||||||
message.Items.Stash,
|
|
||||||
message.Items.Data
|
|
||||||
);
|
|
||||||
|
|
||||||
// Because `adoptOrphanedItems` sets the slotId to `hideout`, we need to re-set it to `main` to work with mail
|
// Because `adoptOrphanedItems` sets the slotId to `hideout`, we need to re-set it to `main` to work with mail
|
||||||
foreach (var item in message.Items.Data.Where(item => item.SlotId == "hideout"))
|
foreach (var item in message.Items.Data.Where(item => item.SlotId == "hideout"))
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using SPTarkov.Common.Extensions;
|
using SPTarkov.Common.Extensions;
|
||||||
using SPTarkov.DI.Annotations;
|
using SPTarkov.DI.Annotations;
|
||||||
|
using SPTarkov.Server.Core.Extensions;
|
||||||
using SPTarkov.Server.Core.Helpers;
|
using SPTarkov.Server.Core.Helpers;
|
||||||
using SPTarkov.Server.Core.Models.Common;
|
using SPTarkov.Server.Core.Models.Common;
|
||||||
using SPTarkov.Server.Core.Models.Eft.Common;
|
using SPTarkov.Server.Core.Models.Eft.Common;
|
||||||
@@ -420,7 +421,7 @@ public class RepairService(
|
|||||||
.Intellect
|
.Intellect
|
||||||
.RepairPointsCostReduction;
|
.RepairPointsCostReduction;
|
||||||
var profileIntellectLevel =
|
var profileIntellectLevel =
|
||||||
_profileHelper.GetSkillFromProfile(pmcData, SkillTypes.Intellect)?.Progress ?? 0;
|
pmcData.GetSkillFromProfile(SkillTypes.Intellect)?.Progress ?? 0;
|
||||||
var intellectPointReduction =
|
var intellectPointReduction =
|
||||||
intellectRepairPointsPerLevel * Math.Truncate(profileIntellectLevel / 100);
|
intellectRepairPointsPerLevel * Math.Truncate(profileIntellectLevel / 100);
|
||||||
|
|
||||||
@@ -629,8 +630,7 @@ public class RepairService(
|
|||||||
// Skill < level 10 + repairing weapon
|
// Skill < level 10 + repairing weapon
|
||||||
if (
|
if (
|
||||||
itemSkillType == SkillTypes.WeaponTreatment
|
itemSkillType == SkillTypes.WeaponTreatment
|
||||||
&& _profileHelper.GetSkillFromProfile(pmcData, SkillTypes.WeaponTreatment)?.Progress
|
&& pmcData.GetSkillFromProfile(SkillTypes.WeaponTreatment)?.Progress < 1000
|
||||||
< 1000
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -641,7 +641,7 @@ public class RepairService(
|
|||||||
new HashSet<SkillTypes> { SkillTypes.LightVests, SkillTypes.HeavyVests }.Contains(
|
new HashSet<SkillTypes> { SkillTypes.LightVests, SkillTypes.HeavyVests }.Contains(
|
||||||
itemSkillType.Value
|
itemSkillType.Value
|
||||||
)
|
)
|
||||||
&& _profileHelper.GetSkillFromProfile(pmcData, itemSkillType.Value)?.Progress < 1000
|
&& pmcData.GetSkillFromProfile(itemSkillType.Value)?.Progress < 1000
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -670,7 +670,7 @@ public class RepairService(
|
|||||||
var receivedDurabilityMaxPercent = buffSettings.ReceivedDurabilityMaxPercent;
|
var receivedDurabilityMaxPercent = buffSettings.ReceivedDurabilityMaxPercent;
|
||||||
|
|
||||||
var skillLevel = Math.Truncate(
|
var skillLevel = Math.Truncate(
|
||||||
(_profileHelper.GetSkillFromProfile(pmcData, itemSkillType.Value)?.Progress ?? 0) / 100
|
(pmcData.GetSkillFromProfile(itemSkillType.Value)?.Progress ?? 0) / 100
|
||||||
);
|
);
|
||||||
|
|
||||||
if (repairDetails.RepairPoints is null)
|
if (repairDetails.RepairPoints is null)
|
||||||
|
|||||||
Reference in New Issue
Block a user