diff --git a/Driver.cpp b/Driver.cpp index ce3d6108..c0882d8e 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -153,6 +153,8 @@ const double EasyReactionTime = 0.5; //[s] przebłyski świadomości dla zwykłe const double HardReactionTime = 0.2; const double EasyAcceleration = 0.85; //[m/ss] const double HardAcceleration = 9.81; +const double PassengetTrainAcceleration = 0.40; +const double HeavyPassengetTrainAcceleration = 0.20; const double CargoTrainAcceleration = 0.25; const double HeavyCargoTrainAcceleration = 0.10; const double PrepareTime = 2.0; //[s] przebłyski świadomości przy odpalaniu @@ -2065,6 +2067,7 @@ void TController::AutoRewident() fBrake_a1[i+1] /= (12*fMass); } + IsPassengerTrain = ( mvOccupied->CategoryFlag == 1 ) && ( mvOccupied->TrainType != dt_EZT ) && ( mvOccupied->TrainType != dt_DMU ) && ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) == 0 ); IsCargoTrain = ( mvOccupied->CategoryFlag == 1 ) && ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ); IsHeavyCargoTrain = ( true == IsCargoTrain ) && ( fBrake_a0[ 1 ] > 0.4 ) && ( iVehicles - ControlledEnginesCount > 0 ) && ( fMass / iVehicles > 50000 ); @@ -6235,6 +6238,9 @@ TController::UpdateSituation(double dt) { } // HACK: limit acceleration for cargo trains, to reduce probability of breaking couplers on sudden jolts // TBD: expand this behaviour to all trains with car(s) exceeding certain weight? + if( ( IsPassengerTrain ) && ( iVehicles - ControlledEnginesCount > 0 ) ) { + AccDesired = std::min( AccDesired, ( iVehicles - ControlledEnginesCount > 8 ? HeavyPassengetTrainAcceleration : PassengetTrainAcceleration ) ); + } if( ( IsCargoTrain ) && ( iVehicles - ControlledEnginesCount > 0 ) ) { AccDesired = std::min( AccDesired, CargoTrainAcceleration ); } diff --git a/Driver.h b/Driver.h index e71f50ed..e1cab36f 100644 --- a/Driver.h +++ b/Driver.h @@ -472,6 +472,7 @@ private: int iVehicles = 0; // ilość pojazdów w składzie int ControlledEnginesCount{ 0 }; // number of powered vehicles under driver's control bool iEngineActive{ false }; // ABu: Czy silnik byl juz zalaczony + bool IsPassengerTrain{ false }; bool IsCargoTrain{ false }; bool IsHeavyCargoTrain{ false }; double fReady = 0.0; // poziom odhamowania wagonów diff --git a/DynObj.cpp b/DynObj.cpp index aad37478..deb9ece5 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -686,7 +686,7 @@ TDynamicObject::toggle_lights() { ( sectionname.find( "compartment" ) == 0 ) || ( sectionname.find( "przedzial" ) == 0 ) ) { // compartments are lit with 75% probability - section.light_level = ( Random() < 0.75 ? 0.75f : 0.15f ); + section.light_level = ( Random() < 0.75 ? 0.75f : 0.10f ); } } SectionLightsActive = true; @@ -1119,21 +1119,22 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist) } } // load chunks visibility - for( auto const §ion : SectionLoadVisibility ) { - section.submodel->iVisible = section.visible; - if( false == section.visible ) { - // if the section root isn't visible we can skip meddling with its children - continue; - } + for( auto const §ion : Sections ) { + // section isn't guaranteed to have load model, so check that first + if( section.load == nullptr ) { continue; } + section.load->iVisible = ( section.load_chunks_visible > 0 ); + // if the section root isn't visible we can skip meddling with its children + if( false == section.load->iVisible ) { continue; } // if the section root is visible set the state of section chunks - auto *sectionchunk { section.submodel->ChildGet() }; - auto visiblechunkcount { section.visible_chunks }; + auto *sectionchunk { section.load->ChildGet() }; + auto visiblechunkcount { section.load_chunks_visible }; while( sectionchunk != nullptr ) { sectionchunk->iVisible = ( visiblechunkcount > 0 ); --visiblechunkcount; sectionchunk = sectionchunk->NextGet(); } } + // driver cabs visibility for( int cabidx = 0; cabidx < LowPolyIntCabs.size(); ++cabidx ) { if( LowPolyIntCabs[ cabidx ] == nullptr ) { continue; } @@ -2136,15 +2137,15 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424" // TODO: definition of relevant compartments in the .mmd file TSubModel *submodel { nullptr }; if( ( submodel = mdLowPolyInt->GetFromName( "cab0" ) ) != nullptr ) { - Sections.push_back( { submodel, nullptr, 0.0f } ); + Sections.push_back( { submodel, nullptr, 0, 0.0f } ); LowPolyIntCabs[ 0 ] = submodel; } if( ( submodel = mdLowPolyInt->GetFromName( "cab1" ) ) != nullptr ) { - Sections.push_back( { submodel, nullptr, 0.0f } ); + Sections.push_back( { submodel, nullptr, 0, 0.0f } ); LowPolyIntCabs[ 1 ] = submodel; } if( ( submodel = mdLowPolyInt->GetFromName( "cab2" ) ) != nullptr ) { - Sections.push_back( { submodel, nullptr, 0.0f } ); + Sections.push_back( { submodel, nullptr, 0, 0.0f } ); LowPolyIntCabs[ 2 ] = submodel; } // passenger car compartments @@ -2280,6 +2281,7 @@ TDynamicObject::init_sections( TModel3d const *Model, std::string const &Namepre Sections.push_back( { sectionsubmodel, nullptr, // pointers to load sections are generated afterwards + 0, 0.0f } ); ++sectioncount; } @@ -2723,58 +2725,49 @@ void TDynamicObject::LoadUpdate() { void TDynamicObject::update_load_sections() { - SectionLoadVisibility.clear(); + SectionLoadOrder.clear(); for( auto §ion : Sections ) { section.load = GetSubmodelFromName( mdLoad, section.compartment->pName ); - if( ( section.load != nullptr ) - && ( section.load->count_children() > 0 ) ) { - SectionLoadVisibility.push_back( { section.load, false } ); + if( section.load != nullptr ) { + // create entry for each load model chunk assigned to the section + // TBD, TODO: store also pointer to chunk submodel and control its visibility more directly, instead of per-section visibility flag? + auto loadchunkcount { section.load->count_children() }; + while( loadchunkcount-- ) { + SectionLoadOrder.push_back( §ion ); + } // HACK: disable automatic self-illumination threshold, at least until 3d model update if( MoverParameters->CompartmentLights.start_type == start_t::manual ) { section.load->SetSelfIllum( 2.0f, true, false ); } } } - shuffle_load_sections(); + shuffle_load_order(); } void TDynamicObject::update_load_visibility() { -/* - if( Random() < 0.25 ) { - shuffle_load_sections(); + // start with clean load chunk visibility slate + for( auto §ion : Sections ) { + section.load_chunks_visible = 0; } -*/ - auto loadpercentage { ( + // each entry in load order sequence matches a single chunk of the section it points to + // the length of load order sequence matches total number of load chunks + auto const loadpercentage { ( MoverParameters->MaxLoad == 0.f ? 0.0 : - 100.0 * MoverParameters->LoadAmount / MoverParameters->MaxLoad ) }; - auto const sectionloadpercentage { ( - SectionLoadVisibility.empty() ? - 0.0 : - 100.0 / SectionLoadVisibility.size() ) }; - // set as many sections as we can, given overall load percentage and how much of full percentage is covered by each chunk - std::for_each( - std::begin( SectionLoadVisibility ), std::end( SectionLoadVisibility ), - [&]( section_visibility §ion ) { - section.visible = ( loadpercentage > 0.0 ); - section.visible_chunks = 0; - auto const sectionchunkcount { section.submodel->count_children() }; - auto const sectionchunkloadpercentage{ ( - sectionchunkcount == 0 ? - 0.0 : - sectionloadpercentage / sectionchunkcount ) }; - auto *sectionchunk { section.submodel->ChildGet() }; - while( sectionchunk != nullptr ) { - if( loadpercentage > 0.0 ) { - ++section.visible_chunks; - loadpercentage -= sectionchunkloadpercentage; - } - sectionchunk = sectionchunk->NextGet(); - } } ); + MoverParameters->LoadAmount / MoverParameters->MaxLoad ) }; + auto visiblechunkcount { ( + SectionLoadOrder.empty() ? + 0 : + static_cast( std::ceil( loadpercentage * SectionLoadOrder.size() ) ) ) }; + for( auto *section : SectionLoadOrder ) { + if( visiblechunkcount == 0 ) { break; } + section->load_chunks_visible++; + --visiblechunkcount; + } } void @@ -2791,16 +2784,16 @@ TDynamicObject::update_load_offset() { } void -TDynamicObject::shuffle_load_sections() { +TDynamicObject::shuffle_load_order() { - std::shuffle( std::begin( SectionLoadVisibility ), std::end( SectionLoadVisibility ), Global.random_engine ); + std::shuffle( std::begin( SectionLoadOrder ), std::end( SectionLoadOrder ), Global.random_engine ); // shift chunks assigned to corridors to the end of the list, so they show up last std::stable_partition( - std::begin( SectionLoadVisibility ), std::end( SectionLoadVisibility ), - []( section_visibility const §ion ) { + std::begin( SectionLoadOrder ), std::end( SectionLoadOrder ), + []( vehicle_section const *section ) { return ( - ( section.submodel->pName.find( "compartment" ) == 0 ) - || ( section.submodel->pName.find( "przedzial" ) == 0 ) ); } ); + ( section->compartment->pName.find( "compartment" ) == 0 ) + || ( section->compartment->pName.find( "przedzial" ) == 0 ) ); } ); // NOTE: potentially we're left with a mix of corridor and external section loads // but that's not necessarily a wrong outcome, so we leave it this way for the time being } diff --git a/DynObj.h b/DynObj.h index 3492589a..b3891864 100644 --- a/DynObj.h +++ b/DynObj.h @@ -230,16 +230,12 @@ public: struct vehicle_section { TSubModel *compartment; TSubModel *load; + int load_chunks_visible; float light_level; }; std::vector Sections; // table of recognized vehicle sections bool SectionLightsActive { false }; // flag indicating whether section lights were set. - struct section_visibility { - TSubModel *submodel; - bool visible; - int visible_chunks; - }; - std::vector SectionLoadVisibility; // visibility of specific sections of the load 3d model + std::vector SectionLoadOrder; // helper, activation/deactivation load chunk sequence private: // zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe @@ -574,7 +570,7 @@ private: void update_load_sections(); void update_load_visibility(); void update_load_offset(); - void shuffle_load_sections(); + void shuffle_load_order(); void update_destinations(); bool Update(double dt, double dt1); bool FastUpdate(double dt); diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index c9377c06..1a2dbf4f 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -10994,7 +10994,6 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) WriteLog( "XBT EStED" ); Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); Hamulec->SetRM( RapidMult ); - Hamulec->SetRV( RapidVel ); if( MBPM < 2 ) { //jesli przystawka wazaca Hamulec->SetLP( 0, MaxBrakePress[ 3 ], 0 ); @@ -11017,7 +11016,6 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); Hamulec->SetLP( Mass, MBPM, MaxBrakePress[1] ); Hamulec->SetRM( RapidMult ); - Hamulec->SetRV( RapidVel ); break; } case TBrakeValve::CV1: @@ -11037,6 +11035,7 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) } Hamulec->SetASBP( MaxBrakePress[ 4 ] ); + Hamulec->SetRV( RapidVel ); switch( BrakeHandle ) { case TBrakeHandle::FV4a: diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index 2127d2f5..2e43eaba 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -1685,11 +1685,6 @@ void TEStED::SetLP( double const TM, double const LM, double const TBP ) TareBP = TBP; } -void TEStED::SetRV(double const RVR) -{ - RV = RVR; -} - //---DAKO CV1--- void TCV1::CheckState( double const BCP, double &dV1 ) @@ -2137,13 +2132,13 @@ double TKE::GetPF( double const PP, double const dt, double const Vel ) if (!((typeid(*FM) == typeid(TDisk1)) || (typeid(*FM) == typeid(TDisk2)))) // jesli zeliwo to schodz RapidStatus = ((BrakeDelayFlag & bdelay_R) == bdelay_R) && - (((Vel > 50) && (RapidStatus)) || (Vel > 70)); + ((RV < 0) || ((Vel > RV) && (RapidStatus)) || (Vel > (RV + 20))); else // jesli tarczowki, to zostan RapidStatus = ((BrakeDelayFlag & bdelay_R) == bdelay_R); // temp:=1.9-0.9*int(RapidStatus); - if ((RM * RM > 0.1)) // jesli jest rapid + if ((RM * RM > 0.001)) // jesli jest rapid if ((RM > 0)) // jesli dodatni (naddatek); temp = 1 - RM * int(RapidStatus); else diff --git a/McZapkie/hamulce.h b/McZapkie/hamulce.h index 58a90a00..17ae713d 100644 --- a/McZapkie/hamulce.h +++ b/McZapkie/hamulce.h @@ -192,8 +192,9 @@ class TBrake { double SizeBC = 0.0; //rozmiar^2 CH (w stosunku do 14") bool DCV = false; //podwojny zawor zwrotny double ASBP = 0.0; //cisnienie hamulca pp - int UniversalFlag = 0; //flaga wcisnietych przyciskow uniwersalnych + double RV = 0.0; // rapid activation vehicle velocity threshold + int UniversalFlag = 0; //flaga wcisnietych przyciskow uniwersalnych int BrakeStatus{ b_off }; //flaga stanu int SoundFlag = 0; @@ -216,7 +217,7 @@ class TBrake { bool Releaser() const; virtual void SetEPS( double const nEPS ); //hamulec EP virtual void SetRM( double const RMR ) {}; //ustalenie przelozenia rapida - virtual void SetRV( double const RVR) {}; //ustalenie przelozenia rapida + virtual void SetRV( double const RVR ) { RV = RVR; }; //ustalenie przelozenia rapida virtual void SetLP(double const TM, double const LM, double const TBP) {}; //parametry przystawki wazacej virtual void SetLBP(double const P) {}; //cisnienie z hamulca pomocniczego virtual void PLC(double const mass) {}; //wspolczynnik cisnienia przystawki wazacej @@ -347,7 +348,6 @@ class TLSt : public TESt4R { protected: double LBP = 0.0; //cisnienie hamulca pomocniczego double RM = 0.0; //przelozenie rapida - double RV = 0.0; double EDFlag = 0.0; //luzowanie hamulca z powodu zalaczonego ED public: @@ -383,7 +383,6 @@ class TEStED : public TLSt { //zawor z EP09 - Est4 z oddzielnym przekladnikiem, double GetEDBCP()/*override*/; //cisnienie tylko z hamulca zasadniczego, uzywane do hamulca ED void PLC(double const mass); //wspolczynnik cisnienia przystawki wazacej void SetLP( double const TM, double const LM, double const TBP ); //parametry przystawki wazacej - void SetRV(double const RVR); //ustalenie predkosci przelaczenia rapida inline TEStED(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TLSt( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) diff --git a/translation.cpp b/translation.cpp index 39a8e207..4a874618 100644 --- a/translation.cpp +++ b/translation.cpp @@ -166,10 +166,10 @@ init() { "right marker light", "light pattern", "rear upper headlight", - "rear left headlight", "rear right headlight", - "rear left marker light", + "rear left headlight", "rear right marker light", + "rear left marker light", "compressor", "local compressor", "converter", @@ -368,10 +368,10 @@ init() { "sygnal prawy", "programator swiatel", "tylny reflektor gorny", - "tylny reflektor lewy", "tylny reflektor prawy", - "tylny sygnal lewy", + "tylny reflektor lewy", "tylny sygnal prawy", + "tylny sygnal lewy", "sprezarka", "sprezarka lokalna", "przetwornica",