mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-20 09:15:56 +02:00
fix: automatic coupler crashes, horns, compressor start delay, radio and cab lever sounds
- automatic couplers don't catch above the safe collision speed (#86): with crash damage on they couple at a closing speed of 15 km/h at most, a faster hit locks the coupling until the vehicles part and the collision runs its course. On the way: CollisionVelocity() read a head-on 10 + 10 km/h as 14.1 km/h (quaternions turn by half the angle), it's now taken from the touching ends; CollisionDetect() took the other vehicle's speed the wrong way round for vehicles facing each other. Head-on hits now derail sooner, at the intended limit, - a single horn lever can't sound both tones at once (eu07/maszyna#392), - a skid ends once the vehicle stops on locked wheels (eu07/maszyna#479), - electronic destination signs are blanked at the end of the timetable (eu07/maszyna#446), - horns need the air or the voltage to sound (eu07/maszyna#290, #76): HornType=[Pneumatic]|Electric and Horn3Type in Cntrl.; a pneumatic horn needs 0.2 MPa in the main reservoir (or the main pipe without one), an electric one the low voltage; the lever stays where it was put, - compressor start delay (#67): CompressorStartDelay [s] in Brake., counted from the compressor getting its power, after the engine starts say; none by default, - the channel and volume buttons of a radio without power do nothing (eu07/maszyna#429); the power check of the radio is TMoverParameters::RadioPowered(), - a lever moved smoothly sounds the positions it passes (#83). Sonar findings in the functions changed: nesting, nested conditionals, commented-out code, std::format, references to const. Unit tests: test::pair for two vehicles running into each other, test_couplers, test_horn, test_wheelslip, test_compressor, test_radio, test_gauge_positions.
This commit is contained in:
@@ -14,6 +14,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "vehicle/Train.h"
|
||||
#include "vehicle/horn.h"
|
||||
|
||||
#include "utilities/Globals.h"
|
||||
#include "simulation/simulation.h"
|
||||
@@ -7841,16 +7842,10 @@ void TTrain::OnCommand_hornlowactivate(TTrain *Train, command_data const &Comman
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
// only need to react to press, sound will continue until stopped
|
||||
if (false == TestFlag(Train->mvOccupied->WarningSignal, 1))
|
||||
if (false == TestFlag(Train->mvOccupied->WarningSignal, horn::low))
|
||||
{
|
||||
// turn on
|
||||
Train->mvOccupied->WarningSignal |= 1;
|
||||
/*
|
||||
if( true == TestFlag( Train->mvOccupied->WarningSignal, 2 ) ) {
|
||||
// low and high horn are treated as mutually exclusive
|
||||
Train->mvControlled->WarningSignal &= ~2;
|
||||
}
|
||||
*/
|
||||
Train->mvOccupied->WarningSignal = horn::pressed(Train->mvOccupied->WarningSignal, horn::low, Train->has_single_horn_lever());
|
||||
// visual feedback
|
||||
Train->ggHornButton.UpdateValue(-1.0);
|
||||
Train->ggHornLowButton.UpdateValue(1.0);
|
||||
@@ -7859,13 +7854,13 @@ void TTrain::OnCommand_hornlowactivate(TTrain *Train, command_data const &Comman
|
||||
else if (Command.action == GLFW_RELEASE)
|
||||
{
|
||||
// turn off
|
||||
/*
|
||||
// NOTE: we turn off both low and high horn, due to unreliability of release event when shift key is involved
|
||||
Train->mvOccupied->WarningSignal &= ~( 1 | 2 );
|
||||
*/
|
||||
Train->mvOccupied->WarningSignal &= ~1;
|
||||
Train->mvOccupied->WarningSignal = horn::released(Train->mvOccupied->WarningSignal, horn::low);
|
||||
// visual feedback
|
||||
Train->ggHornButton.UpdateValue(0.0);
|
||||
if (false == (Train->has_single_horn_lever() && TestFlag(Train->mvOccupied->WarningSignal, horn::high)))
|
||||
{
|
||||
// leave the single lever alone if it was moved to the other tone in the meantime
|
||||
Train->ggHornButton.UpdateValue(0.0);
|
||||
}
|
||||
Train->ggHornLowButton.UpdateValue(0.0);
|
||||
}
|
||||
}
|
||||
@@ -7885,16 +7880,10 @@ void TTrain::OnCommand_hornhighactivate(TTrain *Train, command_data const &Comma
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
// only need to react to press, sound will continue until stopped
|
||||
if (false == TestFlag(Train->mvOccupied->WarningSignal, 2))
|
||||
if (false == TestFlag(Train->mvOccupied->WarningSignal, horn::high))
|
||||
{
|
||||
// turn on
|
||||
Train->mvOccupied->WarningSignal |= 2;
|
||||
/*
|
||||
if( true == TestFlag( Train->mvOccupied->WarningSignal, 1 ) ) {
|
||||
// low and high horn are treated as mutually exclusive
|
||||
Train->mvControlled->WarningSignal &= ~1;
|
||||
}
|
||||
*/
|
||||
Train->mvOccupied->WarningSignal = horn::pressed(Train->mvOccupied->WarningSignal, horn::high, Train->has_single_horn_lever());
|
||||
// visual feedback
|
||||
Train->ggHornButton.UpdateValue(1.0);
|
||||
Train->ggHornHighButton.UpdateValue(1.0);
|
||||
@@ -7903,13 +7892,13 @@ void TTrain::OnCommand_hornhighactivate(TTrain *Train, command_data const &Comma
|
||||
else if (Command.action == GLFW_RELEASE)
|
||||
{
|
||||
// turn off
|
||||
/*
|
||||
// NOTE: we turn off both low and high horn, due to unreliability of release event when shift key is involved
|
||||
Train->mvOccupied->WarningSignal &= ~( 1 | 2 );
|
||||
*/
|
||||
Train->mvOccupied->WarningSignal &= ~2;
|
||||
Train->mvOccupied->WarningSignal = horn::released(Train->mvOccupied->WarningSignal, horn::high);
|
||||
// visual feedback
|
||||
Train->ggHornButton.UpdateValue(0.0);
|
||||
if (false == (Train->has_single_horn_lever() && TestFlag(Train->mvOccupied->WarningSignal, horn::low)))
|
||||
{
|
||||
// leave the single lever alone if it was moved to the other tone in the meantime
|
||||
Train->ggHornButton.UpdateValue(0.0);
|
||||
}
|
||||
Train->ggHornHighButton.UpdateValue(0.0);
|
||||
}
|
||||
}
|
||||
@@ -7953,12 +7942,7 @@ void TTrain::OnCommand_radiotoggle(TTrain *Train, command_data const &Command)
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: we ignore the lack of 3d model to allow system reset after receiving radio-stop signal
|
||||
/*
|
||||
if( false == Train->m_controlmapper.contains( "radio_sw:" ) ) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// NOTE: works without the switch in the 3d model too, to allow system reset after receiving radio-stop signal
|
||||
// only reacting to press, so the sound can loop uninterrupted
|
||||
if (false == Train->mvOccupied->Radio)
|
||||
{
|
||||
@@ -8003,9 +7987,13 @@ void TTrain::OnCommand_radiochannelincrease(TTrain *Train, command_data const &C
|
||||
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
command_data newCommand = Command;
|
||||
newCommand.param1 = Train->RadioChannel() + 1;
|
||||
OnCommand_radiochannelset(Train, newCommand);
|
||||
// the channel buttons of a radio switched off or without power do nothing
|
||||
if (Train->mvOccupied->RadioPowered())
|
||||
{
|
||||
command_data newCommand = Command;
|
||||
newCommand.param1 = Train->RadioChannel() + 1;
|
||||
OnCommand_radiochannelset(Train, newCommand);
|
||||
}
|
||||
|
||||
Train->ggRadioChannelNext.UpdateValue(1.0);
|
||||
}
|
||||
@@ -8021,9 +8009,12 @@ void TTrain::OnCommand_radiochanneldecrease(TTrain *Train, command_data const &C
|
||||
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
command_data newCommand = Command;
|
||||
newCommand.param1 = Train->RadioChannel() - 1;
|
||||
OnCommand_radiochannelset(Train, newCommand);
|
||||
if (Train->mvOccupied->RadioPowered())
|
||||
{
|
||||
command_data newCommand = Command;
|
||||
newCommand.param1 = Train->RadioChannel() - 1;
|
||||
OnCommand_radiochannelset(Train, newCommand);
|
||||
}
|
||||
|
||||
Train->ggRadioChannelPrevious.UpdateValue(1.0);
|
||||
}
|
||||
@@ -8049,7 +8040,7 @@ void TTrain::OnCommand_radiostopsend(TTrain *Train, command_data const &Command)
|
||||
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
if (true == Train->mvOccupied->Radio && (Train->mvOccupied->Power24vIsAvailable || Train->mvOccupied->Power110vIsAvailable))
|
||||
if (Train->mvOccupied->RadioPowered())
|
||||
{
|
||||
simulation::Region->RadioStop(Train->Dynamic()->GetPosition());
|
||||
}
|
||||
@@ -8067,7 +8058,7 @@ void TTrain::OnCommand_radiostopenable(TTrain *Train, command_data const &Comman
|
||||
{
|
||||
if (Command.action == GLFW_PRESS && Train->ggRadioStop.GetValue() == 0)
|
||||
{
|
||||
if (true == Train->mvOccupied->Radio && (Train->mvOccupied->Power24vIsAvailable || Train->mvOccupied->Power110vIsAvailable))
|
||||
if (Train->mvOccupied->RadioPowered())
|
||||
{
|
||||
simulation::Region->RadioStop(Train->Dynamic()->GetPosition());
|
||||
}
|
||||
@@ -8090,7 +8081,7 @@ void TTrain::OnCommand_radiostoptest(TTrain *Train, command_data const &Command)
|
||||
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
if (Train->RadioChannel() == 10 && true == Train->mvOccupied->Radio && (Train->mvOccupied->Power24vIsAvailable || Train->mvOccupied->Power110vIsAvailable))
|
||||
if (Train->RadioChannel() == 10 && Train->mvOccupied->RadioPowered())
|
||||
{
|
||||
Train->Dynamic()->RadioStop();
|
||||
}
|
||||
@@ -8108,7 +8099,7 @@ void TTrain::OnCommand_radiocall1send(TTrain *Train, command_data const &Command
|
||||
{
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
if (Train->RadioChannel() != 10 && true == Train->mvOccupied->Radio && (Train->mvOccupied->Power24vIsAvailable || Train->mvOccupied->Power110vIsAvailable))
|
||||
if (Train->RadioChannel() != 10 && Train->mvOccupied->RadioPowered())
|
||||
{
|
||||
simulation::Events.queue_receivers(radio_message::call1, Train->Dynamic()->GetPosition());
|
||||
}
|
||||
@@ -8127,7 +8118,7 @@ void TTrain::OnCommand_radiocall3send(TTrain *Train, command_data const &Command
|
||||
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
if (Train->RadioChannel() != 10 && true == Train->mvOccupied->Radio && (Train->mvOccupied->Power24vIsAvailable || Train->mvOccupied->Power110vIsAvailable))
|
||||
if (Train->RadioChannel() != 10 && Train->mvOccupied->RadioPowered())
|
||||
{
|
||||
simulation::Events.queue_receivers(radio_message::call3, Train->Dynamic()->GetPosition());
|
||||
}
|
||||
@@ -8146,9 +8137,13 @@ void TTrain::OnCommand_radiovolumeincrease(TTrain *Train, command_data const &Co
|
||||
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
command_data newCommand = Command;
|
||||
newCommand.param1 = Train->m_radiovolume + 0.125;
|
||||
OnCommand_radiovolumeset(Train, newCommand);
|
||||
// so do the volume buttons
|
||||
if (Train->mvOccupied->RadioPowered())
|
||||
{
|
||||
command_data newCommand = Command;
|
||||
newCommand.param1 = Train->m_radiovolume + 0.125;
|
||||
OnCommand_radiovolumeset(Train, newCommand);
|
||||
}
|
||||
Train->ggRadioVolumeNext.UpdateValue(1.0);
|
||||
}
|
||||
else if (Command.action == GLFW_RELEASE)
|
||||
@@ -8163,9 +8158,12 @@ void TTrain::OnCommand_radiovolumedecrease(TTrain *Train, command_data const &Co
|
||||
|
||||
if (Command.action == GLFW_PRESS)
|
||||
{
|
||||
command_data newCommand = Command;
|
||||
newCommand.param1 = Train->m_radiovolume - 0.125;
|
||||
OnCommand_radiovolumeset(Train, newCommand);
|
||||
if (Train->mvOccupied->RadioPowered())
|
||||
{
|
||||
command_data newCommand = Command;
|
||||
newCommand.param1 = Train->m_radiovolume - 0.125;
|
||||
OnCommand_radiovolumeset(Train, newCommand);
|
||||
}
|
||||
Train->ggRadioVolumePrevious.UpdateValue(1.0);
|
||||
}
|
||||
else if (Command.action == GLFW_RELEASE)
|
||||
@@ -10106,7 +10104,7 @@ void TTrain::update_sounds_radio()
|
||||
std::erase_if(m_radiomessages, [](auto const &source) { return false == source.second->is_playing(); });
|
||||
}
|
||||
// adjust audibility of remaining messages based on current radio conditions
|
||||
auto const radioenabled{true == mvOccupied->Radio && (mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable)};
|
||||
auto const radioenabled{mvOccupied->RadioPowered()};
|
||||
for (auto const &[messagechannel, messagesound] : m_radiomessages)
|
||||
{
|
||||
auto const volume{true == radioenabled && Dynamic()->Mechanik != nullptr && messagechannel == RadioChannel() ? m_radiovolume : 0.0};
|
||||
@@ -10893,7 +10891,7 @@ void TTrain::radio_message(sound_source *Message, int const Channel)
|
||||
m_radiomessages.emplace_back(Channel, std::make_shared<sound_source>(m_radiosound));
|
||||
// assign sound to the template and play it
|
||||
auto &message = *m_radiomessages.back().second.get();
|
||||
auto const radioenabled{true == mvOccupied->Radio && (mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable)};
|
||||
auto const radioenabled{mvOccupied->RadioPowered()};
|
||||
auto const volume{true == radioenabled && Dynamic()->Mechanik != nullptr && Channel == RadioChannel() ? 1.0 : 0.0};
|
||||
message.copy_sounds(*Message).gain(static_cast<float>(volume)).play();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user