16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 11:39:19 +02:00

compressor governor lock tweaks, fuel pump cab indicator, optional offset for scenario clock

This commit is contained in:
tmj-fstate
2018-03-29 23:19:14 +02:00
parent 6ffced1d90
commit 1fd89923f6
8 changed files with 307 additions and 170 deletions

View File

@@ -308,6 +308,11 @@ global_settings::ConfigParse(cParser &Parser) {
// max 8 lights per opengl specs, minus one used for sun. at least one light for controlled vehicle // max 8 lights per opengl specs, minus one used for sun. at least one light for controlled vehicle
DynamicLightCount = clamp( DynamicLightCount, 1, 7 ); DynamicLightCount = clamp( DynamicLightCount, 1, 7 );
} }
else if( token == "scenario.time.offset" ) {
// shift (in hours) applied to train timetables
Parser.getTokens( 1, false );
Parser >> ScenarioTimeOffset;
}
else if( token == "scalespeculars" ) { else if( token == "scalespeculars" ) {
// whether strength of specular highlights should be adjusted (generally needed for legacy 3d models) // whether strength of specular highlights should be adjusted (generally needed for legacy 3d models)
Parser.getTokens(); Parser.getTokens();

View File

@@ -79,6 +79,7 @@ struct global_settings {
bool FakeLight{ false }; // toggle between fixed and dynamic daylight bool FakeLight{ false }; // toggle between fixed and dynamic daylight
double fTimeSpeed{ 1.0 }; // przyspieszenie czasu, zmienna do testów double fTimeSpeed{ 1.0 }; // przyspieszenie czasu, zmienna do testów
double fLatitudeDeg{ 52.0 }; // szerokość geograficzna double fLatitudeDeg{ 52.0 }; // szerokość geograficzna
float ScenarioTimeOffset { 0.f }; // time shift (in hours) applied to train timetables
bool bInactivePause{ true }; // automatyczna pauza, gdy okno nieaktywne bool bInactivePause{ true }; // automatyczna pauza, gdy okno nieaktywne
int iSlowMotionMask{ -1 }; // maska wyłączanych właściwości int iSlowMotionMask{ -1 }; // maska wyłączanych właściwości
bool bHideConsole{ false }; // hunter-271211: ukrywanie konsoli bool bHideConsole{ false }; // hunter-271211: ukrywanie konsoli

View File

@@ -3080,89 +3080,175 @@ void TMoverParameters::UpdateBrakePressure(double dt)
// Q: 20160712 // Q: 20160712
// Obliczanie pracy sprężarki // Obliczanie pracy sprężarki
// ************************************************************************************************* // *************************************************************************************************
// TODO: clean the method up, a lot of the code is redundant
void TMoverParameters::CompressorCheck(double dt) void TMoverParameters::CompressorCheck(double dt)
{ {
if( VeselVolume == 0.0 ) { return; }
CompressedVolume = std::max( 0.0, CompressedVolume - dt * AirLeakRate * 0.1 ); // nieszczelności: 0.001=1l/s CompressedVolume = std::max( 0.0, CompressedVolume - dt * AirLeakRate * 0.1 ); // nieszczelności: 0.001=1l/s
// if (CompressorSpeed>0.0) then //ten warunek został sprawdzony przy wywołaniu funkcji if( ( true == CompressorGovernorLock )
if (VeselVolume > 0) && ( Compressor < MinCompressor ) ) {
{ // if the pressure drops below the cut-in level, we can reset compressor governor
if (MaxCompressor - MinCompressor < 0.0001) // TBD, TODO: don't operate the lock without battery power?
{ CompressorGovernorLock = false;
// if (Mains && (MainCtrlPos > 1)) }
if (CompressorAllow && CompressorAllowLocal && Mains && (MainCtrlPos > 0))
{ if (MaxCompressor - MinCompressor < 0.0001) {
if (Compressor < MaxCompressor) // TODO: investigate purpose of this branch and whether it can be removed as it duplicates later code
if ((EngineType == DieselElectric) && (CompressorPower > 0)) if( ( true == CompressorAllow )
CompressedVolume += dt * CompressorSpeed * && ( true == CompressorAllowLocal )
(2.0 * MaxCompressor - Compressor) / MaxCompressor * && ( true == Mains )
(DElist[MainCtrlPos].RPM / DElist[MainCtrlPosNo].RPM); && ( MainCtrlPos > 0 ) ) {
else if( Compressor < MaxCompressor ) {
{ if( ( EngineType == DieselElectric )
CompressedVolume += && ( CompressorPower > 0 ) ) {
dt * CompressorSpeed * (2.0 * MaxCompressor - Compressor) / MaxCompressor; CompressedVolume +=
TotalCurrent += 0.0015 CompressorSpeed
* Voltage; // tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę * ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor
} * ( DElist[ MainCtrlPos ].RPM / DElist[ MainCtrlPosNo ].RPM )
* dt;
}
else {
CompressedVolume +=
CompressorSpeed
* ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor
* dt;
TotalCurrent += 0.0015 * Voltage; // tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
}
}
else {
CompressedVolume = CompressedVolume * 0.8;
SetFlag(SoundFlag, sound::relay | sound::loud);
}
}
}
else {
if( ( ( CompressorPower == 0 )
|| ( CompressorPower == 3 ) )
&& ( ( EngineType == DieselEngine )
|| ( EngineType == DieselElectric ) ) ) {
// experimental: make sure compressor coupled with diesel engine is always ready for work
CompressorAllow = true;
}
if (CompressorFlag) // jeśli sprężarka załączona
{ // sprawdzić możliwe warunki wyłączenia sprężarki
if (CompressorPower == 5) // jeśli zasilanie z sąsiedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if (Couplers[1].Connected != NULL)
CompressorFlag =
( Couplers[ 1 ].Connected->CompressorAllow
&& Couplers[ 1 ].Connected->CompressorAllowLocal
&& Couplers[ 1 ].Connected->Mains
&& Couplers[ 1 ].Connected->ConverterFlag );
else else
{ CompressorFlag = false; // bez tamtego członu nie zadziała
CompressedVolume = CompressedVolume * 0.8; }
SetFlag(SoundFlag, sound::relay | sound::loud); else if (CompressorPower == 4) // jeśli zasilanie z poprzedniego członu
// SetFlag(SoundFlag, sound::loud); { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if (Couplers[0].Connected != NULL)
CompressorFlag =
( Couplers[ 0 ].Connected->CompressorAllow
&& Couplers[ 0 ].Connected->CompressorAllowLocal
&& Couplers[ 0 ].Connected->Mains
&& Couplers[ 0 ].Connected->ConverterFlag );
else
CompressorFlag = false; // bez tamtego członu nie zadziała
}
else
CompressorFlag =
( ( CompressorAllow )
&& ( CompressorAllowLocal )
&& ( Mains )
&& ( ( ConverterFlag )
|| ( CompressorPower == 0 )
|| ( CompressorPower == 3 ) ) );
if( Compressor > MaxCompressor ) {
// wyłącznik ciśnieniowy jest niezależny od sposobu zasilania
// TBD, TODO: don't operate the lock without battery power?
if( ( CompressorPower == 0 )
|| ( CompressorPower == 3 ) ) {
// if the compressor is powered directly by the engine the lock can't turn it off and instead just changes the output
if( false == CompressorGovernorLock ) {
// emit relay sound when the lock engages (the state change itself is below) and presumably changes where the air goes
SetFlag( SoundFlag, sound::relay | sound::loud );
}
}
else {
// if the compressor isn't coupled with the engine the lock can control its state freely
CompressorFlag = false;
}
CompressorGovernorLock = true; // prevent manual activation until the pressure goes below cut-in level
}
if( ( TrainType == dt_ET41 )
|| ( TrainType == dt_ET42 ) ) {
// for these multi-unit engines compressors turn off whenever any of them was affected by the governor
// NOTE: this is crude implementation, TODO: re-implement when a more elegant/flexible system is in place
if( ( Couplers[ 1 ].Connected != nullptr )
&& ( true == TestFlag( Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) {
// the first unit isn't allowed to start its compressor until second unit can start its own as well
CompressorFlag &= ( Couplers[ 1 ].Connected->CompressorGovernorLock == false );
}
if( ( Couplers[ 0 ].Connected != nullptr )
&& ( true == TestFlag( Couplers[ 0 ].CouplingFlag, coupling::permanent ) ) ) {
// the second unit isn't allowed to start its compressor until first unit can start its own as well
CompressorFlag &= ( Couplers[ 0 ].Connected->CompressorGovernorLock == false );
} }
} }
} }
else else {
{ // jeśli nie załączona
if( ( CompressorPower == 0 ) if( ( LastSwitchingTime > CtrlDelay )
&& ( ( EngineType == DieselEngine ) && ( ( Compressor < MinCompressor )
|| ( EngineType == DieselElectric ) ) ) { || ( ( Compressor < MaxCompressor )
// experimental: make sure compressor coupled with diesel engine is always ready for work && ( false == CompressorGovernorLock ) ) ) ) {
CompressorAllow = true; // załączenie przy małym ciśnieniu
} // jeśli nie załączona, a ciśnienie za małe
if (CompressorFlag) // jeśli sprężarka załączona // or if the switch is on and the pressure isn't maxed
{ // sprawdzić możliwe warunki wyłączenia sprężarki if( CompressorPower == 5 ) // jeśli zasilanie z następnego członu
if (CompressorPower == 5) // jeśli zasilanie z sąsiedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if (Couplers[1].Connected != NULL) if( Couplers[ 1 ].Connected != nullptr ) {
CompressorFlag = CompressorFlag =
( Couplers[ 1 ].Connected->CompressorAllow ( Couplers[ 1 ].Connected->CompressorAllow
&& Couplers[ 1 ].Connected->CompressorAllowLocal && Couplers[ 1 ].Connected->CompressorAllowLocal
&& Couplers[ 1 ].Connected->Mains && Couplers[ 1 ].Connected->Mains
&& Couplers[ 1 ].Connected->ConverterFlag ); && Couplers[ 1 ].Connected->ConverterFlag );
else }
else {
CompressorFlag = false; // bez tamtego członu nie zadziała CompressorFlag = false; // bez tamtego członu nie zadziała
}
} }
else if (CompressorPower == 4) // jeśli zasilanie z poprzedniego członu else if( CompressorPower == 4 ) // jeśli zasilanie z poprzedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if (Couplers[0].Connected != NULL) if( Couplers[ 0 ].Connected != nullptr ) {
CompressorFlag = CompressorFlag =
( Couplers[ 0 ].Connected->CompressorAllow ( Couplers[ 0 ].Connected->CompressorAllow
&& Couplers[ 0 ].Connected->CompressorAllowLocal && Couplers[ 0 ].Connected->CompressorAllowLocal
&& Couplers[ 0 ].Connected->Mains && Couplers[ 0 ].Connected->Mains
&& Couplers[ 0 ].Connected->ConverterFlag ); && Couplers[ 0 ].Connected->ConverterFlag );
else }
else {
CompressorFlag = false; // bez tamtego członu nie zadziała CompressorFlag = false; // bez tamtego członu nie zadziała
}
} }
else else {
CompressorFlag = CompressorFlag =
( ( CompressorAllow ) ( ( CompressorAllow )
&& ( CompressorAllowLocal ) && ( CompressorAllowLocal )
&& ( Mains ) && ( Mains )
&& ( ( ConverterFlag ) && ( ( ConverterFlag )
|| ( CompressorPower == 0 ) ) ); || ( CompressorPower == 0 )
|| ( CompressorPower == 3 ) ) );
if( Compressor > MaxCompressor ) {
// wyłącznik ciśnieniowy jest niezależny od sposobu zasilania
CompressorFlag = false;
CompressorGovernorLock = true; // prevent manual activation until the pressure goes below cut-in level
} }
// NOTE: crude way to enforce simultaneous activation of compressors in multi-unit setups
// TODO: replace this with a more universal activation system down the road
if( ( TrainType == dt_ET41 ) if( ( TrainType == dt_ET41 )
|| ( TrainType == dt_ET42 ) ) { || ( TrainType == dt_ET42 ) ) {
// for these multi-unit engines compressors turn off whenever any of them was affected by the governor
// NOTE: this is crude implementation, TODO: re-implement when a more elegant/flexible system is in place if( ( Couplers[1].Connected != nullptr )
if( ( Couplers[ 1 ].Connected != nullptr )
&& ( true == TestFlag( Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) { && ( true == TestFlag( Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) {
// the first unit isn't allowed to start its compressor until second unit can start its own as well // the first unit isn't allowed to start its compressor until second unit can start its own as well
CompressorFlag &= ( Couplers[ 1 ].Connected->CompressorGovernorLock == false ); CompressorFlag &= ( Couplers[ 1 ].Connected->CompressorGovernorLock == false );
@@ -3173,110 +3259,67 @@ void TMoverParameters::CompressorCheck(double dt)
CompressorFlag &= ( Couplers[ 0 ].Connected->CompressorGovernorLock == false ); CompressorFlag &= ( Couplers[ 0 ].Connected->CompressorGovernorLock == false );
} }
} }
}
else {
// jeśli nie załączona
if( Compressor < MinCompressor ) {
// if the pressure drops below the cut-in level, we can reset compressor governor
CompressorGovernorLock = false;
}
if( ( ( Compressor < MinCompressor ) if( CompressorFlag ) {
|| ( ( Compressor < MaxCompressor ) // jeśli została załączona
&& ( false == CompressorGovernorLock ) ) ) LastSwitchingTime = 0; // to trzeba ograniczyć ponowne włączenie
&& ( LastSwitchingTime > CtrlDelay ) ) {
// załączenie przy małym ciśnieniu
// jeśli nie załączona, a ciśnienie za małe
// or if the switch is on and the pressure isn't maxed
if( CompressorPower == 5 ) // jeśli zasilanie z następnego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if( Couplers[ 1 ].Connected != nullptr ) {
CompressorFlag =
( Couplers[ 1 ].Connected->CompressorAllow
&& Couplers[ 1 ].Connected->CompressorAllowLocal
&& Couplers[ 1 ].Connected->Mains
&& Couplers[ 1 ].Connected->ConverterFlag );
}
else {
CompressorFlag = false; // bez tamtego członu nie zadziała
}
}
else if( CompressorPower == 4 ) // jeśli zasilanie z poprzedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if( Couplers[ 0 ].Connected != nullptr ) {
CompressorFlag =
( Couplers[ 0 ].Connected->CompressorAllow
&& Couplers[ 0 ].Connected->CompressorAllowLocal
&& Couplers[ 0 ].Connected->Mains
&& Couplers[ 0 ].Connected->ConverterFlag );
}
else {
CompressorFlag = false; // bez tamtego członu nie zadziała
}
}
else {
CompressorFlag =
( ( CompressorAllow )
&& ( CompressorAllowLocal )
&& ( Mains )
&& ( ( ConverterFlag )
|| ( CompressorPower == 0 ) ) );
}
// NOTE: crude way to enforce simultaneous activation of compressors in multi-unit setups
// TODO: replace this with a more universal activation system down the road
if( ( TrainType == dt_ET41 )
|| ( TrainType == dt_ET42 ) ) {
if( ( Couplers[1].Connected != nullptr )
&& ( true == TestFlag( Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) {
// the first unit isn't allowed to start its compressor until second unit can start its own as well
CompressorFlag &= ( Couplers[ 1 ].Connected->CompressorGovernorLock == false );
}
if( ( Couplers[ 0 ].Connected != nullptr )
&& ( true == TestFlag( Couplers[ 0 ].CouplingFlag, coupling::permanent ) ) ) {
// the second unit isn't allowed to start its compressor until first unit can start its own as well
CompressorFlag &= ( Couplers[ 0 ].Connected->CompressorGovernorLock == false );
}
}
if( CompressorFlag ) {
// jeśli została załączona
LastSwitchingTime = 0; // to trzeba ograniczyć ponowne włączenie
}
} }
} }
}
if( CompressorFlag ) { if( CompressorFlag ) {
if( ( EngineType == DieselElectric ) && ( CompressorPower > 0 ) ) { if( ( EngineType == DieselElectric )
&& ( ( CompressorPower == 0 )
|| ( CompressorPower == 3 ) ) ) {
if( false == CompressorGovernorLock ) {
CompressedVolume += CompressedVolume +=
dt * CompressorSpeed CompressorSpeed
* ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor * ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor
* ( DElist[ MainCtrlPos ].RPM / DElist[ MainCtrlPosNo ].RPM ); * ( DElist[ MainCtrlPos ].RPM / DElist[ MainCtrlPosNo ].RPM )
* dt;
} }
else if( ( EngineType == DieselEngine ) && ( CompressorPower == 0 ) ) { /*
else {
// the lock is active, air is being vented out
CompressedVolume -= 0.1 * dt;
}
*/
}
else if( ( EngineType == DieselEngine )
&& ( ( CompressorPower == 0 )
|| ( CompressorPower == 3 ) ) ) {
if( false == CompressorGovernorLock ) {
// experimental: compressor coupled with diesel engine, output scaled by current engine rotational speed // experimental: compressor coupled with diesel engine, output scaled by current engine rotational speed
CompressedVolume += CompressedVolume +=
dt * CompressorSpeed CompressorSpeed
* ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor * ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor
* ( std::abs( enrot ) / nmax ); * ( std::abs( enrot ) / nmax )
* dt;
}
/*
else {
// the lock is active, air is being vented out
CompressedVolume -= 0.1 * dt;
}
*/
}
else {
CompressedVolume +=
CompressorSpeed
* ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor
* dt;
if( ( CompressorPower == 5 ) && ( Couplers[ 1 ].Connected != NULL ) ) {
// tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
Couplers[ 1 ].Connected->TotalCurrent += 0.0015 * Couplers[ 1 ].Connected->Voltage;
}
else if( ( CompressorPower == 4 ) && ( Couplers[ 0 ].Connected != NULL ) ) {
// tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
Couplers[ 0 ].Connected->TotalCurrent += 0.0015 * Couplers[ 0 ].Connected->Voltage;
} }
else { else {
CompressedVolume += // tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
dt * CompressorSpeed * ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor; TotalCurrent += 0.0015 * Voltage;
if( ( CompressorPower == 5 ) && ( Couplers[ 1 ].Connected != NULL ) )
Couplers[ 1 ].Connected->TotalCurrent +=
0.0015 * Couplers[ 1 ].Connected->Voltage; // tymczasowo tylko obciążenie
// sprężarki, tak z 5A na
// sprężarkę
else if( ( CompressorPower == 4 ) && ( Couplers[ 0 ].Connected != NULL ) )
Couplers[ 0 ].Connected->TotalCurrent +=
0.0015 * Couplers[ 0 ].Connected->Voltage; // tymczasowo tylko obciążenie
// sprężarki, tak z 5A na
// sprężarkę
else
TotalCurrent += 0.0015 *
Voltage; // tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę
} }
} }
} }
@@ -7287,11 +7330,12 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) {
extract_value( CompressorSpeed, "CompressorSpeed", line, "" ); extract_value( CompressorSpeed, "CompressorSpeed", line, "" );
{ {
std::map<std::string, int> compressorpowers{ std::map<std::string, int> compressorpowers{
{ "Main", 0 },
// 1: default, powered by converter, with manual state control
{ "Converter", 2 }, { "Converter", 2 },
{ "Engine", 3 }, { "Engine", 3 }, // equivalent of 0, TODO: separate 'main' and 'engine' in the code
{ "Coupler1", 4 },//włączana w silnikowym EZT z przodu { "Coupler1", 4 },//włączana w silnikowym EZT z przodu
{ "Coupler2", 5 },//włączana w silnikowym EZT z tyłu { "Coupler2", 5 } //włączana w silnikowym EZT z tyłu
{ "Main", 0 }
}; };
auto lookup = compressorpowers.find( extract_value( "CompressorPower", line ) ); auto lookup = compressorpowers.find( extract_value( "CompressorPower", line ) );
CompressorPower = CompressorPower =

110
Train.cpp
View File

@@ -222,6 +222,9 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
{ user_command::linebreakertoggle, &TTrain::OnCommand_linebreakertoggle }, { user_command::linebreakertoggle, &TTrain::OnCommand_linebreakertoggle },
{ user_command::linebreakeropen, &TTrain::OnCommand_linebreakeropen }, { user_command::linebreakeropen, &TTrain::OnCommand_linebreakeropen },
{ user_command::linebreakerclose, &TTrain::OnCommand_linebreakerclose }, { user_command::linebreakerclose, &TTrain::OnCommand_linebreakerclose },
{ user_command::fuelpumptoggle, &TTrain::OnCommand_fuelpumptoggle },
{ user_command::fuelpumpenable, &TTrain::OnCommand_fuelpumpenable },
{ user_command::fuelpumpdisable, &TTrain::OnCommand_fuelpumpdisable },
{ user_command::convertertoggle, &TTrain::OnCommand_convertertoggle }, { user_command::convertertoggle, &TTrain::OnCommand_convertertoggle },
{ user_command::converterenable, &TTrain::OnCommand_converterenable }, { user_command::converterenable, &TTrain::OnCommand_converterenable },
{ user_command::converterdisable, &TTrain::OnCommand_converterdisable }, { user_command::converterdisable, &TTrain::OnCommand_converterdisable },
@@ -1996,6 +1999,45 @@ void TTrain::OnCommand_linebreakerclose( TTrain *Train, command_data const &Comm
} }
} }
void TTrain::OnCommand_fuelpumptoggle( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->FuelPump.is_enabled ) {
// turn on
OnCommand_fuelpumpenable( Train, Command );
}
else {
//turn off
OnCommand_fuelpumpdisable( Train, Command );
}
}
}
void TTrain::OnCommand_fuelpumpenable( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
// visual feedback
Train->ggFuelPumpButton.UpdateValue( 1.0, Train->dsbSwitch );
if( true == Train->mvControlled->FuelPump.is_enabled ) { return; } // already enabled
Train->mvControlled->FuelPumpSwitch( true );
}
}
void TTrain::OnCommand_fuelpumpdisable( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
// visual feedback
Train->ggFuelPumpButton.UpdateValue( 0.0, Train->dsbSwitch );
if( false == Train->mvControlled->FuelPump.is_enabled ) { return; } // already disabled
Train->mvControlled->FuelPumpSwitch( false );
}
}
void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
@@ -3856,12 +3898,6 @@ bool TTrain::Update( double const Deltatime )
} }
} }
if( m_linebreakerstate == 1 ) { if( m_linebreakerstate == 1 ) {
if( ( mvControlled->EngineType == DieselElectric )
&& ( false == mvControlled->ConverterFlag ) ) {
// converter acts as a make-believe fuel pump so if it's off, kill the engine
// TODO: implement actual fuel system and move this check to the mover update
mvControlled->MainSwitch( false );
}
if( false == mvControlled->Mains ) { if( false == mvControlled->Mains ) {
// crude way to catch cases where the main was knocked out and the user is trying to restart it // crude way to catch cases where the main was knocked out and the user is trying to restart it
// because the state of the line breaker isn't changed to match, we need to do it here manually // because the state of the line breaker isn't changed to match, we need to do it here manually
@@ -3909,6 +3945,9 @@ bool TTrain::Update( double const Deltatime )
// finalize state change of the line breaker // finalize state change of the line breaker
m_linebreakerstate = 1; m_linebreakerstate = 1;
} }
else {
m_linebreakerstate = 0;
}
} }
} }
@@ -3946,6 +3985,23 @@ bool TTrain::Update( double const Deltatime )
if (DynamicObject->mdKabina) if (DynamicObject->mdKabina)
{ // Ra: TODO: odczyty klawiatury/pulpitu nie powinny być uzależnione od istnienia modelu kabiny { // Ra: TODO: odczyty klawiatury/pulpitu nie powinny być uzależnione od istnienia modelu kabiny
if( ( DynamicObject->Mechanik != nullptr )
&& ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI
&& ( ( mvOccupied->TrainType == dt_ET40 )
|| ( mvOccupied->TrainType == dt_EP05 ) ) ) {
// dla ET40 i EU05 automatyczne cofanie nastawnika - i tak nie będzie to działać dobrze...
// TODO: remove direct keyboard check, use deltatime to stabilize speed
if( ( glfwGetKey( Global.window, GLFW_KEY_KP_ADD ) != GLFW_TRUE )
&& ( mvOccupied->MainCtrlPos > mvOccupied->MainCtrlActualPos ) ) {
mvOccupied->DecMainCtrl( 1 );
}
if( ( glfwGetKey( Global.window, GLFW_KEY_KP_SUBTRACT ) != GLFW_TRUE )
&& ( mvOccupied->MainCtrlPos < mvOccupied->MainCtrlActualPos ) ) {
mvOccupied->IncMainCtrl( 1 ); // Ra 15-01: a to nie miało być tylko cofanie?
}
}
tor = DynamicObject->GetTrack(); // McZapkie-180203 tor = DynamicObject->GetTrack(); // McZapkie-180203
// McZapkie: predkosc wyswietlana na tachometrze brana jest z obrotow kol // McZapkie: predkosc wyswietlana na tachometrze brana jest z obrotow kol
float maxtacho = 3; float maxtacho = 3;
@@ -4430,6 +4486,7 @@ bool TTrain::Update( double const Deltatime )
btLampkaNapNastHam.Turn(mvControlled->ActiveDir != 0); // napiecie na nastawniku hamulcowym btLampkaNapNastHam.Turn(mvControlled->ActiveDir != 0); // napiecie na nastawniku hamulcowym
btLampkaSprezarka.Turn(mvControlled->CompressorFlag); // mutopsitka dziala btLampkaSprezarka.Turn(mvControlled->CompressorFlag); // mutopsitka dziala
btLampkaSprezarkaOff.Turn( false == mvControlled->CompressorFlag ); btLampkaSprezarkaOff.Turn( false == mvControlled->CompressorFlag );
btLampkaFuelPumpOff.Turn( false == mvControlled->FuelPump.is_active );
// boczniki // boczniki
unsigned char scp; // Ra: dopisałem "unsigned" unsigned char scp; // Ra: dopisałem "unsigned"
// Ra: w SU45 boczniki wchodzą na MainCtrlPos, a nie na MainCtrlActualPos // Ra: w SU45 boczniki wchodzą na MainCtrlPos, a nie na MainCtrlActualPos
@@ -4469,6 +4526,7 @@ bool TTrain::Update( double const Deltatime )
btLampkaNadmPrzetw.Turn( false ); btLampkaNadmPrzetw.Turn( false );
btLampkaSprezarka.Turn( false ); btLampkaSprezarka.Turn( false );
btLampkaSprezarkaOff.Turn( false ); btLampkaSprezarkaOff.Turn( false );
btLampkaFuelPumpOff.Turn( false );
btLampkaBezoporowa.Turn( false ); btLampkaBezoporowa.Turn( false );
} }
if (mvControlled->Signalling == true) { if (mvControlled->Signalling == true) {
@@ -4874,6 +4932,8 @@ bool TTrain::Update( double const Deltatime )
ggCabLightButton.Update(); ggCabLightButton.Update();
ggCabLightDimButton.Update(); ggCabLightDimButton.Update();
ggBatteryButton.Update(); ggBatteryButton.Update();
ggFuelPumpButton.Update();
//------ //------
pyScreens.update(); pyScreens.update();
} }
@@ -5157,15 +5217,22 @@ TTrain::update_sounds( double const Deltatime ) {
volume *= 1 + 0.125 * brakeforceratio; volume *= 1 + 0.125 * brakeforceratio;
} }
// scale volume by track quality // scale volume by track quality
volume *= ( 20.0 + DynamicObject->MyTrack->iDamageFlag ) / 21; // TODO: track quality and/or environment factors as separate subroutine
// scale volume with vehicle speed
// TBD, TODO: disable the scaling for sounds combined from speed-based samples?
volume *= volume *=
interpolate( interpolate(
0.0, 1.0, 0.8, 1.2,
clamp( clamp(
mvOccupied->Vel / 40.0, DynamicObject->MyTrack->iQualityFlag / 20.0,
0.0, 1.0 ) ); 0.0, 1.0 ) );
// for single sample sounds muffle the playback at low speeds
if( false == rsRunningNoise.is_combined() ) {
volume *=
interpolate(
0.0, 1.0,
clamp(
mvOccupied->Vel / 40.0,
0.0, 1.0 ) );
}
if( volume > 0.05 ) { if( volume > 0.05 ) {
rsRunningNoise rsRunningNoise
@@ -5911,6 +5978,8 @@ void TTrain::clear_cab_controls()
ggMainGearStatus.Clear(); ggMainGearStatus.Clear();
ggIgnitionKey.Clear(); ggIgnitionKey.Clear();
ggFuelPumpButton.Clear();
btLampkaPrzetw.Clear(); btLampkaPrzetw.Clear();
btLampkaPrzetwB.Clear(); btLampkaPrzetwB.Clear();
btLampkaPrzetwBOff.Clear(); btLampkaPrzetwBOff.Clear();
@@ -5950,6 +6019,7 @@ void TTrain::clear_cab_controls()
btLampkaSprezarkaB.Clear(); btLampkaSprezarkaB.Clear();
btLampkaSprezarkaOff.Clear(); btLampkaSprezarkaOff.Clear();
btLampkaSprezarkaBOff.Clear(); btLampkaSprezarkaBOff.Clear();
btLampkaFuelPumpOff.Clear();
btLampkaNapNastHam.Clear(); btLampkaNapNastHam.Clear();
btLampkaStycznB.Clear(); btLampkaStycznB.Clear();
btLampkaHamowanie1zes.Clear(); btLampkaHamowanie1zes.Clear();
@@ -6072,9 +6142,14 @@ void TTrain::set_cab_controls() {
1.0 : 1.0 :
0.0 ); 0.0 );
// motor overload relay threshold / shunt mode // motor overload relay threshold / shunt mode
if( mvControlled->Imax == mvControlled->ImaxHi ) { ggMaxCurrentCtrl.PutValue(
ggMaxCurrentCtrl.PutValue( 1.0 ); ( true == mvControlled->ShuntModeAllow ?
} ( true == mvControlled->ShuntMode ?
1.0 :
0.0 ) :
( mvControlled->Imax == mvControlled->ImaxHi ?
1.0 :
0.0 ) ) );
// lights // lights
ggLightsButton.PutValue( mvOccupied->LightsPos - 1 ); ggLightsButton.PutValue( mvOccupied->LightsPos - 1 );
@@ -6169,6 +6244,11 @@ void TTrain::set_cab_controls() {
ShowNextCurrent ? ShowNextCurrent ?
1.0 : 1.0 :
0.0 ); 0.0 );
// fuel pump
ggFuelPumpButton.PutValue(
mvOccupied->FuelPump.is_enabled ?
1.0 :
0.0 );
// we reset all indicators, as they're set during the update pass // we reset all indicators, as they're set during the update pass
// TODO: when cleaning up break setting indicator state into a separate function, so we can reuse it // TODO: when cleaning up break setting indicator state into a separate function, so we can reuse it
@@ -6232,6 +6312,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
{ "i-compressorb:", btLampkaSprezarkaB }, { "i-compressorb:", btLampkaSprezarkaB },
{ "i-compressoroff:", btLampkaSprezarkaOff }, { "i-compressoroff:", btLampkaSprezarkaOff },
{ "i-compressorboff:", btLampkaSprezarkaBOff }, { "i-compressorboff:", btLampkaSprezarkaBOff },
{ "i-fuelpumpoff:", btLampkaFuelPumpOff },
{ "i-voltbrake:", btLampkaNapNastHam }, { "i-voltbrake:", btLampkaNapNastHam },
{ "i-resistorsb:", btLampkaOporyB }, { "i-resistorsb:", btLampkaOporyB },
{ "i-contactorsb:", btLampkaStycznB }, { "i-contactorsb:", btLampkaStycznB },
@@ -6332,6 +6413,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
{ "converterlocal_sw:", ggConverterLocalButton }, { "converterlocal_sw:", ggConverterLocalButton },
{ "converteroff_sw:", ggConverterOffButton }, { "converteroff_sw:", ggConverterOffButton },
{ "main_sw:", ggMainButton }, { "main_sw:", ggMainButton },
{ "fuelpump_sw:", ggFuelPumpButton },
{ "radio_sw:", ggRadioButton }, { "radio_sw:", ggRadioButton },
{ "radiochannel_sw:", ggRadioChannelSelector }, { "radiochannel_sw:", ggRadioChannelSelector },
{ "radiochannelprev_sw:", ggRadioChannelPrevious }, { "radiochannelprev_sw:", ggRadioChannelPrevious },

