mirror of
https://github.com/rmroc451/TweaksAndThings.git
synced 2025-12-16 09:19:37 -06:00
host now can assert safety first; setting added to allow clients to override. Client does not require mod for this to be enforced!
This commit is contained in:
@@ -13,7 +13,7 @@ internal class AutoEngineerControlSetBase_UpdateStatusLabel_Patch
|
|||||||
static void Postfix(AutoEngineerControlSetBase __instance)
|
static void Postfix(AutoEngineerControlSetBase __instance)
|
||||||
{
|
{
|
||||||
TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase<TweaksAndThingsPlugin>.Shared;
|
TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase<TweaksAndThingsPlugin>.Shared;
|
||||||
if (!tweaksAndThings.IsEnabled() || !AutoEngineerOrdersHelper_SendAutoEngineerCommand_Patch.SafetyFirstGoverningApplies()) return;
|
if (!tweaksAndThings.IsEnabled() || !AutoEngineerPlanner_HandleCommand_Patch.SafetyFirstGoverningApplies(__instance.Locomotive)) return;
|
||||||
|
|
||||||
string orig = __instance.statusLabel.text;
|
string orig = __instance.statusLabel.text;
|
||||||
__instance.statusLabel.text = $"{orig}; <b>Safety</b>";
|
__instance.statusLabel.text = $"{orig}; <b>Safety</b>";
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
using Game.Messages;
|
|
||||||
using HarmonyLib;
|
|
||||||
using Model.AI;
|
|
||||||
using Model.Definition;
|
|
||||||
using Railloader;
|
|
||||||
using RMROC451.TweaksAndThings.Extensions;
|
|
||||||
using Serilog;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using UI.EngineControls;
|
|
||||||
|
|
||||||
namespace RMROC451.TweaksAndThings.Patches;
|
|
||||||
|
|
||||||
|
|
||||||
[HarmonyPatch(typeof(AutoEngineerOrdersHelper))]
|
|
||||||
[HarmonyPatch(nameof(AutoEngineerOrdersHelper.SendAutoEngineerCommand), typeof(AutoEngineerMode), typeof(bool), typeof(int), typeof(float), typeof(OrderWaypoint))]
|
|
||||||
[HarmonyPatchCategory("RMROC451TweaksAndThings")]
|
|
||||||
internal class AutoEngineerOrdersHelper_SendAutoEngineerCommand_Patch
|
|
||||||
{
|
|
||||||
|
|
||||||
private static Serilog.ILogger _log => Log.ForContext<AutoEngineerOrdersHelper_SendAutoEngineerCommand_Patch>();
|
|
||||||
|
|
||||||
static bool Prefix(AutoEngineerMode mode, ref int maxSpeedMph)
|
|
||||||
{
|
|
||||||
TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase<TweaksAndThingsPlugin>.Shared;
|
|
||||||
if (!tweaksAndThings.IsEnabled() || !tweaksAndThings.SafetyFirst()) return true;
|
|
||||||
|
|
||||||
if (SafetyFirstGoverningApplies())
|
|
||||||
{
|
|
||||||
int orig = maxSpeedMph;
|
|
||||||
int limitedSpeed = Math.Min(maxSpeedMph, 20);
|
|
||||||
maxSpeedMph = mode switch
|
|
||||||
{
|
|
||||||
AutoEngineerMode.Road => limitedSpeed,
|
|
||||||
AutoEngineerMode.Waypoint => limitedSpeed,
|
|
||||||
_ => maxSpeedMph,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (orig != maxSpeedMph)
|
|
||||||
{
|
|
||||||
_log.Debug($"{Enum.GetName(typeof(AutoEngineerMode), mode)}[{TrainController.Shared.SelectedLocomotive.DisplayName}] {nameof(AutoEngineerOrdersExtensions.MaxSpeedMph)} limited to {limitedSpeed} from {orig}; No Caboose in Consist;");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static bool SafetyFirstGoverningApplies()
|
|
||||||
{
|
|
||||||
var _persistence = new AutoEngineerPersistence(TrainController.Shared.SelectedLocomotive.KeyValueObject);
|
|
||||||
var OrdersHelper = new AutoEngineerOrdersHelper(TrainController.Shared.SelectedLocomotive, _persistence);
|
|
||||||
|
|
||||||
if (TrainController.Shared.SelectedLocomotive.EnumerateCoupled().All(c => c.IsCaboose() || c.MotivePower())) return false;
|
|
||||||
|
|
||||||
bool cabooseReq = SingletonPluginBase<TweaksAndThingsPlugin>.Shared.RequireConsistCabooseForOilerAndHotboxSpotter();
|
|
||||||
string logMessage = $"\n{nameof(SafetyFirstGoverningApplies)}:{Enum.GetName(typeof(AutoEngineerMode), OrdersHelper.Mode)}[{TrainController.Shared.SelectedLocomotive.DisplayName}] ";
|
|
||||||
Func<bool> firstClass = () =>
|
|
||||||
{
|
|
||||||
var output = TrainController.Shared.SelectedEngineExpress();
|
|
||||||
logMessage += $"\nfirst class {output}";
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
|
|
||||||
Func<bool> FreightConsist = () =>
|
|
||||||
{
|
|
||||||
bool output = !TrainController.Shared.SelectedLocomotive.EnumerateCoupled().ConsistNoFreight();
|
|
||||||
logMessage += $"\nFreightConsist? {output}";
|
|
||||||
logMessage += " " + string.Join(" / ", TrainController.Shared.SelectedLocomotive.EnumerateCoupled().Where(c => !c.MotivePower()).Select(c => $"{c.id} {Enum.GetName(typeof(CarArchetype), c.Archetype)}"));
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
|
|
||||||
Func<bool> noCaboose = () =>
|
|
||||||
{
|
|
||||||
bool output = TrainController.Shared.SelectedLocomotive.FindMyCabooseSansLoadRequirement() == null;
|
|
||||||
logMessage += $"\ncaboose? {!output}";
|
|
||||||
return output;
|
|
||||||
};
|
|
||||||
|
|
||||||
logMessage += $"\nCaboose Required {cabooseReq}";
|
|
||||||
|
|
||||||
bool output =
|
|
||||||
cabooseReq &&
|
|
||||||
!firstClass() &&
|
|
||||||
FreightConsist() &&
|
|
||||||
noCaboose();
|
|
||||||
|
|
||||||
logMessage += $"\nGovern AE? {output}";
|
|
||||||
if (_log.IsEnabled(Serilog.Events.LogEventLevel.Verbose))
|
|
||||||
logMessage += $"\n{Environment.StackTrace}";
|
|
||||||
|
|
||||||
_log.Debug(logMessage);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
using Game;
|
||||||
|
using Game.Messages;
|
||||||
|
using Game.State;
|
||||||
|
using HarmonyLib;
|
||||||
|
using Model;
|
||||||
|
using Model.AI;
|
||||||
|
using Model.Definition;
|
||||||
|
using Network;
|
||||||
|
using Network.Messages;
|
||||||
|
using Railloader;
|
||||||
|
using RMROC451.TweaksAndThings.Extensions;
|
||||||
|
using Serilog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UI.EngineControls;
|
||||||
|
using UI.EngineRoster;
|
||||||
|
using static Unity.IO.LowLevel.Unsafe.AsyncReadManagerMetrics;
|
||||||
|
using static UnityEngine.InputSystem.InputRemoting;
|
||||||
|
|
||||||
|
namespace RMROC451.TweaksAndThings.Patches;
|
||||||
|
|
||||||
|
[HarmonyPatch(typeof(AutoEngineerPlanner))]
|
||||||
|
[HarmonyPatch(nameof(AutoEngineerPlanner.HandleCommand))]
|
||||||
|
[HarmonyPatchCategory("RMROC451TweaksAndThings")]
|
||||||
|
internal class AutoEngineerPlanner_HandleCommand_Patch
|
||||||
|
{
|
||||||
|
private static Serilog.ILogger _log => Log.ForContext<AutoEngineerPlanner_HandleCommand_Patch>();
|
||||||
|
private static int governedSpeed = 20;
|
||||||
|
|
||||||
|
static bool Prefix(AutoEngineerPlanner __instance, ref AutoEngineerCommand command, ref IPlayer sender)
|
||||||
|
{
|
||||||
|
TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase<TweaksAndThingsPlugin>.Shared;
|
||||||
|
if (!tweaksAndThings.IsEnabled() || !tweaksAndThings.SafetyFirst() || (sender.IsRemote && !tweaksAndThings.SafetyFirstClientEnforce()) || command.MaxSpeedMph <= governedSpeed) return true;
|
||||||
|
BaseLocomotive loco = TrainController.Shared.SelectedLocomotive;
|
||||||
|
if (TrainController.Shared.TryGetCarForId(command.LocomotiveId, out Car c)) loco = (BaseLocomotive)c;
|
||||||
|
|
||||||
|
if (SafetyFirstGoverningApplies(loco))
|
||||||
|
{
|
||||||
|
int orig = command.MaxSpeedMph;
|
||||||
|
int limitedSpeed = Math.Min(command.MaxSpeedMph, governedSpeed);
|
||||||
|
command.MaxSpeedMph = command.Mode switch
|
||||||
|
{
|
||||||
|
AutoEngineerMode.Road => limitedSpeed,
|
||||||
|
AutoEngineerMode.Waypoint => limitedSpeed,
|
||||||
|
_ => command.MaxSpeedMph,
|
||||||
|
};
|
||||||
|
|
||||||
|
string message = $"{Enum.GetName(typeof(AutoEngineerMode), command.Mode)}[{loco.DisplayName}] governed{{0}}due to Safety First rules.";
|
||||||
|
if (orig != command.MaxSpeedMph)
|
||||||
|
{
|
||||||
|
message = string.Format(message, $" from {orig} to {command.MaxSpeedMph} MPH ");
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
message = string.Format(message, " ");
|
||||||
|
}
|
||||||
|
_log.Debug(message);
|
||||||
|
Multiplayer.SendError(sender, message, AlertLevel.Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool SafetyFirstGoverningApplies(BaseLocomotive loco)
|
||||||
|
{
|
||||||
|
var _persistence = new AutoEngineerPersistence(loco.KeyValueObject);
|
||||||
|
var OrdersHelper = new AutoEngineerOrdersHelper(loco, _persistence);
|
||||||
|
|
||||||
|
if (loco.EnumerateCoupled().All(c => c.IsCaboose() || c.MotivePower())) return false;
|
||||||
|
|
||||||
|
bool cabooseReq = SingletonPluginBase<TweaksAndThingsPlugin>.Shared.RequireConsistCabooseForOilerAndHotboxSpotter();
|
||||||
|
string logMessage = $"\n{nameof(SafetyFirstGoverningApplies)}:{Enum.GetName(typeof(AutoEngineerMode), OrdersHelper.Mode)}[{loco.DisplayName}] ";
|
||||||
|
Func<bool> firstClass = () =>
|
||||||
|
{
|
||||||
|
var output = TrainController.Shared.SelectedEngineExpress();
|
||||||
|
logMessage += $"\nfirst class {output}";
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
Func<bool> FreightConsist = () =>
|
||||||
|
{
|
||||||
|
bool output = !loco.EnumerateCoupled().ConsistNoFreight();
|
||||||
|
logMessage += $"\nFreightConsist? {output}";
|
||||||
|
logMessage += " " + string.Join(" / ", loco.EnumerateCoupled().Where(c => !c.MotivePower()).Select(c => $"{c.id} {Enum.GetName(typeof(CarArchetype), c.Archetype)}"));
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
Func<bool> noCaboose = () =>
|
||||||
|
{
|
||||||
|
bool output = loco.FindMyCabooseSansLoadRequirement() == null;
|
||||||
|
logMessage += $"\ncaboose? {!output}";
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
logMessage += $"\nCaboose Required {cabooseReq}";
|
||||||
|
|
||||||
|
bool output =
|
||||||
|
cabooseReq &&
|
||||||
|
!firstClass() &&
|
||||||
|
FreightConsist() &&
|
||||||
|
noCaboose();
|
||||||
|
|
||||||
|
logMessage += $"\nGovern AE? {output}";
|
||||||
|
if (_log.IsEnabled(Serilog.Events.LogEventLevel.Verbose))
|
||||||
|
logMessage += $"\n{Environment.StackTrace}";
|
||||||
|
|
||||||
|
_log.Debug(logMessage);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (__instance._persistence.Orders.Mode != AutoEngineerMode.Waypoint) yield return wait;
|
if (__instance._persistence.Orders.Mode != AutoEngineerMode.Waypoint || ((AutoEngineerWaypointControls)__instance.aiWaypointControls).Locomotive == null) yield return wait;
|
||||||
|
|
||||||
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 = [];
|
||||||
@@ -117,14 +117,14 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
|
|||||||
//_log.Information($"{locoKey} --> [{locoConsistDestinations.Count}] -> Cache -> {string.Join(Environment.NewLine, locoConsistDestinations.Select(k => $"{locoKey}:{k.Value.DisplayName}"))}");
|
//_log.Information($"{locoKey} --> [{locoConsistDestinations.Count}] -> Cache -> {string.Join(Environment.NewLine, locoConsistDestinations.Select(k => $"{locoKey}:{k.Value.DisplayName}"))}");
|
||||||
|
|
||||||
output |= !locoConsistDestinations.SetEquals(destinations);
|
output |= !locoConsistDestinations.SetEquals(destinations);
|
||||||
_log.Information($"{locoKey} 1-> {output}");
|
//_log.Information($"{locoKey} 1-> {output}");
|
||||||
if (output) lastSeenIntegrationSetCount = default;
|
if (output) lastSeenIntegrationSetCount = default;
|
||||||
output |= lastSeenIntegrationSetCount != selectedLoco.set.NumberOfCars;
|
output |= lastSeenIntegrationSetCount != selectedLoco.set.NumberOfCars;
|
||||||
_log.Information($"{locoKey} 2-> {output}");
|
//_log.Information($"{locoKey} 2-> {output}");
|
||||||
//output |= __instance.optionsDropdown.scrollRect.content.childCount != (destinations.Count + timetableDestinations.Count + 1); //+1 for the default "JumpTo" entry)
|
//output |= __instance.optionsDropdown.scrollRect.content.childCount != (destinations.Count + timetableDestinations.Count + 1); //+1 for the default "JumpTo" entry)
|
||||||
//_log.Information($"{locoKey} 2.5-> {output} {__instance.optionsDropdown.scrollRect.content.childCount} {(destinations.Count)} {timetableDestinations.Count}");
|
//_log.Information($"{locoKey} 2.5-> {output} {__instance.optionsDropdown.scrollRect.content.childCount} {(destinations.Count)} {timetableDestinations.Count}");
|
||||||
output |= selectedLoco.TryGetTimetableTrain(out _) && TimetableController.Shared.CurrentDocument.Modified != timetableSaveTime;
|
output |= selectedLoco.TryGetTimetableTrain(out _) && TimetableController.Shared.CurrentDocument.Modified != timetableSaveTime;
|
||||||
_log.Information($"{locoKey} 3-> {output}");
|
//_log.Information($"{locoKey} 3-> {output}");
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
|
|||||||
OptionsDropdownConfiguration __result;
|
OptionsDropdownConfiguration __result;
|
||||||
jumpTos = jumpTos?.OrderBy(c => c.sortDistance)?.ToList() ?? default;
|
jumpTos = jumpTos?.OrderBy(c => c.sortDistance)?.ToList() ?? default;
|
||||||
var localJumpTos = jumpTos.ToList();
|
var localJumpTos = jumpTos.ToList();
|
||||||
var safetyFirst = AutoEngineerOrdersHelper_SendAutoEngineerCommand_Patch.SafetyFirstGoverningApplies() && jumpTos.Any();
|
var safetyFirst = AutoEngineerPlanner_HandleCommand_Patch.SafetyFirstGoverningApplies(selectedLoco) && jumpTos.Any();
|
||||||
|
|
||||||
rowDatas.AddRange(jumpTos.Select(j =>
|
rowDatas.AddRange(jumpTos.Select(j =>
|
||||||
new DropdownMenu.RowData(
|
new DropdownMenu.RowData(
|
||||||
@@ -227,11 +227,11 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
|
|||||||
|
|
||||||
if (selectedLoco.TryGetTimetableTrain(out Timetable.Train t))
|
if (selectedLoco.TryGetTimetableTrain(out Timetable.Train t))
|
||||||
{
|
{
|
||||||
_log.Information($"{getDictKey(selectedLoco)} -> {t.DisplayStringLong}");
|
//_log.Information($"{getDictKey(selectedLoco)} -> {t.DisplayStringLong}");
|
||||||
foreach (var e in t.Entries)
|
foreach (var e in t.Entries)
|
||||||
{
|
{
|
||||||
var stp = TimetableController.Shared.GetAllStations().FirstOrDefault(ps => ps.code == e.Station);
|
var stp = TimetableController.Shared.GetAllStations().FirstOrDefault(ps => ps.code == e.Station);
|
||||||
_log.Information($"{getDictKey(selectedLoco)} -> {t.DisplayStringLong} -> {e.Station} {stp}");
|
//_log.Information($"{getDictKey(selectedLoco)} -> {t.DisplayStringLong} -> {e.Station} {stp}");
|
||||||
if (stp != null)
|
if (stp != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -315,8 +315,8 @@ internal class LocomotiveControlsUIAdapter_UpdateCarText_Postfix()
|
|||||||
{
|
{
|
||||||
//wire up that loco
|
//wire up that loco
|
||||||
selectedLoco = __instance.Locomotive;
|
selectedLoco = __instance.Locomotive;
|
||||||
numberOfCars = selectedLoco.set.NumberOfCars;
|
numberOfCars = selectedLoco?.set.NumberOfCars ?? -1;
|
||||||
_log.Debug($"{selectedLoco.id} --> HI BOB[{numberOfCars}]");
|
_log.Debug($"{selectedLoco?.id} --> HI BOB[{numberOfCars}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OpsCarPosition? GetCarDestinationIdentifier(Car c)
|
private static OpsCarPosition? GetCarDestinationIdentifier(Car c)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public class Settings
|
|||||||
bool cabooseRequiredForLocoTagOilIndication,
|
bool cabooseRequiredForLocoTagOilIndication,
|
||||||
bool servicingFundPenalty,
|
bool servicingFundPenalty,
|
||||||
bool safetyFirst,
|
bool safetyFirst,
|
||||||
|
bool safetyFirstClientEnforce,
|
||||||
CrewHourLoadMethod loadCrewHoursMethod,
|
CrewHourLoadMethod loadCrewHoursMethod,
|
||||||
float cabeeseSearchRadiusFtInMeters,
|
float cabeeseSearchRadiusFtInMeters,
|
||||||
bool trainBrakeDisplayShowsColorsInCalloutMode
|
bool trainBrakeDisplayShowsColorsInCalloutMode
|
||||||
@@ -42,6 +43,7 @@ public class Settings
|
|||||||
CabooseRequiredForLocoTagOilIndication = cabooseRequiredForLocoTagOilIndication;
|
CabooseRequiredForLocoTagOilIndication = cabooseRequiredForLocoTagOilIndication;
|
||||||
ServicingFundPenalty = servicingFundPenalty;
|
ServicingFundPenalty = servicingFundPenalty;
|
||||||
SafetyFirst = safetyFirst;
|
SafetyFirst = safetyFirst;
|
||||||
|
SafetyFirstClientEnforce = safetyFirstClientEnforce;
|
||||||
LoadCrewHoursMethod = loadCrewHoursMethod;
|
LoadCrewHoursMethod = loadCrewHoursMethod;
|
||||||
CabeeseSearchRadiusFtInMeters = cabeeseSearchRadiusFtInMeters;
|
CabeeseSearchRadiusFtInMeters = cabeeseSearchRadiusFtInMeters;
|
||||||
TrainBrakeDisplayShowsColorsInCalloutMode = trainBrakeDisplayShowsColorsInCalloutMode;
|
TrainBrakeDisplayShowsColorsInCalloutMode = trainBrakeDisplayShowsColorsInCalloutMode;
|
||||||
@@ -57,6 +59,7 @@ public class Settings
|
|||||||
public bool CabooseRequiredForLocoTagOilIndication;
|
public bool CabooseRequiredForLocoTagOilIndication;
|
||||||
public bool ServicingFundPenalty;
|
public bool ServicingFundPenalty;
|
||||||
public bool SafetyFirst;
|
public bool SafetyFirst;
|
||||||
|
public bool SafetyFirstClientEnforce;
|
||||||
public CrewHourLoadMethod LoadCrewHoursMethod;
|
public CrewHourLoadMethod LoadCrewHoursMethod;
|
||||||
public float CabeeseSearchRadiusFtInMeters;
|
public float CabeeseSearchRadiusFtInMeters;
|
||||||
public bool TrainBrakeDisplayShowsColorsInCalloutMode;
|
public bool TrainBrakeDisplayShowsColorsInCalloutMode;
|
||||||
@@ -136,6 +139,8 @@ public static class SettingsExtensions
|
|||||||
input?.settings?.ServicingFundPenalty ?? false;
|
input?.settings?.ServicingFundPenalty ?? false;
|
||||||
public static bool SafetyFirst(this TweaksAndThingsPlugin input) =>
|
public static bool SafetyFirst(this TweaksAndThingsPlugin input) =>
|
||||||
input?.settings?.SafetyFirst ?? false;
|
input?.settings?.SafetyFirst ?? false;
|
||||||
|
public static bool SafetyFirstClientEnforce(this TweaksAndThingsPlugin input) =>
|
||||||
|
input?.settings?.SafetyFirstClientEnforce ?? true;
|
||||||
public static bool DayLoadCrewHours(this TweaksAndThingsPlugin input) =>
|
public static bool DayLoadCrewHours(this TweaksAndThingsPlugin input) =>
|
||||||
(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) =>
|
||||||
|
|||||||
@@ -203,6 +203,23 @@ AutoHotboxSpotter Update: decrease the random wait from 30 - 300 seconds to 15 -
|
|||||||
).Tooltip("Safety First", $@"On non-express timetabled consists, a caboose is required in the consist increase AE max speed > 20 in {Enum.GetName(typeof(AutoEngineerMode), AutoEngineerMode.Road)}/{Enum.GetName(typeof(AutoEngineerMode), AutoEngineerMode.Waypoint)} mode.");
|
).Tooltip("Safety First", $@"On non-express timetabled consists, a caboose is required in the consist increase AE max speed > 20 in {Enum.GetName(typeof(AutoEngineerMode), AutoEngineerMode.Road)}/{Enum.GetName(typeof(AutoEngineerMode), AutoEngineerMode.Waypoint)} mode.");
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region SafetyFirstClient
|
||||||
|
if (settings?.SafetyFirst ?? false)
|
||||||
|
{
|
||||||
|
builder.Spacer(spacing);
|
||||||
|
builder.AddFieldToggle(
|
||||||
|
"Safety First! (Enforce Client Speed Restrictions)",
|
||||||
|
() => settings?.SafetyFirstClientEnforce ?? false,
|
||||||
|
delegate (bool enabled)
|
||||||
|
{
|
||||||
|
if (settings == null) settings = new();
|
||||||
|
settings.SafetyFirstClientEnforce = enabled;
|
||||||
|
builder.Rebuild();
|
||||||
|
}
|
||||||
|
).Tooltip("Safety First! (Enforce Client Speed Restrictions)", $@"Enforce cabeese dominance on clients; uncheck to allow clients to override the 20mph restriction.");
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UiUpdates(UIPanelBuilder builder)
|
private void UiUpdates(UIPanelBuilder builder)
|
||||||
|
|||||||
Reference in New Issue
Block a user