more implementations

This commit is contained in:
CWX
2025-01-19 23:37:28 +00:00
parent e679225064
commit ec006b4b21
3 changed files with 277 additions and 21 deletions
+121 -9
View File
@@ -1,11 +1,22 @@
using SptCommon.Annotations;
using Core.Models.Eft.Common;
using Core.Models.Eft.Common.Tables;
using Core.Models.Enums;
using Core.Models.Utils;
using Core.Servers;
using Core.Services;
using SptCommon.Extensions;
namespace Core.Helpers;
[Injectable]
public class AssortHelper
public class AssortHelper(
ISptLogger<AssortHelper> _logger,
ItemHelper _itemHelper,
DatabaseServer _databaseServer,
LocalisationService _localisationService,
QuestHelper _questHelper
)
{
/**
* Remove assorts from a trader that have not been unlocked yet (via player completing corresponding quest)
@@ -18,11 +29,39 @@ public class AssortHelper
public TraderAssort StripLockedQuestAssort(
PmcData pmcProfile,
string traderId,
List<TraderAssort> traderAssorts,
TraderAssort traderAssorts,
Dictionary<string, Dictionary<string, string>> mergedQuestAssorts,
bool flea = false)
{
throw new NotImplementedException();
var strippedTraderAssorts = traderAssorts;
// Trader assort does not always contain loyal_level_items
if (traderAssorts.LoyalLevelItems is null)
{
_logger.Warning(_localisationService.GetText("assort-missing_loyalty_level_object", traderId));
return traderAssorts;
}
// Iterate over all assorts, removing items that haven't yet been unlocked by quests (ASSORTMENT_UNLOCK)
foreach (var assortId in traderAssorts.LoyalLevelItems)
{
// Get quest id that unlocks assort + statuses quest can be in to show assort
var unlockValues = GetQuestIdAndStatusThatShowAssort(mergedQuestAssorts, assortId.Key);
if (unlockValues is null)
{
continue;
}
// Remove assort if quest in profile does not have status that unlocks assort
var questStatusInProfile = _questHelper.GetQuestStatus(pmcProfile, unlockValues.Value.Key);
if (!unlockValues.Value.Value.Contains(questStatusInProfile))
{
strippedTraderAssorts = RemoveItemFromAssort(traderAssorts, assortId.Key, flea);
}
}
return strippedTraderAssorts;
}
/**
@@ -31,11 +70,36 @@ public class AssortHelper
* @param assortId Assort to look for linked quest id
* @returns quest id + array of quest status the assort should show for
*/
protected (string questId, QuestStatus[] status) GetQuestIdAndStatusThatShowAssort(
protected KeyValuePair<string, List<QuestStatusEnum>>? GetQuestIdAndStatusThatShowAssort(
Dictionary<string, Dictionary<string, string>> mergedQuestAssorts,
string assortId)
{
throw new NotImplementedException();
if (mergedQuestAssorts.Get<Dictionary<string, string>>("started").Contains(assortId))
{
// Assort unlocked by starting quest, assort is visible to player when : started or ready to hand in + handed in
return new KeyValuePair<string, List<QuestStatusEnum>>(
mergedQuestAssorts.Get<Dictionary<string, string>>("started")[assortId],
[QuestStatusEnum.Started, QuestStatusEnum.AvailableForFinish, QuestStatusEnum.Success]
);
}
if (mergedQuestAssorts.Get<Dictionary<string, string>>("success").Contains(assortId))
{
return new KeyValuePair<string, List<QuestStatusEnum>>(
mergedQuestAssorts.Get<Dictionary<string, string>>("success")[assortId],
[QuestStatusEnum.Success]
);
}
if (mergedQuestAssorts.Get<Dictionary<string, string>>("fail").Contains(assortId))
{
return new KeyValuePair<string, List<QuestStatusEnum>>(
mergedQuestAssorts.Get<Dictionary<string, string>>("success")[assortId],
[QuestStatusEnum.Fail]
);
}
return null;
}
/**
@@ -45,9 +109,28 @@ public class AssortHelper
* @param assort traders assorts
* @returns traders assorts minus locked loyalty assorts
*/
public TraderAssort StripLockedLoyaltyAssort(PmcData pmcProfile, string traderId, List<TraderAssort> assort)
public TraderAssort StripLockedLoyaltyAssort(PmcData pmcProfile, string traderId, TraderAssort assort)
{
throw new NotImplementedException();
var strippedAssort = assort;
// Trader assort does not always contain loyal_level_items
if (assort.LoyalLevelItems is null)
{
_logger.Warning(_localisationService.GetText("assort-missing_loyalty_level_object", traderId));
return strippedAssort;
}
// Remove items restricted by loyalty levels above those reached by the player
foreach (var item in assort.LoyalLevelItems)
{
if (assort.LoyalLevelItems[item.Key] > pmcProfile.TradersInfo[traderId].LoyaltyLevel)
{
strippedAssort = RemoveItemFromAssort(assort, item.Key);
}
}
return strippedAssort;
}
/**
@@ -56,8 +139,37 @@ public class AssortHelper
* @param itemID item id to remove from assort
* @returns Modified assort
*/
public TraderAssort RemoveItemFromAssort(List<TraderAssort> assort, string itemID, bool flea = false)
public TraderAssort RemoveItemFromAssort(TraderAssort assort, string itemID, bool flea = false)
{
throw new NotImplementedException();
var idsToRemove = _itemHelper.FindAndReturnChildrenByItems(assort.Items, itemID);
if (assort.BarterScheme[itemID] is not null && flea)
{
foreach (var barterSchemes in assort.BarterScheme[itemID])
{
foreach (var barterScheme in barterSchemes)
{
barterScheme.SptQuestLocked = true;
}
}
return assort;
}
assort.BarterScheme.Remove(itemID);
assort.LoyalLevelItems.Remove(itemID);
foreach (var i in idsToRemove)
{
foreach (var a in assort.Items.ToList())
{
if (a.Id == i)
{
assort.Items.Remove(a);
}
}
}
return assort;
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ using Core.Utils.Cloners;
namespace Core.Helpers;
[Injectable]
[Injectable(InjectionType.Singleton)]
public class HandbookHelper(
DatabaseService _databaseService,
ConfigServer _configServer,
+155 -11
View File
@@ -1,12 +1,40 @@
using SptCommon.Annotations;
using Core.Generators;
using SptCommon.Annotations;
using Core.Models.Eft.Common.Tables;
using Core.Models.Enums;
using Core.Models.Spt.Config;
using Core.Models.Utils;
using Core.Servers;
using Core.Services;
using Core.Utils;
using Core.Utils.Cloners;
namespace Core.Helpers;
[Injectable]
public class TraderAssortHelper()
[Injectable(InjectionType.Singleton)]
public class TraderAssortHelper(
ISptLogger<TraderAssortHelper> _logger,
MathUtil _mathUtil,
TimeUtil _timeUtil,
DatabaseService _databaseService,
ProfileHelper _profileHelper,
AssortHelper _assortHelper,
PaymentHelper _paymentHelper,
RagfairAssortGenerator _ragfairAssortGenerator,
RagfairOfferGenerator _ragfairOfferGenerator,
TraderAssortService _traderAssortService,
LocalisationService _localisationService,
TraderPurchasePersisterService _traderPurchasePersisterService,
TraderHelper _traderHelper,
FenceService _fenceService,
ConfigServer _configServer,
ICloner _cloner
)
{
protected TraderConfig _traderConfig = _configServer.GetConfig<TraderConfig>();
protected Dictionary<string, Dictionary<string, string>> _mergedQuestAssorts = new Dictionary<string, Dictionary<string, string>>();
protected bool createdMergedQuestAssorts = false;
/// <summary>
/// Get a traders assorts
/// Can be used for returning ragfair / fence assorts
@@ -18,7 +46,77 @@ public class TraderAssortHelper()
/// <returns>a traders' assorts</returns>
public TraderAssort GetAssort(string sessionId, string traderId, bool showLockedAssorts = false)
{
throw new NotImplementedException();
var traderClone = _cloner.Clone(_databaseService.GetTrader(traderId));
var fullProfile = _profileHelper.GetFullProfile(sessionId);
var pmcProfile = fullProfile?.CharacterData?.PmcData;
if (traderId == Traders.FENCE)
{
return _fenceService.GetFenceAssorts(pmcProfile);
}
// Strip assorts player should not see yet
if (!showLockedAssorts)
{
traderClone.Assort = _assortHelper.StripLockedLoyaltyAssort(pmcProfile, traderId, traderClone.Assort);
}
ResetBuyRestrictionCurrentValue(traderClone.Assort.Items);
// Append nextResupply value to assorts so client knows when refresh is occuring
traderClone.Assort.NextResupply = traderClone.Base.NextResupply;
// Adjust displayed assort counts based on values stored in profile
var assortPurchasesfromTrader = _traderPurchasePersisterService.GetProfileTraderPurchases(
sessionId,
traderId
);
foreach (var assortId in assortPurchasesfromTrader)
{
// Find assort we want to update current buy count of
var assortToAdjust = traderClone.Assort.Items.FirstOrDefault(x => x.Id == assortId.Key);
if (assortToAdjust is null)
{
_logger.Debug($"Cannot find trader: {traderClone.Base.Nickname} assort: {assortId} to adjust BuyRestrictionCurrent value, skipping");
continue;
}
if (assortToAdjust.Upd is null)
{
_logger.Debug(
$"Unable to adjust assort {assortToAdjust.Id} item: {assortToAdjust.Template} BuyRestrictionCurrent value, assort has a null upd object"
);
continue;
}
assortToAdjust.Upd.BuyRestrictionCurrent = assortPurchasesfromTrader[assortId.Key].PurchaseCount;
}
// Get rid of quest locked assorts
if (!this.createdMergedQuestAssorts)
{
HydrateMergedQuestAssorts();
this.createdMergedQuestAssorts = true;
}
traderClone.Assort = _assortHelper.StripLockedQuestAssort(
pmcProfile,
traderId,
traderClone.Assort,
_mergedQuestAssorts,
showLockedAssorts
);
// Filter out root assorts that are blacklisted for this profile
if (fullProfile.SptData.BlacklistedItemTemplates?.Count > 0)
{
RemoveItemsFromAssort(traderClone.Assort, fullProfile.SptData.BlacklistedItemTemplates);
}
return traderClone.Assort;
}
/// <summary>
@@ -28,7 +126,11 @@ public class TraderAssortHelper()
/// <param name="itemsTplsToRemove">Item TPLs the assort should not have</param>
protected void RemoveItemsFromAssort(TraderAssort assortToFilter, List<string> itemsTplsToRemove)
{
throw new NotImplementedException();
assortToFilter.Items = assortToFilter.Items.Where(
item =>
item.ParentId == "hideout" && itemsTplsToRemove.Contains(item.Template)
)
.ToList();
}
/// <summary>
@@ -37,7 +139,17 @@ public class TraderAssortHelper()
/// <param name="assortItems">Items to adjust</param>
protected void ResetBuyRestrictionCurrentValue(List<Item> assortItems)
{
throw new NotImplementedException();
// iterate over root items
foreach (var assort in assortItems.Where(item => item.SlotId == "hideout"))
{
// no value to adjust
if (assort.Upd.BuyRestrictionCurrent is null)
{
continue;
}
assort.Upd.BuyRestrictionCurrent = 0;
}
}
/// <summary>
@@ -45,7 +157,30 @@ public class TraderAssortHelper()
/// </summary>
protected void HydrateMergedQuestAssorts()
{
throw new NotImplementedException();
// Loop every trader
var traders = _databaseService.GetTraders();
foreach (var trader in traders)
{
// Trader has quest assort data
if (trader.Value.QuestAssort is not null)
{
// Started/Success/fail
foreach (var assort in trader.Value.QuestAssort)
{
// Each assort to quest id record
foreach (var assortId in assort.Value.Values)
{
// Null guard
if (!_mergedQuestAssorts.TryGetValue(assortId, out var _))
{
_mergedQuestAssorts.TryAdd(assortId, new Dictionary<string, string>());
}
_mergedQuestAssorts[assort.Key][assortId] = trader.Value.QuestAssort[assort.Key][assortId];
}
}
}
}
}
/// <summary>
@@ -55,7 +190,13 @@ public class TraderAssortHelper()
/// <param name="trader">trader details to alter</param>
public void ResetExpiredTrader(Trader trader)
{
throw new NotImplementedException();
trader.Assort.Items = GetPristineTraderAssorts(trader.Base.Id);
// Update resupply value to next timestamp
trader.Base.NextResupply = _traderHelper.GetNextUpdateTimestamp(trader.Base.Id);
// Flag a refresh is needed so ragfair update() will pick it up
trader.Base.RefreshTraderRagfairOffers = true;
}
/// <summary>
@@ -65,7 +206,10 @@ public class TraderAssortHelper()
/// <returns>true they need refreshing</returns>
public bool TraderAssortsHaveExpired(string traderID)
{
throw new NotImplementedException();
var time = _timeUtil.GetTimeStamp();
var trader = _databaseService.GetTables().Traders[traderID];
return trader.Base.NextResupply <= time;
}
/// <summary>
@@ -75,6 +219,6 @@ public class TraderAssortHelper()
/// <returns>array of Items</returns>
protected List<Item> GetPristineTraderAssorts(string traderId)
{
throw new NotImplementedException();
return _cloner.Clone(_traderAssortService.GetPristineTraderAssort(traderId).Items);
}
}