diff --git a/Driver.cpp b/Driver.cpp index e38e55c7..81de10c1 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -1006,7 +1006,10 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN sSpeedTable[i].iFlags = 0; // W4 nie liczy się już (nie wyśle SetVelocity) sSpeedTable[i].fVelNext = -1; // można jechać za W4 fLastStopExpDist = -1.0f; // nie ma rozkładu, nie ma usuwania stacji +/* + // NOTE: disabled as it's no longer needed, required time is calculated as part of loading/unloading procedure WaitingSet(60); // tak ze 2 minuty, aż wszyscy wysiądą +*/ // wykonanie kolejnego rozkazu (Change_direction albo Shunt) JumpToNextOrder(); // ma się nie ruszać aż do momentu podania sygnału @@ -2274,7 +2277,7 @@ bool TController::PrepareEngine() { // najpierw ustalamy kierunek, jeśli nie został ustalony if( !iDirection ) { // jeśli nie ma ustalonego kierunku - if( mvOccupied->V == 0 ) { // ustalenie kierunku, gdy stoi + if( mvOccupied->Vel < 0.01 ) { // ustalenie kierunku, gdy stoi iDirection = mvOccupied->CabNo; // wg wybranej kabiny if( !iDirection ) { // jeśli nie ma ustalonego kierunku @@ -4610,20 +4613,7 @@ TController::UpdateSituation(double dt) { } // sprawdzamy możliwe ograniczenia prędkości - if( OrderCurrentGet() & ( Shunt | Obey_train ) ) { - // w Connect nie, bo moveStopHere odnosi się do stanu po połączeniu - if( ( iDrivigFlags & moveStopHere ) - && ( vel == 0.0 ) - && ( VelSignal == 0.0 ) ) { - // jeśli ma czekać na wolną drogę, stoi a wyjazdu nie ma, to ma stać - VelDesired = 0.0; - } - } - if( fStopTime < 0 ) { - // czas postoju przed dalszą jazdą (np. na przystanku) - VelDesired = 0.0; // jak ma czekać, to nie ma jazdy - } - else if( VelSignal >= 0 ) { + if( VelSignal >= 0 ) { // jeśli skład był zatrzymany na początku i teraz już może jechać VelDesired = min_speed( @@ -4640,27 +4630,56 @@ TController::UpdateSituation(double dt) { if( VelforDriver >= 0 ) { // tu jest zero przy zmianie kierunku jazdy // Ra: tu może być 40, jeśli mechanik nie ma znajomości szlaaku, albo kierowca jeździ 70 - VelDesired = min_speed( VelDesired, VelforDriver ); - } - if( ( TrainParams != nullptr ) - && ( TrainParams->CheckTrainLatency() < 5.0 ) - && ( TrainParams->TTVmax > 0.0 ) ) { - // jesli nie spozniony to nie przekraczać rozkladowej VelDesired = min_speed( VelDesired, - TrainParams->TTVmax ); + VelforDriver ); + } + if( fStopTime < 0 ) { + // czas postoju przed dalszą jazdą (np. na przystanku) + VelDesired = 0.0; // jak ma czekać, to nie ma jazdy } - if( ( VelDesired > 0.0 ) - && ( iDrivigFlags & moveGuardSignal ) - && ( OrderCurrentGet() & Obey_train ) ) { + if( ( OrderCurrentGet() & Obey_train ) != 0 ) { + + if( ( TrainParams->CheckTrainLatency() < 5.0 ) + && ( TrainParams->TTVmax > 0.0 ) ) { + // jesli nie spozniony to nie przekraczać rozkladowej + VelDesired = + min_speed( + VelDesired, + TrainParams->TTVmax ); + } + + if( ( ( iDrivigFlags & moveStopHere ) != 0 ) + && ( vel < 0.01 ) + && ( SemNextIndex != -1 ) + && ( SemNextIndex < sSpeedTable.size() ) // BUG: index can point at non-existing slot. investigate reason(s) + && ( sSpeedTable[ SemNextIndex ].fVelNext == 0.0 ) ) { + // don't depart if told to wait at passenger stop until allowed to by the signal + VelDesired = 0.0; + } + } + + if( ( OrderCurrentGet() & ( Shunt | Obey_train ) ) != 0 ) { + // w Connect nie, bo moveStopHere odnosi się do stanu po połączeniu + if( ( ( iDrivigFlags & moveStopHere ) != 0 ) + && ( vel < 0.01 ) + && ( VelSignal == 0.0 ) ) { + // jeśli ma czekać na wolną drogę, stoi a wyjazdu nie ma, to ma stać + VelDesired = 0.0; + } + } + // end of speed caps checks + + if( ( ( OrderCurrentGet() & Obey_train ) != 0 ) + && ( ( iDrivigFlags & moveGuardSignal ) != 0 ) + && ( VelDesired > 0.0 ) ) { // komunikat od kierownika tu, bo musi być wolna droga i odczekany czas stania iDrivigFlags &= ~moveGuardSignal; // tylko raz nadać if( false == tsGuardSignal.empty() ) { tsGuardSignal.stop(); - // w zasadzie to powinien mieć flagę, czy jest dźwiękiem radiowym, czy - // bezpośrednim + // w zasadzie to powinien mieć flagę, czy jest dźwiękiem radiowym, czy bezpośrednim // albo trzeba zrobić dwa dźwięki, jeden bezpośredni, słyszalny w // pobliżu, a drugi radiowy, słyszalny w innych lokomotywach // na razie zakładam, że to nie jest dźwięk radiowy, bo trzeba by zrobić @@ -4675,8 +4694,7 @@ TController::UpdateSituation(double dt) { else { // if (iGuardRadio==iRadioChannel) //zgodność kanału // if (!FreeFlyModeFlag) //obserwator musi być w środku pojazdu - // (albo może mieć radio przenośne) - kierownik mógłby powtarzać - // przy braku reakcji + // (albo może mieć radio przenośne) - kierownik mógłby powtarzać przy braku reakcji // TODO: proper system for sending/receiving radio messages // place the sound in appropriate cab of the manned vehicle tsGuardSignal.owner( pVehicle ); @@ -4684,17 +4702,9 @@ TController::UpdateSituation(double dt) { tsGuardSignal.play( sound_flags::exclusive ); } } -/* - if( ( ( iDrivigFlags & moveStopHere ) == 0 ) - || ( ( SemNextIndex != -1 ) - && ( SemNextIndex < sSpeedTable.size() ) // BUG: index can point at non-existing slot. investigate reason(s) - && ( sSpeedTable[SemNextIndex].fVelNext != 0.0 ) ) ) { - // jeśli można jechać, to odpalić dźwięk kierownika oraz zamknąć drzwi w - // składzie, jeśli nie mamy czekać na sygnał też trzeba odpalić - } -*/ } - if( mvOccupied->V == 0.0 ) { + + if( mvOccupied->Vel < 0.01 ) { // Ra 2014-03: jesli skład stoi, to działa na niego składowa styczna grawitacji AbsAccS = fAccGravity; } @@ -5235,13 +5245,22 @@ TController::UpdateSituation(double dt) { } if (AIControllFlag) { // odhamowywanie składu po zatrzymaniu i zabezpieczanie lokomotywy - if ((OrderList[OrderPos] & (Disconnect | Connect)) == - 0) // przy (p)odłączaniu nie zwalniamy tu hamulca - if ((mvOccupied->V == 0.0) && ((VelDesired == 0.0) || (AccDesired == 0.0))) - if (mvOccupied->BrakeCtrlPos == mvOccupied->Handle->GetPos(bh_RP)) - mvOccupied->IncLocalBrakeLevel(1); // dodatkowy na pozycję 1 - else - mvOccupied->BrakeLevelSet(mvOccupied->Handle->GetPos(bh_RP)); + if( ( ( OrderList[ OrderPos ] & ( Disconnect | Connect ) ) == 0 ) + && ( std::abs( fAccGravity ) < 0.01 ) ) { + // przy (p)odłączaniu nie zwalniamy tu hamulca + // only do this on flats, on slopes keep applied the train brake + if( ( mvOccupied->Vel < 0.01 ) + && ( ( VelDesired == 0.0 ) + || ( AccDesired == 0.0 ) ) ) { + if( mvOccupied->BrakeCtrlPos == mvOccupied->Handle->GetPos( bh_RP ) ) { + // dodatkowy na pozycję 1 + mvOccupied->IncLocalBrakeLevel( 1 ); + } + else { + mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); + } + } + } } break; // rzeczy robione przy jezdzie } // switch (OrderList[OrderPos]) diff --git a/DynObj.cpp b/DynObj.cpp index c57d4a7a..09eb90c2 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -4670,10 +4670,12 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, */ if( true == pAnimations.empty() ) { // jeśli nie ma jeszcze tabeli animacji, można odczytać nowe ilości - int co = 0, ile = -1; + int co = 0; iAnimations = 0; + int ile; do { // kolejne liczby to ilość animacj, -1 to znacznik końca + ile = -1; parser.getTokens( 1, false ); parser >> ile; // ilość danego typu animacji if (ile >= 0) @@ -6426,7 +6428,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub // main engine sound if( true == Vehicle.Mains ) { - if( ( std::fabs( Vehicle.enrot ) > 0.01 ) + if( ( std::abs( Vehicle.enrot ) > 0.01 ) // McZapkie-280503: zeby dla dumb dzialal silnik na jalowych obrotach || ( Vehicle.EngineType == Dumb ) ) { diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index fa217caf..dec46d5e 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -741,6 +741,7 @@ public: double Mred = 0.0; /*Ra: zredukowane masy wirujące; potrzebne do obliczeń hamowania*/ double TotalMass = 0.0; /*wyliczane przez ComputeMass*/ double HeatingPower = 0.0; + double EngineHeatingRPM { 0.0 }; // guaranteed engine revolutions with heating enabled double LightPower = 0.0; /*moc pobierana na ogrzewanie/oswietlenie*/ double BatteryVoltage = 0.0; /*Winger - baterie w elektrykach*/ bool Battery = false; /*Czy sa zalavzone baterie*/ diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 6b8335fe..56e2505e 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -3302,7 +3302,7 @@ void TMoverParameters::CompressorCheck(double dt) CompressedVolume += CompressorSpeed * ( 2.0 * MaxCompressor - Compressor ) / MaxCompressor - * ( DElist[ MainCtrlPos ].RPM / DElist[ MainCtrlPosNo ].RPM ) + * ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) * dt; } else { @@ -3467,7 +3467,7 @@ void TMoverParameters::CompressorCheck(double dt) // the compressor is coupled with the diesel engine, engine revolutions affect the output if( false == CompressorGovernorLock ) { auto const enginefactor { ( - EngineType == DieselElectric ? ( DElist[ MainCtrlPos ].RPM / DElist[ MainCtrlPosNo ].RPM ) : + EngineType == DieselElectric ? ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) : EngineType == DieselEngine ? ( std::abs( enrot ) / nmax ) : 1.0 ) }; // shouldn't ever get here but, eh CompressedVolume += @@ -4436,19 +4436,21 @@ double TMoverParameters::TractionForce( double dt ) { switch( EngineType ) { case DieselElectric: { if( ( true == Mains ) - && ( true == FuelPump.is_active ) ) { + && ( true == FuelPump.is_active ) ) { tmp = DElist[ MainCtrlPos ].RPM / 60.0; if( ( true == Heating ) - && ( HeatingPower > 0 ) - && ( MainCtrlPosNo > MainCtrlPos ) ) { - - int i = MainCtrlPosNo; - while( DElist[ i - 2 ].RPM / 60.0 > tmp ) { - --i; - } - tmp = DElist[ i ].RPM / 60.0; + && ( HeatingPower > 0 ) + && ( EngineHeatingRPM > 0 ) ) { + // bump engine revolutions up if needed, when heating is on + tmp = + std::max( + tmp, + std::min( + DElist[ MainCtrlPosNo ].RPM, + EngineHeatingRPM ) + / 60.0 ); } } else { @@ -4719,6 +4721,7 @@ double TMoverParameters::TractionForce( double dt ) { if( ( true == Mains ) && ( MainCtrlPos > 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 auto const rpmratio { 60.0 * enrot / DElist[ MainCtrlPos ].RPM }; tmp = rpmratio * ( SST[ MainCtrlPos ].Pmax * AnPos ) + ( SST[ MainCtrlPos ].Pmin * ( 1.0 - AnPos ) ); Ft = tmp * 1000.0 / ( abs( tmpV ) + 1.6 ); @@ -4735,6 +4738,7 @@ double TMoverParameters::TractionForce( double dt ) { if( true == Heating ) { power -= HeatingPower; } if( power < 0.0 ) { power = 0.0; } // 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 auto const currentgenpower { ( DElist[ MainCtrlPos ].RPM > 0 ? DElist[ MainCtrlPos ].GenPower * ( 60.0 * enrot / DElist[ MainCtrlPos ].RPM ) : @@ -8444,6 +8448,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { ImaxHi = 2; ImaxLo = 1; } + extract_value( EngineHeatingRPM, "HeatingRPM", Input, "" ); break; } case ElectricInductionMotor: { diff --git a/Train.cpp b/Train.cpp index 1d830d27..5d2f7133 100644 --- a/Train.cpp +++ b/Train.cpp @@ -5198,10 +5198,8 @@ bool TTrain::Update( double const Deltatime ) //--------- // hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy if( ( mvControlled->Heating == true ) - && ( ( mvControlled->ConverterFlag ) - || ( ( mvControlled->EngineType == ElectricSeriesMotor ) - && ( mvControlled->Mains == true ) - && ( mvControlled->ConvOvldFlag == false ) ) ) ) + && ( mvControlled->Mains == true ) + && ( mvControlled->ConvOvldFlag == false ) ) btLampkaOgrzewanieSkladu.Turn( true ); else btLampkaOgrzewanieSkladu.Turn( false ); diff --git a/version.h b/version.h index 7166095d..020fbc89 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 18 -#define VERSION_MINOR 531 +#define VERSION_MINOR 609 #define VERSION_REVISION 0