0
0
mirror of https://github.com/sp-tarkov/modules.git synced 2025-02-13 09:50:43 -05:00

Work towards implementing LK services (!79)

- Move clearing trader service data to raid end instead of as part of BTR Manager
- Fix data type for TraderServices ItemsToPay property
- Add ItemsToReceive property to TraderServices (Used for LK amulet)
- Don't throw NRE when nothing is bound to OnTraderServicePurchased

Co-authored-by: DrakiaXYZ <565558+TheDgtl@users.noreply.github.com>
Reviewed-on: SPT-AKI/Modules#79
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:
DrakiaXYZ 2024-02-12 09:22:45 +00:00 committed by chomp
parent 5622e05b13
commit d08754fb61
8 changed files with 135 additions and 20 deletions

View File

@ -67,7 +67,9 @@ namespace Aki.Custom
new BTRDestroyAtRaidEndPatch().Enable();
new BTRVehicleMovementSpeedPatch().Enable();
new ScavItemCheckmarkPatch().Enable();
}
new ResetTraderServicesPatch().Enable();
}
catch (Exception ex)
{
Logger.LogError($"A PATCH IN {GetType().Name} FAILED. SUBSEQUENT PATCHES HAVE NOT LOADED");

View File

@ -491,7 +491,6 @@ namespace Aki.Custom.BTR
if (TraderServicesManager.Instance != null)
{
TraderServicesManager.Instance.OnTraderServicePurchased -= BtrTraderServicePurchased;
TraderServicesManager.Instance.Clear();
}
if (gameWorld.MainPlayer != null)

View File

@ -0,0 +1,22 @@
using Aki.Reflection.Patching;
using Aki.SinglePlayer.Utils.TraderServices;
using EFT;
using HarmonyLib;
using System.Reflection;
namespace Aki.Custom.Patches
{
public class ResetTraderServicesPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return AccessTools.Method(typeof(BaseLocalGame<GamePlayerOwner>), nameof(BaseLocalGame<GamePlayerOwner>.Stop));
}
[PatchPrefix]
private static void PatchPrefix()
{
TraderServicesManager.Instance.Clear();
}
}
}

View File

@ -63,6 +63,7 @@ namespace Aki.SinglePlayer
new ScavSellAllPriceStorePatch().Enable();
new ScavSellAllRequestPatch().Enable();
new HideoutQuestIgnorePatch().Enable();
new LightKeeperServicesPatch().Enable();
}
catch (Exception ex)
{

View File

@ -0,0 +1,27 @@
using Aki.Reflection.Patching;
using Aki.SinglePlayer.Utils.TraderServices;
using Comfort.Common;
using EFT;
using System.Reflection;
namespace Aki.SinglePlayer.Patches.TraderServices
{
public class LightKeeperServicesPatch : ModulePatch
{
protected override MethodBase GetTargetMethod()
{
return typeof(GameWorld).GetMethod(nameof(GameWorld.OnGameStarted));
}
[PatchPostfix]
public static void PatchPostFix()
{
var gameWorld = Singleton<GameWorld>.Instance;
if (gameWorld != null)
{
gameWorld.gameObject.AddComponent<LightKeeperServicesManager>();
}
}
}
}

View File

@ -0,0 +1,64 @@
using BepInEx.Logging;
using Comfort.Common;
using EFT;
using HarmonyLib.Tools;
using UnityEngine;
namespace Aki.SinglePlayer.Utils.TraderServices
{
internal class LightKeeperServicesManager : MonoBehaviour
{
private static ManualLogSource logger;
GameWorld gameWorld;
BotsController botsController;
private void Awake()
{
logger = BepInEx.Logging.Logger.CreateLogSource(nameof(LightKeeperServicesManager));
gameWorld = Singleton<GameWorld>.Instance;
if (gameWorld == null || TraderServicesManager.Instance == null)
{
logger.LogError("[AKI-LKS] GameWorld or TraderServices null");
Destroy(this);
return;
}
botsController = Singleton<IBotGame>.Instance.BotsController;
if (botsController == null)
{
logger.LogError("[AKI-LKS] BotsController null");
Destroy(this);
return;
}
TraderServicesManager.Instance.OnTraderServicePurchased += OnTraderServicePurchased;
}
private void OnTraderServicePurchased(ETraderServiceType serviceType, string subserviceId)
{
switch (serviceType)
{
case ETraderServiceType.ExUsecLoyalty:
botsController.BotTradersServices.LighthouseKeeperServices.OnFriendlyExUsecPurchased(gameWorld.MainPlayer);
break;
case ETraderServiceType.ZryachiyAid:
botsController.BotTradersServices.LighthouseKeeperServices.OnFriendlyZryachiyPurchased(gameWorld.MainPlayer);
break;
}
}
private void OnDestroy()
{
if (gameWorld == null || botsController == null)
{
return;
}
if (TraderServicesManager.Instance != null)
{
TraderServicesManager.Instance.OnTraderServicePurchased -= OnTraderServicePurchased;
}
}
}
}

View File

@ -10,9 +10,12 @@ namespace Aki.SinglePlayer.Utils.TraderServices
public ETraderServiceType ServiceType { get; set; }
[JsonProperty("itemsToPay")]
public Dictionary<string, int> ItemsToPay { get; set; }
public Dictionary<MongoID, int> ItemsToPay { get; set; }
[JsonProperty("subServices")]
public Dictionary<string, int> SubServices { get; set; }
[JsonProperty("itemsToReceive")]
public MongoID[] ItemsToReceive { get; set; }
}
}

View File

@ -78,24 +78,17 @@ namespace Aki.SinglePlayer.Utils.TraderServices
// Only populate trader services that don't exist yet
if (!servicesData.ContainsKey(traderServiceModel.ServiceType))
{
TraderServiceClass traderService = new TraderServiceClass();
traderService.TraderId = traderId;
traderService.ServiceType = serviceType;
traderService.ItemsToPay = new Dictionary<MongoID, int>();
if (traderServiceModel.ItemsToPay != null)
TraderServiceClass traderService = new TraderServiceClass
{
foreach (var item in traderServiceModel.ItemsToPay)
{
traderService.ItemsToPay[item.Key] = item.Value;
}
}
TraderId = traderId,
ServiceType = serviceType,
UniqueItems = traderServiceModel.ItemsToReceive ?? new MongoID[0],
ItemsToPay = traderServiceModel.ItemsToPay ?? new Dictionary<MongoID, int>(),
// SubServices seem to be populated dynamically in the client (For BTR taxi atleast), so we can just ignore it
// NOTE: For future reference, this is a dict of `point id` to `price` for the BTR taxi
traderService.SubServices = new Dictionary<string, int>();
// TODO: What is this used for? Maybe lightkeeper?
traderService.UniqueItems = new MongoID[] { };
// SubServices seem to be populated dynamically in the client (For BTR taxi atleast), so we can just ignore it
// NOTE: For future reference, this is a dict of `point id` to `price` for the BTR taxi
SubServices = new Dictionary<string, int>()
};
// Convert our format to the backend settings format and store it
serviceData = new ServiceData(traderService);
@ -156,7 +149,11 @@ namespace Aki.SinglePlayer.Utils.TraderServices
_servicePurchased[serviceType] = new Dictionary<string, bool>();
_servicePurchased[serviceType][traderId] = true;
}
OnTraderServicePurchased.Invoke(serviceType, subserviceId);
if (OnTraderServicePurchased != null)
{
OnTraderServicePurchased.Invoke(serviceType, subserviceId);
}
}
public void RemovePurchasedService(ETraderServiceType serviceType, string traderId)