using SPT.Reflection.Patching; using SPT.Reflection.Utils; using EFT; using System.Linq; using System.Reflection; using Comfort.Common; using System; using static LocationSettingsClass; namespace SPT.Custom.Patches { /// /// Local games do not set the locationId property like a network game does, `LocationId` is used by various bsg systems /// e.g. btr/lightkeeper services /// public class SetLocationIdOnRaidStartPatch : ModulePatch { private static PropertyInfo _locationProperty; protected override MethodBase GetTargetMethod() { Type localGameBaseType = PatchConstants.LocalGameType.BaseType; // At this point, gameWorld.MainPlayer isn't set, so we need to use the LocalGame's `Location_0` property _locationProperty = localGameBaseType.GetProperties(PatchConstants.PublicDeclaredFlags) .SingleCustom(x => x.PropertyType == typeof(Location)); // Find the TimeAndWeatherSettings handling method var desiredMethod = localGameBaseType.GetMethods(PatchConstants.PublicDeclaredFlags).SingleOrDefault(IsTargetMethod); Logger.LogDebug($"{GetType().Name} Type: {localGameBaseType?.Name}"); Logger.LogDebug($"{GetType().Name} Method: {desiredMethod?.Name}"); return desiredMethod; } private static bool IsTargetMethod(MethodInfo mi) { // Find method_3(TimeAndWeatherSettings timeAndWeather) var parameters = mi.GetParameters(); return (parameters.Length == 1 && parameters[0].ParameterType == typeof(TimeAndWeatherSettings)); } [PatchPostfix] private static void PatchPostfix(AbstractGame __instance) { var gameWorld = Singleton.Instance; // EFT.HideoutGame is an internal class, so we can't do static type checking :( if (__instance.GetType().Name.Contains("HideoutGame")) { return; } Location location = _locationProperty.GetValue(__instance) as Location; if (location == null) { Logger.LogError($"[SetLocationId] Failed to get location data"); return; } gameWorld.LocationId = location.Id; Logger.LogDebug($"[SetLocationId] Set locationId to: {location.Id}"); } } }