View File

@@ -452,6 +452,7 @@ public: // reszta może by?publiczna
TButton btLampkaSprezarkaB; TButton btLampkaSprezarkaB;
TButton btLampkaSprezarkaOff; TButton btLampkaSprezarkaOff;
TButton btLampkaSprezarkaBOff; TButton btLampkaSprezarkaBOff;
TButton btLampkaFuelPumpOff;
TButton btLampkaBocznik1; TButton btLampkaBocznik1;
TButton btLampkaBocznik2; TButton btLampkaBocznik2;
TButton btLampkaBocznik3; TButton btLampkaBocznik3;

View File

@@ -61,10 +61,11 @@ simulation_time::init() {
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
::memcpy( m_monthdaycounts, monthdaycounts, sizeof( monthdaycounts ) ); ::memcpy( m_monthdaycounts, monthdaycounts, sizeof( monthdaycounts ) );
// potentially adjust scenario clock
auto const requestedtime { clamp_circular<int>( m_time.wHour * 60 + m_time.wMinute + Global.ScenarioTimeOffset * 60, 1440 ) };
auto const requestedhour { ( requestedtime / 60 ) % 60 };
auto const requestedminute { requestedtime % 60 };
// cache requested elements, if any // cache requested elements, if any
WORD const requestedhour = m_time.wHour;
WORD const requestedminute = m_time.wMinute;
::GetLocalTime( &m_time ); ::GetLocalTime( &m_time );
if( Global.fMoveLight > 0.0 ) { if( Global.fMoveLight > 0.0 ) {
@@ -72,10 +73,11 @@ simulation_time::init() {
daymonth( m_time.wDay, m_time.wMonth, m_time.wYear, static_cast<WORD>( Global.fMoveLight ) ); daymonth( m_time.wDay, m_time.wMonth, m_time.wYear, static_cast<WORD>( Global.fMoveLight ) );
} }
if( requestedhour != (WORD)-1 ) { m_time.wHour = clamp( requestedhour, static_cast<WORD>( 0 ), static_cast<WORD>( 23 ) ); } if( requestedhour != -1 ) { m_time.wHour = static_cast<WORD>( clamp( requestedhour, 0, 23 ) ); }
if( requestedminute != (WORD)-1 ) { m_time.wMinute = clamp( requestedminute, static_cast<WORD>( 0 ), static_cast<WORD>( 59 ) ); } if( requestedminute != -1 ) { m_time.wMinute = static_cast<WORD>( clamp( requestedminute, 0, 59 ) ); }
// if the time is taken from the local clock leave the seconds intact, otherwise set them to zero // if the time is taken from the local clock leave the seconds intact, otherwise set them to zero
if( ( requestedhour != (WORD)-1 ) || ( requestedminute != (WORD)-1 ) ) { if( ( requestedhour != -1 )
|| ( requestedminute != 1 ) ) {
m_time.wSecond = 0; m_time.wSecond = 0;
} }

View File

@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h" #include "stdafx.h"
#include "mtable.h" #include "mtable.h"
#include "globals.h"
#include "world.h" #include "world.h"
#include "utilities.h" #include "utilities.h"
@@ -521,20 +522,21 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
// NextStationName:=TimeTable[1].StationName; // NextStationName:=TimeTable[1].StationName;
/* TTVmax:=TimeTable[1].vmax; */ /* TTVmax:=TimeTable[1].vmax; */
} }
if ((iPlus != 0)) // jeżeli jest przesunięcie rozkładu auto const timeoffset { static_cast<int>( Global.ScenarioTimeOffset * 60 ) + iPlus };
if( timeoffset != 0.0 ) // jeżeli jest przesunięcie rozkładu
{ {
long i_end = StationCount + 1; long i_end = StationCount + 1;
for (i = 1; i < i_end; ++i) // bez with, bo ciężko się przenosi na C++ for (i = 1; i < i_end; ++i) // bez with, bo ciężko się przenosi na C++
{ {
if ((TimeTable[i].Ah >= 0)) if ((TimeTable[i].Ah >= 0))
{ {
time = iPlus + TimeTable[i].Ah * 60 + TimeTable[i].Am; // nowe minuty time = clamp_circular( TimeTable[i].Ah * 60 + TimeTable[i].Am + timeoffset, 1440 ); // nowe minuty
TimeTable[i].Am = time % 60; TimeTable[i].Am = time % 60;
TimeTable[i].Ah = (time /*div*/ / 60) % 60; TimeTable[i].Ah = (time /*div*/ / 60) % 60;
} }
if ((TimeTable[i].Dh >= 0)) if ((TimeTable[i].Dh >= 0))
{ {
time = iPlus + TimeTable[i].Dh * 60 + TimeTable[i].Dm; // nowe minuty time = clamp_circular( TimeTable[i].Dh * 60 + TimeTable[i].Dm + timeoffset, 1440 ); // nowe minuty
TimeTable[i].Dm = time % 60; TimeTable[i].Dm = time % 60;
TimeTable[i].Dh = (time /*div*/ / 60) % 60; TimeTable[i].Dh = (time /*div*/ / 60) % 60;
} }

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 18 #define VERSION_MAJOR 18
#define VERSION_MINOR 326 #define VERSION_MINOR 329
#define VERSION_REVISION 0 #define VERSION_REVISION 0