diff --git a/Directory.Build.targets b/Directory.Build.targets index f80f66e..c0a2328 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -12,7 +12,7 @@ 0 1 - 7 + 8 $(MajorVersion).$(MinorVersion).$(PatchVersion) $(AssemblyVersion) $(AssemblyVersion) diff --git a/TweaksAndThings/Extensions/AutoEngineer_Extensions.cs b/TweaksAndThings/Extensions/AutoEngineer_Extensions.cs new file mode 100644 index 0000000..9de603e --- /dev/null +++ b/TweaksAndThings/Extensions/AutoEngineer_Extensions.cs @@ -0,0 +1,93 @@ +using Model.AI; +using System.Collections; +using UnityEngine; + +namespace RMROC451.TweaksAndThings.Extensions +{ + internal static class AutoEngineer_Extensions + { + private static float CabooseHalvedFloat(this float input, bool hasCaboose) => + hasCaboose ? input / 2 : input; + + private static float CabooseAutoOilerLimit(this bool hasCaboose) => + hasCaboose ? 0.99f : AutoOiler.OilIfBelow; + + public static IEnumerator MrocAutoOilerLoop(this AutoOiler oiler, Serilog.ILogger _log) + { + int originIndex = oiler.FindOriginIndex(); + bool hasCaboose = oiler._cars.CabooseInConsist(); + if (originIndex < 0) + { + _log.Error("Couldn't find origin car {car}", oiler._originCar); + oiler._coroutine = null; + yield break; + } + oiler._reverse = originIndex > oiler._cars.Count - originIndex; + _log.Information( + "AutoOiler {name} starting, rev = {reverse}, caboose halving adjustment = {hasCaboose}, oil limit = {limit}", + oiler.name, + oiler._reverse, + hasCaboose, + hasCaboose.CabooseAutoOilerLimit() + ); + while (true) + { + yield return new WaitForSeconds(AutoOiler.StartDelay.CabooseHalvedFloat(hasCaboose)); + int carIndex = originIndex; + float adjustedTimeToWalk = AutoOiler.TimeToWalkCar.CabooseHalvedFloat(hasCaboose); + do + { + if (oiler.TryGetCar(carIndex, out var car)) + { + float num = 0f; + float origOil = car.Oiled; + if (car.NeedsOiling && car.Oiled < hasCaboose.CabooseAutoOilerLimit()) + { + float num2 = 1f - car.Oiled; + car.OffsetOiled(num2); + float num3 = num2 * AutoOiler.TimeToFullyOil.CabooseHalvedFloat(hasCaboose); + num += num3; + oiler._pendingRunDuration += num3; + oiler._oiledCount++; + _log.Information("AutoOiler {name}: oiled {car} from {orig} => {new}", oiler.name, car, origOil, car.Oiled); + } + num += adjustedTimeToWalk; + oiler._pendingRunDuration += adjustedTimeToWalk; + yield return new WaitForSeconds(num); + } + carIndex = oiler.NextIndex(carIndex); + } + while (oiler.InBounds(carIndex)); + oiler._reverse = !oiler._reverse; + oiler.PayWages(); + } + } + + public static IEnumerator MrocAutoHotboxSpotterLoop(this AutoHotboxSpotter spotter, Serilog.ILogger _log) + { + while (true) + { + bool hasCaboose = spotter._cars.CabooseInConsist(); + if (!spotter.HasCars) + { + yield return new WaitForSeconds(1f); + continue; + } + _log.Information("AutoHotboxSpotter {name}: Hotbox Spotter Running, Has Caboose => {hasCaboose}; Has Cars {hasCars}", spotter.name, hasCaboose, spotter.HasCars); + spotter.CheckForHotbox(); + while (spotter.HasCars) + { + int num = Random.Range(60, 300); + if (hasCaboose) + { + var numOrig = num; + num = Random.Range(15, 30); + _log.Information("AutoHotboxSpotter {name}: Next check went from num(60,300) => {numOrig}; to num(15,30) => {hasCaboose}", spotter.name, numOrig, num); + } + yield return new WaitForSeconds(num); + spotter.CheckForHotbox(); + } + } + } + } +} diff --git a/TweaksAndThings/Patches/AutoHotboxSpotter_SpotterLoop_Patch.cs b/TweaksAndThings/Patches/AutoHotboxSpotter_SpotterLoop_Patch.cs new file mode 100644 index 0000000..6b742ce --- /dev/null +++ b/TweaksAndThings/Patches/AutoHotboxSpotter_SpotterLoop_Patch.cs @@ -0,0 +1,26 @@ +using HarmonyLib; +using Model.AI; +using Railloader; +using RMROC451.TweaksAndThings.Extensions; +using Serilog; +using System.Collections; + +namespace RMROC451.TweaksAndThings.Patches; + +[HarmonyPatch(typeof(AutoHotboxSpotter))] +[HarmonyPatch(nameof(AutoHotboxSpotter.SpotterLoop))] +[HarmonyPatchCategory("RMROC451TweaksAndThings")] +internal class AutoHotboxSpotter_SpotterLoop_Patch +{ + private static ILogger _log => Log.ForContext(); + + public static bool Prefix(AutoHotboxSpotter __instance, ref IEnumerator __result) + { + TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared; + if (!tweaksAndThings.IsEnabled) return true; + bool buttonsHaveCost = tweaksAndThings?.settings?.EndGearHelpersRequirePayment ?? false; + + if (buttonsHaveCost) __result = __instance.MrocAutoHotboxSpotterLoop(_log); + return !buttonsHaveCost; //only hit this if !buttonsHaveCost, since Loop is a coroutine + } +} diff --git a/TweaksAndThings/Patches/AutoOiler_Loop_Patch.cs b/TweaksAndThings/Patches/AutoOiler_Loop_Patch.cs new file mode 100644 index 0000000..c496de8 --- /dev/null +++ b/TweaksAndThings/Patches/AutoOiler_Loop_Patch.cs @@ -0,0 +1,26 @@ +using HarmonyLib; +using Model.AI; +using Railloader; +using RMROC451.TweaksAndThings.Extensions; +using Serilog; +using System.Collections; + +namespace RMROC451.TweaksAndThings.Patches; + +[HarmonyPatch(typeof(AutoOiler))] +[HarmonyPatch(nameof(AutoOiler.Loop))] +[HarmonyPatchCategory("RMROC451TweaksAndThings")] +internal class AutoOiler_Loop_Patch +{ + private static ILogger _log => Log.ForContext(); + + public static bool Prefix(AutoOiler __instance, ref IEnumerator __result) + { + TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared; + if (!tweaksAndThings.IsEnabled) return true; + bool buttonsHaveCost = tweaksAndThings?.settings?.EndGearHelpersRequirePayment ?? false; + + if (buttonsHaveCost)__result = __instance.MrocAutoOilerLoop(_log); + return !buttonsHaveCost; //only hit this if !buttonsHaveCost, since Loop is a coroutine + } +} diff --git a/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs b/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs index 78cbc07..e1cd48b 100644 --- a/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs +++ b/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs @@ -26,6 +26,7 @@ namespace RMROC451.TweaksAndThings.Patches; [HarmonyPatchCategory("RMROC451TweaksAndThings")] internal class CarInspector_PopulateCarPanel_Patch { + private static ILogger _log => Log.ForContext(); private static IEnumerable ends = Enum.GetValues(typeof(LogicalEnd)).Cast(); /// @@ -95,13 +96,13 @@ internal class CarInspector_PopulateCarPanel_Patch { try { - if (car.TagCallout != null) tagController.UpdateTag(car, car.TagCallout, OpsController.Shared); - if (ContextMenu.IsShown && ContextMenu.Shared.centerLabel.text == car.DisplayName) CarPickable.HandleShowContextMenu(car); builder.Rebuild(); + if (car.TagCallout != null) tagController.UpdateTags(CameraSelector.shared._currentCamera.GroundPosition, true); //tagController.UpdateTag(car, car.TagCallout, OpsController.Shared); + if (ContextMenu.IsShown && ContextMenu.Shared.centerLabel.text == car.DisplayName) CarPickable.HandleShowContextMenu(car); } catch(Exception ex) { - Log.Warning(ex, $"{nameof(AddObserver)} {car} Exception logged for {key}"); + _log.ForContext("car", car).Warning(ex, $"{nameof(AddObserver)} {car} Exception logged for {key}"); } }, false @@ -125,7 +126,7 @@ internal class CarInspector_PopulateCarPanel_Patch { TrainController tc = UnityEngine.Object.FindObjectOfType(); IEnumerable consist = car.EnumerateCoupled(LogicalEnd.A); - //Log.Information($"{car} => {mrocHelperType} => {string.Join("/", consist.Select(c => c.ToString()))}"); + _log.ForContext("car", car).Verbose($"{car} => {mrocHelperType} => {string.Join("/", consist.Select(c => c.ToString()))}"); CalculateCostIfEnabled(car, mrocHelperType, buttonsHaveCost, consist); @@ -139,7 +140,6 @@ internal class CarInspector_PopulateCarPanel_Patch else { consist = consist.Where(c => c is not BaseLocomotive && c.Archetype != Model.Definition.CarArchetype.Tender); - Log.Information($"{car} => {mrocHelperType} => {string.Join("/", consist.Select(c => c.ToString()))}"); //when ApplyHandbrakesAsNeeded is called, and the consist contains an engine, it stops applying brakes. tc.ApplyHandbrakesAsNeeded(consist.ToList(), PlaceTrainHandbrakes.Automatic); } @@ -166,7 +166,7 @@ internal class CarInspector_PopulateCarPanel_Patch case MrocHelperType.BleedAirSystem: consist = consist.Where(c => c.NotMotivePower()); - Log.Information($"{car} => {mrocHelperType} => {string.Join("/", consist.Select(c => c.ToString()))}"); + _log.ForContext("car", car).Information($"{car} => {mrocHelperType} => {string.Join("/", consist.Select(c => c.ToString()))}"); foreach (Model.Car bleed in consist) { StateManager.ApplyLocal(new PropertyChange(bleed.id, PropertyChange.Control.Bleed, 1)); @@ -187,12 +187,12 @@ internal class CarInspector_PopulateCarPanel_Patch if (cabooseWithAvailCrew == null) timeCost *= 1.5f; var cabooseFoundDisplay = cabooseWithAvailCrew?.DisplayName ?? "No caboose"; - Log.Information($"{nameof(MrocConsistHelper)} {mrocHelperType} : [VACINITY CABEESE FOUND:{cabooseWithAvailCrew?.ToString() ?? "NONE"}] => Consist Length {consist.Count()} => costs {timeCost / 60} minutes of AI Engineer time, $5 per hour = ~${Math.Ceiling((decimal)(timeCost / 3600) * 5)} (*2 if no caboose nearby)"); + _log.ForContext("car", car).Information($"{nameof(MrocConsistHelper)} {mrocHelperType} : [VACINITY CABEESE FOUND:{cabooseWithAvailCrew?.ToString() ?? "NONE"}] => Consist Length {consist.Count()} => costs {timeCost / 60} minutes of AI Engineer time, $5 per hour = ~${Math.Ceiling((decimal)(timeCost / 3600) * 5)} (*2 if no caboose nearby)"); Multiplayer.SendError(StateManager.Shared._playersManager.LocalPlayer, $"{(cabooseWithAvailCrew != null ? $"{cabooseWithAvailCrew.DisplayName} Hours Adjusted: ({tsString})\n" : string.Empty)}Wages: ~(${Math.Ceiling((decimal)(timeCost / 3600) * 5)})"); - if (buttonsHaveCost) StateManager_OnDayDidChange_Patch.UnbilledAutoBrakeCrewRunDuration += timeCost; + StateManager_OnDayDidChange_Patch.UnbilledAutoBrakeCrewRunDuration += timeCost; } } diff --git a/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs b/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs index 825f595..a9acf17 100644 --- a/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs +++ b/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs @@ -3,9 +3,7 @@ using Model; using Model.OpsNew; using Railloader; using RMROC451.TweaksAndThings.Extensions; -using UI; using UI.Tags; -using UnityEngine; namespace RMROC451.TweaksAndThings.Patches; @@ -19,7 +17,6 @@ internal class TagController_UpdateTag_Patch private static void Postfix(Car car, TagCallout tagCallout) { - TagController tagController = UnityEngine.Object.FindObjectOfType(); TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared; if (!tweaksAndThings.IsEnabled || !tweaksAndThings.settings.HandBrakeAndAirTagModifiers) @@ -27,24 +24,14 @@ internal class TagController_UpdateTag_Patch return; } - ProceedWithPostFix(car, tagCallout, tagController); + ProceedWithPostFix(car, tagCallout); return; } - private static void ProceedWithPostFix(Car car, TagCallout tagCallout, TagController tagController) + private static void ProceedWithPostFix(Car car, TagCallout tagCallout) { - bool isAltDownWithCarIssue = GameInput.IsAltDown && car.CarOrEndGearIssue(); tagCallout.callout.Title = string.Format(tagTitleFormat, "{0}", car.DisplayName); - tagCallout.gameObject.SetActive( - tagCallout.gameObject.activeSelf && - (!GameInput.IsAltDown || isAltDownWithCarIssue) - ); - - if (tagCallout.gameObject.activeSelf && isAltDownWithCarIssue) - { - tagController.ApplyImageColor(tagCallout, Color.black); - } tagCallout.callout.Title = (car.CarAndEndGearIssue(), car.EndAirSystemIssue(), car.HandbrakeApplied()) switch