Compare commits

..

8 Commits

23 changed files with 284 additions and 66 deletions

View File

@@ -2,6 +2,6 @@
<PropertyGroup> <PropertyGroup>
<MajorVersion>2</MajorVersion> <MajorVersion>2</MajorVersion>
<MinorVersion>1</MinorVersion> <MinorVersion>1</MinorVersion>
<PatchVersion>7</PatchVersion> <PatchVersion>8</PatchVersion>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

View File

@@ -0,0 +1,60 @@
using HarmonyLib;
using Helpers;
using Railloader;
using Serilog;
using System.Collections;
using Track;
using UI;
using UnityEngine;
using static UI.AutoEngineerDestinationPicker;
namespace RMROC451.TweaksAndThings.Patches;
[HarmonyPatch(typeof(AutoEngineerDestinationPicker))]
[HarmonyPatch(nameof(AutoEngineerDestinationPicker.Loop))]
[HarmonyPatchCategory("RMROC451TweaksAndThings")]
internal class AutoEngineerDestinationPicker_Loop_Patch
{
static bool Prefix(AutoEngineerDestinationPicker __instance, ref IEnumerator __result)
{
TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase<TweaksAndThingsPlugin>.Shared;
if (!tweaksAndThings.IsEnabled()) return true;
__result = Loop(__instance);
return false;
}
private static IEnumerator Loop(AutoEngineerDestinationPicker __instance)
{
Hit valueOrDefault;
Location location;
WaitForSecondsRealtime wait = new WaitForSecondsRealtime(1/60);
while (true)
{
Location? currentOrdersGotoLocation = __instance.GetCurrentOrdersGotoLocation();
Hit? hit = __instance.HitLocation();
if (hit.HasValue)
{
valueOrDefault = hit.GetValueOrDefault();
location = valueOrDefault.Location;
Graph.PositionRotation positionRotation = __instance._graph.GetPositionRotation(location);
__instance.destinationMarker.position = WorldTransformer.GameToWorld(positionRotation.Position);
__instance.destinationMarker.rotation = positionRotation.Rotation;
__instance.destinationMarker.gameObject.SetActive(value: true);
if (!currentOrdersGotoLocation.Equals(location) && __instance.MouseClicked)
{
break;
}
}
else
{
__instance.destinationMarker.gameObject.SetActive(value: false);
}
yield return wait;
}
Log.Debug("DestinationPicker Hit: {hit} {car} {end}", valueOrDefault.Location, valueOrDefault.CarInfo?.car, valueOrDefault.CarInfo?.end);
__instance._ordersHelper.SetWaypoint(location, valueOrDefault.CarInfo?.car.id);
__instance.StopLoop();
}
}

View File

@@ -1,31 +0,0 @@
using Game.Notices;
using Game.State;
using HarmonyLib;
using Model;
using Network;
using Serilog;
using UI.EngineControls;
using UnityEngine;
namespace RMROC451.TweaksAndThings.Patches;
[HarmonyPatch(typeof(AutoEngineerOrdersHelper))]
[HarmonyPatch(nameof(AutoEngineerOrdersHelper.SetWaypoint), typeof(Track.Location), typeof(string))]
[HarmonyPatchCategory("RMROC451TweaksAndThings")]
internal class AutoEngineerOrdersHelper_SetWaypoint_patch
{
private static Serilog.ILogger _log => Log.ForContext<AutoEngineerOrdersHelper_SetWaypoint_patch>();
static void Postfix(AutoEngineerOrdersHelper __instance, Track.Location location, string coupleToCarId)
{
if (StateManager.IsHost)
{
_log.Debug($"start setWP");
Car selectedLoco = __instance._locomotive;
_log.Debug($"{selectedLoco?.DisplayName ?? ""} set WP");
Vector3 gamePoint = location.GetPosition();
EntityReference entityReference = new EntityReference(EntityType.Position, new Vector4(gamePoint.x, gamePoint.y, gamePoint.z, 0));
selectedLoco.PostNotice("ai-wpt-rmroc451", new Hyperlink(entityReference.URI(), $"WP SET"));
}
}
}

View File

