From 786db49b68dad9d0987967b673298eef76e6b4fe Mon Sep 17 00:00:00 2001 From: RMROC451 Date: Sun, 28 Jul 2024 08:13:21 -0500 Subject: [PATCH] #37 refactored caboose crew hours load refill logic, condensing and also allowing passenger stops to work as they were expected to. --- .../CarInspector_PopulateCarPanel_Patch.cs | 2 +- .../IndustryComponent_Service_Patch.cs | 139 ------------------ ...troller_AnnounceCoalescedPayments_Patch.cs | 138 +++++++++++++++++ .../Patches/TagController_UpdateTag_Patch.cs | 1 + 4 files changed, 140 insertions(+), 140 deletions(-) delete mode 100644 TweaksAndThings/Patches/IndustryComponent_Service_Patch.cs create mode 100644 TweaksAndThings/Patches/OpsController_AnnounceCoalescedPayments_Patch.cs diff --git a/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs b/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs index b367792..b936382 100644 --- a/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs +++ b/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs @@ -208,7 +208,7 @@ internal class CarInspector_PopulateCarPanel_Patch float originalTimeCost = consist.CalculateCostForAutoEngineerEndGearSetting(); float timeCost = originalTimeCost; float crewCost = timeCost / 3600; //hours of time deducted from caboose. - var tsString = crewCost.FormatCrewHours(IndustryComponent_Service_Patch.CrewHoursLoad().description); + var tsString = crewCost.FormatCrewHours(OpsController_AnnounceCoalescedPayments_Patch.CrewHoursLoad().description); Car? cabooseWithAvailCrew = NearbyCabooseWithAvailableCrew(car, crewCost, buttonsHaveCost); if (cabooseWithAvailCrew == null) timeCost *= 1.5f; var cabooseFoundDisplay = cabooseWithAvailCrew?.DisplayName ?? "No caboose"; diff --git a/TweaksAndThings/Patches/IndustryComponent_Service_Patch.cs b/TweaksAndThings/Patches/IndustryComponent_Service_Patch.cs deleted file mode 100644 index 4e3af99..0000000 --- a/TweaksAndThings/Patches/IndustryComponent_Service_Patch.cs +++ /dev/null @@ -1,139 +0,0 @@ -using Game.State; -using HarmonyLib; -using Model; -using Model.Definition.Data; -using Model.Ops.Definition; -using Model.OpsNew; -using Railloader; -using RMROC451.TweaksAndThings.Extensions; -using Serilog; -using System.Collections.Generic; -using System.Linq; -using UnityEngine; - -namespace RMROC451.TweaksAndThings.Patches; - -[HarmonyPatch(typeof(CarExtensions))] -[HarmonyPatch(nameof(CarExtensions.LoadString), typeof(CarLoadInfo), typeof(Load))] -[HarmonyPatchCategory("RMROC451TweaksAndThings")] -internal class CarExtensions_LoadString_Patch -{ - public static bool Prefix(CarLoadInfo info, Load load, ref string __result) - { - bool output = load.id == IndustryComponent_Service_Patch.CrewHoursLoad().id; - if (output) __result = info.Quantity.FormatCrewHours(load.description); - - return !output; - } -} - -[HarmonyPatch(typeof(CarPrototypeLibrary))] -[HarmonyPatch(nameof(CarPrototypeLibrary.LoadForId), typeof(string))] -[HarmonyPatchCategory("RMROC451TweaksAndThings")] -internal class CarPrototypeLibrary_LoadForId_Patch -{ - public static bool Prefix(string loadId, ref Load __result) - { - Load load = IndustryComponent_Service_Patch.CrewHoursLoad(); - if (loadId == load.id) __result = load; - - return __result == null; - } -} - -[HarmonyPatch(typeof(TeamTrack))] -[HarmonyPatch(nameof(TeamTrack.Service), typeof(IIndustryContext))] -[HarmonyPatchCategory("RMROC451TweaksAndThings")] -internal class TeamTrack_Service_Patch -{ - public static bool Prefix(IndustryComponent __instance, IIndustryContext ctx) - { - //Log.Information($"{nameof(SimplePassengerStop_Service_Patch)} => {((IndustryContext)ctx)._industry.name}"); - return IndustryComponent_Service_Patch.Prefix(__instance, ctx); - } -} - -[HarmonyPatch(typeof(RepairTrack))] -[HarmonyPatch(nameof(RepairTrack.Service), typeof(IIndustryContext))] -[HarmonyPatchCategory("RMROC451TweaksAndThings")] -internal class RepairTrack_Service_Patch -{ - public static bool Prefix(IndustryComponent __instance, IIndustryContext ctx) - { - //Log.Information($"{nameof(SimplePassengerStop_Service_Patch)} => {((IndustryContext)ctx)._industry.name}"); - return IndustryComponent_Service_Patch.Prefix(__instance, ctx); - } -} - -[HarmonyPatch(typeof(SimplePassengerStop))] -[HarmonyPatch(nameof(SimplePassengerStop.Service), typeof(IIndustryContext))] -[HarmonyPatchCategory("RMROC451TweaksAndThings")] -internal class SimplePassengerStop_Service_Patch -{ - public static bool Prefix(IndustryComponent __instance, IIndustryContext ctx) - { - Log.Information($"{nameof(SimplePassengerStop_Service_Patch)} => {((IndustryContext)ctx)._industry.name}"); - return IndustryComponent_Service_Patch.Prefix(__instance, ctx); - } -} - -internal static class IndustryComponent_Service_Patch -{ - public static Load CrewHoursLoad() - { - Load load = (Load)ScriptableObject.CreateInstance(typeof(Load)); - load.name = "crew-hours"; - load.description = "Crew"; - load.units = LoadUnits.Quantity; - - return load; - } - - public static bool Prefix(IndustryComponent __instance, IIndustryContext ctx) - { - TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared; - if (!StateManager.IsHost || !tweaksAndThings.IsEnabled || !(tweaksAndThings?.settings?.EndGearHelpersRequirePayment ?? false)) return true; - - Load load = CrewHoursLoad(); - - float rate2 = 24 * 2 * 8;// carLoadRate = 8 crew hours in 30 min loading; (24h * 2 to get half hour chunks * 8 hours to load in those chunks) - float num2 = 99999999; //QuantityInStorage for crew-hours (infinite where crew can be shuffling about) - float quantityToLoad = Mathf.Min(num2, IndustryComponent.RateToValue(rate2, ctx.DeltaTime)); - - var carsAtPosition = ctx.CarsAtPosition(); - - var cabeese = from car in carsAtPosition.Where(c => c.CarType == "NE") - where car.IsEmptyOrContains(load) - orderby car.QuantityOfLoad(load).quantity descending - select car; - - foreach (IOpsCar item in cabeese) - { - TrainController tc = UnityEngine.Object.FindAnyObjectByType(); - if (tc.TryGetCarForId(item.Id, out Car car)) - { - List loadSlots = car.Definition.LoadSlots; - float quantity = 0f; - float max = 0f; - for (int i = 0; i < loadSlots.Count; i++) - { - LoadSlot loadSlot = loadSlots[i]; - if (loadSlot.LoadRequirementsMatch(load) && loadSlot.LoadUnits == load.units) - { - CarLoadInfo? loadInfo = car.GetLoadInfo(i); - - quantity = loadInfo.HasValue ? loadInfo.Value.Quantity : 0f; - max = loadSlots[i].MaximumCapacity; - break; - } - } - //Log.Information($"{nameof(IndustryComponent_Service_Patch)} {car} => {car.StoppedDuration} => {quantityToLoad} => {quantity}/{max}"); - if (car.StoppedDuration > 30) item.Load(load, quantityToLoad); - } - - //todo:crew refresh message? - } - - return true; - } -} \ No newline at end of file diff --git a/TweaksAndThings/Patches/OpsController_AnnounceCoalescedPayments_Patch.cs b/TweaksAndThings/Patches/OpsController_AnnounceCoalescedPayments_Patch.cs new file mode 100644 index 0000000..19a22cc --- /dev/null +++ b/TweaksAndThings/Patches/OpsController_AnnounceCoalescedPayments_Patch.cs @@ -0,0 +1,138 @@ +using Game; +using Game.State; +using HarmonyLib; +using Model; +using Model.Definition.Data; +using Model.Ops.Definition; +using Model.OpsNew; +using Network; +using Railloader; +using RMROC451.TweaksAndThings.Extensions; +using RollingStock; +using Serilog; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace RMROC451.TweaksAndThings.Patches; + +[HarmonyPatch(typeof(CarExtensions))] +[HarmonyPatch(nameof(CarExtensions.LoadString), typeof(CarLoadInfo), typeof(Load))] +[HarmonyPatchCategory("RMROC451TweaksAndThings")] +internal class CarExtensions_LoadString_Patch +{ + public static bool Prefix(CarLoadInfo info, Load load, ref string __result) + { + bool output = load.id == OpsController_AnnounceCoalescedPayments_Patch.CrewHoursLoad().id; + if (output) __result = info.Quantity.FormatCrewHours(load.description); + + return !output; + } +} + +[HarmonyPatch(typeof(CarPrototypeLibrary))] +[HarmonyPatch(nameof(CarPrototypeLibrary.LoadForId), typeof(string))] +[HarmonyPatchCategory("RMROC451TweaksAndThings")] +internal class CarPrototypeLibrary_LoadForId_Patch +{ + public static bool Prefix(string loadId, ref Load __result) + { + Load load = OpsController_AnnounceCoalescedPayments_Patch.CrewHoursLoad(); + if (loadId == load.id) __result = load; + + return __result == null; + } +} + +[HarmonyPatch(typeof(OpsController))] +[HarmonyPatch(nameof(OpsController.AnnounceCoalescedPayments))] +[HarmonyPatchCategory("RMROC451TweaksAndThings")] +internal class OpsController_AnnounceCoalescedPayments_Patch +{ + static Dictionary CrewCarDict = []; + public static (bool spotted, bool filling) CrewCarStatus(Car car) + { + bool found = CrewCarDict.TryGetValue(car.id, out (bool spotted, bool filling) val); + + if (!found) CrewCarDict.Add(car.id, (false, false)); + + return val; + } + + static GameDateTime dateTime = TimeWeather.Now; + static readonly IEnumerable refillLocations = [ + typeof(PassengerStop), + typeof(SimplePassengerStop), + typeof(TeamTrack), + typeof(RepairTrack) + ]; + + public static Load CrewHoursLoad() + { + Load load = (Load)ScriptableObject.CreateInstance(typeof(Load)); + load.name = "crew-hours"; + load.description = "Crew"; + load.units = LoadUnits.Quantity; + + return load; + } + + private static void CarLoadCrewHelper(Car car, float deltaTime) + { + float rate2 = 24 * 2 * 8;// carLoadRate = 8 crew hours in 30 min loading; (24h * 2 to get half hour chunks * 8 hours to load in those chunks) + float num2 = 99999999; //QuantityInStorage for crew-hours (infinite where crew can be shuffling about) + float quantityToLoad = Mathf.Min(num2, IndustryComponent.RateToValue(rate2, deltaTime)); + + if (car.IsCaboose() && !CrewCarStatus(car).spotted) + { + CrewCarDict[car.id] = (true, CrewCarDict[car.id].filling); + } + if (car.IsCabooseAndStoppedForLoadRefresh()) + { + if (!CrewCarDict[car.id].filling) Multiplayer.Broadcast($"{Hyperlink.To(car)}: \"Topping off caboose crew.\""); + CrewCarDict[car.id] = (CrewCarDict[car.id].spotted, true); + var data = car.QuantityCapacityOfLoad(CrewHoursLoad()); + if ((data.quantity + quantityToLoad > data.capacity) && data.quantity < data.capacity) + { + Multiplayer.Broadcast($"{Hyperlink.To(car)}: \"Caboose crew topped off.\""); + CrewCarDict[car.id] = (CrewCarDict[car.id].spotted, false); + } + new OpsCarAdapter(car, OpsController.Shared).Load(CrewHoursLoad(), quantityToLoad); + } + } + + public static bool Prefix(IndustryComponent __instance) + { + TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared; + if (!StateManager.IsHost || !tweaksAndThings.IsEnabled || !(tweaksAndThings?.settings?.EndGearHelpersRequirePayment ?? false)) return true; + + + TrainController tc = UnityEngine.Object.FindAnyObjectByType(); + try { + + var passengerStops = OpsController.Shared.AllIndustries + .SelectMany(i => i.TrackDisplayables.Where(t => refillLocations.Contains(t.GetType()))); + //Log.Information($"{nameof(OpsController_AnnounceCoalescedPayments_Patch)} => Caboose Helper => PassengerStops => {string.Join(",", passengerStops)}"); + + var cabeese = passengerStops + .SelectMany(t => t.TrackSpans?.Select(s => (tc.CarsOnSpan(s) ?? []).Where(c => c.IsCaboose()))?.SelectMany(c => c?.Select(c2 => (t, c2)))); + //Log.Information($"{nameof(OpsController_AnnounceCoalescedPayments_Patch)} => Caboose Helper => PassengerStops Cabeese => {string.Join(",", cabeese?.Select(c => $"{c.t} : {c.c2}") ?? [])}"); + + CrewCarDict = CrewCarDict.Where(kvp => cabeese.Select(c => c.c2.id).Contains(kvp.Key)).ToDictionary(k => k.Key, v => v.Value); + + var deltaTime = (float)(TimeWeather.Now.TotalSeconds - dateTime.TotalSeconds); + foreach (var caboose in cabeese) + { + //Log.Information($"{nameof(OpsController_AnnounceCoalescedPayments_Patch)} => Caboose Helper ({deltaTime}) => {caboose.t} : {caboose.c2}"); + CarLoadCrewHelper(caboose.c2, deltaTime); + } + dateTime = TimeWeather.Now; + } catch (System.Exception ex) + { + Log.Error(ex, "error with announce caboose helper"); + } + + return true; + } +} \ No newline at end of file diff --git a/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs b/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs index 7fe04e2..5fda423 100644 --- a/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs +++ b/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs @@ -36,6 +36,7 @@ internal class TagController_UpdateTag_Patch tagCallout.callout.Title = string.Format(tagTitleFormat, "{0}", car.DisplayName); List tags = []; + if (OpsController_AnnounceCoalescedPayments_Patch.CrewCarStatus(car).spotted) tags.Add("+"); if (car.HasHotbox) tags.Add(TextSprites.Hotbox); if (car.EndAirSystemIssue()) tags.Add(TextSprites.CycleWaybills); if (car.HandbrakeApplied()) tags.Add(TextSprites.HandbrakeWheel);