diff --git a/Driver.cpp b/Driver.cpp index 35208c67..f14e01ac 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1765,15 +1765,10 @@ void TController::Activation() if (iDirection) { // jeśli jest ustalony kierunek TDynamicObject *old = pVehicle, *d = pVehicle; // w tym siedzi AI - TController *drugi; // jakby były dwa, to zamienić miejscami, a nie robić wycieku pamięci - // poprzez nadpisanie + TController *drugi; // jakby były dwa, to zamienić miejscami, a nie robić wycieku pamięci poprzez nadpisanie auto const localbrakelevel { mvOccupied->LocalBrakePosA }; - while (mvControlling->MainCtrlPos) // samo zapętlenie DecSpeed() nie wystarcza :/ - DecSpeed(true); // wymuszenie zerowania nastawnika jazdy - while (mvOccupied->ActiveDir < 0) - mvOccupied->DirectionForward(); // kierunek na 0 - while (mvOccupied->ActiveDir > 0) - mvOccupied->DirectionBackward(); + ZeroSpeed(); + ZeroDirection(); if (TestFlag(d->MoverParameters->Couplers[iDirectionOrder < 0 ? 1 : 0].CouplingFlag, ctrain_controll)) { mvControlling->MainSwitch( false); // dezaktywacja czuwaka, jeśli przejście do innego członu mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca w opuszczanym pojeździe @@ -2396,7 +2391,7 @@ void TController::SetDriverPsyche() } if (mvControlling && mvOccupied) { // with Controlling do - if (mvControlling->MainCtrlPos < 3) + if (mvControlling->MainCtrlPowerPos() < 3) ReactionTime = mvControlling->InitialCtrlDelay + ReactionTime; if (mvOccupied->BrakeCtrlPos > 1) ReactionTime = 0.5 * ReactionTime; @@ -2493,17 +2488,16 @@ bool TController::PrepareEngine() { // część wykonawcza dla sterowania przez komputer if (mvControlling->ConvOvldFlag) { // wywalił bezpiecznik nadmiarowy przetwornicy - while (DecSpeed(true)) - ; // zerowanie napędu + ZeroSpeed(); mvControlling->ConvOvldFlag = false; // reset nadmiarowego } else if (false == IsLineBreakerClosed) { - while (DecSpeed(true)) - ; // zerowanie napędu + ZeroSpeed(); if( mvOccupied->TrainType == dt_SN61 ) { // specjalnie dla SN61 żeby nie zgasł - if( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn == 0 ) { - mvControlling->IncMainCtrl( 1 ); + while( ( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn == 0 ) + && ( mvControlling->IncMainCtrl( 1 ) ) ) { + ; } } if( ( mvControlling->EnginePowerSource.SourceType != TPowerSource::CurrentCollector ) @@ -2521,6 +2515,10 @@ bool TController::PrepareEngine() mvOccupied->MotorBlowersSwitch( true, end::front ); mvOccupied->MotorBlowersSwitchOff( false, end::rear ); mvOccupied->MotorBlowersSwitch( true, end::rear ); + // enable train brake if it's off + if( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_NP ) ) { + mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); + } } } else @@ -2558,9 +2556,7 @@ bool TController::ReleaseEngine() { VelDesired = 0.0; AccDesired = std::min( AccDesired, -1.25 ); // hamuj solidnie ReactionTime = 0.1; - while( DecSpeed( true ) ) { - ; // zerowanie nastawników - } + ZeroSpeed(); IncBrake(); // don't bother with the rest until we're standing still return false; @@ -2597,12 +2593,8 @@ bool TController::ReleaseEngine() { ; } } - while( DecSpeed( true ) ) { - ; // zerowanie nastawników - } - // set direction to neutral - while( ( mvOccupied->ActiveDir > 0 ) && ( mvOccupied->DirectionBackward() ) ) { ; } - while( ( mvOccupied->ActiveDir < 0 ) && ( mvOccupied->DirectionForward() ) ) { ; } + ZeroSpeed(); + ZeroDirection(); // zamykanie drzwi mvOccupied->OperateDoors( side::right, false ); @@ -2714,9 +2706,17 @@ bool TController::IncBrake() } } } + + standalone = standalone && ( mvControlling->EIMCtrlType == 0 ); + if( true == standalone ) { - OK = mvOccupied->IncLocalBrakeLevel( - 1 + static_cast( std::floor( 0.5 + std::fabs( AccDesired ) ) ) ); // hamowanie lokalnym bo luzem jedzie + if( mvControlling->EIMCtrlType > 0 ) { + OK = IncBrakeEIM(); + } + else { + OK = mvOccupied->IncLocalBrakeLevel( + 1 + static_cast( std::floor( 0.5 + std::fabs( AccDesired ) ) ) ); // hamowanie lokalnym bo luzem jedzie + } } else { if( mvOccupied->BrakeCtrlPos + 1 == mvOccupied->BrakeCtrlPosNo ) { @@ -2854,8 +2854,10 @@ bool TController::DecBrake() mvOccupied->BrakeLevelSet(0.0); } } - if (!OK) - OK = mvOccupied->DecLocalBrakeLevel(2); + if( !OK ) { + OK = DecBrakeEIM(); +// OK = mvOccupied->DecLocalBrakeLevel(2); + } if (mvOccupied->PipePress < 3.0) Need_BrakeRelease = true; break; @@ -2944,7 +2946,7 @@ bool TController::IncSpeed() return false; // to nici z ruszania } if (!mvControlling->FuseFlag) //&&mvControlling->StLinFlag) //yBARC - if ((mvControlling->MainCtrlPos == 0) || + if ((mvControlling->IsMainCtrlNoPowerPos()) || (mvControlling->StLinFlag)) // youBy polecił dodać 2012-09-08 v367 // na pozycji 0 przejdzie, a na pozostałych będzie czekać, aż się załączą liniowe (zgaśnie DelayCtrlFlag) if (Ready || (iDrivigFlags & movePress)) { @@ -3026,7 +3028,7 @@ bool TController::IncSpeed() } if( ( mvControlling->Im == 0 ) - && ( mvControlling->MainCtrlPos > 2 ) ) { + && ( mvControlling->MainCtrlPowerPos() > 1 ) ) { // brak prądu na dalszych pozycjach // nie załączona lokomotywa albo wywalił nadmiarowy Need_TryAgain = true; @@ -3094,6 +3096,13 @@ bool TController::IncSpeed() return OK; } +void TController::ZeroSpeed( bool const Enforce ) { + + while( DecSpeed( Enforce ) ) { + ; + } +} + bool TController::DecSpeed(bool force) { // zmniejszenie prędkości (ale nie hamowanie) bool OK = false; // domyślnie false, aby wyszło z pętli while @@ -3103,20 +3112,20 @@ bool TController::DecSpeed(bool force) iDrivigFlags &= ~moveIncSpeed; // usunięcie flagi jazdy if (force) // przy aktywacji kabiny jest potrzeba natychmiastowego wyzerowania if (mvControlling->MainCtrlPosNo > 0) // McZapkie-041003: wagon sterowniczy, np. EZT - mvControlling->DecMainCtrl(1 + (mvControlling->MainCtrlPos > 2 ? 1 : 0)); + mvControlling->DecMainCtrl((mvControlling->MainCtrlPowerPos() > 1 ? 2 : 1)); mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania return false; case TEngineType::ElectricSeriesMotor: OK = mvControlling->DecScndCtrl(2); // najpierw bocznik na zero if (!OK) - OK = mvControlling->DecMainCtrl(1 + (mvControlling->MainCtrlPos > 2 ? 1 : 0)); + OK = mvControlling->DecMainCtrl((mvControlling->MainCtrlPowerPos() > 1 ? 2 : 1)); mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania break; case TEngineType::Dumb: case TEngineType::DieselElectric: OK = mvControlling->DecScndCtrl(2); if (!OK) - OK = mvControlling->DecMainCtrl(2 + (mvControlling->MainCtrlPos / 2)); + OK = mvControlling->DecMainCtrl(2 + (mvControlling->MainCtrlPowerPos() / 2)); break; case TEngineType::ElectricInductionMotor: OK = DecSpeedEIM(); @@ -3135,12 +3144,14 @@ bool TController::DecSpeed(bool force) if (mvControlling->RList[mvControlling->MainCtrlPos].Mn > 0) OK = mvControlling->DecMainCtrl(1); } - else - while ((mvControlling->RList[mvControlling->MainCtrlPos].Mn > 0) && - (mvControlling->MainCtrlPos > 1)) - OK = mvControlling->DecMainCtrl(1); + else { + while( ( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn > 0 ) + && ( mvControlling->MainCtrlPowerPos() > 1 ) ) { + OK = mvControlling->DecMainCtrl( 1 ); + } + } if (force) // przy aktywacji kabiny jest potrzeba natychmiastowego wyzerowania - OK = mvControlling->DecMainCtrl(1 + (mvControlling->MainCtrlPos > 2 ? 1 : 0)); + OK = mvControlling->DecMainCtrl((mvControlling->MainCtrlPowerPos() > 2 ? 2 : 1)); break; } return OK; @@ -3240,8 +3251,7 @@ void TController::SpeedSet() if( ( false == mvControlling->StLinFlag ) && ( false == mvControlling->DelayCtrlFlag ) ) { // styczniki liniowe rozłączone yBARC - while( DecSpeed() ) - ; // zerowanie napędu + ZeroSpeed(); } else if (Ready || (iDrivigFlags & movePress)) // o ile może jechać if (fAccGravity < -0.10) // i jedzie pod górę większą niż 10 promil @@ -4104,9 +4114,14 @@ TController::UpdateSituation(double dt) { // TODO: check if this situation still happens and the hack is still needed if( ( false == AIControllFlag ) && ( iDrivigFlags & moveDoorOpened ) - && ( mvOccupied->Doors.close_control != control_t::driver ) - && ( mvControlling->MainCtrlPos > ( mvControlling->EngineType != TEngineType::DieselEngine ? 0 : 1 ) ) ) { // for diesel 1st position is effectively 0 - Doors( false ); + && ( mvOccupied->Doors.close_control != control_t::driver ) ) { + // for diesel engines react when engine is put past idle revolutions + // for others straightforward master controller check + if( ( mvControlling->EngineType == TEngineType::DieselEngine ? + mvControlling->RList[ mvControlling->MainCtrlPos ].Mn > 0 : + mvControlling->MainCtrlPowerPos() > 0 ) ) { + Doors( false ); + } } // basic situational ai operations @@ -4167,7 +4182,7 @@ TController::UpdateSituation(double dt) { // is moving if( ( fOverhead2 >= 0.0 ) || iOverheadZero ) { // jeśli jazda bezprądowa albo z opuszczonym pantografem - while( DecSpeed( true ) ) { ; } // zerowanie napędu + ZeroSpeed(); } if( ( fOverhead2 > 0.0 ) || iOverheadDown ) { // jazda z opuszczonymi pantografami @@ -4263,7 +4278,7 @@ TController::UpdateSituation(double dt) { if( ( true == TestFlag( iDrivigFlags, moveStartHornNow ) ) && ( true == Ready ) && ( iEngineActive != 0 ) - && ( mvControlling->MainCtrlPos > 0 ) ) { + && ( mvControlling->MainCtrlPowerPos() > 0 ) ) { // uruchomienie trąbienia przed ruszeniem fWarningDuration = 0.3; // czas trąbienia mvOccupied->WarningSignal = pVehicle->iHornWarning; // wysokość tonu (2=wysoki) @@ -4783,7 +4798,7 @@ TController::UpdateSituation(double dt) { // jeśli dociskanie w celu odczepienia // 3. faza odczepiania. SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2 - if( ( mvControlling->MainCtrlPos > 0 ) + if( ( mvControlling->MainCtrlPowerPos() > 0 ) || ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) { // jeśli jazda WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute)); @@ -4874,16 +4889,15 @@ TController::UpdateSituation(double dt) { if (iDrivigFlags & movePress) { // 4. faza odczepiania: zwolnij i zmień kierunek SetVelocity(0, 0, stopJoin); // wyłączyć przyspieszanie - if (!DecSpeed()) // jeśli już bardziej wyłączyć się nie da - { // ponowna zmiana kierunku - WriteLog( mvOccupied->Name + " ponowna zmiana kierunku" ); - DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na właściwy - iDrivigFlags &= ~movePress; // koniec dociskania - JumpToNextOrder(); // zmieni światła - TableClear(); // skanowanie od nowa - iDrivigFlags &= ~moveStartHorn; // bez trąbienia przed ruszeniem - SetVelocity(fShuntVelocity, fShuntVelocity); // ustawienie prędkości jazdy - } + ZeroSpeed(); + // ponowna zmiana kierunku + WriteLog( mvOccupied->Name + " ponowna zmiana kierunku" ); + DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na właściwy + iDrivigFlags &= ~movePress; // koniec dociskania + JumpToNextOrder(); // zmieni światła + TableClear(); // skanowanie od nowa + iDrivigFlags &= ~moveStartHorn; // bez trąbienia przed ruszeniem + SetVelocity(fShuntVelocity, fShuntVelocity); // ustawienie prędkości jazdy } } @@ -5449,7 +5463,7 @@ TController::UpdateSituation(double dt) { if( ( true == mvOccupied->RadioStopFlag ) // radio-stop && ( mvOccupied->Vel > 0.0 ) ) { // and still moving // if the radio-stop was issued don't waste effort trying to fight it - while( true == DecSpeed() ) { ; } // just throttle down... + ZeroSpeed(); // just throttle down... return; // ...and don't touch any other controls } @@ -5613,7 +5627,7 @@ TController::UpdateSituation(double dt) { if( false == TestFlag( iDrivigFlags, movePress ) ) { // jeśli nie dociskanie if( AccDesired < -0.05 ) { - while( true == DecSpeed() ) { ; } // jeśli hamujemy, to nie przyspieszamy + ZeroSpeed(); } else if( ( vel > VelDesired ) || ( fAccGravity < -0.01 ? @@ -6402,21 +6416,35 @@ void TController::TakeControl(bool yes) void TController::DirectionForward(bool forward) { // ustawienie jazdy do przodu dla true i do tyłu dla false (zależy od kabiny) - while (mvControlling->MainCtrlPos) // samo zapętlenie DecSpeed() nie wystarcza - DecSpeed(true); // wymuszenie zerowania nastawnika jazdy, inaczej się może zawiesić - if (forward) - while (mvOccupied->ActiveDir <= 0) - mvOccupied->DirectionForward(); // do przodu w obecnej kabinie - else - while (mvOccupied->ActiveDir >= 0) - mvOccupied->DirectionBackward(); // do tyłu w obecnej kabinie - if( mvOccupied->TrainType == dt_SN61 ) { - // specjalnie dla SN61 żeby nie zgasł - if( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn == 0 ) { - mvControlling->IncMainCtrl( 1 ); + ZeroSpeed( true ); // TODO: check if force switch is needed anymore here + if( forward ) { + // do przodu w obecnej kabinie + while( ( mvOccupied->ActiveDir <= 0 ) + && ( mvOccupied->DirectionForward() ) ) { + ; // all work is done in the header } } -}; + else { + // do tyłu w obecnej kabinie + while( ( mvOccupied->ActiveDir >= 0 ) + && ( mvOccupied->DirectionBackward() ) ) { + ; // all work is done in the header + } + } + if( mvOccupied->TrainType == dt_SN61 ) { + // specjalnie dla SN61 żeby nie zgasł + while( ( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn == 0 ) + && ( mvControlling->IncMainCtrl( 1 ) ) ) { + ; // all work is done in the header + } + } +} + +void TController::ZeroDirection() { + + while( ( mvOccupied->ActiveDir > 0 ) && ( mvOccupied->DirectionBackward() ) ) { ; } + while( ( mvOccupied->ActiveDir < 0 ) && ( mvOccupied->DirectionForward() ) ) { ; } +} Mtable::TTrainParameters const * TController::TrainTimetable() const { diff --git a/Driver.h b/Driver.h index e1b29651..0c0188e4 100644 --- a/Driver.h +++ b/Driver.h @@ -211,6 +211,7 @@ private: bool DecBrake(); bool IncSpeed(); bool DecSpeed(bool force = false); + void ZeroSpeed( bool const Enforce = false ); bool IncBrakeEIM(); bool DecBrakeEIM(); bool IncSpeedEIM(); @@ -224,6 +225,7 @@ private: int CheckDirection(); void WaitingSet(double Seconds); void DirectionForward(bool forward); + void ZeroDirection(); int OrderDirectionChange(int newdir, TMoverParameters *Vehicle); void Lights(int head, int rear); std::string StopReasonText() const; diff --git a/DynObj.cpp b/DynObj.cpp index 3e449752..d17294c3 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -1591,6 +1591,8 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424" Error("Parameters mismatch: dynamic object " + asName + " from \"" + BaseDir + "/" + Type_Name + "\"" ); return 0.0; // zerowa długość to brak pojazdu } + // controller position + MoverParameters->MainCtrlPos = MoverParameters->MainCtrlNoPowerPos(); // ustawienie pozycji hamulca MoverParameters->LocalBrakePosA = 0.0; if (driveractive) @@ -2298,6 +2300,8 @@ void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int co } } */ + if( Platform == 0 ) { return; } // edge case, if there's no accessible platforms discard the request + m_exchange.unload_count += Disembark; m_exchange.load_count += Embark; m_exchange.platforms = Platform; @@ -2967,7 +2971,7 @@ bool TDynamicObject::Update(double dt, double dt1) } MEDLogTime += dt1; - if ((MoverParameters->Vel < 0.1) || (MoverParameters->MainCtrlPos > 0)) + if ((MoverParameters->Vel < 0.1) || (MoverParameters->MainCtrlPowerPos() > 0)) { MEDLogInactiveTime += dt1; } @@ -4067,7 +4071,7 @@ void TDynamicObject::RenderSounds() { else { // basic clash couplersounds.dsbBufferClamp - .gain( 0.65f ) + .gain( 1.f ) .play( sound_flags::exclusive ); } } @@ -4092,7 +4096,7 @@ void TDynamicObject::RenderSounds() { else { // basic clash couplersounds.dsbCouplerStretch - .gain( 0.65f ) + .gain( 1.f ) .play( sound_flags::exclusive ); } } diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 0c8be69f..782c9fd2 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -980,12 +980,13 @@ public: double TUHEX_Sum2 = 750; /*nastawa2 sterownika hamowania ED*/ double TUHEX_Sum3 = 750; /*nastawa3 sterownika hamowania ED*/ int TUHEX_Stages = 0; /*liczba stopni hamowania ED*/ - + // TODO: wrap resistor fans variables and state into a device int RVentType = 0; /*0 - brak, 1 - jest, 2 - automatycznie wlaczany*/ double RVentnmax = 1.0; /*maks. obroty wentylatorow oporow rozruchowych*/ double RVentCutOff = 0.0; /*rezystancja wylaczania wentylatorow dla RVentType=2*/ double RVentSpeed { 0.5 }; //rozpedzanie sie wentylatora obr/s^2} double RVentMinI { 50.0 }; //przy jakim pradzie sie wylaczaja} + bool RVentForceOn { false }; // forced activation switch int CompressorPower = 1; // 0: main circuit, 1: z przetwornicy, reczne, 2: w przetwornicy, stale, 3: diesel engine, 4: converter of unit in front, 5: converter of unit behind int SmallCompressorPower = 0; /*Winger ZROBIC*/ bool Trafo = false; /*pojazd wyposażony w transformator*/ @@ -1207,6 +1208,7 @@ public: int LightsPos = 0; int ActiveDir = 0; //czy lok. jest wlaczona i w ktorym kierunku: //względem wybranej kabiny: -1 - do tylu, +1 - do przodu, 0 - wylaczona + int MaxMainCtrlPosNoDirChange { 0 }; // can't change reverser state with master controller set above this position int CabNo = 0; //numer kabiny, z której jest sterowanie: 1 lub -1; w przeciwnym razie brak sterowania - rozrzad int DirAbsolute = 0; //zadany kierunek jazdy względem sprzęgów (1=w strone 0,-1=w stronę 1) int ActiveCab = 0; //numer kabiny, w ktorej jest obsada (zwykle jedna na skład) @@ -1355,6 +1357,7 @@ public: int DettachStatus(int ConnectNo); bool Dettach(int ConnectNo); bool DirectionForward(); + bool DirectionBackward( void );/*! kierunek ruchu*/ void BrakeLevelSet(double b); bool BrakeLevelAdd(double b); bool IncBrakeLevel(); // wersja na użytek AI @@ -1391,6 +1394,9 @@ public: /*! glowny nastawnik:*/ bool IncMainCtrl(int CtrlSpeed); bool DecMainCtrl(int CtrlSpeed); + bool IsMainCtrlNoPowerPos() const; // whether the master controller is set to position which won't generate any extra power + int MainCtrlNoPowerPos() const; // highest setting of master controller which won't cause engine to generate extra power + int MainCtrlPowerPos() const; // current setting of master controller, relative to the highest setting not generating extra power /*! pomocniczy nastawnik:*/ bool IncScndCtrl(int CtrlSpeed); bool DecScndCtrl(int CtrlSpeed); @@ -1454,7 +1460,6 @@ public: double ComputeRotatingWheel(double WForce, double dt, double n) const; /*--funkcje dla lokomotyw*/ - bool DirectionBackward(void);/*! kierunek ruchu*/ bool WaterPumpBreakerSwitch( bool State, range_t const Notify = range_t::consist ); // water pump breaker state toggle bool WaterPumpSwitch( bool State, range_t const Notify = range_t::consist ); // water pump state toggle bool WaterPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // water pump state toggle @@ -1578,6 +1583,7 @@ private: bool readLightsList( std::string const &Input ); void BrakeValveDecode( std::string const &s ); //Q 20160719 void BrakeSubsystemDecode(); //Q 20160719 + bool EIMDirectionChangeAllow( void ); }; //double Distance(TLocation Loc1, TLocation Loc2, TDimension Dim1, TDimension Dim2); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 56f1e9b2..db89fbf7 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -502,7 +502,7 @@ bool TMoverParameters::Dettach(int ConnectNo) bool TMoverParameters::DirectionForward() { - if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (MainCtrlPos == 0)) + if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (MainCtrlPos <= MaxMainCtrlPosNoDirChange) && (EIMDirectionChangeAllow())) { ++ActiveDir; DirAbsolute = ActiveDir * CabNo; @@ -512,7 +512,7 @@ bool TMoverParameters::DirectionForward() SendCtrlToNext("Direction", ActiveDir, CabNo); return true; } - else if ((ActiveDir == 1) && (MainCtrlPos == 0) && (TrainType == dt_EZT) && (EngineType != TEngineType::ElectricInductionMotor)) + else if ((ActiveDir == 1) && (IsMainCtrlNoPowerPos()) && (TrainType == dt_EZT) && (EngineType != TEngineType::ElectricInductionMotor)) return MinCurrentSwitch(true); //"wysoki rozruch" EN57 return false; }; @@ -641,7 +641,7 @@ TMoverParameters::CurrentSwitch(bool const State) { // for SM42/SP42 if( ( EngineType == TEngineType::DieselElectric ) && ( true == ShuntModeAllow ) - && ( MainCtrlPos == 0 ) ) { + && ( IsMainCtrlNoPowerPos() ) ) { ShuntMode = State; return true; } @@ -1732,17 +1732,17 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed) case TEngineType::DieselEngine: { - if( CtrlSpeed > 1 ) { - while( MainCtrlPos < MainCtrlPosNo ) { - IncMainCtrl( 1 ); + if( CtrlSpeed > 1 ) { + while( ( MainCtrlPos < MainCtrlPosNo ) + && ( IncMainCtrl( 1 ) ) ) { + ; + } } + else { + ++MainCtrlPos; } - else { - ++MainCtrlPos; - if( MainCtrlPos > 0 ) { CompressorAllow = true; } - else { CompressorAllow = false; } - } - OK = true; + CompressorAllow = ( MainCtrlPowerPos() > 0 ); + OK = true; break; } @@ -1805,6 +1805,7 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed) } else { + // TBD, TODO: replace with mainctrlpowerpos() check? if (MainCtrlPos > 0) { if ((TrainType != dt_ET22) || @@ -1903,6 +1904,25 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed) return OK; } +bool TMoverParameters::IsMainCtrlNoPowerPos() const { + // TODO: wrap controller pieces into a class for potential specializations, similar to brake subsystems + return MainCtrlPos <= MainCtrlNoPowerPos(); +} + +int TMoverParameters::MainCtrlNoPowerPos() const { + + switch( EIMCtrlType ) { + case 1: { return 3; } + case 2: { return 3; } + default: { return 0; } + } +} + +int TMoverParameters::MainCtrlPowerPos() const { + + return MainCtrlPos - MainCtrlNoPowerPos(); +} + // ************************************************************************************************* // Q: 20160710 // zwiększenie bocznika @@ -1911,14 +1931,13 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) { bool OK = false; - if ((MainCtrlPos == 0) && (CabNo != 0) && (TrainType == dt_ET42) && (ScndCtrlPos == 0) && - (DynamicBrakeFlag)) + if ((IsMainCtrlNoPowerPos()) && (CabNo != 0) && (TrainType == dt_ET42) && (ScndCtrlPos == 0) && (DynamicBrakeFlag)) { OK = DynamicBrakeSwitch(false); } else if ((ScndCtrlPosNo > 0) && (CabNo != 0) && !((TrainType == dt_ET42) && - ((Imax == ImaxHi) || ((DynamicBrakeFlag) && (MainCtrlPos > 0))))) + ((Imax == ImaxHi) || ((DynamicBrakeFlag) && (MainCtrlPowerPos() > 0))))) { // if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (ScndCtrlPos0 @@ -2326,7 +2345,7 @@ bool TMoverParameters::DirectionBackward(void) DB = true; // return DB; // exit; TODO: czy dobrze przetlumaczone? } - if ((MainCtrlPosNo > 0) && (ActiveDir > -1) && (MainCtrlPos == 0)) + if ((MainCtrlPosNo > 0) && (ActiveDir > -1) && (MainCtrlPos <= MaxMainCtrlPosNoDirChange) && (EIMDirectionChangeAllow())) { if (EngineType == TEngineType::WheelsDriven) CabNo--; @@ -2344,6 +2363,13 @@ bool TMoverParameters::DirectionBackward(void) return DB; } +bool TMoverParameters::EIMDirectionChangeAllow(void) +{ + bool OK = false; + OK = (EngineType != TEngineType::ElectricInductionMotor || ((eimic <= 0) && (eimic_real <= 0) && (Vel < 0.1))); + return OK; +} + // ************************************************************************************************* // Q: 20160710 // załączenie przycisku przeciwpoślizgowego @@ -2946,7 +2972,7 @@ bool TMoverParameters::DynamicBrakeSwitch(bool Switch) { bool DBS; - if ((DynamicBrakeType == dbrake_switch) && (MainCtrlPos == 0)) + if ((DynamicBrakeType == dbrake_switch) && (IsMainCtrlNoPowerPos())) { DynamicBrakeFlag = Switch; DBS = true; @@ -3240,7 +3266,7 @@ void TMoverParameters::CompressorCheck(double dt) if( ( true == CompressorAllow ) && ( true == CompressorAllowLocal ) && ( true == Mains ) - && ( MainCtrlPos > 0 ) ) { + && ( MainCtrlPowerPos() > 0 ) ) { if( Compressor < MaxCompressor ) { if( ( EngineType == TEngineType::DieselElectric ) && ( CompressorPower > 0 ) ) { @@ -4400,8 +4426,9 @@ double TMoverParameters::TractionForce( double dt ) { switch( RVentType ) { case 1: { // manual - if( ( ActiveDir != 0 ) - && ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) { + if( ( true == RVentForceOn ) + || ( ( ActiveDir != 0 ) + && ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) ) { RventRot += ( RVentnmax - RventRot ) * RVentSpeed * dt; } else { @@ -4423,9 +4450,12 @@ double TMoverParameters::TractionForce( double dt ) { * RVentSpeed * dt; } else if( ( DynamicBrakeType == dbrake_automatic ) - && ( true == DynamicBrakeFlag ) ) { + && ( true == DynamicBrakeFlag ) ) { RventRot += ( RVentnmax * motorcurrent / ImaxLo - RventRot ) * RVentSpeed * dt; } + else if( RVentForceOn ) { + RventRot += ( RVentnmax - RventRot ) * RVentSpeed * dt; + } else { RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt ); } @@ -4485,7 +4515,7 @@ double TMoverParameters::TractionForce( double dt ) { } case TEngineType::DieselEngine: { EnginePower = ( 2 * dizel_Mstand + dmoment ) * enrot * ( 2.0 * M_PI / 1000.0 ); - if( MainCtrlPos > 1 ) { + if( MainCtrlPowerPos() > 1 ) { // dodatkowe opory z powodu sprezarki} dmoment -= dizel_Mstand * ( 0.2 * enrot / dizel_nmax ); } @@ -4682,7 +4712,7 @@ double TMoverParameters::TractionForce( double dt ) { auto const tmpV { nrot * Pirazy2 * 0.5 * WheelDiameter * DirAbsolute }; //*CabNo*ActiveDir; // jazda manewrowa if( true == ShuntMode ) { - if( ( true == Mains ) && ( MainCtrlPos > 0 ) ) { + if( ( true == Mains ) && ( MainCtrlPowerPos() > 0 ) ) { Voltage = ( SST[ MainCtrlPos ].Umax * AnPos ) + ( SST[ MainCtrlPos ].Umin * ( 1.0 - AnPos ) ); // NOTE: very crude way to approximate power generated at current rpm instead of instant top output // NOTE, TODO: doesn't take into account potentially increased revolutions if heating is on, fix it @@ -4713,7 +4743,7 @@ double TMoverParameters::TractionForce( double dt ) { PosRatio = currentgenpower / DElist[MainCtrlPosNo].GenPower; // stosunek mocy teraz do mocy max // NOTE: Mains in this context is working diesel engine - if( ( true == Mains ) && ( MainCtrlPos > 0 ) ) { + if( ( true == Mains ) && ( MainCtrlPowerPos() > 0 ) ) { if( tmpV < ( Vhyp * power / DElist[ MainCtrlPosNo ].GenPower ) ) { // czy na czesci prostej, czy na hiperboli @@ -4815,7 +4845,7 @@ double TMoverParameters::TractionForce( double dt ) { Voltage = 0; // przekazniki bocznikowania, kazdy inny dla kazdej pozycji - if ((MainCtrlPos == 0) || (ShuntMode) || (false==Mains)) + if ((IsMainCtrlNoPowerPos()) || (ShuntMode) || (false==Mains)) ScndCtrlPos = 0; else { @@ -5298,7 +5328,7 @@ bool TMoverParameters::FuseFlagCheck(void) const bool TMoverParameters::FuseOn(void) { bool FO = false; - if ((MainCtrlPos == 0) && (ScndCtrlPos == 0) && (TrainType != dt_ET40) && + if ((IsMainCtrlNoPowerPos()) && (ScndCtrlPos == 0) && (TrainType != dt_ET40) && ((Mains) || (TrainType != dt_EZT)) && (!TestFlag(EngDmgFlag, 1))) { // w ET40 jest blokada nastawnika, ale czy działa dobrze? SendCtrlToNext("FuseSwitch", 1, CabNo); @@ -5786,7 +5816,7 @@ bool TMoverParameters::MotorConnectorsCheck() { ( false == Mains ) || ( true == FuseFlag ) || ( true == StLinSwitchOff ) - || ( MainCtrlPos == 0 ) + || ( IsMainCtrlNoPowerPos() ) || ( ActiveDir == 0 ) }; if( connectorsoff ) { return false; } @@ -5794,8 +5824,9 @@ bool TMoverParameters::MotorConnectorsCheck() { auto const connectorson { ( true == StLinFlag ) || ( ( MainCtrlActualPos == 0 ) - && ( ( MainCtrlPos == 1 ) - || ( ( TrainType == dt_EZT ) && ( MainCtrlPos > 0 ) ) ) ) }; + && ( ( TrainType != dt_EZT ? + MainCtrlPowerPos() == 1 : + MainCtrlPowerPos() > 0 ) ) ) }; return connectorson; } @@ -6043,7 +6074,7 @@ bool TMoverParameters::dizel_AutoGearCheck(void) { if (dizel_engagestate > 0) dizel_EngageSwitch(0); - if ((MainCtrlPos == 0) && (ScndCtrlActualPos > 0)) + if ((IsMainCtrlNoPowerPos()) && (ScndCtrlActualPos > 0)) dizel_automaticgearstatus = -1; } else @@ -6131,12 +6162,13 @@ bool TMoverParameters::dizel_StartupCheck() { // test the fuel pump // TODO: add fuel pressure check - if( false == FuelPump.is_active ) { + if( ( false == FuelPump.is_active ) + || ( ( EngineType == TEngineType::DieselEngine ) && ( RList[ MainCtrlPos ].R == 0.0 ) ) ) { engineisready = false; - if( FuelPump.start_type == start_t::manual ) { +// if( FuelPump.start_type == start_t::manual ) { // with manual pump control startup procedure is done only once per starter switch press dizel_startup = false; - } +// } } // test the oil pump if( ( false == OilPump.is_active ) @@ -6326,10 +6358,10 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt) if (hydro_TC) //jesli przetwornik momentu { //napelnianie przetwornika - if ((MainCtrlPos > 0) && (Mains) && (enrot>dizel_nmin*0.9)) + if ((MainCtrlPowerPos() > 0) && (Mains) && (enrot>dizel_nmin*0.9)) hydro_TC_Fill += hydro_TC_FillRateInc * dt; //oproznianie przetwornika - if (((MainCtrlPos == 0) && (Vel<3)) + if (((IsMainCtrlNoPowerPos()) && (Vel<3)) || (!Mains) || (enrot hydro_TC_LockupSpeed) && (Mains) && (enrot > 0.9 * dizel_nmin) && (MainCtrlPos>0)) + if ((Vel > hydro_TC_LockupSpeed) && (Mains) && (enrot > 0.9 * dizel_nmin) && (MainCtrlPowerPos() > 0)) hydro_TC_LockupRate += hydro_TC_FillRateInc*dt; //luzowanie sprzegla blokujacego - if ((Vel < (MainCtrlPos>0 ? hydro_TC_LockupSpeed : hydro_TC_UnlockSpeed)) || (!Mains) || (enrot < 0.8 * dizel_nmin)) + if ((Vel < (MainCtrlPowerPos() > 0 ? hydro_TC_LockupSpeed : hydro_TC_UnlockSpeed)) || (!Mains) || (enrot < 0.8 * dizel_nmin)) hydro_TC_LockupRate -= hydro_TC_FillRateDec*dt; //obcinanie zakresu hydro_TC_LockupRate = clamp(hydro_TC_LockupRate, 0.0, 1.0); @@ -8495,6 +8527,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { extract_value( MainCtrlPosNo, "MCPN", line, "" ); extract_value( ScndCtrlPosNo, "SCPN", line, "" ); extract_value( ScndInMain, "SCIM", line, "" ); + extract_value( MaxMainCtrlPosNoDirChange, "DirChangeMaxPos", line, "" ); std::string autorelay; extract_value( autorelay, "AutoRelay", line, "" ); diff --git a/Train.cpp b/Train.cpp index d1b77982..41c0416a 100644 --- a/Train.cpp +++ b/Train.cpp @@ -170,6 +170,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::secondcontrollerdecreasefast, &TTrain::OnCommand_secondcontrollerdecreasefast }, { user_command::secondcontrollerset, &TTrain::OnCommand_secondcontrollerset }, { user_command::notchingrelaytoggle, &TTrain::OnCommand_notchingrelaytoggle }, + { user_command::tempomattoggle, &TTrain::OnCommand_tempomattoggle }, { user_command::mucurrentindicatorothersourceactivate, &TTrain::OnCommand_mucurrentindicatorothersourceactivate }, { user_command::independentbrakeincrease, &TTrain::OnCommand_independentbrakeincrease }, { user_command::independentbrakeincreasefast, &TTrain::OnCommand_independentbrakeincreasefast }, @@ -262,6 +263,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::motorblowerstogglefront, &TTrain::OnCommand_motorblowerstogglefront }, { user_command::motorblowerstogglerear, &TTrain::OnCommand_motorblowerstogglerear }, { user_command::motorblowersdisableall, &TTrain::OnCommand_motorblowersdisableall }, + { user_command::coolingfanstoggle, &TTrain::OnCommand_coolingfanstoggle }, { user_command::motorconnectorsopen, &TTrain::OnCommand_motorconnectorsopen }, { user_command::motorconnectorsclose, &TTrain::OnCommand_motorconnectorsclose }, { user_command::motordisconnect, &TTrain::OnCommand_motordisconnect }, @@ -780,8 +782,8 @@ void TTrain::OnCommand_jointcontrollerset( TTrain *Train, command_data const &Co clamp( 1.0 - ( Command.param1 * 2 ), 0.0, 1.0 ) ); - if( Train->mvControlled->MainCtrlPos > 0 ) { - Train->set_master_controller( 0 ); + if( Train->mvControlled->MainCtrlPowerPos() > 0 ) { + Train->set_master_controller( Train->mvControlled->MainCtrlNoPowerPos() ); } } } @@ -837,7 +839,7 @@ void TTrain::OnCommand_mastercontrollerdecrease( TTrain *Train, command_data con if( Command.action != GLFW_RELEASE ) { // on press or hold if( ( Train->ggJointCtrl.SubModel != nullptr ) - && ( Train->mvControlled->MainCtrlPos == 0 ) ) { + && ( Train->mvControlled->IsMainCtrlNoPowerPos() ) ) { OnCommand_independentbrakeincrease( Train, Command ); } else { @@ -857,7 +859,7 @@ void TTrain::OnCommand_mastercontrollerdecreasefast( TTrain *Train, command_data if( Command.action != GLFW_RELEASE ) { // on press or hold if( ( Train->ggJointCtrl.SubModel != nullptr ) - && ( Train->mvControlled->MainCtrlPos == 0 ) ) { + && ( Train->mvControlled->IsMainCtrlNoPowerPos() ) ) { OnCommand_independentbrakeincreasefast( Train, Command ); } else { @@ -931,6 +933,45 @@ void TTrain::OnCommand_notchingrelaytoggle( TTrain *Train, command_data const &C } } +void TTrain::OnCommand_tempomattoggle( TTrain *Train, command_data const &Command ) { + + if( Command.action == GLFW_REPEAT ) { return; } + + if( Train->ggScndCtrlButton.type() == TGaugeType::push ) { + // impulse switch + if( Command.action == GLFW_RELEASE ) { + // just move the button back to default position + // visual feedback + Train->ggScndCtrlButton.UpdateValue( 0.0, Train->dsbSwitch ); + return; + } + // glfw_press + if( Train->mvControlled->ScndCtrlPos == 0 ) { + // turn on if needed + Train->mvControlled->IncScndCtrl( 1 ); + } + // visual feedback + Train->ggScndCtrlButton.UpdateValue( 1.0, Train->dsbSwitch ); + } + else { + // two-state switch + if( Command.action == GLFW_RELEASE ) { return; } + + if( Train->mvControlled->ScndCtrlPos == 0 ) { + // turn on + Train->mvControlled->IncScndCtrl( 1 ); + // visual feedback + Train->ggScndCtrlButton.UpdateValue( 1.0, Train->dsbSwitch ); + } + else { + //turn off + Train->mvControlled->DecScndCtrl( 2 ); + // visual feedback + Train->ggScndCtrlButton.UpdateValue( 0.0, Train->dsbSwitch ); + } + } +} + void TTrain::OnCommand_mucurrentindicatorothersourceactivate( TTrain *Train, command_data const &Command ) { if( Train->ggNextCurrentButton.SubModel == nullptr ) { @@ -3059,6 +3100,13 @@ void TTrain::OnCommand_motorblowersdisableall( TTrain *Train, command_data const } } +void TTrain::OnCommand_coolingfanstoggle( TTrain *Train, command_data const &Command ) { + + if( Command.action != GLFW_PRESS ) { return; } + + Train->mvControlled->RVentForceOn = ( !Train->mvControlled->RVentForceOn ); +} + void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &Command ) { // TODO: don't rely on presense of 3d model to determine presence of the switch @@ -5189,10 +5237,10 @@ bool TTrain::Update( double const Deltatime ) fPress[i][0] = p->MoverParameters->BrakePress; fPress[i][1] = p->MoverParameters->PipePress; fPress[i][2] = p->MoverParameters->ScndPipePress; - bDoors[i][1] = ( false == p->MoverParameters->Doors.instances[ side::left ].is_closed ); - bDoors[i][2] = ( false == p->MoverParameters->Doors.instances[ side::right ].is_closed ); - bDoors[i][3] = ( p->MoverParameters->Doors.instances[ side::left ].step_position > 0.0 ); - bDoors[i][4] = ( p->MoverParameters->Doors.instances[ side::right ].step_position > 0.0 ); + bDoors[i][1] = ( p->MoverParameters->Doors.instances[ side::left ].position > 0.f ); + bDoors[i][2] = ( p->MoverParameters->Doors.instances[ side::right ].position > 0.f ); + bDoors[i][3] = ( p->MoverParameters->Doors.instances[ side::left ].step_position > 0.f ); + bDoors[i][4] = ( p->MoverParameters->Doors.instances[ side::right ].step_position > 0.f ); bDoors[i][0] = ( bDoors[i][1] || bDoors[i][2] ); iDoorNo[i] = p->iAnimType[ANIM_DOORS]; iUnits[i] = iUnitNo; @@ -5459,7 +5507,12 @@ bool TTrain::Update( double const Deltatime ) } if (ggIgnitionKey.SubModel) { - ggIgnitionKey.UpdateValue(mvControlled->dizel_startup); + ggIgnitionKey.UpdateValue( + ( mvControlled->Mains ) + || ( mvControlled->dizel_startup ) + || ( fMainRelayTimer > 0.f ) + || ( ggMainButton.GetDesiredValue() > 0.95 ) + || ( ggMainOnButton.GetDesiredValue() > 0.95 ) ); ggIgnitionKey.Update(); } } @@ -5670,6 +5723,7 @@ bool TTrain::Update( double const Deltatime ) // others btLampkaMalfunction.Turn( mvControlled->dizel_heat.PA ); btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ end::front ].is_active ) && ( mvControlled->MotorBlowers[ end::rear ].is_active ) ); + btLampkaCoolingFans.Turn( mvControlled->RventRot > 1.0 ); // universal devices state indicators for( auto idx = 0; idx < btUniversals.size(); ++idx ) { btUniversals[ idx ].Turn( ggUniversals[ idx ].GetValue() > 0.5 ); @@ -5730,6 +5784,7 @@ bool TTrain::Update( double const Deltatime ) // others btLampkaMalfunction.Turn( false ); btLampkaMotorBlowers.Turn( false ); + btLampkaCoolingFans.Turn( false ); // universal devices state indicators for( auto &universal : btUniversals ) { universal.Turn( false ); @@ -5868,6 +5923,7 @@ bool TTrain::Update( double const Deltatime ) dsbNastawnikBocz ); ggScndCtrl.Update(); } + ggScndCtrlButton.Update(); if (ggDirKey.SubModel) { if (mvControlled->TrainType != dt_EZT) ggDirKey.UpdateValue( @@ -7193,6 +7249,7 @@ void TTrain::clear_cab_controls() ggMainCtrl.Clear(); ggMainCtrlAct.Clear(); ggScndCtrl.Clear(); + ggScndCtrlButton.Clear(); ggDirKey.Clear(); ggBrakeCtrl.Clear(); ggLocalBrake.Clear(); @@ -7365,6 +7422,7 @@ void TTrain::clear_cab_controls() btLampkaMalfunction.Clear(); btLampkaMalfunctionB.Clear(); btLampkaMotorBlowers.Clear(); + btLampkaCoolingFans.Clear(); ggLeftLightButton.Clear(); ggRightLightButton.Clear(); @@ -7661,6 +7719,13 @@ void TTrain::set_cab_controls( int const Cab ) { 1.f : 0.f ); } + // tempomat + if( ggScndCtrlButton.type() != TGaugeType::push ) { + ggScndCtrlButton.PutValue( + ( mvControlled->ScndCtrlPos > 0 ) ? + 1.f : + 0.f ); + } // 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 @@ -7702,6 +7767,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co { "i-highcurrent:", btLampkaWysRozr }, { "i-vent_trim:", btLampkaWentZaluzje }, { "i-motorblowers:", btLampkaMotorBlowers }, + { "i-coolingfans:", btLampkaCoolingFans }, { "i-trainheating:", btLampkaOgrzewanieSkladu }, { "i-security_aware:", btLampkaCzuwaka }, { "i-security_cabsignal:", btLampkaSHP }, @@ -7919,6 +7985,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "cablight_sw:", ggCabLightButton }, { "cablightdim_sw:", ggCabLightDimButton }, { "battery_sw:", ggBatteryButton }, + { "tempomat_sw:", ggScndCtrlButton }, { "universal0:", ggUniversals[ 0 ] }, { "universal1:", ggUniversals[ 1 ] }, { "universal2:", ggUniversals[ 2 ] }, @@ -7940,7 +8007,8 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con } // TODO: move viable dedicated gauges to the automatic array std::unordered_map const autoboolgauges = { - { "doorstep_sw:", &mvOccupied->Doors.step_enabled } + { "doorstep_sw:", &mvOccupied->Doors.step_enabled }, + { "coolingfans_sw:", &mvControlled->RVentForceOn } }; { auto lookup = autoboolgauges.find( Label ); diff --git a/Train.h b/Train.h index 056bdd1b..1e49b3a0 100644 --- a/Train.h +++ b/Train.h @@ -169,6 +169,7 @@ class TTrain static void OnCommand_secondcontrollerdecreasefast( TTrain *Train, command_data const &Command ); static void OnCommand_secondcontrollerset( TTrain *Train, command_data const &Command ); static void OnCommand_notchingrelaytoggle( TTrain *Train, command_data const &Command ); + static void OnCommand_tempomattoggle( TTrain *Train, command_data const &Command ); static void OnCommand_mucurrentindicatorothersourceactivate( TTrain *Train, command_data const &Command ); static void OnCommand_independentbrakeincrease( TTrain *Train, command_data const &Command ); static void OnCommand_independentbrakeincreasefast( TTrain *Train, command_data const &Command ); @@ -265,6 +266,7 @@ class TTrain static void OnCommand_motorblowersenablerear( TTrain *Train, command_data const &Command ); static void OnCommand_motorblowersdisablerear( TTrain *Train, command_data const &Command ); static void OnCommand_motorblowersdisableall( TTrain *Train, command_data const &Command ); + static void OnCommand_coolingfanstoggle( TTrain *Train, command_data const &Command ); static void OnCommand_motorconnectorsopen( TTrain *Train, command_data const &Command ); static void OnCommand_motorconnectorsclose( TTrain *Train, command_data const &Command ); static void OnCommand_motordisconnect( TTrain *Train, command_data const &Command ); @@ -379,7 +381,7 @@ public: // reszta może by?publiczna TGauge ggMainCtrl; TGauge ggMainCtrlAct; TGauge ggScndCtrl; - TGauge ggScndCtrlButton; // NOTE: not used? + TGauge ggScndCtrlButton; TGauge ggDirKey; TGauge ggBrakeCtrl; TGauge ggLocalBrake; @@ -580,6 +582,7 @@ public: // reszta może by?publiczna TButton btLampkaMalfunction; TButton btLampkaMalfunctionB; TButton btLampkaMotorBlowers; + TButton btLampkaCoolingFans; TButton btCabLight; // hunter-171012: lampa oswietlajaca kabine // Ra 2013-12: wirtualne "lampki" do odbijania na haslerze w PoKeys diff --git a/command.cpp b/command.cpp index 6b49e343..25eeac6c 100644 --- a/command.cpp +++ b/command.cpp @@ -224,7 +224,9 @@ commanddescription_sequence Commands_descriptions = { { "batterydisable", command_target::vehicle }, { "motorblowerstogglefront", command_target::vehicle }, { "motorblowerstogglerear", command_target::vehicle }, - { "motorblowersdisableall", command_target::vehicle } + { "motorblowersdisableall", command_target::vehicle }, + { "coolingfanstoggle", command_target::vehicle }, + { "tempomattoggle", command_target::vehicle } }; diff --git a/command.h b/command.h index 3cdd6bd0..9e321ffe 100644 --- a/command.h +++ b/command.h @@ -218,6 +218,8 @@ enum class user_command { motorblowerstogglefront, motorblowerstogglerear, motorblowersdisableall, + coolingfanstoggle, + tempomattoggle, none = -1 }; diff --git a/driverkeyboardinput.cpp b/driverkeyboardinput.cpp index 0ece6a48..1b530384 100644 --- a/driverkeyboardinput.cpp +++ b/driverkeyboardinput.cpp @@ -227,7 +227,8 @@ driverkeyboard_input::default_bindings() { { user_command::motorblowerstogglefront, GLFW_KEY_N | keymodifier::shift }, { user_command::motorblowerstogglerear, GLFW_KEY_M | keymodifier::shift }, { user_command::motorblowersdisableall, GLFW_KEY_M | keymodifier::control } - + // coolingfanstoggle + // tempomattoggle }; } diff --git a/drivermouseinput.cpp b/drivermouseinput.cpp index a8e04c07..5792999b 100644 --- a/drivermouseinput.cpp +++ b/drivermouseinput.cpp @@ -494,6 +494,9 @@ drivermouse_input::default_bindings() { { "shuntmodepower:", { user_command::secondcontrollerincrease, user_command::secondcontrollerdecrease } }, + { "tempomat_sw:", { + user_command::tempomattoggle, + user_command::none } }, { "dirkey:", { user_command::reverserincrease, user_command::reverserdecrease } }, @@ -552,6 +555,9 @@ drivermouse_input::default_bindings() { { "motorblowersalloff_sw:", { user_command::motorblowersdisableall, user_command::none } }, + { "coolingfans_sw:", { + user_command::coolingfanstoggle, + user_command::none } }, { "main_off_bt:", { user_command::linebreakeropen, user_command::none } }, diff --git a/driveruipanels.cpp b/driveruipanels.cpp index 62a89990..f10ae4c9 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -238,12 +238,14 @@ timetable_panel::update() { { // current time std::snprintf( m_buffer.data(), m_buffer.size(), - locale::strings[ locale::string::driver_timetable_time ].c_str(), + locale::strings[ locale::string::driver_timetable_header ].c_str(), + 40, 40, + locale::strings[ locale::string::driver_timetable_name ].c_str(), time.wHour, time.wMinute, time.wSecond ); - text_lines.emplace_back( m_buffer.data(), Global.UITextColor ); + title = m_buffer.data(); } auto *vehicle { ( diff --git a/simulationtime.cpp b/simulationtime.cpp index b2574756..f1c5531e 100644 --- a/simulationtime.cpp +++ b/simulationtime.cpp @@ -121,7 +121,7 @@ scenario_time::update( double const Deltatime ) { } m_time.wHour -= 24; } - int leap { ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 ) }; + int leap { is_leap( m_time.wYear ) }; while( m_time.wDay > m_monthdaycounts[ leap ][ m_time.wMonth ] ) { m_time.wDay -= m_monthdaycounts[ leap ][ m_time.wMonth ]; @@ -130,7 +130,7 @@ scenario_time::update( double const Deltatime ) { if( m_time.wMonth > 12 ) { ++m_time.wYear; - leap = ( m_time.wYear % 4 == 0 ) && ( m_time.wYear % 100 != 0 ) || ( m_time.wYear % 400 == 0 ); + leap = is_leap( m_time.wYear ); m_time.wMonth -= 12; } } @@ -144,7 +144,7 @@ scenario_time::year_day( int Day, const int Month, const int Year ) const { { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; - int const leap { ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ) }; + int const leap { is_leap( Year ) }; for( int i = 1; i < Month; ++i ) Day += daytab[ leap ][ i ]; @@ -159,7 +159,7 @@ scenario_time::daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Yea { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } }; - int const leap { ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ) }; + int const leap { is_leap( Year ) }; WORD idx = 1; while( ( idx < 13 ) && ( Yearday >= daytab[ leap ][ idx ] ) ) { @@ -222,7 +222,7 @@ scenario_time::day_of_month( int const Week, int const Weekday, int const Month, { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; - int const leap { ( Year % 4 == 0 ) && ( Year % 100 != 0 ) || ( Year % 400 == 0 ) }; + int const leap { is_leap( Year ) }; while( day > daytab[ leap ][ Month ] ) { day -= 7; @@ -248,4 +248,10 @@ scenario_time::convert_transition_time( SYSTEMTIME &Time ) const { Time.wDay = day_of_month( Time.wDay, Time.wDayOfWeek + 1, Time.wMonth, m_time.wYear ); } +bool +scenario_time::is_leap( int const Year ) const { + + return ( ( Year % 4 == 0 ) && ( ( Year % 100 != 0 ) || ( Year % 400 == 0 ) ) ); + +} //--------------------------------------------------------------------------- diff --git a/simulationtime.h b/simulationtime.h index 45f4352e..58a8b317 100644 --- a/simulationtime.h +++ b/simulationtime.h @@ -61,6 +61,9 @@ private: // returns number of days between specified days of week int weekdays( int const First, int const Second ) const; + // returns true if specified year is a leap year, false otherwise + bool + is_leap( int const Year ) const; SYSTEMTIME m_time; double m_milliseconds{ 0.0 }; diff --git a/sun.cpp b/sun.cpp index 0acf3864..b2cce6a6 100644 --- a/sun.cpp +++ b/sun.cpp @@ -185,17 +185,11 @@ void cSun::move() { m_body.rascen = clamp_circular( radtodeg * std::atan2( top, bottom ) ); - // Greenwich mean sidereal time - m_observer.gmst = 6.697375 + 0.0657098242 * daynumber + m_observer.utime; + // Greenwich mean sidereal time (hours) + m_observer.gmst = clamp_circular( 6.697375 + 0.0657098242 * daynumber + m_observer.utime, 24.0 ); - m_observer.gmst -= 24.0 * (int)( m_observer.gmst / 24.0 ); - if( m_observer.gmst < 0.0 ) m_observer.gmst += 24.0; - - // local mean sidereal time - m_observer.lmst = m_observer.gmst * 15.0 + m_observer.longitude; - - m_observer.lmst -= 360.0 * (int)( m_observer.lmst / 360.0 ); - if( m_observer.lmst < 0.0 ) m_observer.lmst += 360.0; + // local mean sidereal time (deg) + m_observer.lmst = clamp_circular( m_observer.gmst * 15.0 + m_observer.longitude ); // hour angle m_body.hrang = m_observer.lmst - m_body.rascen; diff --git a/translation.cpp b/translation.cpp index 8bfe7b1a..cd7d56bc 100644 --- a/translation.cpp +++ b/translation.cpp @@ -56,8 +56,8 @@ init() { "Drive according to signals and timetable", "Bank consist ahead", + "%-*.*s Time: %d:%02d:%02d", // HACK: some manual padding to account for longer 'time' equivalent in polish version "Timetable", - "Time: %d:%02d:%02d", "(no timetable)", "Consist weight: %d t (specified) %d t (actual)\nConsist length: %d m", @@ -84,6 +84,7 @@ init() { "master controller", "second controller", "shunt mode power", + "tempomat", "reverser", "train brake", "independent brake", @@ -104,6 +105,7 @@ init() { "motor blowers A", "motor blowers B", "all motor blowers", + "cooling fans", "line breaker", "line breaker", "alerter", @@ -219,8 +221,8 @@ init() { "Prowadzic sklad wedlug sygnalow i rozkladu", "Popychac sklad z przodu", + "%-*.*s Godzina: %d:%02d:%02d", "Rozklad jazdy", - "Godzina: %d:%02d:%02d", "(brak rozkladu)", "Brutto: %d t (rozkladowe) %d t (rzeczywiste)\nDlugosc pociagu: %d m", @@ -247,6 +249,7 @@ init() { "nastawnik jazdy", "nastawnik dodatkowy", "sterowanie analogowe", + "tempomat", "nastawnik kierunku", "hamulec zespolony", "hamulec pomocniczy", @@ -267,6 +270,7 @@ init() { "wentylatory silnikow trakcyjnych A", "wentylatory silnikow trakcyjnych B", "wszystkie wentylatory silnikow trakcyjnych", + "wentylatory oporow rozruchowych", "wylacznik szybki", "wylacznik szybki", "czuwak", @@ -363,6 +367,7 @@ init() { "jointctrl:", "scndctrl:", "shuntmodepower:", + "tempomat_sw:", "dirkey:", "brakectrl:", "localbrake:", @@ -383,6 +388,7 @@ init() { "motorblowersfront_sw:", "motorblowersrear_sw:", "motorblowersalloff_sw:", + "coolingfans_sw:", "main_off_bt:", "main_on_bt:", "security_reset_bt:", diff --git a/translation.h b/translation.h index ce6624c4..18edda94 100644 --- a/translation.h +++ b/translation.h @@ -46,7 +46,7 @@ enum string { driver_scenario_bank, driver_timetable_header, - driver_timetable_time, + driver_timetable_name, driver_timetable_notimetable, driver_timetable_consistdata, @@ -73,6 +73,7 @@ enum string { cab_jointctrl, cab_scndctrl, cab_shuntmodepower, + cab_tempomat, cab_dirkey, cab_brakectrl, cab_localbrake, @@ -93,6 +94,7 @@ enum string { cab_motorblowersfront_sw, cab_motorblowersrear_sw, cab_motorblowersalloff_sw, + cab_coolingfans_sw, cab_main_off_bt, cab_main_on_bt, cab_security_reset_bt,