Two complaints, one cause underneath them.
The brake and squeal sounds came out in shreds as a train got going. Both are
shaped from UnitBrakeForce and Vel, and both of those are results of a physics
step. An update arrives ten times a second; in the twenty-odd frames between
them the local physics carries on computing its own speed and its own brake
force for a train it has no business simulating, they fall away, and the next
update snaps them back. rsBrake pitches on Vel and rsPisk gains on the brake
force ratio, so what the ear got was that sawtooth.
So the physics outputs of somebody else's train are now put back after every
local step, not only on the frame an update lands: speed, brake force, wheel
and engine revolutions, engine power, wheelslip, sand, and the running flags of
the converter and the compressors, which the local physics kept switching off
because the conditions it evaluates are not the ones the owner is evaluating.
The relays are the same problem wearing a different hat. MainCtrlActualPos - the
notch the resistors are actually on, as opposed to the one the handle is at -
was being stepped by the local automatic notching, off its own guesses, so the
clicks either fired at the wrong moment or never fired at all. It travels now,
together with ScndCtrlActualPos and StLinFlag, which stops the local notching
inventing anything, and every relay heard here is one that operated over there.
The brake unit keeps a sound bitfield of its own, and that is where the
accelerator and the cylinder venting live. Reading it clears it, so watching it
had to be done without consuming it: TBrake grows PeekSoundFlag(), and only the
flags that have just come up count as an event - the vehicle only clears them
when it has an accelerator sound to play, so a bit that stays lit is one event,
not one per frame. RaiseSoundFlag() hands them to the far end.
Snapshot version 5.
When the Autorewident function is enabled, the EP fuse switch will no longer automatically engage or disengage if the player is controlling the train. This would happen for example when approaching a station.
TNESt3::GetPF() is a *major* hotspot in simulation state update. The leading cause is the use of typeid (RTTI) which is implemented in the C++ runtime essentially as a string compare. This change eliminates the use of typeid and instead caches statically typed pointers for the few TPrzekladnik subclass objects that need their parameters adjusted in TNESt3::GetPF(). As a bonus some virtual methods on TPrzekladnik can now be removed. Overall this change reduces the TNESt3::GetPF() contribution from about 25% to 16%.
The dumb3d->glm / utilities-simplification refactor replaced the old custom
clamp() (which tolerated Lo>Hi, returning the upper bound) with std::clamp,
where inverted bounds are undefined behaviour. Only a few sites were patched
afterwards, by hand, with std::minmax plumbing (incl. a stray `static` inside
a per-axle loop). Others silently produced wrong results in the AI braking /
acceleration path.
Add a safe_clamp() helper (normalizes inverted bounds) and use it ONLY where
Lo<=Hi cannot be proven at compile time (config min/max pairs, sign-dependent
expressions, container underflow). Sites with constant bounds or [0, x>=0]
keep std::clamp. Remove the manual std::minmax workarounds and rewrite the
damaged-track jolt code value-first.
- The `TMoverParameters::derail()` function has been renamed to `::Derail()`, with a capital D.
- All derail events now use that function.
- Simplified and unified the logic behind different derail types.
- The `dtrack_freerail` track type is now slightly increasing the chance of derailing on a tight curve, as it was the intention.
- A new `DerailReason` enum has been created which holds all derail types.
- The `DerailReason` field in the `TMoverParameters` class has been removed.
- This was a transient field which is not necessary anymore.
- The logging functionality as such has been moved from `DynObj.cpp` to `Mover.cpp`.
Add engine temperature monitoring to diesel locomotive heat management system:
- Add engine field to heat_data struct (fluid_circuit_t type)
- Add EngineMaxTemperature config extraction in .fiz files
- Add engine overheat detection logic (is_hot check)
- Include engine.is_hot in PT status check
Implements issue #77: Oil, water and engine overheat lamps for diesel locomotives
- Add engine_max_temp and engine_is_hot fields to heat_data structure
- Add EngineMaxTemperature field extraction from .fiz files
- Add engine overheat check comparing Ts with engine_max_temp
- Add four new overheat lamp indicators:
- i-oil_overheat
- i-water_overheat
- i-wateraux_overheat
- i-engine_overheat
- Add lamp update logic to turn on/off based on is_hot flags
- Add lamp initialization in clear_cab_controls()
This implements issue #77 - overheat lamps for diesel engines.
The lamps will turn on when:
- Oil temperature exceeds OilMaxTemperature
- Water temperature exceeds WaterMaxTemperature
- Auxiliary water temperature exceeds WaterAuxMaxTemperature
- Engine temperature exceeds EngineMaxTemperature
Each check includes 8-degree hysteresis to prevent rapid on/off cycling.
Added a new optional section to .fiz files: `ffBrakeList`. It is used instead of `ffList` whenever the vehicle has its ED braking engaged.
Example (dynamic/pkp/elf_v1/inverter_kp.fiz):
```
ffList: Size=3
0 2.0
33.7 2.08
34.0 2.12
130.4 8.10
endff
ffBrakeList: Size=4
0 2.0
33.7 2.08
34.8 2.08
34.8 2.17
130.4 8.10
endff
```
```/home/debian/autobuilder/output/build/maszyna/application.h:41:10: error: extra qualification ‘eu07_application::’ on member ‘DiscordRPCService’ [-fpermissive]
41 | void eu07_application::DiscordRPCService(); // discord rich presence service function (runs as separate thread)
| ^~~~~~~~~~~~~~~~```
Czy C++20 jest nam potrzebne?
```/home/debian/autobuilder/output/build/maszyna/McZapkie/Mover.cpp:11346:34: error: ‘std::string’ {aka ‘class std::__cxx11::basic_string<char>’} has no member named ‘_Starts_with’
11346 | if (PantType._Starts_with("DSA")) // zakladam ze wszystkie pantografy DSA sa takie same
| ^~~~~~~~~~~~```
Kompletny absurd z 7cac46d:
```/home/debian/autobuilder/output/build/maszyna/particles.cpp:477:29: error: cannot bind non-const lvalue reference of type ‘cParser&’ to an rvalue of type ‘cParser’
477 | if( source.deserialize( cParser( templatepath + templatename + ".txt", cParser::buffer_FILE ) ) ) {
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~```