fixes #46; only care about caboose crew hours on certain actions, it's presence is enough in other cases.

This commit is contained in:
2025-08-24 09:57:45 -05:00
parent f1ba2ed6f1
commit fa7e7dfcd2
11 changed files with 29 additions and 20 deletions

View File

@@ -21,7 +21,6 @@
"mixintos": { "mixintos": {
"container:ne-caboose01": "file(mroc-cabeese.json)", "container:ne-caboose01": "file(mroc-cabeese.json)",
"container:ne-caboose02": "file(mroc-cabeese.json)", "container:ne-caboose02": "file(mroc-cabeese.json)",
"container:ne-caboose03": "file(mroc-cabeese.json)", "container:ne-caboose03": "file(mroc-cabeese.json)"
"game-graph": "file(tweakedLoadIDS.json)"
} }
} }

View File

@@ -19,7 +19,7 @@ namespace RMROC451.TweaksAndThings.Extensions
public static IEnumerator MrocAutoOilerLoop(this AutoOiler oiler, Serilog.ILogger _log, bool cabooseRequired) public static IEnumerator MrocAutoOilerLoop(this AutoOiler oiler, Serilog.ILogger _log, bool cabooseRequired)
{ {
int originIndex = oiler.FindOriginIndex(); int originIndex = oiler.FindOriginIndex();
Model.Car? foundCaboose = oiler._originCar.FindMyCaboose(0.0f, false); Model.Car? foundCaboose = oiler._originCar.FindMyCabooseSansLoadRequirement();
if (originIndex < 0) if (originIndex < 0)
{ {
_log.Error("Couldn't find origin car {car}", oiler._originCar); _log.Error("Couldn't find origin car {car}", oiler._originCar);
@@ -41,7 +41,7 @@ namespace RMROC451.TweaksAndThings.Extensions
while (true) while (true)
{ {
yield return new WaitForSeconds(AutoOiler.StartDelay.CabooseHalvedFloat(foundCaboose)); yield return new WaitForSeconds(AutoOiler.StartDelay.CabooseHalvedFloat(foundCaboose));
foundCaboose = oiler._originCar.FindMyCaboose(0.0f,false); foundCaboose = oiler._originCar.FindMyCabooseSansLoadRequirement();
int carIndex = originIndex; int carIndex = originIndex;
float adjustedTimeToWalk = AutoOiler.TimeToWalkCar.CabooseHalvedFloat(foundCaboose); float adjustedTimeToWalk = AutoOiler.TimeToWalkCar.CabooseHalvedFloat(foundCaboose);
do do
@@ -80,7 +80,7 @@ namespace RMROC451.TweaksAndThings.Extensions
public static IEnumerator MrocAutoHotboxSpotterLoop(this AutoHotboxSpotter spotter, Serilog.ILogger _log, bool cabooseRequired) public static IEnumerator MrocAutoHotboxSpotterLoop(this AutoHotboxSpotter spotter, Serilog.ILogger _log, bool cabooseRequired)
{ {
Func<Model.Car?> foundCaboose = () => spotter._locomotive.FindMyCaboose(0.0f, false); Func<Model.Car?> foundCaboose = () => spotter._locomotive.FindMyCabooseSansLoadRequirement();
while (true) while (true)
{ {
if (!spotter.HasCars) if (!spotter.HasCars)

View File

@@ -7,6 +7,7 @@ using Model.Definition.Data;
using Model.Ops; using Model.Ops;
using Model.Ops.Timetable; using Model.Ops.Timetable;
using Railloader; using Railloader;
using RMROC451.TweaksAndThings.Patches;
using Serilog; using Serilog;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@@ -98,21 +99,28 @@ public static class Car_Extensions
input.SelectedLocomotive.TryGetTimetableTrain(out Timetable.Train t) && input.SelectedLocomotive.TryGetTimetableTrain(out Timetable.Train t) &&
t.TrainClass == Timetable.TrainClass.First; t.TrainClass == Timetable.TrainClass.First;
public static Car? FindMyCaboose(this Car car, float timeNeeded, bool decrement = false) => public static Car? FindMyCabooseSansLoadRequirement(this Car car) =>
FindMyCaboose(car, 0f, decrement: false, requireLoad: false);
public static Car? FindMyCabooseWithLoadRequirement(this Car car, float timeNeeded, bool decrement) =>
FindMyCaboose(car, timeNeeded, decrement, requireLoad: false);
private static Car? FindMyCaboose(this Car car, float timeNeeded, bool decrement = false, bool requireLoad = true) =>
( (
car.CarCaboose() ?? car.CarsNearCurrentCar(timeNeeded, decrement).FindNearestCabooseFromNearbyCars() car.CarCaboose() ?? car.CarsNearCurrentCar(timeNeeded, decrement).FindNearestCabooseFromNearbyCars()
)?.CabooseWithSufficientCrewHours(timeNeeded, decrement); )?.CabooseWithSufficientCrewHours(timeNeeded, decrement);
public static Car? CabooseWithSufficientCrewHours(this Car car, float timeNeeded, bool decrement = false) public static Car? CabooseWithSufficientCrewHours(this Car car, float timeNeeded, bool requireLoad, bool decrement = false)
{ {
Car? output = null; Car? output = null;
if (car is null || !car.IsCaboose()) return null; if (car is null || !car.IsCaboose()) return null;
if (!requireLoad) return car;
List<LoadSlot> loadSlots = car.Definition.LoadSlots; List<LoadSlot> loadSlots = car.Definition.LoadSlots;
for (int i = 0; i < loadSlots.Count; i++) for (int i = 0; i < loadSlots.Count; i++)
{ {
CarLoadInfo? loadInfo = car.GetLoadInfo(i); CarLoadInfo? loadInfo = car.GetLoadInfo(i);
if (loadInfo.HasValue) if (loadInfo.HasValue && loadInfo.Value.LoadId == OpsController_AnnounceCoalescedPayments_Patch.CrewLoadHours.id)
{ {
CarLoadInfo valueOrDefault = loadInfo.GetValueOrDefault(); CarLoadInfo valueOrDefault = loadInfo.GetValueOrDefault();
output = valueOrDefault.Quantity >= timeNeeded ? car : null; output = valueOrDefault.Quantity >= timeNeeded ? car : null;

View File

@@ -72,7 +72,7 @@ internal class AutoEngineerOrdersHelper_SendAutoEngineerCommand_Patch
Func<bool> noCaboose = () => Func<bool> noCaboose = () =>
{ {
var output = TrainController.Shared.SelectedLocomotive.FindMyCaboose(0.0f, false) == null; bool output = (bool)TrainController.Shared.SelectedLocomotive.FindMyCabooseSansLoadRequirement();
logMessage += $"\ncaboose? {!output}"; logMessage += $"\ncaboose? {!output}";
return output; return output;
}; };

View File

@@ -227,8 +227,8 @@ internal class CarInspector_PopulateCarPanel_Patch
float originalTimeCost = consist.CalculateCostForAutoEngineerEndGearSetting(); float originalTimeCost = consist.CalculateCostForAutoEngineerEndGearSetting();
float timeCost = originalTimeCost; float timeCost = originalTimeCost;
float crewCost = timeCost / 3600; //hours of time deducted from caboose. float crewCost = timeCost / 3600; //hours of time deducted from caboose.
var tsString = crewCost.FormatCrewHours(OpsController_AnnounceCoalescedPayments_Patch.CrewHoursLoad().description); var tsString = crewCost.FormatCrewHours(OpsController_AnnounceCoalescedPayments_Patch.CrewLoadHours.description);
Car? cabooseWithAvailCrew = car.FindMyCaboose(crewCost, buttonsHaveCost); Car? cabooseWithAvailCrew = car.FindMyCabooseWithLoadRequirement(crewCost, buttonsHaveCost);
if (cabooseWithAvailCrew == null) timeCost *= 1.5f; if (cabooseWithAvailCrew == null) timeCost *= 1.5f;
var cabooseFoundDisplay = cabooseWithAvailCrew?.DisplayName ?? "No caboose"; var cabooseFoundDisplay = cabooseWithAvailCrew?.DisplayName ?? "No caboose";

View File

@@ -62,7 +62,7 @@ internal class CarPickable_Activate_Patch
var consist = car.EnumerateCoupled(); var consist = car.EnumerateCoupled();
bool handbrakesApplied = consist.Any(c => c.HandbrakeApplied()); bool handbrakesApplied = consist.Any(c => c.HandbrakeApplied());
bool airSystemIssues = consist.Any(c => c.EndAirSystemIssue()); bool airSystemIssues = consist.Any(c => c.EndAirSystemIssue());
Func<bool> cabooseNear = () => (bool)car.FindMyCaboose(0.0f, false); Func<bool> cabooseNear = () => (bool)car.FindMyCabooseSansLoadRequirement();
bool needsOiling = GameInput.IsShiftDown && consist.All(c => c.IsStopped()) && consist.Any(c => c.NeedsOiling || c.HasHotbox) && (!tweaksAndThings.RequireConsistCabooseForOilerAndHotboxSpotter() || cabooseNear()); bool needsOiling = GameInput.IsShiftDown && consist.All(c => c.IsStopped()) && consist.Any(c => c.NeedsOiling || c.HasHotbox) && (!tweaksAndThings.RequireConsistCabooseForOilerAndHotboxSpotter() || cabooseNear());
var chargeIt = handbrakesApplied || airSystemIssues || needsOiling; var chargeIt = handbrakesApplied || airSystemIssues || needsOiling;
//CTRL + ALT + SHIFT : BrakesAngleCocksAndOiling //CTRL + ALT + SHIFT : BrakesAngleCocksAndOiling

View File

@@ -52,7 +52,7 @@ internal class EngineRosterRow_Refresh_Patch
bool cabooseRequirementFulfilled = bool cabooseRequirementFulfilled =
!tweaksAndThings.RequireConsistCabooseForOilerAndHotboxSpotter() !tweaksAndThings.RequireConsistCabooseForOilerAndHotboxSpotter()
|| consist.ConsistNoFreight() || consist.ConsistNoFreight()
|| (bool)engineOrTender.FindMyCaboose(0.0f, false); || (bool)engineOrTender.FindMyCabooseSansLoadRequirement();
float offendingPercentage = 100f; float offendingPercentage = 100f;
foreach (Car loco in locos) foreach (Car loco in locos)

View File

@@ -24,7 +24,7 @@ internal class CarExtensions_LoadString_Patch
{ {
public static bool Prefix(CarLoadInfo info, Load load, ref string __result) public static bool Prefix(CarLoadInfo info, Load load, ref string __result)
{ {
bool output = load.id == OpsController_AnnounceCoalescedPayments_Patch.CrewHoursLoad().id; bool output = load.id == OpsController_AnnounceCoalescedPayments_Patch.CrewLoadHours.id;
if (output) __result = info.Quantity.FormatCrewHours(load.description); if (output) __result = info.Quantity.FormatCrewHours(load.description);
return !output; return !output;
@@ -38,7 +38,7 @@ internal class CarPrototypeLibrary_LoadForId_Patch
{ {
public static bool Prefix(string loadId, ref Load __result) public static bool Prefix(string loadId, ref Load __result)
{ {
Load load = OpsController_AnnounceCoalescedPayments_Patch.CrewHoursLoad(); Load load = OpsController_AnnounceCoalescedPayments_Patch.CrewLoadHours;
if (loadId == load.id) __result = load; if (loadId == load.id) __result = load;
return __result == null; return __result == null;
@@ -70,7 +70,9 @@ internal class OpsController_AnnounceCoalescedPayments_Patch
typeof(RepairTrack) typeof(RepairTrack)
}; };
public static Load CrewHoursLoad() private static Load _crewLoadHours;
internal static Load CrewLoadHours => _crewLoadHours ?? CrewHoursLoad();
private static Load CrewHoursLoad()
{ {
Load load = (Load)ScriptableObject.CreateInstance(typeof(Load)); Load load = (Load)ScriptableObject.CreateInstance(typeof(Load));
load.name = "crew-hours"; load.name = "crew-hours";

View File

@@ -36,11 +36,11 @@ internal class StateManager_OnDayDidChange_Patch
{ {
foreach (var car in TrainController.Shared.Cars.Where(Car_Extensions.IsCaboose)) foreach (var car in TrainController.Shared.Cars.Where(Car_Extensions.IsCaboose))
{ {
var data = car.QuantityCapacityOfLoad(OpsController_AnnounceCoalescedPayments_Patch.CrewHoursLoad()); var data = car.QuantityCapacityOfLoad(OpsController_AnnounceCoalescedPayments_Patch.CrewLoadHours);
if (data.quantity < data.capacity) if (data.quantity < data.capacity)
{ {
Multiplayer.Broadcast($"{Hyperlink.To(car)}: \"Caboose crew topped off.\""); Multiplayer.Broadcast($"{Hyperlink.To(car)}: \"Caboose crew topped off.\"");
new OpsCarAdapter(car, OpsController.Shared).Load(OpsController_AnnounceCoalescedPayments_Patch.CrewHoursLoad(), data.capacity - data.quantity); new OpsCarAdapter(car, OpsController.Shared).Load(OpsController_AnnounceCoalescedPayments_Patch.CrewLoadHours, data.capacity - data.quantity);
} }
} }
} }

View File

@@ -43,7 +43,7 @@ internal class TagController_UpdateTag_Patch
//if (car.EnableOiling) tags.Add(car.HasHotbox ? TextSprites.Hotbox : $"<cspace=-1em>{TextSprites.Warning}{car.Oiled.TriColorPiePercent(1)}</cspace>"); //if (car.EnableOiling) tags.Add(car.HasHotbox ? TextSprites.Hotbox : $"<cspace=-1em>{TextSprites.Warning}{car.Oiled.TriColorPiePercent(1)}</cspace>");
if (car.EnableOiling) tags.Add(car.HasHotbox ? TextSprites.Hotbox : car.Oiled.TriColorPiePercent(1, oilSpriteName)); if (car.EnableOiling) tags.Add(car.HasHotbox ? TextSprites.Hotbox : car.Oiled.TriColorPiePercent(1, oilSpriteName));
IEnumerable<Car> consist = car.EnumerateCoupled().Where(c => c.EnableOiling); IEnumerable<Car> consist = car.EnumerateCoupled().Where(c => c.EnableOiling);
Func<bool> cabooseRequirementFulfilled = () => (!cabooseRequired || consist.ConsistNoFreight() || car.FindMyCaboose(0.0f, false)); Func<bool> cabooseRequirementFulfilled = () => (!cabooseRequired || consist.ConsistNoFreight() || (bool)car.FindMyCabooseSansLoadRequirement());
if (StateManager.Shared.Storage.OilFeature if (StateManager.Shared.Storage.OilFeature
&& car.IsLocomotive && car.IsLocomotive
&& !car.NeedsOiling && !car.NeedsOiling

View File

@@ -129,7 +129,7 @@ public static class SettingsExtensions
public static bool RequireConsistCabooseForOilerAndHotboxSpotter(this TweaksAndThingsPlugin input) => public static bool RequireConsistCabooseForOilerAndHotboxSpotter(this TweaksAndThingsPlugin input) =>
input?.settings?.RequireConsistCabooseForOilerAndHotboxSpotter ?? false; input?.settings?.RequireConsistCabooseForOilerAndHotboxSpotter ?? false;
public static bool CabooseNonMotiveAllowedSetting(this TweaksAndThingsPlugin input, Car car) => public static bool CabooseNonMotiveAllowedSetting(this TweaksAndThingsPlugin input, Car car) =>
input.EndGearHelpersRequirePayment() && !car.MotivePower() && (bool)car.FindMyCaboose(0.0f, false); input.EndGearHelpersRequirePayment() && !car.MotivePower() && (bool)car.FindMyCabooseSansLoadRequirement();
public static bool CabooseRequiredForLocoOilIndicator(this TweaksAndThingsPlugin input) => public static bool CabooseRequiredForLocoOilIndicator(this TweaksAndThingsPlugin input) =>
input?.settings?.CabooseRequiredForLocoTagOilIndication ?? false; input?.settings?.CabooseRequiredForLocoTagOilIndication ?? false;
public static bool ServiceFundPenalties(this TweaksAndThingsPlugin input) => public static bool ServiceFundPenalties(this TweaksAndThingsPlugin input) =>