Skip to content

Commit b3e29a1

Browse files
authored
Merge pull request #10 from Deadevilgrounds/master
A few fixes for brakes and precoupled cargo
2 parents ba5bf49 + a53838d commit b3e29a1

File tree

2 files changed

+174
-30
lines changed

2 files changed

+174
-30
lines changed

DVRouteManager/LocoAI.cs

Lines changed: 59 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,29 @@ public bool StartAI(RouteTracker routeTracker)
226226
return true;
227227
}
228228

229+
private IEnumerator ReleaseAllBrakes()
230+
{
231+
//// ── Release handbrakes on wagons ─────────────────────────────
232+
//foreach (TrainCar car in loco.trainset.cars)
233+
//{
234+
// if (!car.IsLoco && car.brakeSystem.hasHandbrake)
235+
// {
236+
// car.brakeSystem.SetHandbrakePosition(0f);
237+
// Terminal.Log($"Released handbrake on {car.logicCar.ID}");
238+
// }
239+
//}
240+
241+
// ── Release loco brakes (train + independent) ────────────────
242+
// Use a loop to step them down smoothly
243+
for (int i = 0; i < 10; i++)
244+
{
245+
remoteControl.UpdateIndependentBrake(-1.0f);
246+
remoteControl.UpdateBrake(-1.0f);
247+
248+
yield return new WaitForSeconds(0.3f);
249+
}
250+
}
251+
229252
private IEnumerator AICoroutine()
230253
{
231254
const float TIME_WAIT = 0.3f;
@@ -250,6 +273,8 @@ private IEnumerator AICoroutine()
250273

251274
RouteTracker.TrackingState lastState = RouteTracker.TrackState;
252275

276+
yield return ReleaseAllBrakes();
277+
253278
while (running)
254279
{
255280
float speed = Mathf.Abs(remoteControl.GetForwardSpeed() * 3.6f);
@@ -390,6 +415,8 @@ IEnumerator Reverse()
390415
yield return null;
391416
remoteControl.UpdateReverser(direction ? ToggleDirection.DOWN : ToggleDirection.UP);
392417
yield return null;
418+
419+
yield return ReleaseAllBrakes();
393420
}
394421

395422
IEnumerator BrakePulse(int level, float waitTime)
@@ -446,35 +473,46 @@ private IEnumerator FreightHaulCoroutine(RouteTask task, TrainCar loco)
446473
Track carTrack = freightTrainset.firstCar.Bogies[0].track.LogicTrack();
447474
Track locoTrack = loco.trainset.firstCar.Bogies[0].track.LogicTrack();
448475

449-
var toCarsTask = Route.FindRoute(locoTrack, carTrack, ReversingStrategy.ChooseBest, loco.trainset);
450-
while (!toCarsTask.IsCompleted) yield return null;
476+
bool alreadyCoupled = loco.trainset == freightTrainset;
451477

452-
if (!_freightHaulActive) yield break;
453-
454-
if (toCarsTask.IsFaulted || toCarsTask.Result == null)
478+
if (loco.trainset == freightTrainset)
455479
{
456-
Terminal.Log("Freight haul: cannot find route to cars – " + (toCarsTask.Exception?.InnerException?.Message ?? "null"));
457-
_freightHaulActive = false;
458-
yield break;
480+
Terminal.Log("Freight haul: already coupled to target trainset, skipping routing to cars");
459481
}
482+
else
483+
{
460484

461-
var chain1 = RouteTaskChain.FromDestination(carTrack, loco.trainset);
462-
var tracker1 = new RouteTracker(chain1, true);
463-
tracker1.SetRoute(toCarsTask.Result, loco.trainset);
464-
Module.ActiveRoute.Route = toCarsTask.Result;
465-
Module.ActiveRoute.RouteTracker = tracker1;
485+
var toCarsTask = Route.FindRoute(locoTrack, carTrack, ReversingStrategy.ChooseBest, loco.trainset);
486+
while (!toCarsTask.IsCompleted) yield return null;
466487

467-
StartAI(tracker1);
468-
while (running && _freightHaulActive) yield return null;
488+
if (!_freightHaulActive) yield break;
469489

470-
if (!_freightHaulActive) { Stop(); yield break; }
490+
if (toCarsTask.IsFaulted || toCarsTask.Result == null)
491+
{
492+
Terminal.Log("Freight haul: cannot find route to cars – " + (toCarsTask.Exception?.InnerException?.Message ?? "null"));
493+
_freightHaulActive = false;
494+
yield break;
495+
}
471496

472-
// ── Phase 2: couple and release handbrakes ───────────────────────
473-
Terminal.Log("Freight haul: phase 2 – coupling");
474-
yield return TryCoupleAndReleaseHandbrakes(loco);
475-
yield return new WaitForSeconds(1.5f);
497+
var chain1 = RouteTaskChain.FromDestination(carTrack, loco.trainset);
498+
var tracker1 = new RouteTracker(chain1, true);
499+
tracker1.SetRoute(toCarsTask.Result, loco.trainset);
500+
Module.ActiveRoute.Route = toCarsTask.Result;
501+
Module.ActiveRoute.RouteTracker = tracker1;
476502

477-
if (!_freightHaulActive) yield break;
503+
StartAI(tracker1);
504+
while (running && _freightHaulActive) yield return null;
505+
506+
if (!_freightHaulActive) { Stop(); yield break; }
507+
508+
// ── Phase 2: couple and release handbrakes ───────────────────────
509+
Terminal.Log("Freight haul: phase 2 – coupling");
510+
yield return TryCoupleAndReleaseHandbrakes(loco);
511+
yield return new WaitForSeconds(1.5f);
512+
513+
if (!_freightHaulActive) yield break;
514+
515+
}
478516

479517
// ── Phase 3: drive to destination ────────────────────────────────
480518
Terminal.Log($"Freight haul: phase 3 – routing to {task.DestinationTrack.ID.FullID}");

DVRouteManager/LocoCruiseControl.cs

Lines changed: 115 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ public class LocoCruiseControl : IDisposable
6767
private MethodInfo _tryGetPortMI;
6868
private PropertyInfo _portValueProp;
6969

70+
// DM3 cache for simFlow.TryGetPort
71+
private SimController _dm3SimCtrl;
72+
private MethodInfo _dm3TryGetPortMI;
73+
private PropertyInfo _dm3PortValueProp;
74+
7075
// ────────────────────────────────────────────────────────────────────
7176

7277
public LocoCruiseControl(ILocomotiveRemoteControl remoteControl, TrainCar car = null)
@@ -176,24 +181,126 @@ protected float MaintainSpeed(float targetAcceleration, float dt, float speed, f
176181
}
177182

178183
if (error < -3.0f || TargetSpeed < Mathf.Epsilon)
179-
remoteControl.UpdateIndependentBrake(0.3f * error * -1.0f * dt);
180-
else if (remoteControl.GetTargetIndependentBrake() > Mathf.Epsilon)
181-
remoteControl.UpdateIndependentBrake(-30.0f * dt);
184+
remoteControl.UpdateBrake(0.3f * error * -1.0f * dt);
185+
else if (remoteControl.GetTargetBrake() > Mathf.Epsilon)
186+
remoteControl.UpdateBrake(-30.0f * dt);
182187

183188
remoteControl.UpdateThrottle(ThrottleCurveFactor(remoteControl.GetTargetThrottle(), controlValue > 0.0f) * controlValue);
184189

185190
return targetAcceleration;
186191
}
187192