@@ -1,5 +1,6 @@
using Game; using Game;
using Game.Messages; using Game.Messages;
using Game.Notices;
using Game.State; using Game.State;
using HarmonyLib; using HarmonyLib;
using Model; using Model;
@@ -15,8 +16,10 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Track;
using UI.EngineControls; using UI.EngineControls;
using UI.EngineRoster; using UI.EngineRoster;
using UnityEngine;
using static Unity.IO.LowLevel.Unsafe.AsyncReadManagerMetrics; using static Unity.IO.LowLevel.Unsafe.AsyncReadManagerMetrics;
using static UnityEngine.InputSystem.InputRemoting; using static UnityEngine.InputSystem.InputRemoting;
@@ -33,9 +36,9 @@ internal class AutoEngineerPlanner_HandleCommand_Patch
static bool Prefix(AutoEngineerPlanner __instance, ref AutoEngineerCommand command, ref IPlayer sender) static bool Prefix(AutoEngineerPlanner __instance, ref AutoEngineerCommand command, ref IPlayer sender)
{ {
TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase<TweaksAndThingsPlugin>.Shared; TweaksAndThingsPlugin tweaksAndThings = SingletonPluginBase<TweaksAndThingsPlugin>.Shared;
LocoNoticeWPSet(__instance, command, sender);
if (!tweaksAndThings.IsEnabled() || !tweaksAndThings.SafetyFirst() || (sender.IsRemote && !tweaksAndThings.SafetyFirstClientEnforce()) || command.MaxSpeedMph <= governedSpeed) return true; if (!tweaksAndThings.IsEnabled() || !tweaksAndThings.SafetyFirst() || (sender.IsRemote && !tweaksAndThings.SafetyFirstClientEnforce()) || command.MaxSpeedMph <= governedSpeed) return true;
BaseLocomotive loco = TrainController.Shared.SelectedLocomotive; BaseLocomotive loco = __instance._locomotive;
if (TrainController.Shared.TryGetCarForId(command.LocomotiveId, out Car c)) loco = (BaseLocomotive)c;
if (SafetyFirstGoverningApplies(loco)) if (SafetyFirstGoverningApplies(loco))
{ {
@@ -50,9 +53,10 @@ internal class AutoEngineerPlanner_HandleCommand_Patch
string message = $"{Enum.GetName(typeof(AutoEngineerMode), command.Mode)}[{loco.DisplayName}] governed{{0}}due to Safety First rules."; string message = $"{Enum.GetName(typeof(AutoEngineerMode), command.Mode)}[{loco.DisplayName}] governed{{0}}due to Safety First rules.";
if (orig != command.MaxSpeedMph) if (orig != command.MaxSpeedMph)
{ {
message = string.Format(message, $" from {orig} to {command.MaxSpeedMph} MPH "); message = string.Format(message, $" from {orig} to {command.MaxSpeedMph} MPH ");
}else }
else
{ {
message = string.Format(message, " "); message = string.Format(message, " ");
} }
@@ -63,6 +67,47 @@ internal class AutoEngineerPlanner_HandleCommand_Patch
return true; return true;
} }
private static void LocoNoticeWPSet(AutoEngineerPlanner __instance, AutoEngineerCommand command, IPlayer sender)
{
OrderWaypoint? wp =
string.IsNullOrEmpty(command.WaypointLocationString) ?
null :
new OrderWaypoint?(new OrderWaypoint(command.WaypointLocationString, command.WaypointCoupleToCarId));
if (
wp.HasValue &&
!string.IsNullOrEmpty(wp.Value.LocationString) &&
!__instance._orders.Waypoint.Equals(wp)
)
{
_log.Debug($"start setWP");
Car selectedLoco = __instance._locomotive;
_log.Debug($"{selectedLoco?.DisplayName ?? ""} set WP");
if (LocationPositionFromString(wp.Value, out Vector3 gamePoint))
{
EntityReference entityReference = new EntityReference(EntityType.Position, new Vector4(gamePoint.x, gamePoint.y, gamePoint.z, 0));
selectedLoco.PostNotice("ai-wpt-rmroc451", new Hyperlink(entityReference.URI(), $"WP SET [{sender.Name}]"));
}
}
}
internal static bool LocationPositionFromString(OrderWaypoint waypoint, out Vector3 position)
{
Location location;
position = default;
try
{
location = Graph.Shared.ResolveLocationString(waypoint.LocationString);
position = location.GetPosition();
return true;
}
catch (Exception exception)
{
Log.Error(exception, "Couldn't get location from waypoint: {locStr}", waypoint.LocationString);
return false;
}
}
internal static bool SafetyFirstGoverningApplies(BaseLocomotive loco) internal static bool SafetyFirstGoverningApplies(BaseLocomotive loco)
{ {
var _persistence = new AutoEngineerPersistence(loco.KeyValueObject); var _persistence = new AutoEngineerPersistence(loco.KeyValueObject);

View File

@@ -1,4 +1,5 @@
using HarmonyLib; using Game.State;
using HarmonyLib;
using Model; using Model;
using Railloader; using Railloader;
using RMROC451.TweaksAndThings.Enums; using RMROC451.TweaksAndThings.Enums;
@@ -8,6 +9,8 @@ using System;
using System.Linq; using System.Linq;
using UI; using UI;
using UI.ContextMenu; using UI.ContextMenu;
using UnityEngine;
using ContextMenu = UI.ContextMenu.ContextMenu;
namespace RMROC451.TweaksAndThings.Patches; namespace RMROC451.TweaksAndThings.Patches;
@@ -34,50 +37,79 @@ internal class CarPickable_HandleShowContextMenu_Patch
{ {
trainController.SelectedCar = ((trainController.SelectedCar == car) ? null : car); trainController.SelectedCar = ((trainController.SelectedCar == car) ? null : car);
}); });
if (GameInput.IsShiftDown)
bool shiftPagination = (tweaksAndThings.ShiftForPagination() && GameInput.IsShiftDown) || !tweaksAndThings.ShiftForPagination();
bool nonShiftShow = (tweaksAndThings.ShiftForPagination() && !GameInput.IsShiftDown) || !tweaksAndThings.ShiftForPagination();
if (shiftPagination && car.EnumerateCoupled().Any(c => c.SupportsBleed()))
{ {
if (!car.EnumerateCoupled().Any(c => !c.SupportsBleed())) Sprite? bleedConsist = MapWindow_OnClick_Patch.LoadTexture("BleedConsist.png", "BleedConsist");
if (bleedConsist == null) bleedConsist = SpriteName.Bleed.Sprite();
shared.AddButton(ContextMenuQuadrant.Brakes, $"Bleed Consist", bleedConsist, delegate
{ {
shared.AddButton(ContextMenuQuadrant.Brakes, $"Bleed Consist", SpriteName.Bleed, delegate CarInspector_PopulateCarPanel_Patch.MrocConsistHelper(car, MrocHelperType.BleedAirSystem, buttonsHaveCost);
{
CarInspector_PopulateCarPanel_Patch.MrocConsistHelper(car, MrocHelperType.BleedAirSystem, buttonsHaveCost);
});
}
shared.AddButton(ContextMenuQuadrant.Brakes, $"{(car.EnumerateCoupled().Any(c => c.HandbrakeApplied()) ? "Release " : "Set ")} Consist", SpriteName.Handbrake, delegate
{
CarInspector_PopulateCarPanel_Patch.MrocConsistHelper(car, MrocHelperType.Handbrake, buttonsHaveCost);
}); });
}
if (nonShiftShow && car.SupportsBleed())
{
Sprite? bleedCar = MapWindow_OnClick_Patch.LoadTexture("BleedCar.png", "BleedCar");
if (bleedCar == null) bleedCar = SpriteName.Bleed.Sprite();
shared.AddButton(ContextMenuQuadrant.Brakes, "Bleed", bleedCar, car.SetBleed);
}
if (car.EnumerateCoupled().Any(c => c.EndAirSystemIssue())) if (shiftPagination)
{ {
shared.AddButton(ContextMenuQuadrant.General, $"Air Up Consist", SpriteName.Select, delegate string text = car.EnumerateCoupled().Any(c => c.HandbrakeApplied()) ? "Release " : "Set ";
Sprite? consistBrakes = MapWindow_OnClick_Patch.LoadTexture($"Consist{text.Trim()}Brake.png", $"{text.Trim()}Consist");
if (consistBrakes == null) consistBrakes = SpriteName.Handbrake.Sprite();
shared.AddButton(ContextMenuQuadrant.Brakes, $"{text}Consist", consistBrakes, delegate
{
CarInspector_PopulateCarPanel_Patch.MrocConsistHelper(car, MrocHelperType.Handbrake, buttonsHaveCost);
});
}
if (nonShiftShow)
{
string textCar = car.HandbrakeApplied() ? "Release " : "Set ";
Sprite? carBrakes = MapWindow_OnClick_Patch.LoadTexture($"{textCar.Trim()}Brake.png", $"{textCar.Trim()}Brake");
if (carBrakes == null) carBrakes = SpriteName.Handbrake.Sprite();
shared.AddButton(ContextMenuQuadrant.Brakes, $"{textCar}Handbrake", carBrakes, delegate
{
bool apply = !car.air.handbrakeApplied;
car.SetHandbrake(apply);
});
}
if (shiftPagination && car.EnumerateCoupled().Any(c => c.EndAirSystemIssue()))
{
Sprite? connectAir = MapWindow_OnClick_Patch.LoadTexture($"ConnectAir.png", "ConnectAir");
if (connectAir == null) connectAir = SpriteName.Select.Sprite();
shared.AddButton(ContextMenuQuadrant.General, $"Air Up Consist", connectAir, delegate
{ {
CarInspector_PopulateCarPanel_Patch.MrocConsistHelper(car, MrocHelperType.GladhandAndAnglecock, buttonsHaveCost); CarInspector_PopulateCarPanel_Patch.MrocConsistHelper(car, MrocHelperType.GladhandAndAnglecock, buttonsHaveCost);
}); });
}
} }
else
if (StateManager.IsHost && shiftPagination && car.EnumerateCoupled().Any(c => c.NeedsOiling || c.HasHotbox))
{ {
if (car.SupportsBleed()) Sprite? oilCan = MapWindow_OnClick_Patch.LoadTexture("OilCan.png", "OilCan");
if (oilCan == null) oilCan = SpriteName.Select.Sprite();
shared.AddButton(ContextMenuQuadrant.General, $"Oil Consist", oilCan, delegate
{ {
shared.AddButton(ContextMenuQuadrant.Brakes, "Bleed", SpriteName.Bleed, car.SetBleed); CarInspector_PopulateCarPanel_Patch.MrocConsistHelper(car, MrocHelperType.Oil, buttonsHaveCost);
}
shared.AddButton(ContextMenuQuadrant.Brakes, car.air.handbrakeApplied ? "Release Handbrake" : "Apply Handbrake", SpriteName.Handbrake, delegate
{
bool apply = !car.air.handbrakeApplied;
car.SetHandbrake(apply);
}); });
} }
shared.AddButton(ContextMenuQuadrant.General, $"Follow", SpriteName.Inspect, delegate Sprite? follow = MapWindow_OnClick_Patch.LoadTexture($"Follow.png", "ConnectAir");
if (follow == null) follow = SpriteName.Inspect.Sprite();
shared.AddButton(ContextMenuQuadrant.General, $"Follow", follow, delegate
{ {
CameraSelector.shared.FollowCar(car); CameraSelector.shared.FollowCar(car);
}); });
string secondaryLine = car.Waybill.HasValue ? $"{Environment.NewLine}{car.Waybill.Value.Destination.DisplayName}" : string.Empty; string secondaryLine = car.Waybill.HasValue ? $"{Environment.NewLine}{car.Waybill.Value.Destination.DisplayName}" : string.Empty;
secondaryLine = secondaryLine.Length > 10 + Environment.NewLine.Length ? $"{secondaryLine.Substring(0, 7+ Environment.NewLine.Length)}..." : secondaryLine; secondaryLine = secondaryLine.Length > 10 + Environment.NewLine.Length ? $"{secondaryLine.Substring(0, 7 + Environment.NewLine.Length)}..." : secondaryLine;
shared.Show($"{car.DisplayName}{secondaryLine}"); shared.Show($"{car.EnumerateCoupled().Count()} Cars{Environment.NewLine}{car.DisplayName}{secondaryLine}");
shared.BuildItemAngles(); shared.BuildItemAngles();
shared.StartCoroutine(shared.AnimateButtonsShown()); shared.StartCoroutine(shared.AnimateButtonsShown());
return false; return false;

View File

@@ -15,6 +15,7 @@ using UI.EngineRoster;
using UI.Tooltips; using UI.Tooltips;
using UnityEngine; using UnityEngine;
using Game.State; using Game.State;
using Game;
namespace RMROC451.TweaksAndThings.Patches; namespace RMROC451.TweaksAndThings.Patches;
@@ -34,6 +35,8 @@ internal class EngineRosterRow_Refresh_Patch
string fuelInfoText = string.Empty; string fuelInfoText = string.Empty;
string fuelInfoTooltip = string.Empty; string fuelInfoTooltip = string.Empty;
TweakyTweakTweakers(__instance);
if (tweaksAndThings == null || if (tweaksAndThings == null ||
rosterFuelColumnSettings == null || rosterFuelColumnSettings == null ||
!tweaksAndThings.IsEnabled() || !tweaksAndThings.IsEnabled() ||
@@ -52,7 +55,7 @@ internal class EngineRosterRow_Refresh_Patch
bool cabooseRequirementFulfilled = bool cabooseRequirementFulfilled =
!tweaksAndThings.RequireConsistCabooseForOilerAndHotboxSpotter() !tweaksAndThings.RequireConsistCabooseForOilerAndHotboxSpotter()
|| consist.ConsistNoFreight() || consist.ConsistNoFreight()
|| (bool)engineOrTender.FindMyCabooseSansLoadRequirement(); || (bool)engineOrTender.FindMyCabooseSansLoadRequirement();
float offendingPercentage = 100f; float offendingPercentage = 100f;
foreach (Car loco in locos) foreach (Car loco in locos)
@@ -131,13 +134,54 @@ internal class EngineRosterRow_Refresh_Patch
default: default:
break; break;
} }
} catch (Exception ex) }
catch (Exception ex)
{ {
rosterFuelColumnSettings.EngineRosterFuelStatusColumn = EngineRosterFuelDisplayColumn.None; rosterFuelColumnSettings.EngineRosterFuelStatusColumn = EngineRosterFuelDisplayColumn.None;
Log.Error(ex, "Error Detecting fuel status for engine roster"); Log.Error(ex, "Error Detecting fuel status for engine roster");
} }
} }
private static void TweakyTweakTweakers(EngineRosterRow __instance)
{
var helperData = EngineTextHelper(__instance._engine);
if (helperData.HasValue)
{
__instance.nameLabel.text = helperData.Value.nameLabel;
__instance.nameTooltip.tooltipText += helperData.Value.nameTooltip;
}
__instance.crewLabel.text = string.Empty;
for (int i = __instance._crewComponents.Count - 1; i >= 0; i--)
{
string str = __instance._crewComponents[i];
if ((new[] { "MU", "AE" }).Contains(str))
str = $"<sup>{str} </sup>";
__instance.crewLabel.text = $"{str}{__instance.crewLabel.text}";
}
}
internal static (string nameLabel, string nameTooltip, int selectedCount)? EngineTextHelper(Car loco, bool mapIcon = false)
{
(string nameLabel, string nameTooltip, int selectedCount)? output = null;
int selectedCount = 0;
Dictionary<PlayerId, IPlayer> dictionary = StateManager.Shared.PlayersManager.AllPlayers.ToDictionary((IPlayer p) => p.PlayerId, (IPlayer p) => p);
List<string> usersSelected = new();
foreach (var kvp in dictionary)
{
if (new PlayerProperties(PlayerPropertiesManager.Shared._object[kvp.Key.ToString()]).SelectedCarId == loco.id)
{
usersSelected.Add(kvp.Value.Name);
selectedCount++;
}
}
if (selectedCount > 0 && dictionary.Count > 1)
output = ($"{(mapIcon && loco is BaseLocomotive ? loco.Ident.RoadNumber : loco.DisplayName)}<sub>{selectedCount}</sub>", $"{Environment.NewLine}Selected by: {string.Join(", ", usersSelected)}", selectedCount);
return output;
}
private static void SetLabelAndTooltip(ref TMP_Text label, ref UITooltipProvider tooltip, string fuelInfoText, string fuelInfoTooltip) private static void SetLabelAndTooltip(ref TMP_Text label, ref UITooltipProvider tooltip, string fuelInfoText, string fuelInfoTooltip)
{ {
label.text = $" {fuelInfoText} {label.text}"; label.text = $" {fuelInfoText} {label.text}";

View File

@@ -34,6 +34,11 @@ internal class MapWindow_OnClick_Patch
public static Sprite? LoadTexture(string fileName, string name) public static Sprite? LoadTexture(string fileName, string name)
{ {
string path = Path.Combine(SingletonPluginBase<TweaksAndThingsPlugin>.Shared.ModDirectory, fileName); string path = Path.Combine(SingletonPluginBase<TweaksAndThingsPlugin>.Shared.ModDirectory, fileName);
if (!File.Exists(path))
{
_log.Debug($"Unable to find {name} icon at {path}!");
return null;
}
Texture2D texture2D = new Texture2D(128, 128, TextureFormat.DXT5, mipChain: false); Texture2D texture2D = new Texture2D(128, 128, TextureFormat.DXT5, mipChain: false);
texture2D.name = name; texture2D.name = name;
texture2D.wrapMode = TextureWrapMode.Clamp; texture2D.wrapMode = TextureWrapMode.Clamp;

View File

@@ -0,0 +1,42 @@
using HarmonyLib;
using Helpers;
using Model.Database;
using Model.Definition;
using Model.Definition.Data;
using Model.Ops;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
namespace RMROC451.TweaksAndThings.Patches;
[HarmonyPatch(typeof(PrefabStoreExtensions))]
[HarmonyPatch(nameof(PrefabStoreExtensions.Random))]
[HarmonyPatchCategory("RMROC451TweaksAndThings")]
internal static class PrefabStoreExtensions_Random_Patch
{
public static bool Prefix(IPrefabStore prefabStore, CarTypeFilter carTypeFilter, IndustryContext.CarSizePreference sizePreference, Random rnd, ref TypedContainerItem<CarDefinition> __result)
{
List<TypedContainerItem<CarDefinition>> list =
(from p in prefabStore.AllCarDefinitionInfos.ToList().FindAll((TypedContainerItem<CarDefinition> p) =>
carTypeFilter.Matches(p.Definition.CarType) && !p.Metadata.Tags.Any(t => t.Equals("deprecated")))
orderby p.Definition.WeightEmpty
select p).ToList();
if (list.Count == 0)
{
Log.Error($"Couldn't find car for condition: {carTypeFilter}");
__result = null;
}
__result = list.RandomElementUsingNormalDistribution(sizePreference switch
{
IndustryContext.CarSizePreference.Small => 0.2f,
IndustryContext.CarSizePreference.Medium => 0.4f,
IndustryContext.CarSizePreference.Large => 0.6f,
IndustryContext.CarSizePreference.ExtraLarge => 0.8f,
_ => 0.5f,
}, rnd);
return false;
}
}

View File

@@ -55,4 +55,8 @@
<ItemGroup> <ItemGroup>
<Publicize Include="Assembly-CSharp" /> <Publicize Include="Assembly-CSharp" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="Images\**" CopyToOutputDirectory="Always"/>
</ItemGroup>
</Project> </Project>

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 shiftPaginationOnContextMenu
) )
{ {
WebhookSettingsList = webhookSettingsList; WebhookSettingsList = webhookSettingsList;
@@ -47,6 +48,7 @@ public class Settings
LoadCrewHoursMethod = loadCrewHoursMethod; LoadCrewHoursMethod = loadCrewHoursMethod;
CabeeseSearchRadiusFtInMeters = cabeeseSearchRadiusFtInMeters; CabeeseSearchRadiusFtInMeters = cabeeseSearchRadiusFtInMeters;
TrainBrakeDisplayShowsColorsInCalloutMode = trainBrakeDisplayShowsColorsInCalloutMode; TrainBrakeDisplayShowsColorsInCalloutMode = trainBrakeDisplayShowsColorsInCalloutMode;
ShiftPaginationOnContextMenu = shiftPaginationOnContextMenu;
} }
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 ShiftPaginationOnContextMenu;
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 ShiftForPagination(this TweaksAndThingsPlugin input) =>
input?.settings?.ShiftPaginationOnContextMenu ?? 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(
"Context Menu Shift Modifier",
() => this.ShiftForPagination(),
delegate (bool enabled)
{
if (settings == null) settings = new();
settings.ShiftPaginationOnContextMenu = enabled;
builder.Rebuild();
}
).Tooltip("Context Menu Shift Modifier", $@"When enabled/checked, utilizing `SHIFT` while initiating the context menu of a car will show consist level options, and without shows only car level. If this is unchecked, all car/consist options show up in a happy goulash!");
builder.Spacer(spacing); builder.Spacer(spacing);
EngineRosterShowsFuelStatusUISection(builder); EngineRosterShowsFuelStatusUISection(builder);
} }