mirror of
https://github.com/sp-tarkov/modules.git
synced 2025-02-13 06:10:45 -05:00
Add handling of trader service requirements (!86)
This is primarily handled by the server, but the client does have precautionary code in it Co-authored-by: DrakiaXYZ <565558+TheDgtl@users.noreply.github.com> Reviewed-on: SPT-AKI/Modules#86 Co-authored-by: DrakiaXYZ <drakiaxyz@noreply.dev.sp-tarkov.com> Co-committed-by: DrakiaXYZ <drakiaxyz@noreply.dev.sp-tarkov.com>
This commit is contained in:
parent
9328c4c956
commit
f7ded0abf3
@ -17,5 +17,20 @@ namespace Aki.SinglePlayer.Utils.TraderServices
|
|||||||
|
|
||||||
[JsonProperty("itemsToReceive")]
|
[JsonProperty("itemsToReceive")]
|
||||||
public MongoID[] ItemsToReceive { get; set; }
|
public MongoID[] ItemsToReceive { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("requirements")]
|
||||||
|
public TraderServiceRequirementsModel Requirements { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TraderServiceRequirementsModel
|
||||||
|
{
|
||||||
|
[JsonProperty("completedQuests")]
|
||||||
|
public string[] CompletedQuests { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("standings")]
|
||||||
|
public Dictionary<string, float> Standings { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("side")]
|
||||||
|
public ESideType Side { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,12 +1,18 @@
|
|||||||
using Aki.Common.Http;
|
using Aki.Common.Http;
|
||||||
using Comfort.Common;
|
using Comfort.Common;
|
||||||
using EFT;
|
using EFT;
|
||||||
|
using EFT.Quests;
|
||||||
|
using HarmonyLib;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using static BackendConfigSettingsClass;
|
using static BackendConfigSettingsClass;
|
||||||
using TraderServiceClass = GClass1794;
|
using TraderServiceClass = GClass1794;
|
||||||
|
using QuestDictClass = GClass2133<string>;
|
||||||
|
using StandingListClass = GClass2135<float>;
|
||||||
|
|
||||||
namespace Aki.SinglePlayer.Utils.TraderServices
|
namespace Aki.SinglePlayer.Utils.TraderServices
|
||||||
{
|
{
|
||||||
@ -34,10 +40,12 @@ namespace Aki.SinglePlayer.Utils.TraderServices
|
|||||||
|
|
||||||
private Dictionary<ETraderServiceType, Dictionary<string, bool>> _servicePurchased { get; set; }
|
private Dictionary<ETraderServiceType, Dictionary<string, bool>> _servicePurchased { get; set; }
|
||||||
private HashSet<string> _cachedTraders = new HashSet<string>();
|
private HashSet<string> _cachedTraders = new HashSet<string>();
|
||||||
|
private FieldInfo _playerQuestControllerField;
|
||||||
|
|
||||||
public TraderServicesManager()
|
public TraderServicesManager()
|
||||||
{
|
{
|
||||||
_servicePurchased = new Dictionary<ETraderServiceType, Dictionary<string, bool>>();
|
_servicePurchased = new Dictionary<ETraderServiceType, Dictionary<string, bool>>();
|
||||||
|
_playerQuestControllerField = AccessTools.Field(typeof(Player), "_questController");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
@ -90,8 +98,28 @@ namespace Aki.SinglePlayer.Utils.TraderServices
|
|||||||
SubServices = new Dictionary<string, int>()
|
SubServices = new Dictionary<string, int>()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert our format to the backend settings format and store it
|
// Convert our format to the backend settings format
|
||||||
serviceData = new ServiceData(traderService);
|
serviceData = new ServiceData(traderService);
|
||||||
|
|
||||||
|
// Populate requirements if provided
|
||||||
|
if (traderServiceModel.Requirements != null)
|
||||||
|
{
|
||||||
|
if (traderServiceModel.Requirements.Standings != null)
|
||||||
|
{
|
||||||
|
serviceData.TraderServiceRequirements.Standings = new StandingListClass();
|
||||||
|
serviceData.TraderServiceRequirements.Standings.AddRange(traderServiceModel.Requirements.Standings);
|
||||||
|
|
||||||
|
// BSG has a bug in their code, we _need_ to initialize this if Standings isn't null
|
||||||
|
serviceData.TraderServiceRequirements.CompletedQuests = new QuestDictClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (traderServiceModel.Requirements.CompletedQuests != null)
|
||||||
|
{
|
||||||
|
serviceData.TraderServiceRequirements.CompletedQuests = new QuestDictClass();
|
||||||
|
serviceData.TraderServiceRequirements.CompletedQuests.Concat(traderServiceModel.Requirements.CompletedQuests);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
servicesData[serviceData.ServiceType] = serviceData;
|
servicesData[serviceData.ServiceType] = serviceData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,16 +136,47 @@ namespace Aki.SinglePlayer.Utils.TraderServices
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We should probably actually calculate this?
|
var IsServiceAvailable = this.IsServiceAvailable(player, servicesDataPair.Value.TraderServiceRequirements);
|
||||||
var CanAfford = true;
|
|
||||||
|
|
||||||
// Check whether we've purchased this service yet
|
// Check whether we've purchased this service yet
|
||||||
var traderService = servicesDataPair.Key;
|
var traderService = servicesDataPair.Key;
|
||||||
var WasPurchasedInThisRaid = IsServicePurchased(traderService, traderId);
|
var WasPurchasedInThisRaid = IsServicePurchased(traderService, traderId);
|
||||||
traderInfo.SetServiceAvailability(traderService, CanAfford, WasPurchasedInThisRaid);
|
traderInfo.SetServiceAvailability(traderService, IsServiceAvailable, WasPurchasedInThisRaid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsServiceAvailable(Player player, ServiceRequirements requirements)
|
||||||
|
{
|
||||||
|
// Handle standing requirements
|
||||||
|
if (requirements.Standings != null)
|
||||||
|
{
|
||||||
|
foreach (var entry in requirements.Standings)
|
||||||
|
{
|
||||||
|
if (!player.Profile.TradersInfo.ContainsKey(entry.Key) ||
|
||||||
|
player.Profile.TradersInfo[entry.Key].Standing < entry.Value)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle quest requirements
|
||||||
|
if (requirements.CompletedQuests != null)
|
||||||
|
{
|
||||||
|
AbstractQuestControllerClass questController = _playerQuestControllerField.GetValue(player) as AbstractQuestControllerClass;
|
||||||
|
foreach (string questId in requirements.CompletedQuests)
|
||||||
|
{
|
||||||
|
var conditional = questController.Quests.GetConditional(questId);
|
||||||
|
if (conditional == null || conditional.QuestStatus != EQuestStatus.Success)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void AfterPurchaseTraderService(ETraderServiceType serviceType, AbstractQuestControllerClass questController, string subServiceId = null)
|
public void AfterPurchaseTraderService(ETraderServiceType serviceType, AbstractQuestControllerClass questController, string subServiceId = null)
|
||||||
{
|
{
|
||||||
GameWorld gameWorld = Singleton<GameWorld>.Instance;
|
GameWorld gameWorld = Singleton<GameWorld>.Instance;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user