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