From 64dea17e6ffa1176f48195ee7d779059210c75da Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 27 Mar 2018 00:49:17 +0200 Subject: [PATCH] basic fuel pump, brake reservoirs air leaks, support for combined axle clatter sounds, dedicated loud buffer clash and coupler stretch sounds --- Driver.cpp | 12 ++- DynObj.cpp | 133 +++++++++++++++++-------- DynObj.h | 2 + McZapkie/MOVER.h | 13 ++- McZapkie/Mover.cpp | 229 ++++++++++++++++++++++++++++++------------- McZapkie/hamulce.cpp | 11 +++ McZapkie/hamulce.h | 2 + Train.h | 5 + World.cpp | 1 + command.cpp | 3 + command.h | 3 + keyboardinput.cpp | 6 ++ mouseinput.cpp | 3 + translation.h | 1 + version.h | 2 +- 15 files changed, 316 insertions(+), 110 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 0590b80f..c939958b 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -2226,6 +2226,7 @@ bool TController::PrepareEngine() if (AIControllFlag) { // część wykonawcza dla sterowania przez komputer mvOccupied->BatterySwitch(true); + mvOccupied->FuelPumpSwitch( true ); if (mvControlling->EnginePowerSource.SourceType == CurrentCollector) { // jeśli silnikowy jest pantografującym mvControlling->PantFront( true ); @@ -3053,7 +3054,7 @@ void TController::Doors( bool const Open, int const Side ) { && ( false == mvOccupied->DepartureSignal ) && ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) { mvOccupied->signal_departure( true ); // załącenie bzyczka - fActionTime = -3.0 - 0.1 * Random( 10 ); // 3-4 second wait + fActionTime = -1.5 - 0.1 * Random( 10 ); // 1.5-2.5 second wait } } @@ -3070,8 +3071,15 @@ void TController::Doors( bool const Open, int const Side ) { } vehicle = vehicle->Next(); // pojazd podłączony z tyłu (patrząc od czoła) } - fActionTime = -2.5 - 0.1 * Random( 10 ); // 2.5-3.5 sec wait, +potentially 0.5 remaining + fActionTime = -2.0 - 0.1 * Random( 15 ); // 2.0-3.5 sec wait, +potentially 0.5 remaining iDrivigFlags &= ~moveDoorOpened; // zostały zamknięte - nie wykonywać drugi raz + + if( Random( 100 ) < Random( 100 ) ) { + // potentially turn off the warning before actual departure + // TBD, TODO: dedicated buzzer duration counter + mvOccupied->signal_departure( false ); + } + } } } diff --git a/DynObj.cpp b/DynObj.cpp index 1b711cec..da4436ce 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -3190,8 +3190,13 @@ bool TDynamicObject::Update(double dt, double dt1) } if( dRailLength != -1 ) { if( MoverParameters->Vel > 0 ) { - - double volume = ( 20.0 + MyTrack->iDamageFlag ) / 21; + // TODO: track quality and/or environment factors as separate subroutine + auto volume = + interpolate( + 0.8, 1.2, + clamp( + MyTrack->iQualityFlag / 20.0, + 0.0, 1.0 ) ); switch( MyTrack->eEnvironment ) { case e_tunnel: { volume *= 1.1; @@ -3212,7 +3217,15 @@ bool TDynamicObject::Update(double dt, double dt1) if( axle.distance < 0 ) { axle.distance += dRailLength; if( MoverParameters->Vel > 2.5 ) { - axle.clatter.gain( volume ).play(); + // NOTE: for combined clatter sound we supply 1/100th of actual value, as the sound module converts does the opposite, converting received (typically) 0-1 values to 0-100 range + auto const frequency = ( + true == axle.clatter.is_combined() ? + MoverParameters->Vel * 0.01 : + 1.0 ); + axle.clatter + .pitch( frequency ) + .gain( volume ) + .play(); // crude bump simulation, drop down on even axles, move back up on the odd ones MoverParameters->AccVert += interpolate( @@ -3250,23 +3263,6 @@ bool TDynamicObject::Update(double dt, double dt1) } } */ - if ((MoverParameters->TrainType == dt_ET40) || (MoverParameters->TrainType == dt_EP05)) - { // dla ET40 i EU05 automatyczne cofanie nastawnika - i tak - // nie będzie to działać dobrze... - /* if - ((MoverParameters->MainCtrlPos>MoverParameters->MainCtrlActualPos)&&(abs(MoverParameters->Im)>MoverParameters->IminHi)) - { - MoverParameters->DecMainCtrl(1); - } */ - if( ( glfwGetKey( Global.window, GLFW_KEY_KP_ADD ) != GLFW_TRUE ) - && ( MoverParameters->MainCtrlPos > MoverParameters->MainCtrlActualPos ) ) { - MoverParameters->DecMainCtrl( 1 ); - } - if( ( glfwGetKey( Global.window, GLFW_KEY_KP_SUBTRACT ) != GLFW_TRUE ) - && ( MoverParameters->MainCtrlPos < MoverParameters->MainCtrlActualPos ) ) { - MoverParameters->IncMainCtrl( 1 ); // Ra 15-01: a to nie miało być tylko cofanie? - } - } if (MoverParameters->Vel != 0) { // McZapkie-050402: krecenie kolami: @@ -3972,22 +3968,29 @@ void TDynamicObject::RenderSounds() { // volume calculation volume = - bogiesound.m_amplitudeoffset + - bogiesound.m_amplitudefactor * MoverParameters->Vel; + bogiesound.m_amplitudeoffset + + bogiesound.m_amplitudefactor * MoverParameters->Vel; if( brakeforceratio > 0.0 ) { // hamulce wzmagaja halas volume *= 1 + 0.125 * brakeforceratio; } // scale volume by track quality - volume *= ( 20.0 + MyTrack->iDamageFlag ) / 21; - // scale volume with vehicle speed - // TBD, TODO: disable the scaling for sounds combined from speed-based samples? + // TODO: track quality and/or environment factors as separate subroutine volume *= interpolate( - 0.0, 1.0, + 0.8, 1.2, clamp( - MoverParameters->Vel / 40.0, + MyTrack->iQualityFlag / 20.0, 0.0, 1.0 ) ); + // for single sample sounds muffle the playback at low speeds + if( false == bogiesound.is_combined() ) { + volume *= + interpolate( + 0.0, 1.0, + clamp( + MoverParameters->Vel / 40.0, + 0.0, 1.0 ) ); + } if( volume > 0.05 ) { // apply calculated parameters to all motor instances @@ -4069,21 +4072,51 @@ void TDynamicObject::RenderSounds() { if( true == TestFlag( coupler.sounds, sound::bufferclash ) ) { // zderzaki uderzaja o siebie - couplersounds.dsbBufferClamp - .gain( - true == TestFlag( coupler.sounds, sound::loud ) ? - 1.f : - 0.65f ) - .play( sound_flags::exclusive ); + if( true == TestFlag( coupler.sounds, sound::loud ) ) { + // loud clash + if( false == couplersounds.dsbBufferClamp_loud.empty() ) { + // dedicated sound for loud clash + couplersounds.dsbBufferClamp_loud + .gain( 1.f ) + .play( sound_flags::exclusive ); + } + else { + // fallback on the standard sound + couplersounds.dsbBufferClamp + .gain( 1.f ) + .play( sound_flags::exclusive ); + } + } + else { + // basic clash + couplersounds.dsbBufferClamp + .gain( 0.65f ) + .play( sound_flags::exclusive ); + } } if( true == TestFlag( coupler.sounds, sound::couplerstretch ) ) { // sprzegi sie rozciagaja - couplersounds.dsbCouplerStretch - .gain( - true == TestFlag( coupler.sounds, sound::loud ) ? - 1.f : - 0.65f ) - .play( sound_flags::exclusive ); + if( true == TestFlag( coupler.sounds, sound::loud ) ) { + // loud stretch + if( false == couplersounds.dsbCouplerStretch_loud.empty() ) { + // dedicated sound for loud stretch + couplersounds.dsbCouplerStretch_loud + .gain( 1.f ) + .play( sound_flags::exclusive ); + } + else { + // fallback on the standard sound + couplersounds.dsbCouplerStretch + .gain( 1.f ) + .play( sound_flags::exclusive ); + } + } + else { + // basic clash + couplersounds.dsbCouplerStretch + .gain( 0.65f ) + .play( sound_flags::exclusive ); + } } coupler.sounds = 0; @@ -5257,6 +5290,15 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, couplersounds.dsbCouplerStretch = couplerstretch; } } + else if( token == "couplerstretch_loud:" ) { + // coupler stretching + sound_source couplerstretch { sound_placement::external }; + couplerstretch.deserialize( parser, sound_type::single ); + couplerstretch.owner( this ); + for( auto &couplersounds : m_couplersounds ) { + couplersounds.dsbCouplerStretch_loud = couplerstretch; + } + } else if( token == "bufferclamp:" ) { // buffers hitting one another sound_source bufferclash { sound_placement::external }; @@ -5266,6 +5308,15 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, couplersounds.dsbBufferClamp = bufferclash; } } + else if( token == "bufferclamp_loud:" ) { + // buffers hitting one another + sound_source bufferclash { sound_placement::external }; + bufferclash.deserialize( parser, sound_type::single ); + bufferclash.owner( this ); + for( auto &couplersounds : m_couplersounds ) { + couplersounds.dsbBufferClamp_loud = bufferclash; + } + } } while( token != "" ); @@ -5377,12 +5428,16 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, m_couplersounds[ side::front ].dsbCouplerAttach.offset( frontcoupleroffset ); m_couplersounds[ side::front ].dsbCouplerDetach.offset( frontcoupleroffset ); m_couplersounds[ side::front ].dsbCouplerStretch.offset( frontcoupleroffset ); + m_couplersounds[ side::front ].dsbCouplerStretch_loud.offset( frontcoupleroffset ); m_couplersounds[ side::front ].dsbBufferClamp.offset( frontcoupleroffset ); + m_couplersounds[ side::front ].dsbBufferClamp_loud.offset( frontcoupleroffset ); auto const rearcoupleroffset { glm::vec3{ 0.f, 1.f, MoverParameters->Dim.L * -0.5f } }; m_couplersounds[ side::rear ].dsbCouplerAttach.offset( rearcoupleroffset ); m_couplersounds[ side::rear ].dsbCouplerDetach.offset( rearcoupleroffset ); m_couplersounds[ side::rear ].dsbCouplerStretch.offset( rearcoupleroffset ); + m_couplersounds[ side::rear ].dsbCouplerStretch_loud.offset( rearcoupleroffset ); m_couplersounds[ side::rear ].dsbBufferClamp.offset( rearcoupleroffset ); + m_couplersounds[ side::rear ].dsbBufferClamp_loud.offset( rearcoupleroffset ); } //--------------------------------------------------------------------------- diff --git a/DynObj.h b/DynObj.h index caa307e7..664eb18f 100644 --- a/DynObj.h +++ b/DynObj.h @@ -275,7 +275,9 @@ private: sound_source dsbCouplerAttach { sound_placement::external }; // moved from cab sound_source dsbCouplerDetach { sound_placement::external }; // moved from cab sound_source dsbCouplerStretch { sound_placement::external }; // moved from cab + sound_source dsbCouplerStretch_loud { sound_placement::external }; sound_source dsbBufferClamp { sound_placement::external }; // moved from cab + sound_source dsbBufferClamp_loud { sound_placement::external }; }; struct pantograph_sounds { diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 222004de..f1056f95 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -85,7 +85,6 @@ const double Steel2Steel_friction = 0.15; //tarcie statyczne const double g = 9.81; //przyspieszenie ziemskie const double SandSpeed = 0.1; //ile kg/s} const double Pirazy2 = 6.2831853071794f; -#define PI 3.1415926535897f //-- var, const, procedure --------------------------------------------------- static bool const Go = true; @@ -618,6 +617,15 @@ struct TCoupling { int sounds { 0 }; // sounds emitted by the coupling devices }; +// basic approximation of a fuel pump +// TODO: fuel consumption, optional automatic engine start after activation +struct fuel_pump { + + bool is_enabled { false }; // device is allowed/requested to operate + bool is_active { false }; // device is working + start start_type { start::manual }; +}; + class TMoverParameters { // Ra: wrapper na kod pascalowy, przejmujący jego funkcje Q: 20160824 - juz nie wrapper a klasa bazowa :) public: @@ -904,6 +912,7 @@ public: bool ConverterAllow = false; /*zezwolenie na prace przetwornicy NBMX*/ bool ConverterAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere) bool ConverterFlag = false; /*! czy wlaczona przetwornica NBMX*/ + fuel_pump FuelPump; int BrakeCtrlPos = -2; /*nastawa hamulca zespolonego*/ double BrakeCtrlPosR = 0.0; /*nastawa hamulca zespolonego - plynna dla FV4a*/ @@ -1190,12 +1199,14 @@ public: /*--funkcje dla lokomotyw*/ bool DirectionBackward(void);/*! kierunek ruchu*/ + bool FuelPumpSwitch( bool State, int const Notify = range::consist ); // fuel pump state toggle bool MainSwitch( bool const State, int const Notify = range::consist );/*! wylacznik glowny*/ bool ConverterSwitch( bool State, int const Notify = range::consist );/*! wl/wyl przetwornicy*/ bool CompressorSwitch( bool State, int const Notify = range::consist );/*! wl/wyl sprezarki*/ /*-funkcje typowe dla lokomotywy elektrycznej*/ void ConverterCheck( double const Timestep ); // przetwornica + void FuelPumpCheck( double const Timestep ); bool FuseOn(void); //bezpiecznik nadamiary bool FuseFlagCheck(void); // sprawdzanie flagi nadmiarowego void FuseOff(void); // wylaczenie nadmiarowego diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 7f22b320..2ae53a80 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1572,6 +1572,14 @@ void TMoverParameters::ConverterCheck( double const Timestep ) { } }; +// fuel pump status update +void TMoverParameters::FuelPumpCheck( double const Timestep ) { + + FuelPump.is_active = ( + ( true == FuelPump.is_enabled ) + && ( true == Battery ) ); +} + double TMoverParameters::ShowCurrent(int AmpN) { // Odczyt poboru prądu na podanym amperomierzu switch (EngineType) @@ -2339,13 +2347,38 @@ bool TMoverParameters::AntiSlippingButton(void) return (AntiSlippingBrake() /*|| Sandbox(true)*/); } +// fuel pump state toggle +bool TMoverParameters::FuelPumpSwitch( bool State, int const Notify ) { + + if( FuelPump.start_type == start::automatic ) { + // automatic fuel pump ignores 'manual' state commands + return false; + } + + bool const initialstate { FuelPump.is_enabled }; + + FuelPump.is_enabled = State; + + if( Notify != range::local ) { + SendCtrlToNext( + "FuelPumpSwitch", + ( FuelPump.is_enabled ? 1 : 0 ), + CabNo, + ( Notify == range::unit ? + coupling::control | coupling::permanent : + coupling::control ) ); + } + + return ( FuelPump.is_enabled != initialstate ); +} + // ************************************************************************************************* // Q: 20160713 // włączenie / wyłączenie obwodu głownego // ************************************************************************************************* bool TMoverParameters::MainSwitch( bool const State, int const Notify ) { - bool MS = false; // Ra: przeniesione z końca + bool const initialstate { Mains }; if( ( Mains != State ) && ( MainCtrlPosNo > 0 ) ) { @@ -2357,46 +2390,59 @@ bool TMoverParameters::MainSwitch( bool const State, int const Notify ) && ( false == TestFlag( DamageFlag, dtrain_out ) ) && ( false == TestFlag( EngDmgFlag, 1 ) ) ) ) { - if( true == Mains ) { - // jeśli był załączony - if( Notify != range::local ) { - // wysłanie wyłączenia do pozostałych? - SendCtrlToNext( - "MainSwitch", int( State ), CabNo, - ( Notify == range::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); + if( true == State ) { + // switch on + if( ( EngineType == DieselEngine ) + || ( EngineType == DieselElectric ) ) { + + if( true == FuelPump.start_type == start::automatic ) { + // potentially force start of the fuel pump + // TODO: the whole diesel start sequence is a special kind of a mess, clean it up when refactoring + FuelPump.is_enabled = true; + FuelPumpCheck( 0.0 ); + } + if( true == FuelPump.is_active ) { + Mains = true; + dizel_enginestart = true; + } + } + else { + Mains = true; } } - Mains = State; - MS = true; // wartość zwrotna - LastSwitchingTime = 0; - - if( true == Mains ) { - // jeśli został załączony - if( Notify != range::local ) { - // wysłanie wyłączenia do pozostałych? - SendCtrlToNext( - "MainSwitch", int( State ), CabNo, - ( Notify == range::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); + else { + Mains = false; + if( true == FuelPump.start_type == start::automatic ) { + // if the engine is off, switch off automatic fuel pump + FuelPump.is_enabled = false; } } - if( ( EngineType == DieselEngine ) - || ( EngineType == DieselElectric ) ) { - dizel_enginestart = State; - } if( ( TrainType == dt_EZT ) && ( false == State ) ) { ConvOvldFlag = true; } + + if( Mains != initialstate ) { + LastSwitchingTime = 0; + } + + if( Notify != range::local ) { + // pass the command to other vehicles + SendCtrlToNext( + "MainSwitch", + ( State ? 1 : 0 ), + CabNo, + ( Notify == range::unit ? + coupling::control | coupling::permanent : + coupling::control ) ); + } + } } // else MainSwitch:=false; - return MS; + return ( Mains != initialstate ); } // ************************************************************************************************* @@ -3023,6 +3069,8 @@ void TMoverParameters::UpdateBrakePressure(double dt) dpLocalValve = 0; dpBrake = 0; + Hamulec->ForceLeak( dt * AirLeakRate * 0.25 ); // fake air leaks from brake system reservoirs + BrakePress = Hamulec->GetBCP(); // BrakePress:=(Hamulec as TEst4).ImplsRes.pa; Volume = Hamulec->GetBRP(); @@ -3066,8 +3114,9 @@ void TMoverParameters::CompressorCheck(double dt) } else { - if( ( EngineType == DieselEngine ) - && ( CompressorPower == 0 ) ) { + if( ( CompressorPower == 0 ) + && ( ( EngineType == DieselEngine ) + || ( EngineType == DieselElectric ) ) ) { // experimental: make sure compressor coupled with diesel engine is always ready for work CompressorAllow = true; } @@ -4065,7 +4114,7 @@ double TMoverParameters::CouplerForce(int CouplerN, double dt) // 090503: dzwieki pracy sprzegu SetFlag( Couplers[ CouplerN ].sounds, - ( absdV > 0.1 ? + ( absdV > 0.035 ? ( sound::couplerstretch | sound::loud ) : sound::couplerstretch ) ); } @@ -4168,8 +4217,9 @@ double TMoverParameters::TractionForce(double dt) // youBy switch( EngineType ) { case DieselElectric: { - if( true == ConverterFlag ) { - // NOTE: converter is currently a stand-in for a fuel pump + if( ( true == Mains ) + && ( true == FuelPump.is_active ) ) { + tmp = DElist[ MainCtrlPos ].RPM / 60.0; if( ( true == Heating ) @@ -4436,7 +4486,8 @@ double TMoverParameters::TractionForce(double dt) PosRatio = currentgenpower / DElist[MainCtrlPosNo].GenPower; // stosunek mocy teraz do mocy max - if( ( MainCtrlPos > 0 ) && ( ConverterFlag ) ) { + // NOTE: Mains in this context is working diesel engine + if( ( true == Mains ) && ( MainCtrlPos > 0 ) ) { if( tmpV < ( Vhyp * power / DElist[ MainCtrlPosNo ].GenPower ) ) { // czy na czesci prostej, czy na hiperboli @@ -5690,10 +5741,15 @@ bool TMoverParameters::dizel_AutoGearCheck(void) // ************************************************************************************************* bool TMoverParameters::dizel_Update(double dt) { - double const fillspeed { 2 }; - bool DU { false }; + FuelPumpCheck( dt ); + // potentially automatic engine start after fuel pump was activated + if( ( true == Mains ) + && ( false == FuelPump.is_active ) ) { + // knock out the engine if the fuel pump isn't feeding it + // TBD, TODO: grace period before the engine is starved for fuel and knocked out + MainSwitch( false ); + } - // dizel_Update:=false; if( ( true == dizel_enginestart ) && ( LastSwitchingTime >= InitialCtrlDelay ) ) { dizel_enginestart = false; @@ -5707,9 +5763,12 @@ bool TMoverParameters::dizel_Update(double dt) DElist[ 0 ].RPM / 60.0 ) ); } + bool DU { false }; + if( EngineType == DieselEngine ) { dizel_EngageChange( dt ); DU = dizel_AutoGearCheck(); + double const fillspeed { 2 }; dizel_fill = dizel_fill + fillspeed * dt * ( dizel_fillcheck( MainCtrlPos ) - dizel_fill ); } @@ -5722,19 +5781,24 @@ bool TMoverParameters::dizel_Update(double dt) // ************************************************************************************************* double TMoverParameters::dizel_fillcheck(int mcp) { - double realfill, nreg; + auto realfill { 0.0 }; - realfill = 0; - nreg = 0; - if (Mains && (MainCtrlPosNo > 0)) - { - if (dizel_enginestart && - (LastSwitchingTime >= 0.9 * InitialCtrlDelay)) // wzbogacenie przy rozruchu - realfill = 1; - else - realfill = RList[mcp].R; // napelnienie zalezne od MainCtrlPos + if( ( true == Mains ) + && ( MainCtrlPosNo > 0 ) + && ( true == FuelPump.is_active ) ) { + + if( ( true == dizel_enginestart ) + && ( LastSwitchingTime >= 0.9 * InitialCtrlDelay ) ) { + // wzbogacenie przy rozruchu + realfill = 1; + } + else { + // napelnienie zalezne od MainCtrlPos + realfill = RList[ mcp ].R; + } if (dizel_nmax_cutoff > 0) { + auto nreg { 0.0 }; switch (RList[MainCtrlPos].Mn) { case 0: @@ -5749,13 +5813,8 @@ double TMoverParameters::dizel_fillcheck(int mcp) break; default: realfill = 0; // sluczaj + break; } - /*if (enrot > nreg) - realfill = realfill * (3.9 - 3.0 * abs(enrot) / nreg); - if (enrot > dizel_nmax_cutoff) - realfill = realfill * (9.8 - 9.0 * abs(enrot) / dizel_nmax_cutoff); - if (enrot < dizel_nmin) - realfill = realfill * (1.0 + (dizel_nmin - abs(enrot)) / dizel_nmin);*/ if (enrot > nreg) //nad predkoscia regulatora zeruj dawke realfill = 0; if (enrot < nreg) //pod predkoscia regulatora dawka zadana @@ -5764,11 +5823,8 @@ double TMoverParameters::dizel_fillcheck(int mcp) realfill = 1; } } - if (realfill < 0) - realfill = 0; - if (realfill > 1) - realfill = 1; - return realfill; + + return clamp( realfill, 0.0, 1.0 ); } // ************************************************************************************************* @@ -5794,7 +5850,7 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt) Moment = -dizel_Mstand; } if( ( enrot < dizel_nmin / 10.0 ) - && ( eAngle < PI / 2.0 ) ) { + && ( eAngle < M_PI_2 ) ) { // wstrzymywanie przy malych obrotach Moment -= dizel_Mstand; } @@ -7553,7 +7609,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { // converter { - std::map starts{ + std::map starts { { "Manual", start::manual }, { "Automatic", start::automatic } }; @@ -7564,6 +7620,20 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { start::manual; } extract_value( ConverterStartDelay, "ConverterStartDelay", line, "" ); + + // fuel pump + { + std::map starts { + { "Manual", start::manual }, + { "Automatic", start::automatic } + }; + auto lookup = starts.find( extract_value( "FuelStart", line ) ); + FuelPump.start_type = + lookup != starts.end() ? + lookup->second : + start::manual; + } + } void TMoverParameters::LoadFIZ_Light( std::string const &line ) { @@ -8451,16 +8521,41 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C OK = BrakeReleaser(Round(CValue1)); // samo się przesyła dalej // OK:=SendCtrlToNext(command,CValue1,CValue2); //to robiło kaskadę 2^n } + else if (Command == "FuelPumpSwitch") { + if( FuelPump.start_type == start::manual ) { + // automatic fuel pump ignores 'manual' state commands + FuelPump.is_enabled = ( CValue1 == 1 ); + } + OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + } else if (Command == "MainSwitch") { - if (CValue1 == 1) - { - Mains = true; - if ((EngineType == DieselEngine) && Mains) - dizel_enginestart = true; + if (CValue1 == 1) { + + if( ( EngineType == DieselEngine ) + || ( EngineType == DieselElectric ) ) { + if( true == FuelPump.start_type == start::automatic ) { + // potentially force start of the fuel pump + // TODO: the whole diesel start sequence is a special kind of mess, clean it up when refactoring + FuelPump.is_enabled = true; + FuelPumpCheck( 0.0 ); + } + if( true == FuelPump.is_active ) { + Mains = true; + dizel_enginestart = true; + } + } + else { + Mains = true; + } } - else - Mains = false; + else { + Mains = false; + if( true == FuelPump.start_type == start::automatic ) { + // if the engine is off, switch off automatic fuel pump + FuelPump.is_enabled = false; + } + } OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); } else if (Command == "Direction") diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index e5f64025..10f2e949 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -412,6 +412,17 @@ void TBrake::ForceEmptiness() BrakeRes->Act(); } +// removes specified amount of air from the reservoirs +// NOTE: experimental feature, for now limited only to brake reservoir +void TBrake::ForceLeak( double const Amount ) { + + BrakeRes->Flow( -Amount * BrakeRes->P() ); + ValveRes->Flow( -Amount * ValveRes->P() * 0.01 ); // this reservoir has hard coded, tiny capacity compared to other parts + + BrakeRes->Act(); + ValveRes->Act(); +} + //---WESTINGHOUSE--- void TWest::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) diff --git a/McZapkie/hamulce.h b/McZapkie/hamulce.h index f36fec48..ac6fbf9a 100644 --- a/McZapkie/hamulce.h +++ b/McZapkie/hamulce.h @@ -211,6 +211,8 @@ class TBrake { int GetStatus(); //flaga statusu, moze sie przydac do odglosow void SetASBP( double const Press ); //ustalenie cisnienia pp virtual void ForceEmptiness(); + // removes specified amount of air from the reservoirs + virtual void ForceLeak( double const Amount ); int GetSoundFlag(); int GetBrakeStatus() const { return BrakeStatus; } void SetBrakeStatus( int const Status ) { BrakeStatus = Status; } diff --git a/Train.h b/Train.h index 1f254959..9b530afc 100644 --- a/Train.h +++ b/Train.h @@ -213,6 +213,9 @@ class TTrain static void OnCommand_linebreakertoggle( TTrain *Train, command_data const &Command ); static void OnCommand_linebreakeropen( TTrain *Train, command_data const &Command ); static void OnCommand_linebreakerclose( TTrain *Train, command_data const &Command ); + static void OnCommand_fuelpumptoggle( TTrain *Train, command_data const &Command ); + static void OnCommand_fuelpumpenable( TTrain *Train, command_data const &Command ); + static void OnCommand_fuelpumpdisable( TTrain *Train, command_data const &Command ); static void OnCommand_convertertoggle( TTrain *Train, command_data const &Command ); static void OnCommand_converterenable( TTrain *Train, command_data const &Command ); static void OnCommand_converterdisable( TTrain *Train, command_data const &Command ); @@ -402,6 +405,8 @@ public: // reszta może by?publiczna TGauge ggSignallingButton; TGauge ggDoorSignallingButton; + TGauge ggFuelPumpButton; // fuel pump switch + TButton btLampkaPoslizg; TButton btLampkaStyczn; TButton btLampkaNadmPrzetw; diff --git a/World.cpp b/World.cpp index b6005609..09b440b4 100644 --- a/World.cpp +++ b/World.cpp @@ -1323,6 +1323,7 @@ TWorld::Update_UI() { uitextline2 += ( vehicle->MoverParameters->PantRearUp ? ( vehicle->MoverParameters->PantRearVolt > 0.0 ? "O" : "o" ) : "." );; uitextline2 += ( vehicle->MoverParameters->PantFrontUp ? ( vehicle->MoverParameters->PantFrontVolt > 0.0 ? "P" : "p" ) : "." );; uitextline2 += ( vehicle->MoverParameters->PantPressLockActive ? "!" : ( vehicle->MoverParameters->PantPressSwitchActive ? "*" : "." ) ); + uitextline2 += ( vehicle->MoverParameters->FuelPump.is_enabled ? ( vehicle->MoverParameters->FuelPump.is_active ? "F" : "f" ) : "." );; uitextline2 += ( false == vehicle->MoverParameters->ConverterAllowLocal ? "-" : ( vehicle->MoverParameters->ConverterAllow ? ( vehicle->MoverParameters->ConverterFlag ? "X" : "x" ) : "." ) ); uitextline2 += ( vehicle->MoverParameters->ConvOvldFlag ? "!" : "." ); uitextline2 += ( false == vehicle->MoverParameters->CompressorAllowLocal ? "-" : ( ( vehicle->MoverParameters->CompressorAllow || vehicle->MoverParameters->CompressorPower > 1 ) ? ( vehicle->MoverParameters->CompressorFlag ? "C" : "c" ) : "." ) ); diff --git a/command.cpp b/command.cpp index 289013f0..ba7e2d3b 100644 --- a/command.cpp +++ b/command.cpp @@ -63,6 +63,9 @@ commanddescription_sequence Commands_descriptions = { { "reverserforward", command_target::vehicle }, { "reverserneutral", command_target::vehicle }, { "reverserbackward", command_target::vehicle }, + { "fuelpumptoggle", command_target::vehicle }, + { "fuelpumpenable", command_target::vehicle }, + { "fuelpumpdisable", command_target::vehicle }, { "linebreakertoggle", command_target::vehicle }, { "linebreakeropen", command_target::vehicle }, { "linebreakerclose", command_target::vehicle }, diff --git a/command.h b/command.h index 99e24e74..ee5b1f3a 100644 --- a/command.h +++ b/command.h @@ -57,6 +57,9 @@ enum class user_command { reverserforward, reverserneutral, reverserbackward, + fuelpumptoggle, + fuelpumpenable, + fuelpumpdisable, linebreakertoggle, linebreakeropen, linebreakerclose, diff --git a/keyboardinput.cpp b/keyboardinput.cpp index bed57883..e0c63d02 100644 --- a/keyboardinput.cpp +++ b/keyboardinput.cpp @@ -255,6 +255,12 @@ keyboard_input::default_bindings() { { -1 }, // reverserbackward { -1 }, + // fuelpumptoggle + { GLFW_KEY_F }, + // fuelpumpenable, + { -1 }, + // fuelpumpdisable, + { -1 }, // linebreakertoggle { GLFW_KEY_M }, // linebreakeropen diff --git a/mouseinput.cpp b/mouseinput.cpp index 004749e7..582162b2 100644 --- a/mouseinput.cpp +++ b/mouseinput.cpp @@ -243,6 +243,9 @@ mouse_input::default_bindings() { { "maxcurrent_sw:", { user_command::motoroverloadrelaythresholdtoggle, user_command::none } }, + { "fuelpump_sw:", { + user_command::fuelpumptoggle, + user_command::none } }, { "main_off_bt:", { user_command::linebreakeropen, user_command::none } }, diff --git a/translation.h b/translation.h index 6233b87f..e7dbf543 100644 --- a/translation.h +++ b/translation.h @@ -29,6 +29,7 @@ static std::unordered_map m_cabcontrols = { { "brakeprofileg_sw:", "brake acting speed: cargo" }, { "brakeprofiler_sw:", "brake acting speed: rapid" }, { "maxcurrent_sw:", "motor overload relay threshold" }, + { "fuelpump_sw:", "fuel pump" }, { "main_off_bt:", "line breaker" }, { "main_on_bt:", "line breaker" }, { "security_reset_bt:", "alerter" }, diff --git a/version.h b/version.h index c7d482bd..bc9715f3 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 18 -#define VERSION_MINOR 318 +#define VERSION_MINOR 326 #define VERSION_REVISION 0