From c4ef056102110f60123a81ec03e8dfedf870285b Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Wed, 26 Aug 2020 13:43:24 +0200 Subject: [PATCH] build 200824. emergency_brake getvalues event support, utf bom parsing fix, brake state vehicle debug panel enhancement, ai cab change logic fixes, ai door operation logic fixes, minor ai logic fixes, gfx renderer framerate calculation tweak, minor bug fixes --- Camera.cpp | 11 +++ Classes.h | 3 +- Driver.cpp | 159 +++++++++++++++++++++++++++------------- Driver.h | 4 +- DynObj.cpp | 15 ++-- DynObj.h | 6 +- McZapkie/Mover.cpp | 26 +------ MemCell.cpp | 5 ++ driverkeyboardinput.cpp | 4 +- driveruipanels.cpp | 4 +- mtable.cpp | 27 +++---- opengl33renderer.cpp | 2 +- openglrenderer.cpp | 2 +- parser.cpp | 11 +++ parser.h | 1 + translation.cpp | 4 +- version.h | 2 +- 17 files changed, 180 insertions(+), 106 deletions(-) diff --git a/Camera.cpp b/Camera.cpp index c777dad5..6e033ec2 100644 --- a/Camera.cpp +++ b/Camera.cpp @@ -189,11 +189,22 @@ void TCamera::Update() // attached movement position update auto movement { Velocity * -2.0 }; movement.y = -movement.y; + auto const *owner { ( + m_owner->Mechanik ? + m_owner->Mechanik : + m_owner->ctOwner ) }; + if( ( owner ) + && ( owner->Occupied()->CabOccupied < 0 ) ) { + movement *= -1.f; + movement.y = -movement.y; + } +/* if( ( m_owner->ctOwner ) && ( m_owner->ctOwner->Vehicle()->DirectionGet() != m_owner->DirectionGet() ) ) { movement *= -1.f; movement.y = -movement.y; } +*/ movement.RotateY( Angle.y ); m_owneroffset += movement * deltatime; diff --git a/Classes.h b/Classes.h index 652b8564..9145e739 100644 --- a/Classes.h +++ b/Classes.h @@ -76,7 +76,8 @@ enum class TCommandType cm_ChangeDirection, cm_PassengerStopPoint, cm_OutsideStation, - cm_Shunt, +// cm_Shunt, // unused? + cm_EmergencyBrake, cm_Command // komenda pobierana z komórki }; diff --git a/Driver.cpp b/Driver.cpp index 91f4b991..196d4c6b 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -268,12 +268,18 @@ void TSpeedPos::CommandCheck() fVelNext = -1; iFlags |= spOutsideStation; // W5 break; + case TCommandType::cm_EmergencyBrake: + fVelNext = -1; + break; default: // inna komenda w evencie skanowanym powoduje zatrzymanie i wysłanie tej komendy // nie manewrowa, nie przystanek, nie zatrzymać na SBL iFlags &= ~(spShuntSemaphor | spPassengerStopPoint | spStopOnSBL); // jak nieznana komenda w komórce sygnałowej, to zatrzymujemy - fVelNext = 0.0; + fVelNext = ( + evEvent->is_command() ? + 0.0 : // ask for a stop if we have a command for the vehicle + -1.0 ); // if we don't or it was already passed then don't be a bother } }; @@ -336,10 +342,14 @@ bool TSpeedPos::Update() std::string TSpeedPos::GetName() const { - if (iFlags & spTrack) // jeśli tor + if( iFlags & spTrack ) // jeśli tor return trTrack->name(); else if( iFlags & spEvent ) // jeśli event - return evEvent->m_name; + return + evEvent->m_name + + " [" + to_string( static_cast( evEvent->input_value( 1 ) ) ) + + ", " + to_string( static_cast( evEvent->input_value( 2 ) ) ) + + "]"; else return ""; } @@ -877,7 +887,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN // stop points are irrelevant when not in one of the basic modes if( ( OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank ) ) == 0 ) { continue; } // first 19 chars of the command is expected to be "PassengerStopPoint:" so we skip them - if ( ToLower(sSpeedTable[i].evEvent->input_text()).compare( 19, sizeof(asNextStop), ToLower(asNextStop)) != 0 ) + if( ToLower( sSpeedTable[ i ].evEvent->input_text() ).compare( 19, sizeof( asNextStop ), ToLower( asNextStop ) ) != 0 ) { // jeśli nazwa nie jest zgodna if( ( false == IsScheduledPassengerStopVisible ) // check if our next scheduled stop didn't show up earlier in the scan && ( sSpeedTable[i].fDist < ( 1.15 * fBrakeDist + 300 ) ) @@ -998,7 +1008,6 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN // w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko iDrivigFlags &= ~moveStopCloser; } - if (TrainParams.UpdateMTable( simulation::Time, asNextStop) ) { // to się wykona tylko raz po zatrzymaniu na W4 if( TrainParams.StationIndex < TrainParams.StationCount ) { @@ -1012,12 +1021,13 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN // HACK: manual check if we didn't already do load exchange at this stop // TODO: remove the check once the station system is in place if( m_lastexchangestop != asNextStop ) { - auto const platformside = static_cast( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10; - auto const exchangetime = simulation::Station.update_load( pVehicles[ end::front ], TrainParams, platformside ); + m_lastexchangestop = asNextStop; + m_lastexchangedirection = pVehicle->DirectionGet(); + m_lastexchangeplatforms = static_cast( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10; + auto const exchangetime { simulation::Station.update_load( pVehicles[ end::front ], TrainParams, m_lastexchangeplatforms ) }; WaitingSet( exchangetime ); // announce the stop name while at it announce( announcement_t::current ); - m_lastexchangestop = asNextStop; m_makenextstopannouncement = true; } @@ -1053,11 +1063,21 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN } } + if( pVehicle->DirectionGet() != m_lastexchangedirection ) { + // generally means the ai driver moved to the opposite end of the consist + // TODO: investigate whether user playing with the reverser can mess this up + auto const left { ( m_lastexchangedirection > 0 ) ? 1 : 2 }; + auto const right { 3 - left }; + m_lastexchangeplatforms = + ( ( m_lastexchangeplatforms & left ) != 0 ? right : 0 ) + + ( ( m_lastexchangeplatforms & right ) != 0 ? left : 0 ); + m_lastexchangedirection = pVehicle->DirectionGet(); + } if( ( false == TrainParams.IsMaintenance() ) && ( ( false == TestFlag( iDrivigFlags, moveDoorOpened ) ) || ( true == DoesAnyDoorNeedOpening ) ) ) { iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz - Doors( true, static_cast( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10 ); + Doors( true, m_lastexchangeplatforms ); } if (OrderCurrentGet() & ( Shunt | Loose_shunt )) { @@ -1181,6 +1201,15 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN } SemNextStopIndex = -1; // jeśli minęliśmy semafor od ograniczenia to go kasujemy ze zmiennej sprawdzającej dla skanowania w przód } + switch( sSpeedTable[ i ].evEvent->input_command() ) { + case TCommandType::cm_EmergencyBrake: { + pVehicle->RadioStop(); + sSpeedTable[ i ].iFlags = 0; // signal reveived, deactivate + } + default: { + break; + } + } } if( sSpeedTable[ i ].fDist > 0.0 ) { // check signals ahead @@ -1333,8 +1362,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN //sprawdzenie eventów pasywnych przed nami if( ( mvOccupied->CategoryFlag & 1 ) - && ( sSpeedTable[ i ].fDist > Obstacle.distance - 20 ) ) { - // jak sygnał jest dalej niż zawalidroga + && ( sSpeedTable[ i ].fDist > Obstacle.distance - 20 ) ) { + // jak sygnał jest dalej niż zawalidroga v = 0.0; // to może być podany dla tamtego: jechać tak, jakby tam stop był } else @@ -1378,8 +1407,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN if( go == TCommandType::cm_Unknown ) { // jeśli nie było komendy wcześniej - pierwsza się liczy - ustawianie VelSignal if( ( v < 0.0 ) - || ( v >= 1.0 ) ) { - // bo wartość 0.1 służy do hamowania tylko + || ( v >= 1.0 ) ) { + // bo wartość 0.1 służy do hamowania tylko go = TCommandType::cm_SetVelocity; // może odjechać // Ra 2014-06: (VelSignal) nie może być tu ustawiane, bo semafor może być daleko // VelSignal=v; //nie do końca tak, to jest druga prędkość; -1 nie wpisywać... @@ -1888,52 +1917,68 @@ void TController::Activation() iDirection = iDirectionOrder; // kierunek (względem sprzęgów pojazdu z AI) właśnie został ustalony (zmieniony) 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 - auto const localbrakelevel { mvOccupied->LocalBrakePosA }; + auto *initialvehicle { pVehicle }; +/* + auto const initiallocalbrakelevel { mvOccupied->LocalBrakePosA }; +*/ + auto const initialspringbrakestate { mvOccupied->SpringBrake.Activate }; // switch off tempomat SpeedCntrl( 0.0 ); mvControlling->DecScndCtrl( 2 ); // reset controls ZeroSpeed(); ZeroDirection(); - mvOccupied->SpringBrakeActivate( true ); - if (TestFlag(d->MoverParameters->Couplers[iDirectionOrder < 0 ? end::rear : end::front].CouplingFlag, coupling::control)) { - mvControlling->MainSwitch( false ); // dezaktywacja czuwaka, jeśli przejście do innego członu - mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca w opuszczanym pojeździe - // mvOccupied->BrakeLevelSet((mvOccupied->BrakeHandle==FVel6)?4:-2); //odcięcie na - // zaworze maszynisty, FVel6 po drugiej stronie nie luzuje - mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos(bh_NP) ); // odcięcie na zaworze maszynisty - BrakeLevelSet( gbh_NP ); //ustawienie zmiennej GBH - } mvOccupied->CabOccupied = mvOccupied->CabActive; // użytkownik moze zmienić CabOccupied wychodząc mvOccupied->CabDeactivisation(); // tak jest w Train.cpp + if (TestFlag(pVehicle->MoverParameters->Couplers[iDirectionOrder < 0 ? end::rear : end::front].CouplingFlag, coupling::control)) { + ZeroLocalBrake(); + if( initialspringbrakestate ) { + mvOccupied->SpringBrakeActivate( false ); + } + // odcięcie na zaworze maszynisty, FVel6 po drugiej stronie nie luzuje + mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos(bh_NP) ); // odcięcie na zaworze maszynisty + BrakeLevelSet( mvOccupied->BrakeCtrlPos ); //ustawienie zmiennej GBH + } // przejście AI na drugą stronę EN57, ET41 itp. + // TODO: clean this up, there's lot of redundancy with TMoverParameters::ChangeCab() and TTrain::MoveToVehicle() { int movedirection { ( iDirection < 0 ? end::rear : end::front ) }; - d = pVehicle->FirstFind( movedirection, coupling::control ); - if( pVehicle != d ) { - drugi = d->Mechanik; // zapamiętanie tego, co ewentualnie tam siedzi, żeby w razie dwóch zamienić miejscami - d->Mechanik = this; // na razie bilokacja - d->MoverParameters->SetInternalCommand("", 0, 0); // usunięcie ewentualnie zalegającej komendy (Change_direction?) - if( d->DirectionGet() != pVehicle->DirectionGet() ) { + auto *targetvehicle { pVehicle->FirstFind( movedirection, coupling::control ) }; + if( pVehicle != targetvehicle ) { + auto *targetvehicledriver { targetvehicle->Mechanik }; // zapamiętanie tego, co ewentualnie tam siedzi, żeby w razie dwóch zamienić miejscami + // move to the new vehicle + targetvehicle->Mechanik = this; // na razie bilokacja + targetvehicle->MoverParameters->SetInternalCommand("", 0, 0); // usunięcie ewentualnie zalegającej komendy (Change_direction?) + if( targetvehicle->DirectionGet() != pVehicle->DirectionGet() ) { // jeśli są przeciwne do siebie to będziemy jechać w drugą stronę względem zasiedzianego pojazdu iDirection = -iDirection; } - pVehicle->Mechanik = drugi; // wsadzamy tego, co ewentualnie był (podwójna trakcja) -/* - pVehicle->MoverParameters->CabActive = 0; // wyłączanie kabin po drodze - pVehicle->MoverParameters->CabOccupied = 0; // i zaznaczenie, że nie ma tam nikogo -*/ - pVehicle = d; // a mechu ma nowy pojazd (no, człon) + // move the other driver to our old vehicle + pVehicle->Mechanik = targetvehicledriver; // wsadzamy tego, co ewentualnie był (podwójna trakcja) + // NOTE: having caboccupied != 0 (by swapping in the driver from the target vehicle) may lead to dysfunctional brake + // TODO: investigate and resolve if necessary + pVehicle->MoverParameters->CabOccupied = targetvehicle->MoverParameters->CabOccupied; + if( pVehicle->Mechanik ) { // not guaranteed, as target vehicle can be empty + pVehicle->Mechanik->BrakeLevelSet( pVehicle->MoverParameters->BrakeCtrlPos ); + } + // finish driver swap + pVehicle = targetvehicle; } } - if (pVehicle != old) + if (pVehicle != initialvehicle) { // jeśli zmieniony został pojazd prowadzony - TTrain *train = simulation::Trains.find(old->name()); - if (train) - train->MoveToVehicle(pVehicle); + auto *train { simulation::Trains.find( initialvehicle->name() ) }; + if( train ) { + train->MoveToVehicle( pVehicle ); + } ControllingSet(); // utworzenie połączenia do sterowanego pojazdu (może się zmienić) - silnikowy dla EZT + if( ( mvOccupied->BrakeCtrlPosNo > 0 ) + && ( ( mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic ) + || ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) ) { + mvOccupied->LimPipePress = mvOccupied->PipePress; + mvOccupied->ActFlowSpeed = 0; + } + BrakeLevelSet( mvOccupied->BrakeCtrlPos ); } if( mvControlling->EngineType == TEngineType::DieselEngine ) { // dla 2Ls150 - przed ustawieniem kierunku - można zmienić tryb pracy @@ -1945,12 +1990,17 @@ void TController::Activation() } // Ra: to przełączanie poniżej jest tu bez sensu mvOccupied->CabOccupied = iDirection; // aktywacja kabiny w prowadzonym pojeżdzie (silnikowy może być odwrotnie?) - // mvOccupied->CabActive=iDirection; - // mvOccupied->DirActive=0; //żeby sam ustawił kierunek mvOccupied->CabActivisation(); // uruchomienie kabin w członach DirectionForward(true); // nawrotnik do przodu - if (localbrakelevel > 0.0) // hamowanie tylko jeśli był wcześniej zahamowany (bo możliwe, że jedzie!) - mvOccupied->LocalBrakePosA = localbrakelevel; // zahamuj jak wcześniej +/* + // NOTE: this won't restore local brake if the vehicle has integrated local brake control + // TBD, TODO: fix or let the ai activate the brake again as part of its standard logic? + if (initiallocalbrakelevel > 0.0) // hamowanie tylko jeśli był wcześniej zahamowany (bo możliwe, że jedzie!) + mvOccupied->LocalBrakePosA = initiallocalbrakelevel; // zahamuj jak wcześniej +*/ + if( initialspringbrakestate ) { + mvOccupied->SpringBrakeActivate( initialspringbrakestate ); + } CheckVehicles(); // sprawdzenie składu, AI zapali światła TableClear(); // resetowanie tabelki skanowania torów } @@ -3180,13 +3230,15 @@ bool TController::DecBrake() return OK; }; -bool TController::ZeroLocalBrake() { +void TController::ZeroLocalBrake() { if( mvOccupied->UniCtrlIntegratedLocalBrakeCtrl ) { - return DecBrakeEIM(); + while( DecBrakeEIM() ) { + ; + } } else { - return mvOccupied->DecLocalBrakeLevel( 2 ); + mvOccupied->DecLocalBrakeLevel( LocalBrakePosNo ); } } @@ -3197,7 +3249,8 @@ bool TController::DecBrakeEIM() { case 0: { if( mvOccupied->MED_amax != 9.81 ) { - auto const brakeposition { clamp( -1.0 * mvOccupied->AIHintLocalBrakeAccFactor * std::max( 0.0, AccDesired ) / mvOccupied->MED_amax, 0.0, 1.0 ) }; + auto const desiredacceleration { ( mvOccupied->Vel > 0.01 ? AccDesired : std::max( 0.0, AccDesired ) ) }; + auto const brakeposition { clamp( -1.0 * mvOccupied->AIHintLocalBrakeAccFactor * desiredacceleration / mvOccupied->MED_amax, 0.0, 1.0 ) }; OK = ( brakeposition != mvOccupied->LocalBrakePosA ); mvOccupied->LocalBrakePosA = brakeposition; } @@ -3244,7 +3297,7 @@ bool TController::IncSpeed() // zamykanie drzwi - tutaj wykonuje tylko AI (zmienia fActionTime) Doors( false ); } - if (mvOccupied->SpringBrake.IsActive && mvOccupied->SpringBrake.Activate) { + if (mvOccupied->SpringBrake.Activate) { mvOccupied->SpringBrakeActivate(false); } // Doors() call can potentially adjust fActionTime @@ -6482,6 +6535,7 @@ TController::UpdateSituation(double dt) { if( ( mvOccupied->EqvtPipePress < 4.5 ) && ( fReady > 0.35 ) + && ( mvOccupied->Compressor >= 7.5 ) // don't charge without sufficient pressure in the tank && ( BrakeChargingCooldown >= 0.0 ) && ( ( ActualProximityDist > 100.0 ) // don't charge if we're about to be braking soon || ( min_speed( mvOccupied->Vel, VelNext ) == mvOccupied->Vel ) ) ) { @@ -6504,8 +6558,9 @@ TController::UpdateSituation(double dt) { */ } - if( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition < 0 ) - && ( mvOccupied->EqvtPipePress > ( fReady < 0.25 ? 5.1 : 5.2 ) ) ) { + if( ( mvOccupied->Compressor < 5.0 ) + || ( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition < 0 ) + && ( mvOccupied->EqvtPipePress > ( fReady < 0.25 ? 5.1 : 5.2 ) ) ) ) { /* GBH mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); */ BrakeLevelSet( gbh_RP ); } diff --git a/Driver.h b/Driver.h index 9a93cac9..72ed1f51 100644 --- a/Driver.h +++ b/Driver.h @@ -233,7 +233,7 @@ private: void SetDriverPsyche(); bool IncBrake(); bool DecBrake(); - bool ZeroLocalBrake(); + void ZeroLocalBrake(); bool IncSpeed(); bool DecSpeed( bool force = false ); void ZeroSpeed( bool const Enforce = false ); @@ -450,6 +450,8 @@ private: std::string asNextStop; // nazwa następnego punktu zatrzymania wg rozkładu int iStationStart = 0; // numer pierwszej stacji pokazywanej na podglądzie rozkładu std::string m_lastexchangestop; // HACK: safeguard to prevent multiple load exchanges per station + int m_lastexchangeplatforms { 0 }; // cached station platforms for last exchange + int m_lastexchangedirection { 0 }; // double fLastStopExpDist = -1.0; // odległość wygasania ostateniego przystanku int iRadioChannel = 1; // numer aktualnego kanału radiowego int iGuardRadio = 0; // numer kanału radiowego kierownika (0, gdy nie używa radia) diff --git a/DynObj.cpp b/DynObj.cpp index 75ba03ab..e1d1fc9e 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2632,7 +2632,7 @@ bool TDynamicObject::UpdateForce(double dt) } // initiates load change by specified amounts, with a platform on specified side -void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int const Platform ) { +void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int const Platforms ) { /* if( ( MoverParameters->Doors.open_control == control_t::passenger ) || ( MoverParameters->Doors.open_control == control_t::mixed ) ) { @@ -2647,15 +2647,21 @@ 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 + if( Platforms == 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; + m_exchange.platforms = Platforms; m_exchange.time = 0.0; } // calculates time needed to complete current load change +float TDynamicObject::LoadExchangeTime( int const Platforms ) { + + m_exchange.platforms = Platforms; + return LoadExchangeTime(); +} + float TDynamicObject::LoadExchangeTime() const { if( ( m_exchange.unload_count < 0.01 ) && ( m_exchange.load_count < 0.01 ) ) { return 0.f; } @@ -4754,8 +4760,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co token = ""; parser.getTokens(); parser >> token; - if( ( token == "models:" ) - || ( token == "\xef\xbb\xbfmodels:" ) ) { // crude way to handle utf8 bom potentially appearing before the first token + if( token == "models:" ) { // modele i podmodele m_materialdata.multi_textures = 0; // czy jest wiele tekstur wymiennych? parser.getTokens(); diff --git a/DynObj.h b/DynObj.h index 6ec6b1da..ef92fa25 100644 --- a/DynObj.h +++ b/DynObj.h @@ -598,8 +598,10 @@ private: void AttachNext(TDynamicObject *Object, int iType = 1); bool UpdateForce(double dt); // initiates load change by specified amounts, with a platform on specified side - void LoadExchange( int const Disembark, int const Embark, int const Platform ); - // calculates time needed to complete current load change + void LoadExchange( int const Disembark, int const Embark, int const Platforms ); + // calculates time needed to complete current load change, using specified platforms + float LoadExchangeTime( int const Platforms ); + // calculates time needed to complete current load change, using previously specified platforms float LoadExchangeTime() const; // calculates current load exchange factor, where 1 = nominal rate, higher = faster float LoadExchangeSpeed() const; // TODO: make private when cleaning up diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index a6519f3f..a0c9a6d8 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -609,42 +609,20 @@ bool TMoverParameters::DecBrakeLevel() bool TMoverParameters::ChangeCab(int direction) { // zmiana kabiny i resetowanie ustawien - if (abs(CabOccupied + direction) < 2) + if (std::abs(CabOccupied + direction) < 2) { - // if (CabOccupied+direction=0) then LastCab:=CabOccupied; CabOccupied = CabOccupied + direction; if( ( BrakeCtrlPosNo > 0 ) && ( ( BrakeSystem == TBrakeSystem::Pneumatic ) || ( BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) ) { - // if (BrakeHandle==FV4a) //!!!POBIERAĆ WARTOŚĆ Z KLASY ZAWORU!!! - // BrakeLevelSet(-2); //BrakeCtrlPos=-2; - // else if ((BrakeHandle==FVel6)||(BrakeHandle==St113)) - // BrakeLevelSet(2); - // else - // BrakeLevelSet(1); BrakeLevelSet(Handle->GetPos(bh_NP)); LimPipePress = PipePress; ActFlowSpeed = 0; } else - // if (TrainType=dt_EZT) and (BrakeCtrlPosNo>0) then - // BrakeCtrlPos:=5; //z Megapacka - // else - // BrakeLevelSet(0); //BrakeCtrlPos=0; BrakeLevelSet(Handle->GetPos(bh_NP)); - // if not TestFlag(BrakeStatus,b_dmg) then - // BrakeStatus:=b_off; //z Megapacka MainCtrlPos = MainCtrlNoPowerPos(); ScndCtrlPos = 0; - // Ra: to poniżej jest bez sensu - można przejść nie wyłączając - // if ((EngineType!=DieselEngine)&&(EngineType!=DieselElectric)) - //{ - // Mains=false; - // CompressorAllow=false; - // ConverterAllow=false; - //} - // DirActive=0; - // DirAbsolute=0; return true; } return false; @@ -6170,7 +6148,7 @@ double TMoverParameters::TractionForce( double dt ) { if( ( RlistSize > 0 ) && ( ( std::abs( eimv[ eimv_If ] ) > 1.0 ) - && ( tmpV > 0.1 ) ) ) { + && ( tmpV > 0.0001 ) ) ) { int i = 0; while( ( i < RlistSize - 1 ) diff --git a/MemCell.cpp b/MemCell.cpp index c8dca3e7..d8690a84 100644 --- a/MemCell.cpp +++ b/MemCell.cpp @@ -81,6 +81,11 @@ TCommandType TMemCell::CommandCheck() eCommand = TCommandType::cm_SetProximityVelocity; bCommand = false; // ta komenda nie jest wysyłana } + else if( szText == "Emergency_brake" ) + { + eCommand = TCommandType::cm_EmergencyBrake; + bCommand = false; + } else { eCommand = TCommandType::cm_Unknown; // ciąg nierozpoznany (nie jest komendą) diff --git a/driverkeyboardinput.cpp b/driverkeyboardinput.cpp index 55c2b659..008f6806 100644 --- a/driverkeyboardinput.cpp +++ b/driverkeyboardinput.cpp @@ -136,8 +136,8 @@ driverkeyboard_input::default_bindings() { { user_command::hornhighactivate, GLFW_KEY_S }, { user_command::whistleactivate, GLFW_KEY_Z }, { user_command::radiotoggle, GLFW_KEY_R | keymodifier::control }, - { user_command::radiochannelincrease, GLFW_KEY_R | keymodifier::shift }, - { user_command::radiochanneldecrease, GLFW_KEY_R }, + { user_command::radiochannelincrease, GLFW_KEY_EQUAL }, + { user_command::radiochanneldecrease, GLFW_KEY_MINUS }, { user_command::radiostopsend, GLFW_KEY_PAUSE | keymodifier::shift | keymodifier::control }, { user_command::radiostoptest, GLFW_KEY_R | keymodifier::shift | keymodifier::control }, { user_command::radiocall3send, GLFW_KEY_BACKSPACE }, diff --git a/driveruipanels.cpp b/driveruipanels.cpp index d9d5e2be..c535bbba 100644 --- a/driveruipanels.cpp +++ b/driveruipanels.cpp @@ -763,10 +763,12 @@ debug_panel::update_section_vehicle( std::vector &Output ) { locale::strings[ locale::string::debug_vehicle_brakespressures ].c_str(), // brakes mover.fBrakeCtrlPos, - mover.LocalBrakePosA, mover.BrakeOpModeFlag, update_vehicle_brake().c_str(), mover.LoadFlag, + mover.LocalBrakePosA, + ( mover.ManualBrakePos / ManualBrakePosNo ), + ( mover.SpringBrake.Activate ? 1.f : 0.f ), // cylinders mover.BrakePress, mover.LocBrakePress, diff --git a/mtable.cpp b/mtable.cpp index 3e6714f4..2fce8841 100644 --- a/mtable.cpp +++ b/mtable.cpp @@ -467,23 +467,24 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax) { auto const stationware { Split( record->StationWare, ',' ) }; for( auto const &entry : stationware ) { - if( entry.front() == 'R' ) { - auto const entrysplit { split_string_and_number( entry ) }; - if( ( entrysplit.first == "R" ) - && ( entrysplit.second <= 10 ) ) { - auto const radiochannel { entrysplit.second }; - if( ( record->radio_channel == -1 ) - || ( radiochannel != activeradiochannel ) ) { - // if the station has more than one radiochannel listed, - // it generally means we should switch to the one we weren't using so far - // TODO: reverse this behaviour (keep the channel used so far) once W28 signs are included in the system - record->radio_channel = radiochannel; - } + if( entry.front() != 'R' ) { + continue; + } + auto const entrysplit { split_string_and_number( entry ) }; + if( ( entrysplit.first == "R" ) + && ( entrysplit.second <= 10 ) ) { + auto const radiochannel { entrysplit.second }; + if( ( record->radio_channel == -1 ) + || ( radiochannel != activeradiochannel ) ) { + // if the station has more than one radiochannel listed, + // it generally means we should switch to the one we weren't using so far + // TODO: reverse this behaviour (keep the channel used so far) once W28 signs are included in the system + record->radio_channel = radiochannel; } } } if( record->radio_channel != -1 ) { - activeradiochannel == record->radio_channel; + activeradiochannel = record->radio_channel; } } record->TrackNo = atoi(s.c_str()); diff --git a/opengl33renderer.cpp b/opengl33renderer.cpp index abb7a5d9..8c7e7465 100644 --- a/opengl33renderer.cpp +++ b/opengl33renderer.cpp @@ -4112,7 +4112,7 @@ void opengl33_renderer::Update(double const Deltatime) // TODO: it doesn't make much sense with vsync if( Global.targetfps == 0.0f ) { // automatic adjustment - auto const framerate = interpolate( 1000.f / Timer::subsystem.gfx_color.average(), m_framerate, 0.25f ); + auto const framerate = interpolate( 1000.f / Timer::subsystem.gfx_color.average(), m_framerate, 0.75f ); float targetfactor; if( framerate > 120.0 ) { targetfactor = 3.00f; } else if( framerate > 90.0 ) { targetfactor = 1.50f; } diff --git a/openglrenderer.cpp b/openglrenderer.cpp index 601ee9a7..c1568d4d 100644 --- a/openglrenderer.cpp +++ b/openglrenderer.cpp @@ -4170,7 +4170,7 @@ opengl_renderer::Update( double const Deltatime ) { // adjust draw ranges etc, based on recent performance if( Global.targetfps == 0.0f ) { // automatic adjustment - auto const framerate = 0.5f * ( m_framerate + 1000.f / Timer::subsystem.gfx_color.average() ); + auto const framerate = interpolate( 1000.f / Timer::subsystem.gfx_color.average(), m_framerate, 0.75f ); float targetfactor; if( framerate > 120.0 ) { targetfactor = 3.00f; } else if( framerate > 90.0 ) { targetfactor = 1.50f; } diff --git a/parser.cpp b/parser.cpp index 7fc7d7c0..9d1dd943 100644 --- a/parser.cpp +++ b/parser.cpp @@ -211,6 +211,17 @@ std::string cParser::readToken( bool ToLower, const char *Break ) { } } while( token == "" && mStream->peek() != EOF ); // double check in case of consecutive separators } + // check the first token for potential presence of utf bom + if( mFirstToken ) { + mFirstToken = false; + if( token.rfind( "\xef\xbb\xbf", 0 ) == 0 ) { + token.erase( 0, 3 ); + } + if( true == token.empty() ) { + // potentially possible if our first token was standalone utf bom + token = readToken( ToLower, Break ); + } + } if( false == parameters.empty() ) { // if there's parameter list, check the token for potential parameters to replace diff --git a/parser.h b/parser.h index 2fb82f48..c3b00e9f 100644 --- a/parser.h +++ b/parser.h @@ -104,6 +104,7 @@ class cParser //: public std::stringstream std::streamoff mSize { 0 }; // size of open stream, for progress report. std::size_t mLine { 0 }; // currently processed line bool mIncFile { false }; // the parser is processing an *.inc file + bool mFirstToken { true }; // processing first token in the current file; helper used when checking for utf bom typedef std::map commentmap; commentmap mComments { commentmap::value_type( "/*", "*/" ), diff --git a/translation.cpp b/translation.cpp index 5eed05d5..ee79678b 100644 --- a/translation.cpp +++ b/translation.cpp @@ -76,7 +76,7 @@ init() { "Controllers:\n master: %d(%d), secondary: %s\nEngine output: %.1f, current: %.0f\nRevolutions:\n engine: %.0f, motors: %.0f\n engine fans: %.0f, motor fans: %.0f+%.0f, cooling fans: %.0f+%.0f", " (shunt mode)", "\nTemperatures:\n engine: %.2f, oil: %.2f, water: %.2f%c%.2f", - "Brakes:\n train: %.2f, independent: %.2f, mode: %d, delay: %s, load flag: %d\nBrake cylinder pressures:\n train: %.2f, independent: %.2f, status: 0x%.2x\nPipe pressures:\n brake: %.2f (hat: %.2f), main: %.2f, control: %.2f\nTank pressures:\n auxiliary: %.2f, main: %.2f, control: %.2f", + "Brakes:\n train: %.2f (mode: %d, delay: %s, load flag: %d)\n independent: %.2f, manual: %.2f, spring: %.2f\nBrake cylinder pressures:\n train: %.2f, independent: %.2f, status: 0x%.2x\nPipe pressures:\n brake: %.2f (hat: %.2f), main: %.2f, control: %.2f\nTank pressures:\n auxiliary: %.2f, main: %.2f, control: %.2f", " pantograph: %.2f%cMT", "Forces:\n tractive: %.1f, brake: %.1f, friction: %.2f%s\nAcceleration:\n tangential: %.2f, normal: %.2f (path radius: %s)\nVelocity: %.2f, distance traveled: %.2f\nPosition: [%.2f, %.2f, %.2f]", @@ -281,7 +281,7 @@ init() { "Nastawniki:\n glowny: %d(%d), dodatkowy: %s\nMoc silnika: %.1f, prad silnika: %.0f\nObroty:\n silnik: %.0f, motory: %.0f\n went.silnika: %.0f, went.motorow: %.0f+%.0f, went.chlodnicy: %.0f+%.0f", " (tryb manewrowy)", "\nTemperatury:\n silnik: %.2f, olej: %.2f, woda: %.2f%c%.2f", - "Hamulce:\n zespolony: %.2f, pomocniczy: %.2f, tryb: %d, nastawa: %s, ladunek: %d\nCisnienie w cylindrach:\n zespolony: %.2f, pomocniczy: %.2f, status: 0x%.2x\nCisnienia w przewodach:\n glowny: %.2f (kapturek: %.2f), zasilajacy: %.2f, kontrolny: %.2f\nCisnienia w zbiornikach:\n pomocniczy: %.2f, glowny: %.2f, sterujacy: %.2f", + "Hamulce:\n zespolony: %.2f (tryb: %d, nastawa: %s, ladunek: %d)\n pomocniczy: %.2f, postojowy: %.2f, sprezynowy: %.2f\nCisnienie w cylindrach:\n zespolony: %.2f, pomocniczy: %.2f, status: 0x%.2x\nCisnienia w przewodach:\n glowny: %.2f (kapturek: %.2f), zasilajacy: %.2f, kontrolny: %.2f\nCisnienia w zbiornikach:\n pomocniczy: %.2f, glowny: %.2f, sterujacy: %.2f", " pantograf: %.2f%cZG", "Sily:\n napedna: %.1f, hamowania: %.1f, tarcie: %.2f%s\nPrzyspieszenia:\n styczne: %.2f, normalne: %.2f (promien: %s)\nPredkosc: %.2f, pokonana odleglosc: %.2f\nPozycja: [%.2f, %.2f, %.2f]", diff --git a/version.h b/version.h index b192cd9c..c9dce266 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 20 -#define VERSION_MINOR 806 +#define VERSION_MINOR 824 #define VERSION_REVISION 0