From 0b444d6364d6fd2a1a84b38cdc269109c9a84d78 Mon Sep 17 00:00:00 2001 From: RMROC451 Date: Fri, 26 Jul 2024 10:13:35 -0500 Subject: [PATCH 1/6] #27 fix issue with last car end gear issue detection --- TweaksAndThings/Extensions/Car_Extensions.cs | 26 +++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/TweaksAndThings/Extensions/Car_Extensions.cs b/TweaksAndThings/Extensions/Car_Extensions.cs index f861712..0783eec 100644 --- a/TweaksAndThings/Extensions/Car_Extensions.cs +++ b/TweaksAndThings/Extensions/Car_Extensions.cs @@ -12,10 +12,14 @@ namespace RMROC451.TweaksAndThings.Extensions; public static class Car_Extensions { + private static bool EndGearIssue(this Car car, Car.LogicalEnd end) => + (!car[end].IsCoupled && car[end].IsAnglecockOpen) || + (car[end].IsCoupled && !car[end].IsAirConnectedAndOpen); + public static bool EndAirSystemIssue(this Car car) { - bool AEndAirSystemIssue = car[Car.LogicalEnd.A].IsCoupled && !car[Car.LogicalEnd.A].IsAirConnectedAndOpen; - bool BEndAirSystemIssue = car[Car.LogicalEnd.B].IsCoupled && !car[Car.LogicalEnd.B].IsAirConnectedAndOpen; + bool AEndAirSystemIssue = car.EndGearIssue(Car.LogicalEnd.A); + bool BEndAirSystemIssue = car.EndGearIssue(Car.LogicalEnd.B); bool EndAirSystemIssue = AEndAirSystemIssue || BEndAirSystemIssue; return EndAirSystemIssue; } @@ -104,18 +108,18 @@ public static class Car_Extensions Rect rect = new Rect(new Vector2(center.x - 30f, center.z - 30f), Vector2.one * 30f * 2f); var cars = tc.CarIdsInRect(rect); Log.Information($"{nameof(HuntingForCabeeseNearCar)} => {cars.Count()}"); - List<(string carId, float distance)> source = + List<(string carId, float distance)> source = cars .Select(carId => + { + Car car = tc.CarForId(carId); + if (car == null || !car.CabooseWithSufficientCrewHours(timeNeeded, carIdsCheckedAlready)) { - Car car = tc.CarForId(carId); - if (car == null || !car.CabooseWithSufficientCrewHours(timeNeeded, carIdsCheckedAlready)) - { - return (carId: carId, distance: 1000f); - } - Vector3 a = WorldTransformer.WorldToGame(car.GetMotionSnapshot().Position); - return (carId: carId, distance: Vector3.Distance(a, center)); - }).ToList(); + return (carId: carId, distance: 1000f); + } + Vector3 a = WorldTransformer.WorldToGame(car.GetMotionSnapshot().Position); + return (carId: carId, distance: Vector3.Distance(a, center)); + }).ToList(); return source; } } From d7e35828b813098f24454fa280182b27ad9c4f32 Mon Sep 17 00:00:00 2001 From: RMROC451 Date: Fri, 26 Jul 2024 10:15:09 -0500 Subject: [PATCH 2/6] #28 add hotbox icon to tag update info --- .../Patches/TagController_UpdateTag_Patch.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs b/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs index a9acf17..7fe04e2 100644 --- a/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs +++ b/TweaksAndThings/Patches/TagController_UpdateTag_Patch.cs @@ -3,6 +3,8 @@ using Model; using Model.OpsNew; using Railloader; using RMROC451.TweaksAndThings.Extensions; +using System.Collections.Generic; +using System.Linq; using UI.Tags; namespace RMROC451.TweaksAndThings.Patches; @@ -32,13 +34,16 @@ internal class TagController_UpdateTag_Patch private static void ProceedWithPostFix(Car car, TagCallout tagCallout) { tagCallout.callout.Title = string.Format(tagTitleFormat, "{0}", car.DisplayName); + List tags = []; + + if (car.HasHotbox) tags.Add(TextSprites.Hotbox); + if (car.EndAirSystemIssue()) tags.Add(TextSprites.CycleWaybills); + if (car.HandbrakeApplied()) tags.Add(TextSprites.HandbrakeWheel); tagCallout.callout.Title = - (car.CarAndEndGearIssue(), car.EndAirSystemIssue(), car.HandbrakeApplied()) switch + tags.Any() switch { - (true, _, _) => $"{tagCallout.callout.Title}{tagTitleAndIconDelimeter}{TextSprites.CycleWaybills}{TextSprites.HandbrakeWheel}".Replace("{0}", "2"), - (_, true, _) => $"{tagCallout.callout.Title}{tagTitleAndIconDelimeter}{TextSprites.CycleWaybills}".Replace("{0}", "1"), - (_, _, true) => $"{tagCallout.callout.Title}{tagTitleAndIconDelimeter}{TextSprites.HandbrakeWheel}".Replace("{0}", "1"), + true => $"{tagCallout.callout.Title}{tagTitleAndIconDelimeter}{string.Join("", tags)}".Replace("{0}", tags.Count().ToString()), _ => car.DisplayName }; } From d4d18d8c9210534f8f8b71794491366db990f146 Mon Sep 17 00:00:00 2001 From: RMROC451 Date: Fri, 26 Jul 2024 10:17:09 -0500 Subject: [PATCH 3/6] #25 adding follow to car context menu --- .../Patches/CarPickable_HandleShowContextMenu_Patch.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TweaksAndThings/Patches/CarPickable_HandleShowContextMenu_Patch.cs b/TweaksAndThings/Patches/CarPickable_HandleShowContextMenu_Patch.cs index 723f828..36e82c9 100644 --- a/TweaksAndThings/Patches/CarPickable_HandleShowContextMenu_Patch.cs +++ b/TweaksAndThings/Patches/CarPickable_HandleShowContextMenu_Patch.cs @@ -45,6 +45,11 @@ internal class CarPickable_HandleShowContextMenu_Patch }); } + shared.AddButton(ContextMenuQuadrant.Unused2, $"Follow", SpriteName.Inspect, delegate + { + CameraSelector.shared.FollowCar(car); + }); + shared.BuildItemAngles(); shared.StartCoroutine(shared.AnimateButtonsShown()); } From 5eed492b47f24e22eb7b8e60035d1d556fa7c2fb Mon Sep 17 00:00:00 2001 From: RMROC451 Date: Fri, 26 Jul 2024 12:20:52 -0500 Subject: [PATCH 4/6] #24 adding consist info to non motive power cars, that have a caboose, when `Caboose Use` mod setting is enabled. --- .../CarInspector_PopulateCarPanel_Patch.cs | 50 ++++++++++++++----- TweaksAndThings/Settings/Settings.cs | 3 ++ 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs b/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs index e1cd48b..1d86828 100644 --- a/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs +++ b/TweaksAndThings/Patches/CarInspector_PopulateCarPanel_Patch.cs @@ -1,9 +1,9 @@ -using Game.Messages; +using Core; +using Game.Messages; using Game.State; using HarmonyLib; using KeyValue.Runtime; using Model; -using Model.OpsNew; using Network; using Railloader; using RMROC451.TweaksAndThings.Enums; @@ -13,6 +13,7 @@ using Serilog; using System; using System.Collections.Generic; using System.Linq; +using UI; using UI.Builder; using UI.CarInspector; using UI.ContextMenu; @@ -40,36 +41,61 @@ internal class CarInspector_PopulateCarPanel_Patch TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared; if (!tweaksAndThings.IsEnabled) return true; - bool buttonsHaveCost = tweaksAndThings?.settings?.EndGearHelpersRequirePayment ?? false; + bool buttonsHaveCost = tweaksAndThings.EndGearHelpersRequirePayment(); - var consist = __instance._car.EnumerateCoupled(LogicalEnd.A); + var consist = __instance._car._set.Cars; builder = AddCarConsistRebuildObservers(builder, consist); builder.HStack(delegate (UIPanelBuilder hstack) { var buttonName = $"{(consist.Any(c => c.HandbrakeApplied()) ? "Release " : "Set ")} {TextSprites.HandbrakeWheel}"; - hstack.AddButtonCompact(buttonName, delegate { + hstack.AddButtonCompact(buttonName, delegate + { MrocConsistHelper(__instance._car, MrocHelperType.Handbrake, buttonsHaveCost); hstack.Rebuild(); }).Tooltip(buttonName, $"Iterates over cars in this consist and {(consist.Any(c => c.HandbrakeApplied()) ? "releases" : "sets")} {TextSprites.HandbrakeWheel}."); if (consist.Any(c => c.EndAirSystemIssue())) { - hstack.AddButtonCompact("Connect Air", delegate { + hstack.AddButtonCompact("Connect Air", delegate + { MrocConsistHelper(__instance._car, MrocHelperType.GladhandAndAnglecock, buttonsHaveCost); hstack.Rebuild(); }).Tooltip("Connect Consist Air", "Iterates over each car in this consist and connects gladhands and opens anglecocks."); } - hstack.AddButtonCompact("Bleed Consist", delegate { + hstack.AddButtonCompact("Bleed Consist", delegate + { MrocConsistHelper(__instance._car, MrocHelperType.BleedAirSystem, buttonsHaveCost); hstack.Rebuild(); }).Tooltip("Bleed Air Lines", "Iterates over each car in this consist and bleeds the air out of the lines."); }); + CabooseUiEnhancer(__instance, builder, consist, tweaksAndThings); + return true; } + private static void CabooseUiEnhancer(CarInspector __instance, UIPanelBuilder builder, IEnumerable consist, TweaksAndThingsPlugin plugin) + { + if (plugin.CabooseNonMotiveAllowedSetting(__instance._car)) + { + builder.HStack(delegate (UIPanelBuilder hstack) + { + hstack.AddField("Consist Info", hstack.HStack(delegate (UIPanelBuilder field) + { + int consistLength = consist.Count(); + int tonnage = LocomotiveControlsHoverArea.CalculateTonnage(consist); + int lengthInMeters = UnityEngine.Mathf.CeilToInt(LocomotiveControlsHoverArea.CalculateLengthInMeters(consist.ToList()) * 3.28084f); + var newSubTitle = () => string.Format("{0}, {1:N0}T, {2:N0}ft, {3:0.0} mph", consistLength.Pluralize("car"), tonnage, lengthInMeters, __instance._car.VelocityMphAbs); + + field.AddLabel(() => newSubTitle(), UIPanelBuilder.Frequency.Fast) + .Tooltip("Consist Info", "Reflects info about consist.").FlexibleWidth(); + })); + }); + } + } + private static UIPanelBuilder AddCarConsistRebuildObservers(UIPanelBuilder builder, IEnumerable consist) { TagController tagController = UnityEngine.Object.FindFirstObjectByType(); @@ -100,7 +126,7 @@ internal class CarInspector_PopulateCarPanel_Patch 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) + catch (Exception ex) { _log.ForContext("car", car).Warning(ex, $"{nameof(AddObserver)} {car} Exception logged for {key}"); } @@ -114,7 +140,7 @@ internal class CarInspector_PopulateCarPanel_Patch //var dh = new DownloadHandlerAudioClip($"file://{cacheFileName}", AudioType.MPEG); //dh.compressed = true; // This - + //using (UnityWebRequest wr = new UnityWebRequest($"file://{cacheFileName}", "GET", dh, null)) { // yield return wr.SendWebRequest(); // if (wr.responseCode == 200) { @@ -125,7 +151,7 @@ internal class CarInspector_PopulateCarPanel_Patch public static void MrocConsistHelper(Model.Car car, MrocHelperType mrocHelperType, bool buttonsHaveCost) { TrainController tc = UnityEngine.Object.FindObjectOfType(); - IEnumerable consist = car.EnumerateCoupled(LogicalEnd.A); + IEnumerable consist = car._set.Cars; _log.ForContext("car", car).Verbose($"{car} => {mrocHelperType} => {string.Join("/", consist.Select(c => c.ToString()))}"); CalculateCostIfEnabled(car, mrocHelperType, buttonsHaveCost, consist); @@ -194,7 +220,7 @@ internal class CarInspector_PopulateCarPanel_Patch StateManager_OnDayDidChange_Patch.UnbilledAutoBrakeCrewRunDuration += timeCost; } - } + } public static Car? NearbyCabooseWithAvailableCrew(Car car, float timeNeeded, bool decrement = false) { @@ -206,7 +232,7 @@ internal class CarInspector_PopulateCarPanel_Patch carIdsCheckedAlready.Add(car.id); //check consist, for cabeese - IEnumerable consist = car.EnumerateCoupled(LogicalEnd.A); + IEnumerable consist = car._set.Cars; output = consist.FirstOrDefault(c => c.CabooseWithSufficientCrewHours(timeNeeded, carIdsCheckedAlready, decrement)); if (output != null) return output; //short out if we are good carIdsCheckedAlready.UnionWith(consist.Select(c => c.id)); diff --git a/TweaksAndThings/Settings/Settings.cs b/TweaksAndThings/Settings/Settings.cs index ff5ca35..9e3a1cd 100644 --- a/TweaksAndThings/Settings/Settings.cs +++ b/TweaksAndThings/Settings/Settings.cs @@ -91,4 +91,7 @@ public static class SettingsExtensions return output; } + public static bool CabooseNonMotiveAllowedSetting(this TweaksAndThingsPlugin input, Car car) => + input.EndGearHelpersRequirePayment() && car.set.Cars.CabooseInConsist() && car.NotMotivePower(); + } \ No newline at end of file From 5774c7f04c9d8a806914ea644910db59cc6bd358 Mon Sep 17 00:00:00 2001 From: RMROC451 Date: Fri, 26 Jul 2024 12:25:03 -0500 Subject: [PATCH 5/6] #29 #30 Allow caboose setting to require that a caboose is present in the consist to use the AI Engineer's AutoOiler & AutoHotboxSpotter. --- Directory.Build.targets | 3 +- .../Extensions/AutoEngineer_Extensions.cs | 33 ++++-- .../AutoHotboxSpotter_SpotterLoop_Patch.cs | 5 +- .../Patches/AutoOiler_Loop_Patch.cs | 5 +- ...CarPickable_HandleShowContextMenu_Patch.cs | 10 +- TweaksAndThings/Settings/Settings.cs | 24 +++- TweaksAndThings/TweaksAndThingsPlugin.cs | 107 +++++++++++------- updates.json | 12 ++ 8 files changed, 135 insertions(+), 64 deletions(-) create mode 100644 updates.json diff --git a/Directory.Build.targets b/Directory.Build.targets index c0a2328..a8b529e 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -6,6 +6,7 @@ $(GameDir)/Mods/$(AssemblyName) $(GameModDir)/ + $([System.DateTime]::UtcNow.ToString(`o`)) @@ -30,7 +31,7 @@ - + $(OutputPath)/Mods diff --git a/TweaksAndThings/Extensions/AutoEngineer_Extensions.cs b/TweaksAndThings/Extensions/AutoEngineer_Extensions.cs index 9de603e..ddfc50f 100644 --- a/TweaksAndThings/Extensions/AutoEngineer_Extensions.cs +++ b/TweaksAndThings/Extensions/AutoEngineer_Extensions.cs @@ -12,7 +12,7 @@ namespace RMROC451.TweaksAndThings.Extensions private static float CabooseAutoOilerLimit(this bool hasCaboose) => hasCaboose ? 0.99f : AutoOiler.OilIfBelow; - public static IEnumerator MrocAutoOilerLoop(this AutoOiler oiler, Serilog.ILogger _log) + public static IEnumerator MrocAutoOilerLoop(this AutoOiler oiler, Serilog.ILogger _log, bool cabooseRequired) { int originIndex = oiler.FindOriginIndex(); bool hasCaboose = oiler._cars.CabooseInConsist(); @@ -21,13 +21,17 @@ namespace RMROC451.TweaksAndThings.Extensions _log.Error("Couldn't find origin car {car}", oiler._originCar); oiler._coroutine = null; yield break; + } else if (CabooseRequirementChecker(string.Format("{0} {1}", oiler.GetType().Name, oiler.name), cabooseRequired, hasCaboose, _log)) + { + 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, + "AutoOiler {name} starting, rev = {reverse}, caboose required = {req}, caboose halving adjustment = {hasCaboose}, oil limit = {limit}", + oiler.name, + oiler._reverse, + cabooseRequired, + hasCaboose, hasCaboose.CabooseAutoOilerLimit() ); while (true) @@ -63,7 +67,7 @@ namespace RMROC451.TweaksAndThings.Extensions } } - public static IEnumerator MrocAutoHotboxSpotterLoop(this AutoHotboxSpotter spotter, Serilog.ILogger _log) + public static IEnumerator MrocAutoHotboxSpotterLoop(this AutoHotboxSpotter spotter, Serilog.ILogger _log, bool cabooseRequired) { while (true) { @@ -73,7 +77,11 @@ namespace RMROC451.TweaksAndThings.Extensions yield return new WaitForSeconds(1f); continue; } - _log.Information("AutoHotboxSpotter {name}: Hotbox Spotter Running, Has Caboose => {hasCaboose}; Has Cars {hasCars}", spotter.name, hasCaboose, spotter.HasCars); + _log.Information("AutoHotboxSpotter {name}: Hotbox Spotter Running, Has Caboose => {hasCaboose}; Has Cars {hasCars}; Requires Caboose {requiresCaboose}", spotter.name, hasCaboose, spotter.HasCars, cabooseRequired); + if (CabooseRequirementChecker(string.Format("{0} {1}", spotter.GetType().Name, spotter.name), cabooseRequired, hasCaboose, _log)) + { + yield break; + } spotter.CheckForHotbox(); while (spotter.HasCars) { @@ -82,12 +90,21 @@ namespace RMROC451.TweaksAndThings.Extensions { 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); + _log.Information("AutoHotboxSpotter {name}: Next check went from num(60,300) => {numOrig}; to num(15,30) => {hasCaboose}; Requires Caboose {requiresCaboose}", spotter.name, numOrig, num, hasCaboose, cabooseRequired); } yield return new WaitForSeconds(num); spotter.CheckForHotbox(); } } } + + private static bool CabooseRequirementChecker(string name, bool cabooseRequired, bool hasCaboose, Serilog.ILogger _log) + { + bool error = cabooseRequired && !hasCaboose; + if (error) { + _log.Debug("{name}: Couldn't find required caboose!", name); + } + return error; + } } } diff --git a/TweaksAndThings/Patches/AutoHotboxSpotter_SpotterLoop_Patch.cs b/TweaksAndThings/Patches/AutoHotboxSpotter_SpotterLoop_Patch.cs index 6b742ce..f0fd551 100644 --- a/TweaksAndThings/Patches/AutoHotboxSpotter_SpotterLoop_Patch.cs +++ b/TweaksAndThings/Patches/AutoHotboxSpotter_SpotterLoop_Patch.cs @@ -18,9 +18,10 @@ internal class AutoHotboxSpotter_SpotterLoop_Patch { TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared; if (!tweaksAndThings.IsEnabled) return true; - bool buttonsHaveCost = tweaksAndThings?.settings?.EndGearHelpersRequirePayment ?? false; + bool buttonsHaveCost = tweaksAndThings.EndGearHelpersRequirePayment(); + bool cabooseRequired = tweaksAndThings.RequireConsistCabooseForOilerAndHotboxSpotter(); - if (buttonsHaveCost) __result = __instance.MrocAutoHotboxSpotterLoop(_log); + if (buttonsHaveCost) __result = __instance.MrocAutoHotboxSpotterLoop(_log, cabooseRequired); 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 index c496de8..afc2602 100644 --- a/TweaksAndThings/Patches/AutoOiler_Loop_Patch.cs +++ b/TweaksAndThings/Patches/AutoOiler_Loop_Patch.cs @@ -18,9 +18,10 @@ internal class AutoOiler_Loop_Patch { TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared; if (!tweaksAndThings.IsEnabled) return true; - bool buttonsHaveCost = tweaksAndThings?.settings?.EndGearHelpersRequirePayment ?? false; + bool buttonsHaveCost = tweaksAndThings.EndGearHelpersRequirePayment(); + bool cabooseRequired = tweaksAndThings.RequireConsistCabooseForOilerAndHotboxSpotter(); - if (buttonsHaveCost)__result = __instance.MrocAutoOilerLoop(_log); + if (buttonsHaveCost) __result = __instance.MrocAutoOilerLoop(_log, cabooseRequired); return !buttonsHaveCost; //only hit this if !buttonsHaveCost, since Loop is a coroutine } } diff --git a/TweaksAndThings/Patches/CarPickable_HandleShowContextMenu_Patch.cs b/TweaksAndThings/Patches/CarPickable_HandleShowContextMenu_Patch.cs index 36e82c9..6e8b31c 100644 --- a/TweaksAndThings/Patches/CarPickable_HandleShowContextMenu_Patch.cs +++ b/TweaksAndThings/Patches/CarPickable_HandleShowContextMenu_Patch.cs @@ -7,7 +7,6 @@ using RollingStock; using System.Linq; using UI; using UI.ContextMenu; -using static Model.Car; namespace RMROC451.TweaksAndThings.Patches; @@ -21,15 +20,14 @@ internal class CarPickable_HandleShowContextMenu_Patch TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared; if (!tweaksAndThings.IsEnabled) return; - bool buttonsHaveCost = tweaksAndThings?.settings?.EndGearHelpersRequirePayment ?? false; + bool buttonsHaveCost = tweaksAndThings.EndGearHelpersRequirePayment(); ContextMenu shared = ContextMenu.Shared; - var consist = car.EnumerateCoupled(LogicalEnd.A); - shared.AddButton(ContextMenuQuadrant.Unused2, $"{(consist.Any(c => c.HandbrakeApplied()) ? "Release " : "Set ")} Consist", SpriteName.Handbrake, delegate + shared.AddButton(ContextMenuQuadrant.Unused2, $"{(car._set.Cars.Any(c => c.HandbrakeApplied()) ? "Release " : "Set ")} Consist", SpriteName.Handbrake, delegate { CarInspector_PopulateCarPanel_Patch.MrocConsistHelper(car, MrocHelperType.Handbrake, buttonsHaveCost); }); - if (consist.Any(c => c.EndAirSystemIssue())) + if (car._set.Cars.Any(c => c.EndAirSystemIssue())) { shared.AddButton(ContextMenuQuadrant.Unused2, $"Air Up Consist", SpriteName.Select, delegate { @@ -37,7 +35,7 @@ internal class CarPickable_HandleShowContextMenu_Patch }); } - if (consist.Any(c => c.SupportsBleed())) + if (car._set.Cars.Any(c => c.SupportsBleed())) { shared.AddButton(ContextMenuQuadrant.Unused2, $"Bleed Consist", SpriteName.Bleed, delegate { diff --git a/TweaksAndThings/Settings/Settings.cs b/TweaksAndThings/Settings/Settings.cs index 9e3a1cd..4d51ffa 100644 --- a/TweaksAndThings/Settings/Settings.cs +++ b/TweaksAndThings/Settings/Settings.cs @@ -2,6 +2,9 @@ using System.Collections.Generic; using System.Linq; using RMROC451.TweaksAndThings.Enums; +using UI.Builder; +using Model; +using RMROC451.TweaksAndThings.Extensions; namespace RMROC451.TweaksAndThings; @@ -18,19 +21,26 @@ public class Settings List webhookSettingsList, bool handBrakeAndAirTagModifiers, RosterFuelColumnSettings engineRosterFuelColumnSettings, - bool endGearHelpersRequirePayment + bool endGearHelpersRequirePayment, + bool requireConsistCabooseForOilerAndHotboxSpotter, + bool cabooseAllowsConsistInfo ) { WebhookSettingsList = webhookSettingsList; HandBrakeAndAirTagModifiers = handBrakeAndAirTagModifiers; EngineRosterFuelColumnSettings = engineRosterFuelColumnSettings; EndGearHelpersRequirePayment = endGearHelpersRequirePayment; + RequireConsistCabooseForOilerAndHotboxSpotter = requireConsistCabooseForOilerAndHotboxSpotter; + CabooseAllowsConsistInfo = cabooseAllowsConsistInfo; } + public readonly UIState _selectedTabState = new UIState(null); public List? WebhookSettingsList; public bool HandBrakeAndAirTagModifiers; public RosterFuelColumnSettings? EngineRosterFuelColumnSettings; public bool EndGearHelpersRequirePayment; + public bool RequireConsistCabooseForOilerAndHotboxSpotter; + public bool CabooseAllowsConsistInfo; internal void AddAnotherRow() { @@ -82,15 +92,21 @@ public static class SettingsExtensions { public static List SanitizeEmptySettings(this IEnumerable? settings) { - List output = - settings?.Where(s => !string.IsNullOrEmpty(s.WebhookUrl))?.ToList() ?? + List output = + settings?.Where(s => !string.IsNullOrEmpty(s.WebhookUrl))?.ToList() ?? new(); output.Add(new()); return output; } - + + public static bool CabooseAllowsConsistInfo(this TweaksAndThingsPlugin input) => + input?.settings?.CabooseAllowsConsistInfo ?? false; + public static bool EndGearHelpersRequirePayment(this TweaksAndThingsPlugin input) => + input?.settings?.EndGearHelpersRequirePayment ?? false; + public static bool RequireConsistCabooseForOilerAndHotboxSpotter(this TweaksAndThingsPlugin input) => + input?.settings?.RequireConsistCabooseForOilerAndHotboxSpotter ?? false; public static bool CabooseNonMotiveAllowedSetting(this TweaksAndThingsPlugin input, Car car) => input.EndGearHelpersRequirePayment() && car.set.Cars.CabooseInConsist() && car.NotMotivePower(); diff --git a/TweaksAndThings/TweaksAndThingsPlugin.cs b/TweaksAndThings/TweaksAndThingsPlugin.cs index d1e0380..30d488a 100644 --- a/TweaksAndThings/TweaksAndThingsPlugin.cs +++ b/TweaksAndThings/TweaksAndThingsPlugin.cs @@ -82,16 +82,73 @@ public class TweaksAndThingsPlugin : SingletonPluginBase, settings.WebhookSettingsList = settings?.WebhookSettingsList.SanitizeEmptySettings(); - //WebhookUISection(ref builder); - //builder.AddExpandingVerticalSpacer(); - WebhooksListUISection(ref builder); - builder.AddExpandingVerticalSpacer(); - HandbrakesAndAnglecocksUISection(ref builder); - builder.AddExpandingVerticalSpacer(); - EnginRosterShowsFuelStatusUISection(ref builder); + builder.AddTabbedPanels(settings._selectedTabState, delegate (UITabbedPanelBuilder tabBuilder) + { + tabBuilder.AddTab("Caboose Mods", "cabooseUpdates", CabooseMods); + tabBuilder.AddTab("UI", "rosterUi", UiUpdates); + tabBuilder.AddTab("Webhooks", "webhooks", WebhooksListUISection); + }); } - private void EnginRosterShowsFuelStatusUISection(ref UIPanelBuilder builder) + private void CabooseMods(UIPanelBuilder builder) + { + builder.AddField( + "Caboose Use", + builder.AddToggle( + () => settings?.EndGearHelpersRequirePayment ?? false, + delegate (bool enabled) + { + if (settings == null) settings = new(); + settings.EndGearHelpersRequirePayment = enabled; + builder.Rebuild(); + } + ) + ).Tooltip("Enable End Gear Helper Cost", @$"Will cost 1 minute of AI Brake Crew & Caboose Crew time per car in the consist when the new inspector buttons are utilized. + +1.5x multiplier penalty to AI Brake Crew cost if no sufficiently crewed caboose nearby. + +Caboose starts reloading `Crew Hours` at any Team or Repair track (no waybill), after being stationary for 30 seconds. + +AutoOiler Update: Increases limit that crew will oiling a car from 75% -> 99%, also halves the time it takes (simulating crew from lead end and caboose handling half the train) + +AutoHotboxSpotter Update: decrease the random wait from 30 - 300 seconds to 15 - 30 seconds (Safety Is Everyone's Job)"); + + builder.AddField( + $"AutoAI\nRequirement", + builder.AddToggle( + () => settings?.RequireConsistCabooseForOilerAndHotboxSpotter ?? false, + delegate (bool enabled) + { + if (settings == null) settings = new(); + settings.RequireConsistCabooseForOilerAndHotboxSpotter = enabled; + builder.Rebuild(); + } + ) + ).Tooltip("AI Engineer Requires Caboose", $@"A caboose is required in the consist to check for Hotboxes and perform Auto Oiler, if checked."); + } + + private void UiUpdates(UIPanelBuilder builder) + { + builder.AddField( + "Enable Tag Updates", + builder.AddToggle( + () => settings?.HandBrakeAndAirTagModifiers ?? false, + delegate (bool enabled) + { + if (settings == null) settings = new(); + settings.HandBrakeAndAirTagModifiers = enabled; + builder.Rebuild(); + } + ) + ).Tooltip("Enable Tag Updates", $@"Will suffix tag title with: +{TextSprites.CycleWaybills} if Air System issue. +{TextSprites.HandbrakeWheel} if there is a handbrake set. +{TextSprites.Hotbox} if a hotbox."); + + EngineRosterShowsFuelStatusUISection(builder); + } + + private void EngineRosterShowsFuelStatusUISection(UIPanelBuilder builder) { var columns = Enum.GetValues(typeof(EngineRosterFuelDisplayColumn)).Cast().Select(i => i.ToString()).ToList(); builder.AddSection("Fuel Display in Engine Roster", delegate (UIPanelBuilder builder) @@ -123,39 +180,7 @@ public class TweaksAndThingsPlugin : SingletonPluginBase, }); } - private void HandbrakesAndAnglecocksUISection(ref UIPanelBuilder builder) - { - builder.AddSection("Tag Callout Handbrake and Air System Helper", delegate (UIPanelBuilder builder) - { - builder.AddField( - "Enable Tag Updates", - builder.AddToggle( - () => settings?.HandBrakeAndAirTagModifiers ?? false, - delegate (bool enabled) - { - if (settings == null) settings = new(); - settings.HandBrakeAndAirTagModifiers = enabled; - builder.Rebuild(); - } - ) - ).Tooltip("Enable Tag Updates", $"Will add {TextSprites.CycleWaybills} to the car tag title having Air System issues. Also prepends {TextSprites.HandbrakeWheel} if there is a handbrake set.\n\nHolding Left Alt while tags are displayed only shows tag titles that have issues."); - - builder.AddField( - "Caboose Use", - builder.AddToggle( - () => settings?.EndGearHelpersRequirePayment ?? false, - delegate (bool enabled) - { - if (settings == null) settings = new(); - settings.EndGearHelpersRequirePayment = enabled; - builder.Rebuild(); - } - ) - ).Tooltip("Enable End Gear Helper Cost", $"Will cost 1 minute of AI Brake Crew & Caboose Crew time per car in the consist when the new inspector buttons are utilized.\n\n1.5x multiplier penalty to AI Brake Crew cost if no sufficiently crewed caboose nearby.\n\nCaboose starts reloading `Crew Hours` at any Team or Repair track (no waybill), after being stationary for 30 seconds."); - }); - } - - private void WebhooksListUISection(ref UIPanelBuilder builder) + private void WebhooksListUISection(UIPanelBuilder builder) { builder.AddSection("Webhooks List", delegate (UIPanelBuilder builder) { diff --git a/updates.json b/updates.json new file mode 100644 index 0000000..638be2c --- /dev/null +++ b/updates.json @@ -0,0 +1,12 @@ +{ + "RMROC451.TweaksAndThings": { + "version": "1.0.0", + "changelog": [ + { + "version": "*", + "date": "2024-07-26T14:31:49.0948925Z", + "desc": "https://github.com/rmroc451/TweaksAndThings/releases" + } + ] + } +} \ No newline at end of file From 1f48bf04aaef38b4ec3942861479653e083023b2 Mon Sep 17 00:00:00 2001 From: RMROC451 Date: Fri, 26 Jul 2024 12:35:52 -0500 Subject: [PATCH 6/6] increment version number --- Directory.Build.targets | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Directory.Build.targets b/Directory.Build.targets index a8b529e..25f64fa 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -2,7 +2,7 @@ $([System.IO.Directory]::GetDirectories(`$(GameDir)`, `*_Data`)[0])\Managed - + $(GameDir)/Mods/$(AssemblyName) $(GameModDir)/ @@ -11,9 +11,9 @@ - 0 - 1 - 8 + 1 + 0 + 0 $(MajorVersion).$(MinorVersion).$(PatchVersion) $(AssemblyVersion) $(AssemblyVersion) @@ -44,15 +44,15 @@ - + - + - + @@ -65,7 +65,7 @@ - +