193+
private float GetDM3Rpm()
194+
{
195+
try
196+
{
197+
if (_dm3SimCtrl == null)
198+
_dm3SimCtrl = trainCar?.SimController;
199+
200+
if (_dm3SimCtrl?.simFlow == null)
201+
return -1f;
202+
203+
if (_dm3TryGetPortMI == null)
204+
_dm3TryGetPortMI = _dm3SimCtrl.simFlow.GetType()
205+
.GetMethod("TryGetPort", BindingFlags.Instance | BindingFlags.Public);
206+
207+
if (_dm3TryGetPortMI == null)
208+
return -1f;
209+
210+
var args = new object[] { "de.RPM", null, true };
211+
if (!(bool)_dm3TryGetPortMI.Invoke(_dm3SimCtrl.simFlow, args) || args[1] == null)
212+
return -1f;
213+
214+
if (_dm3PortValueProp == null)
215+
_dm3PortValueProp = args[1].GetType().GetProperty("Value");
216+
217+
return _dm3PortValueProp != null
218+
? (float)_dm3PortValueProp.GetValue(args[1])
219+
: -1f;
220+
}
221+
catch
222+
{
223+
return -1f;
224+
}
225+
}
226+
227+
private struct DM3GearPosition
228+
{
229+
public int GearA;
230+
public int GearB;
231+
232+
public DM3GearPosition(int gearA, int gearB)
233+
{
234+
GearA = gearA;
235+
GearB = gearB;
236+
}
237+
238+
public override string ToString()
239+
{
240+
return $"{GearA},{GearB}";
241+
}
242+
}
243+
244+
private int _currentDM3GearIndex = 0;
245+
246+
private static readonly DM3GearPosition[] DM3_GEAR_SEQUENCE =
247+
{
248+
new DM3GearPosition(1, 1),
249+
new DM3GearPosition(1, 2),
250+
new DM3GearPosition(2, 1),
251+
new DM3GearPosition(2, 2),
252+
new DM3GearPosition(3, 1),
253+
// new DM3GearPosition(1, 3), // intentionally skipped
254+
new DM3GearPosition(3, 2),
255+
new DM3GearPosition(2, 3),
256+
new DM3GearPosition(3, 3),
257+
};
258+
259+
private bool ShiftDM3Gear(int direction)
260+
{
261+
var controls = GetInteriorControls();
262+
if (controls == null)
263+
return false;
264+
265+
int targetIndex = _currentDM3GearIndex + direction;
266+
267+
DM3GearPosition current = DM3_GEAR_SEQUENCE[_currentDM3GearIndex];
268+
DM3GearPosition target = DM3_GEAR_SEQUENCE[targetIndex];
269+
270+
if (target.GearA > current.GearA)
271+
controls.MoveScrollable(InteriorControlsManager.ControlType.GearboxA, 1);
272+
else if (target.GearA < current.GearA)
273+
controls.MoveScrollable(InteriorControlsManager.ControlType.GearboxA, -1);
274+
275+
if (target.GearB > current.GearB)
276+
controls.MoveScrollable(InteriorControlsManager.ControlType.GearboxB, 1);
277+
else if (target.GearB < current.GearB)
278+
controls.MoveScrollable(InteriorControlsManager.ControlType.GearboxB, -1);
279+
280+
_currentDM3GearIndex = targetIndex;
281+
return true;
282+
}
283+
188284
// ── DM3 gear management ──────────────────────────────────────────────
189285
// Returns true while a shift is in progress (PID caller should skip output).
190286
private bool HandleDM3GearShift(float dt)
191287
{
192-
float rpm = _indicators?.engineRpm?.Value ?? 0f;
288+
float rpm = GetDM3Rpm();
289+
if (rpm < 0f)
290+
return false;
291+
193292
float now = Time.time;
194293

195294
if (_awaitingShift)
196295
{
296+
int targetIndex = _currentDM3GearIndex + _pendingShiftDir;
297+
if (targetIndex < 0 || targetIndex >= DM3_GEAR_SEQUENCE.Length)
298+
{
299+
_lastGearRpm = rpm;
300+
_awaitingShift = false;
301+
return false; // Dont shift if already on min or max gear
302+
}
303+
197304
// Zero throttle and wait for RPM to settle before moving the lever
198305
remoteControl.UpdateThrottle(-100f);
199306

@@ -203,14 +310,13 @@ private bool HandleDM3GearShift(float dt)
203310
var controls = GetInteriorControls();
204311
if (controls != null)
205312
{
206-
controls.MoveScrollable(InteriorControlsManager.ControlType.GearboxA, _pendingShiftDir);
207-
controls.MoveScrollable(InteriorControlsManager.ControlType.GearboxB, _pendingShiftDir);
313+
ShiftDM3Gear(_pendingShiftDir);
208314
#if DEBUG
209-
Terminal.Log($"DM3: gear lever moved {(_pendingShiftDir > 0 ? "up" : "down")} (RPM {rpm:0})");
315+
Terminal.Log($"DM3: shifted to {DM3_GEAR_SEQUENCE[_currentDM3GearIndex]} (RPM {rpm:0})");
210316
#endif
317+
_awaitingShift = false;
318+
_lastShiftTime = now;
211319
}
212-
_awaitingShift = false;
213-
_lastShiftTime = now;
214320
}
215321

216322
_lastGearRpm = rpm;

0 commit comments

Comments
 (0)