Fixes [Copy Repair, Disable Waypoint, Enable Simple Controls]

- Added Copy Repair Destination Feature  (Equipment Tab)
- Option to disable waypoint jump/get back the option for simplified controls
This commit is contained in:
Faizan Khan
2026-05-17 01:12:26 +05:30
parent cbca69d66b
commit 0c93a507ba
4 changed files with 136 additions and 9 deletions

View File

@@ -1,4 +1,5 @@
using Game.Messages; using Game.Messages;
using Game.Notices;
using Game.State; using Game.State;
using HarmonyLib; using HarmonyLib;
using Model; using Model;
@@ -41,12 +42,22 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
{ {
try 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; 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) catch (Exception ex)
{ {
@@ -61,11 +72,19 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
while (true) 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); PrepLocoUsage((AutoEngineerWaypointControls)__instance.aiWaypointControls, out BaseLocomotive selectedLoco, out int numberOfCars);
HashSet<OpsCarPosition?> destinations = []; HashSet<OpsCarPosition?> 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; timetableSaveTime = TimetableController.Shared.CurrentDocument.Modified;
lastSeenIntegrationSetCount = selectedLoco.set.NumberOfCars; lastSeenIntegrationSetCount = selectedLoco.set.NumberOfCars;
@@ -132,7 +151,18 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
private static OptionsDropdownConfiguration WireUpJumpTosToSettingMenu(AutoEngineerWaypointControls __instance, BaseLocomotive selectedLoco, List<DropdownMenu.RowData> rowDatas, Action<int> func, int origCount, int maxRowOrig, AutoEngineerOrdersHelper aeoh, ref List<(string destinationId, string destination, float? distance, float sortDistance, Location? location)> jumpTos) private static OptionsDropdownConfiguration WireUpJumpTosToSettingMenu(AutoEngineerWaypointControls __instance, BaseLocomotive selectedLoco, List<DropdownMenu.RowData> rowDatas, Action<int> func, int origCount, int maxRowOrig, AutoEngineerOrdersHelper aeoh, ref List<(string destinationId, string destination, float? distance, float sortDistance, Location? location)> jumpTos)
{ {
OptionsDropdownConfiguration __result; OptionsDropdownConfiguration __result;
jumpTos = jumpTos?.OrderBy(c => c.sortDistance)?.ToList() ?? default; TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase<TweaksAndThingsPlugin>.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 localJumpTos = jumpTos.ToList();
var safetyFirst = AutoEngineerPlanner_HandleCommand_Patch.SafetyFirstGoverningApplies(selectedLoco) && jumpTos.Any(); var safetyFirst = AutoEngineerPlanner_HandleCommand_Patch.SafetyFirstGoverningApplies(selectedLoco) && jumpTos.Any();
@@ -364,6 +394,12 @@ internal class LocomotiveControlsUIAdapter_UpdateOptionsDropdown_Prefix
{ {
static bool Prefix(LocomotiveControlsUIAdapter __instance) static bool Prefix(LocomotiveControlsUIAdapter __instance)
{ {
return false; TweaksAndThingsPlugin tweaksAndThings =
SingletonPluginBase<TweaksAndThingsPlugin>.Shared;
if (!tweaksAndThings.IsEnabled())
return true;
return tweaksAndThings.DisableWaypointControls();
} }
} }

View File

@@ -0,0 +1,74 @@
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;
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<TweaksAndThingsPlugin>.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 {(updatedCount == 1 ? "car" : "cars")}."
: $"Cleared repair destination from {updatedCount} connected {(updatedCount == 1 ? "car" : "cars")}.",
default);
hstack.Rebuild();
})
.Tooltip(
"Copy Repair Destination",
"Copies or clears this car's repair destination across all connected cars in the consist.");
});
}
}

View File

@@ -31,7 +31,8 @@ public class Settings
bool safetyFirstClientEnforce, bool safetyFirstClientEnforce,
CrewHourLoadMethod loadCrewHoursMethod, CrewHourLoadMethod loadCrewHoursMethod,
float cabeeseSearchRadiusFtInMeters, float cabeeseSearchRadiusFtInMeters,
bool trainBrakeDisplayShowsColorsInCalloutMode bool trainBrakeDisplayShowsColorsInCalloutMode,
bool disableWaypointControls
) )
{ {
WebhookSettingsList = webhookSettingsList; WebhookSettingsList = webhookSettingsList;
@@ -47,6 +48,7 @@ public class Settings
LoadCrewHoursMethod = loadCrewHoursMethod; LoadCrewHoursMethod = loadCrewHoursMethod;
CabeeseSearchRadiusFtInMeters = cabeeseSearchRadiusFtInMeters; CabeeseSearchRadiusFtInMeters = cabeeseSearchRadiusFtInMeters;
TrainBrakeDisplayShowsColorsInCalloutMode = trainBrakeDisplayShowsColorsInCalloutMode; TrainBrakeDisplayShowsColorsInCalloutMode = trainBrakeDisplayShowsColorsInCalloutMode;
DisableWaypointControls = disableWaypointControls;
} }
public readonly UIState<string> _selectedTabState = new UIState<string>(null); public readonly UIState<string> _selectedTabState = new UIState<string>(null);
@@ -63,6 +65,7 @@ public class Settings
public CrewHourLoadMethod LoadCrewHoursMethod; public CrewHourLoadMethod LoadCrewHoursMethod;
public float CabeeseSearchRadiusFtInMeters; public float CabeeseSearchRadiusFtInMeters;
public bool TrainBrakeDisplayShowsColorsInCalloutMode; public bool TrainBrakeDisplayShowsColorsInCalloutMode;
public bool DisableWaypointControls;
internal void AddAnotherRow() internal void AddAnotherRow()
{ {
@@ -145,5 +148,7 @@ public static class SettingsExtensions
(input?.settings?.LoadCrewHoursMethod ?? CrewHourLoadMethod.Tracks) == CrewHourLoadMethod.Daily; (input?.settings?.LoadCrewHoursMethod ?? CrewHourLoadMethod.Tracks) == CrewHourLoadMethod.Daily;
public static bool TrainBrakeDisplayShowsColorsInCalloutMode(this TweaksAndThingsPlugin input) => public static bool TrainBrakeDisplayShowsColorsInCalloutMode(this TweaksAndThingsPlugin input) =>
input?.settings?.TrainBrakeDisplayShowsColorsInCalloutMode ?? false; input?.settings?.TrainBrakeDisplayShowsColorsInCalloutMode ?? false;
public static bool DisableWaypointControls(this TweaksAndThingsPlugin input) =>
input?.settings?.DisableWaypointControls ?? false;
} }

View File

@@ -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."); ).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); builder.Spacer(spacing);
EngineRosterShowsFuelStatusUISection(builder); EngineRosterShowsFuelStatusUISection(builder);
} }