diff --git a/.gitignore b/.gitignore
index 8a30d25..80b3e40 100644
--- a/.gitignore
+++ b/.gitignore
@@ -396,3 +396,8 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
+
+# Trash
+.claude
+claude.md
+todo.md
\ No newline at end of file
diff --git a/Assembly.version b/Assembly.version
index 8829fb5..10bd975 100644
--- a/Assembly.version
+++ b/Assembly.version
@@ -2,6 +2,6 @@
2
1
- 7
+ 8
\ No newline at end of file
diff --git a/README.md b/README.md
index 0255838..8a0be5b 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,18 @@ This is a mod for Railroader which is available on Steam.
This mod requires Railloader by Zamu.
+## Credits & Project History
+
+This project was originally created and developed by RMROC451.
+
+I have created fixes and additional features which maybe pulled to main project over time.
+
+The goal of this repository is to preserve, maintain, and continue improving the mod for the Railroader community while respecting and crediting the original work and vision of RMROC451.
+
+Special thanks to:
+- RMROC451 — original creator of Tweaks and Things
+- Zamu
+
## Usage
1. Download and install Railloader by Zamu from here: https://railroader.stelltis.ch/
* Verify you have a Mods folder in the root of your railroader directory. If You do NOT have a Mods folder, you didn't complete this step successfully.
diff --git a/TweaksAndThings/Patches/AutoEngineerWaypointControls_ConfigureOptionsDropdown_Patch.cs b/TweaksAndThings/Patches/AutoEngineerWaypointControls_ConfigureOptionsDropdown_Patch.cs
index 6737d87..1f234d3 100644
--- a/TweaksAndThings/Patches/AutoEngineerWaypointControls_ConfigureOptionsDropdown_Patch.cs
+++ b/TweaksAndThings/Patches/AutoEngineerWaypointControls_ConfigureOptionsDropdown_Patch.cs
@@ -1,4 +1,5 @@
using Game.Messages;
+using Game.Notices;
using Game.State;
using HarmonyLib;
using Model;
@@ -41,12 +42,22 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
{
try
{
+ if (lastLocoSeenCarId != null &&
+ lastLocoSeenCarId.Equals(TrainController.Shared?.SelectedLocomotive.id) &&
+ watchyWatchy != null)
+ return;
+
+ if (watchyWatchy != null)
+ ((MonoBehaviour)__instance).StopCoroutine(watchyWatchy);
- if (lastLocoSeenCarId != null && lastLocoSeenCarId.Equals(TrainController.Shared?.SelectedLocomotive.id) && watchyWatchy != null) return;
- if (watchyWatchy != null) ((MonoBehaviour)__instance).StopCoroutine(watchyWatchy);
watchyWatchy = null;
- if (__instance._persistence.Orders.Mode == AutoEngineerMode.Waypoint) watchyWatchy = ((MonoBehaviour)__instance).StartCoroutine(UpdateCogCoroutine(__instance));
+ if (__instance._persistence.Orders.Mode == AutoEngineerMode.Waypoint)
+ {
+ watchyWatchy =
+ ((MonoBehaviour)__instance)
+ .StartCoroutine(UpdateCogCoroutine(__instance));
+ }
}
catch (Exception ex)
{
@@ -61,11 +72,19 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
while (true)
{
- if (__instance._persistence.Orders.Mode != AutoEngineerMode.Waypoint || ((AutoEngineerWaypointControls)__instance.aiWaypointControls).Locomotive == null) yield return wait;
+ if (__instance._persistence.Orders.Mode != AutoEngineerMode.Waypoint || ((AutoEngineerWaypointControls)__instance.aiWaypointControls).Locomotive == null)
+ {
+ yield return wait;
+ continue;
+ }
PrepLocoUsage((AutoEngineerWaypointControls)__instance.aiWaypointControls, out BaseLocomotive selectedLoco, out int numberOfCars);
HashSet destinations = [];
- if (!tweaksAndThings.IsEnabled() || !ShouldRecalc(__instance, selectedLoco, out destinations)) yield return wait;
+ if (!tweaksAndThings.IsEnabled() || tweaksAndThings.DisableWaypointControls() || !ShouldRecalc(__instance, selectedLoco, out destinations))
+ {
+ yield return wait;
+ continue;
+ }
timetableSaveTime = TimetableController.Shared.CurrentDocument.Modified;
lastSeenIntegrationSetCount = selectedLoco.set.NumberOfCars;
@@ -132,7 +151,18 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
private static OptionsDropdownConfiguration WireUpJumpTosToSettingMenu(AutoEngineerWaypointControls __instance, BaseLocomotive selectedLoco, List rowDatas, Action func, int origCount, int maxRowOrig, AutoEngineerOrdersHelper aeoh, ref List<(string destinationId, string destination, float? distance, float sortDistance, Location? location)> jumpTos)
{
OptionsDropdownConfiguration __result;
- jumpTos = jumpTos?.OrderBy(c => c.sortDistance)?.ToList() ?? default;
+ TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared;
+
+ // Check if waypoint controls are disabled
+ if (tweaksAndThings.DisableWaypointControls())
+ {
+ jumpTos = new List<(string, string, float?, float, Location?)>();
+ }
+ else
+ {
+ jumpTos = jumpTos?.OrderBy(c => c.sortDistance)?.ToList() ?? default;
+ }
+
var localJumpTos = jumpTos.ToList();
var safetyFirst = AutoEngineerPlanner_HandleCommand_Patch.SafetyFirstGoverningApplies(selectedLoco) && jumpTos.Any();
@@ -364,6 +394,12 @@ internal class LocomotiveControlsUIAdapter_UpdateOptionsDropdown_Prefix
{
static bool Prefix(LocomotiveControlsUIAdapter __instance)
{
- return false;
+ TweaksAndThingsPlugin tweaksAndThings =
+ SingletonPluginBase.Shared;
+
+ if (!tweaksAndThings.IsEnabled())
+ return true;
+
+ return tweaksAndThings.DisableWaypointControls();
}
-}
+}
\ No newline at end of file
diff --git a/TweaksAndThings/Patches/CarInspector_PopulateEquipmentPanel_Patch.cs b/TweaksAndThings/Patches/CarInspector_PopulateEquipmentPanel_Patch.cs
new file mode 100644
index 0000000..8b5bd39
--- /dev/null
+++ b/TweaksAndThings/Patches/CarInspector_PopulateEquipmentPanel_Patch.cs
@@ -0,0 +1,75 @@
+using Game.Messages;
+using Game.Notices;
+using Game.State;
+using HarmonyLib;
+using Model;
+using Model.Ops;
+using Network;
+using Railloader;
+using System;
+using System.Linq;
+using UI.Builder;
+using UI.CarInspector;
+using Core;
+
+namespace RMROC451.TweaksAndThings.Patches;
+
+[HarmonyPatch(typeof(CarInspector))]
+[HarmonyPatch(nameof(CarInspector.PopulateEquipmentPanel))]
+[HarmonyPatchCategory("RMROC451TweaksAndThings")]
+internal static class CarInspector_PopulateEquipmentPanel_Patch
+{
+ [HarmonyPrefix]
+ private static void Prefix(CarInspector __instance, UIPanelBuilder builder)
+ {
+ TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase.Shared;
+ if (!tweaksAndThings.IsEnabled()) return;
+
+ builder.HStack(hstack =>
+ {
+ hstack.AddButtonCompact("Copy Repair Dest", delegate
+ {
+ Car selectedCar = __instance._car;
+
+ bool hasDestination = selectedCar.TryGetOverrideDestination(
+ OverrideDestination.Repair,
+ OpsController.Shared,
+ out (OpsCarPosition, string)? destination);
+
+ int updatedCount = selectedCar
+ .EnumerateCoupled()
+ .Where(car => car.id != selectedCar.id)
+ .Select(car =>
+ {
+ if (hasDestination)
+ {
+ car.SetOverrideDestination(
+ OverrideDestination.Repair,
+ destination);
+ }
+ else
+ {
+ car.SetOverrideDestination(
+ OverrideDestination.Repair,
+ null);
+ }
+
+ return 1;
+ })
+ .Sum();
+
+ Multiplayer.SendError(
+ StateManager.Shared.PlayersManager.LocalPlayer,
+ hasDestination
+ ? $"Copied repair destination to {updatedCount} connected {"car".Pluralize(updatedCount == 1 ? 1 : 0)}."
+ : $"Cleared repair destination from {updatedCount} connected {"car".Pluralize(updatedCount == 1 ? 1 : 0)}.",
+ default);
+
+ hstack.Rebuild();
+ })
+ .Tooltip(
+ "Copy Repair Destination",
+ "Copies or clears this car's repair destination across all connected cars in the consist.");
+ });
+ }
+}
\ No newline at end of file
diff --git a/TweaksAndThings/Settings/Settings.cs b/TweaksAndThings/Settings/Settings.cs
index c8e93af..1e9b659 100644
--- a/TweaksAndThings/Settings/Settings.cs
+++ b/TweaksAndThings/Settings/Settings.cs
@@ -31,7 +31,8 @@ public class Settings
bool safetyFirstClientEnforce,
CrewHourLoadMethod loadCrewHoursMethod,
float cabeeseSearchRadiusFtInMeters,
- bool trainBrakeDisplayShowsColorsInCalloutMode
+ bool trainBrakeDisplayShowsColorsInCalloutMode,
+ bool disableWaypointControls
)
{
WebhookSettingsList = webhookSettingsList;
@@ -47,6 +48,7 @@ public class Settings
LoadCrewHoursMethod = loadCrewHoursMethod;
CabeeseSearchRadiusFtInMeters = cabeeseSearchRadiusFtInMeters;
TrainBrakeDisplayShowsColorsInCalloutMode = trainBrakeDisplayShowsColorsInCalloutMode;
+ DisableWaypointControls = disableWaypointControls;
}
public readonly UIState _selectedTabState = new UIState(null);
@@ -63,6 +65,7 @@ public class Settings
public CrewHourLoadMethod LoadCrewHoursMethod;
public float CabeeseSearchRadiusFtInMeters;
public bool TrainBrakeDisplayShowsColorsInCalloutMode;
+ public bool DisableWaypointControls;
internal void AddAnotherRow()
{
@@ -145,5 +148,7 @@ public static class SettingsExtensions
(input?.settings?.LoadCrewHoursMethod ?? CrewHourLoadMethod.Tracks) == CrewHourLoadMethod.Daily;
public static bool TrainBrakeDisplayShowsColorsInCalloutMode(this TweaksAndThingsPlugin input) =>
input?.settings?.TrainBrakeDisplayShowsColorsInCalloutMode ?? false;
+ public static bool DisableWaypointControls(this TweaksAndThingsPlugin input) =>
+ input?.settings?.DisableWaypointControls ?? false;
}
\ No newline at end of file
diff --git a/TweaksAndThings/TweaksAndThingsPlugin.cs b/TweaksAndThings/TweaksAndThingsPlugin.cs
index e7382f5..f4da1c3 100644
--- a/TweaksAndThings/TweaksAndThingsPlugin.cs
+++ b/TweaksAndThings/TweaksAndThingsPlugin.cs
@@ -262,6 +262,18 @@ AutoHotboxSpotter Update: decrease the random wait from 30 - 300 seconds to 15 -
}
).Tooltip("Train Brake Color Mode", $@"When enabled/checked and car tag callout mode is enabled (showing car tags hovering over them), the train brake display of the selected locomotive will change the cars/engines to their destination area's color to help you visualize sets of cars at a glance.");
+ builder.Spacer(spacing);
+ builder.AddFieldToggle(
+ "Disable Waypoint Controls",
+ () => settings?.DisableWaypointControls ?? false,
+ delegate (bool enabled)
+ {
+ if (settings == null) settings = new();
+ settings.DisableWaypointControls = enabled;
+ builder.Rebuild();
+ }
+ ).Tooltip("Disable Waypoint Controls", @"When enabled, removes the waypoint set/jump options from the engine control menu. This disables the option to jump to waypoints or set waypoints based on consist car destinations, allowing only default engine controls.");
+
builder.Spacer(spacing);
EngineRosterShowsFuelStatusUISection(builder);
}