From b5f334a1fad9a674257627e69510e8b644b586c3 Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Tue, 8 May 2018 16:18:08 +0200 Subject: [PATCH] build 180508. configurable maximum oil pressure, door closing animation delay, whistle sound, indicators for water temperature and oil pressure in controlled vehicle/unit, minor bug fixes --- Driver.cpp | 2 +- DynObj.cpp | 105 ++++++++++++++++++++++++++------------------ DynObj.h | 3 ++ Globals.cpp | 6 +++ Globals.h | 1 + McZapkie/MOVER.h | 5 ++- McZapkie/Mover.cpp | 71 ++++++++++++++++-------------- Train.cpp | 106 +++++++++++++++++++++++++-------------------- Train.h | 5 +++ World.cpp | 1 + command.cpp | 1 + command.h | 1 + keyboardinput.cpp | 4 +- mouseinput.cpp | 3 ++ translation.h | 1 + version.h | 2 +- 16 files changed, 192 insertions(+), 125 deletions(-) diff --git a/Driver.cpp b/Driver.cpp index 3c165ca6..42533eba 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -3515,7 +3515,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N if (NewValue1 > 0) { fWarningDuration = NewValue1; // czas trąbienia - mvOccupied->WarningSignal = (NewValue2 > 1) ? 2 : 1; // wysokość tonu + mvOccupied->WarningSignal = NewValue2; // horn combination flag } } else if (NewCommand == "Radio_channel") diff --git a/DynObj.cpp b/DynObj.cpp index 3b7b73bf..67e43ddd 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -555,9 +555,9 @@ void TDynamicObject::UpdateMirror( TAnim *pAnim ) { // only animate the mirror if it's located on the same end of the vehicle as the active cab auto const isactive { ( - ( ( pAnim->iNumber & 0xf ) >> 4 ) == ( MoverParameters->ActiveCab > 0 ? side::front : side::rear ) ? - 1.0 : - 0.0 ) }; + MoverParameters->ActiveCab > 0 ? ( ( pAnim->iNumber >> 4 ) == side::front ? 1.0 : 0.0 ) : + MoverParameters->ActiveCab < 0 ? ( ( pAnim->iNumber >> 4 ) == side::rear ? 1.0 : 0.0 ) : + 0.0 ) }; if( pAnim->iNumber & 1 ) pAnim->smAnimated->SetRotate( @@ -2025,7 +2025,7 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424" } if( true == setambient ) { // TODO: pull ambient temperature from environment data - MoverParameters->dizel_HeatSet( 15.f ); + MoverParameters->dizel_HeatSet( Global.AirTemperature ); } } // temperature /* else if (ActPar.substr(0, 1) == "") // tu mozna wpisac inny prefiks i inne rzeczy @@ -3636,21 +3636,29 @@ bool TDynamicObject::Update(double dt, double dt1) && ( true == MoverParameters->DoorLeftOpened ) ) { dDoorMoveL += dt1 * MoverParameters->DoorOpenSpeed; dDoorMoveL = std::min( dDoorMoveL, MoverParameters->DoorMaxShiftL ); + DoorDelayL = 0.f; } - if( ( dDoorMoveL > 0 ) + if( ( dDoorMoveL > 0.0 ) && ( false == MoverParameters->DoorLeftOpened ) ) { - dDoorMoveL -= dt1 * MoverParameters->DoorCloseSpeed; - dDoorMoveL = std::max( dDoorMoveL, 0.0 ); + DoorDelayL += dt1; + if( DoorDelayL > MoverParameters->DoorCloseDelay ) { + dDoorMoveL -= dt1 * MoverParameters->DoorCloseSpeed; + dDoorMoveL = std::max( dDoorMoveL, 0.0 ); + } } if( ( dDoorMoveR < MoverParameters->DoorMaxShiftR ) && ( true == MoverParameters->DoorRightOpened ) ) { dDoorMoveR += dt1 * MoverParameters->DoorOpenSpeed; dDoorMoveR = std::min( dDoorMoveR, MoverParameters->DoorMaxShiftR ); - } - if( ( dDoorMoveR > 0 ) + DoorDelayR = 0.f; + } + if( ( dDoorMoveR > 0.0 ) && ( false == MoverParameters->DoorRightOpened ) ) { - dDoorMoveR -= dt1 * MoverParameters->DoorCloseSpeed; - dDoorMoveR = std::max( dDoorMoveR, 0.0 ); + DoorDelayR += dt1; + if( DoorDelayR > MoverParameters->DoorCloseDelay ) { + dDoorMoveR -= dt1 * MoverParameters->DoorCloseSpeed; + dDoorMoveR = std::max( dDoorMoveR, 0.0 ); + } } // doorsteps if( ( dDoorstepMoveL < 1.0 ) @@ -3660,7 +3668,8 @@ bool TDynamicObject::Update(double dt, double dt1) dDoorstepMoveL + MoverParameters->PlatformSpeed * dt1 ); } if( ( dDoorstepMoveL > 0.0 ) - && ( false == MoverParameters->DoorLeftOpened ) ) { + && ( false == MoverParameters->DoorLeftOpened ) + && ( DoorDelayL > MoverParameters->DoorCloseDelay ) ) { dDoorstepMoveL = std::max( 0.0, dDoorstepMoveL - MoverParameters->PlatformSpeed * dt1 ); @@ -3672,7 +3681,8 @@ bool TDynamicObject::Update(double dt, double dt1) dDoorstepMoveR + MoverParameters->PlatformSpeed * dt1 ); } if( ( dDoorstepMoveR > 0.0 ) - && ( false == MoverParameters->DoorRightOpened ) ) { + && ( false == MoverParameters->DoorRightOpened ) + && ( DoorDelayR > MoverParameters->DoorCloseDelay ) ) { dDoorstepMoveR = std::max( 0.0, dDoorstepMoveR - MoverParameters->PlatformSpeed * dt1 ); @@ -3990,7 +4000,14 @@ void TDynamicObject::RenderSounds() { } // NBMX sygnal odjazdu if( MoverParameters->DoorClosureWarning ) { - if( MoverParameters->DepartureSignal ) { + if( ( MoverParameters->DepartureSignal ) +/* + || ( ( MoverParameters->DoorCloseCtrl = control::autonomous ) + && ( ( ( false == MoverParameters->DoorLeftOpened ) && ( dDoorMoveL > 0.0 ) ) + || ( ( false == MoverParameters->DoorRightOpened ) && ( dDoorMoveR > 0.0 ) ) ) ) +*/ + ) { + // for the autonomous doors play the warning automatically whenever a door is closing // MC: pod warunkiem ze jest zdefiniowane w chk sDepartureSignal.play( sound_flags::exclusive | sound_flags::looping ); } @@ -4056,6 +4073,12 @@ void TDynamicObject::RenderSounds() { else { sHorn2.stop(); } + if( TestFlag( MoverParameters->WarningSignal, 4 ) ) { + sHorn3.play( sound_flags::exclusive | sound_flags::looping ); + } + else { + sHorn3.stop(); + } // szum w czasie jazdy if( ( GetVelocity() > 0.5 ) && ( false == m_bogiesounds.empty() ) @@ -4452,43 +4475,37 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, ++co; } while ( (ile >= 0) && (co < ANIM_TYPES) ); //-1 to znacznik końca - parser.getTokens(); parser >> token; - } - } - - if( true == pAnimations.empty() ) { - // Ra: tworzenie tabeli animacji, jeśli jeszcze nie było - pAnimations.resize( iAnimations ); - int i, j, k = 0, sm = 0; - for (j = 0; j < ANIM_TYPES; ++j) - for (i = 0; i < iAnimType[j]; ++i) + pAnimations.resize( iAnimations ); + int i, j, k = 0, sm = 0; + for (j = 0; j < ANIM_TYPES; ++j) + for (i = 0; i < iAnimType[j]; ++i) + { + if (j == ANIM_PANTS) // zliczamy poprzednie animacje + if (!pants) + if (iAnimType[ANIM_PANTS]) // o ile jakieś pantografy są (a domyślnie są) + pants = &pAnimations[k]; // zapamiętanie na potrzeby wyszukania submodeli + pAnimations[k].iShift = sm; // przesunięcie do przydzielenia wskaźnika + sm += pAnimations[k++].TypeSet(j); // ustawienie typu animacji i zliczanie tablicowanych submodeli + } + if (sm) // o ile są bardziej złożone animacje { - if (j == ANIM_PANTS) // zliczamy poprzednie animacje - if (!pants) - if (iAnimType[ANIM_PANTS]) // o ile jakieś pantografy są (a domyślnie są) - pants = &pAnimations[k]; // zapamiętanie na potrzeby wyszukania submodeli - pAnimations[k].iShift = sm; // przesunięcie do przydzielenia wskaźnika - sm += pAnimations[k++].TypeSet(j); // ustawienie typu animacji i zliczanie tablicowanych submodeli + pAnimated = new TSubModel *[sm]; // tabela na animowane submodele + for (k = 0; k < iAnimations; ++k) + pAnimations[k].smElement = pAnimated + pAnimations[k].iShift; // przydzielenie wskaźnika do tabelki } - if (sm) // o ile są bardziej złożone animacje - { - pAnimated = new TSubModel *[sm]; // tabela na animowane submodele - for (k = 0; k < iAnimations; ++k) - pAnimations[k].smElement = pAnimated + pAnimations[k].iShift; // przydzielenie wskaźnika do tabelki } } - if(token == "lowpolyinterior:") { + else if(token == "lowpolyinterior:") { // ABu: wnetrze lowpoly parser.getTokens(); parser >> asModel; asModel = BaseDir + asModel; // McZapkie-200702 - dynamics maja swoje modele w dynamic/basedir Global.asCurrentTexturePath = BaseDir; // biezaca sciezka do tekstur to dynamic/... mdLowPolyInt = TModelsManager::GetModel(asModel, true); - // Global.asCurrentTexturePath=AnsiString(szTexturePath); //kiedyś uproszczone wnętrze mieszało tekstury nieba } - if( token == "brakemode:" ) { + else if( token == "brakemode:" ) { // Ra 15-01: gałka nastawy hamulca parser.getTokens(); parser >> asAnimName; @@ -4496,7 +4513,7 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, // jeszcze wczytać kąty obrotu dla poszczególnych ustawień } - if( token == "loadmode:" ) { + else if( token == "loadmode:" ) { // Ra 15-01: gałka nastawy hamulca parser.getTokens(); parser >> asAnimName; @@ -4566,7 +4583,7 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, // Ra: pantografy po nowemu mają literki i numerki } // Pantografy - Winger 160204 - if( token == "animpantrd1prefix:" ) { + else if( token == "animpantrd1prefix:" ) { // prefiks ramion dolnych 1 parser.getTokens(); parser >> token; float4x4 m; // macierz do wyliczenia pozycji i wektora ruchu pantografu @@ -4733,6 +4750,7 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, } } } + else if( token == "pantfactors:" ) { // Winger 010304: // parametry pantografow @@ -5153,12 +5171,17 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, // pliki z trabieniem wysokoton. sHorn2.deserialize( parser, sound_type::multipart, sound_parameters::range ); sHorn2.owner( this ); - + // TBD, TODO: move horn selection to ai config file if( iHornWarning ) { iHornWarning = 2; // numer syreny do użycia po otrzymaniu sygnału do jazdy } } + else if( token == "horn3:" ) { + sHorn3.deserialize( parser, sound_type::multipart, sound_parameters::range ); + sHorn3.owner( this ); + } + else if( token == "departuresignal:" ) { // pliki z sygnalem odjazdu sDepartureSignal.deserialize( parser, sound_type::multipart, sound_parameters::range ); diff --git a/DynObj.h b/DynObj.h index b2094cce..8ed4913e 100644 --- a/DynObj.h +++ b/DynObj.h @@ -267,6 +267,8 @@ private: public: TAnim *pants; // indeks obiektu animującego dla pantografu 0 double NoVoltTime; // czas od utraty zasilania + float DoorDelayL{ 0.f }; // left side door closing delay timer + float DoorDelayR{ 0.f }; // right side door closing delay timer double dDoorMoveL; // NBMX double dDoorMoveR; // NBMX double dDoorstepMoveL{ 0.0 }; @@ -418,6 +420,7 @@ private: sound_source sDepartureSignal { sound_placement::general }; sound_source sHorn1 { sound_placement::external, 5 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; sound_source sHorn2 { sound_placement::external, 5 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; + sound_source sHorn3 { sound_placement::external, 5 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; std::vector m_bogiesounds; // TBD, TODO: wrapper for all bogie-related sounds (noise, brakes, squeal etc) sound_source m_wheelflat { sound_placement::external, EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; sound_source rscurve { sound_placement::external, EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; // youBy diff --git a/Globals.cpp b/Globals.cpp index 0ef35fe2..4c1e9048 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -318,6 +318,12 @@ global_settings::ConfigParse(cParser &Parser) { Parser.getTokens( 1, false ); Parser >> ScenarioTimeCurrent; } + else if( token == "scenario.weather.temperature" ) { + // selected device for audio renderer + Parser.getTokens(); + Parser >> AirTemperature; + AirTemperature = clamp( AirTemperature, -15.f, 45.f ); + } else if( token == "scalespeculars" ) { // whether strength of specular highlights should be adjusted (generally needed for legacy 3d models) Parser.getTokens(); diff --git a/Globals.h b/Globals.h index 2a008830..f141c17e 100644 --- a/Globals.h +++ b/Globals.h @@ -45,6 +45,7 @@ struct global_settings { bool DLFont{ false }; // switch indicating presence of basic font bool bActive{ true }; // czy jest aktywnym oknem int iPause{ 0 }; // globalna pauza ruchu: b0=start,b1=klawisz,b2=tło,b3=lagi,b4=wczytywanie + float AirTemperature{ 15.f }; // settings // filesystem bool bLoadTraction{ true }; diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 4430987e..2507d7f6 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -637,6 +637,7 @@ struct oil_pump { start start_type { start::manual }; float resource_amount { 1.f }; float pressure_minimum { 0.f }; // lowest acceptable working pressure + float pressure_maximum { 0.f }; // oil pressure at maximum engine revolutions float pressure_target { 0.f }; float pressure_present { 0.f }; }; @@ -943,6 +944,7 @@ public: double DoorOpenSpeed = 1.0; double DoorCloseSpeed = 1.0; /*predkosc otwierania i zamykania w j.u. */ double DoorMaxShiftL = 0.5; double DoorMaxShiftR = 0.5; double DoorMaxPlugShift = 0.1;/*szerokosc otwarcia lub kat*/ int DoorOpenMethod = 2; /*sposob otwarcia - 1: przesuwne, 2: obrotowe, 3: trójelementowe*/ + float DoorCloseDelay { 0.f }; // delay (in seconds) before the door begin closing, once conditions to close are met double PlatformSpeed = 0.5; /*szybkosc stopnia*/ double PlatformMaxShift { 45.0 }; /*wysuniecie stopnia*/ int PlatformOpenMethod { 2 }; /*sposob animacji stopnia*/ @@ -1065,7 +1067,7 @@ public: 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) double LastSwitchingTime = 0.0; /*czas ostatniego przelaczania czegos*/ - //WarningSignal: byte; {0: nie trabi, 1,2: trabi} + int WarningSignal = 0; // 0: nie trabi, 1,2,4: trabi bool DepartureSignal = false; /*sygnal odjazdu*/ bool InsideConsist = false; /*-zmienne dla lokomotywy elektrycznej*/ @@ -1184,7 +1186,6 @@ public: double TotalMassxg = 0.0; /*TotalMass*g*/ Math3D::vector3 vCoulpler[2]; // powtórzenie współrzędnych sprzęgów z DynObj :/ - int WarningSignal = 0; // tymczasowo 8bit, ze względu na funkcje w MTools double fBrakeCtrlPos = -2.0; // płynna nastawa hamulca zespolonego bool bPantKurek3 = true; // kurek trójdrogowy (pantografu): true=połączenie z ZG, false=połączenie z małą sprężarką // domyślnie zbiornik pantografu połączony jest ze zbiornikiem głównym int iProblem = 0; // flagi problemów z taborem, aby AI nie musiało porównywać; 0=może jechać diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index a85795e3..c60fa0df 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -1613,10 +1613,9 @@ void TMoverParameters::OilPumpCheck( double const Timestep ) { OilPump.pressure_minimum > 0.f ? OilPump.pressure_minimum : 0.15f }; // arbitrary fallback value - auto const maxpressure { 0.65f }; // arbitrary value OilPump.pressure_target = ( - enrot > 0.1 ? interpolate( minpressure, maxpressure, static_cast( clamp( enrot / maxrevolutions, 0.0, 1.0 ) ) ) * OilPump.resource_amount : + enrot > 0.1 ? interpolate( minpressure, OilPump.pressure_maximum, static_cast( clamp( enrot / maxrevolutions, 0.0, 1.0 ) ) ) * OilPump.resource_amount : true == OilPump.is_active ? minpressure : 0.f ); @@ -6320,6 +6319,8 @@ void TMoverParameters::dizel_Heat( double const dt ) { auto const gwmin2 { 400.0 }; auto const gwmax2 { 4000.0 }; + dizel_heat.Te = Global.AirTemperature; + auto const engineon { ( Mains ? 1 : 0 ) }; auto const engineoff { ( Mains ? 0 : 1 ) }; auto const rpm { enrot * 60 }; @@ -6709,14 +6710,14 @@ TMoverParameters::update_autonomous_doors( double const Deltatime ) { // the door are closed if their timer goes below 0, or if the vehicle is moving at > 5 km/h // NOTE: timer value of 0 is 'special' as it means the door will stay open until vehicle is moving if( true == DoorLeftOpened ) { - if( ( DoorLeftOpenTimer < 0.0 ) + if( ( ( DoorStayOpen > 0.0 ) && ( DoorLeftOpenTimer < 0.0 ) ) || ( Vel > 5.0 ) ) { // close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving) DoorLeft( false, range::local ); } } if( true == DoorRightOpened ) { - if( ( DoorRightOpenTimer < 0.0 ) + if( ( ( DoorStayOpen > 0.0 ) && ( DoorRightOpenTimer < 0.0 ) ) || ( Vel > 5.0 ) ) { // close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving) DoorRight( false, range::local ); @@ -7861,6 +7862,7 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) { extract_value( DoorOpenSpeed, "OpenSpeed", line, "" ); extract_value( DoorCloseSpeed, "CloseSpeed", line, "" ); + extract_value( DoorCloseDelay, "DoorCloseDelay", line, "" ); extract_value( DoorMaxShiftL, "DoorMaxShiftL", line, "" ); extract_value( DoorMaxShiftR, "DoorMaxShiftR", line, "" ); extract_value( DoorMaxPlugShift, "DoorMaxShiftPlug", line, "" ); @@ -8363,7 +8365,6 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { extract_value(hydro_R_MinVel, "R_MinVel", Input, ""); } } - extract_value( OilPump.pressure_minimum, "MinOilPressure", Input, "" ); break; } case DieselElectric: { //youBy @@ -8384,7 +8385,6 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { ImaxHi = 2; ImaxLo = 1; } - extract_value( OilPump.pressure_minimum, "OilMinPressure", Input, "" ); break; } case ElectricInductionMotor: { @@ -8424,29 +8424,36 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { } } // engine type - // engine cooling factore - extract_value( dizel_heat.kw, "HeatKW", Input, "" ); - extract_value( dizel_heat.kv, "HeatKV", Input, "" ); - extract_value( dizel_heat.kfe, "HeatKFE", Input, "" ); - extract_value( dizel_heat.kfs, "HeatKFS", Input, "" ); - extract_value( dizel_heat.kfo, "HeatKFO", Input, "" ); - extract_value( dizel_heat.kfo2, "HeatKFO2", Input, "" ); - // engine cooling systems - extract_value( dizel_heat.water.config.temp_min, "WaterMinTemperature", Input, "" ); - extract_value( dizel_heat.water.config.temp_max, "WaterMaxTemperature", Input, "" ); - extract_value( dizel_heat.water.config.temp_flow, "WaterFlowTemperature", Input, "" ); - extract_value( dizel_heat.water.config.temp_cooling, "WaterCoolingTemperature", Input, "" ); - extract_value( dizel_heat.water.config.shutters, "WaterShutters", Input, "" ); - extract_value( dizel_heat.auxiliary_water_circuit, "WaterAuxCircuit", Input, "" ); - extract_value( dizel_heat.water_aux.config.temp_min, "WaterAuxMinTemperature", Input, "" ); - extract_value( dizel_heat.water_aux.config.temp_max, "WaterAuxMaxTemperature", Input, "" ); - extract_value( dizel_heat.water_aux.config.temp_cooling, "WaterAuxCoolingTemperature", Input, "" ); - extract_value( dizel_heat.water_aux.config.shutters, "WaterAuxShutters", Input, "" ); - extract_value( dizel_heat.oil.config.temp_min, "OilMinTemperature", Input, "" ); - extract_value( dizel_heat.oil.config.temp_max, "OilMaxTemperature", Input, "" ); - // water heater - extract_value( WaterHeater.config.temp_min, "HeaterMinTemperature", Input, "" ); - extract_value( WaterHeater.config.temp_max, "HeaterMaxTemperature", Input, "" ); + // NOTE: elements shared by both diesel engine variants; crude but, eh + if( ( EngineType == DieselEngine ) + || ( EngineType == DieselElectric ) ) { + // oil pump + extract_value( OilPump.pressure_minimum, "OilMinPressure", Input, "" ); + extract_value( OilPump.pressure_maximum, "OilMaxPressure", Input, "" ); + // engine cooling factore + extract_value( dizel_heat.kw, "HeatKW", Input, "" ); + extract_value( dizel_heat.kv, "HeatKV", Input, "" ); + extract_value( dizel_heat.kfe, "HeatKFE", Input, "" ); + extract_value( dizel_heat.kfs, "HeatKFS", Input, "" ); + extract_value( dizel_heat.kfo, "HeatKFO", Input, "" ); + extract_value( dizel_heat.kfo2, "HeatKFO2", Input, "" ); + // engine cooling systems + extract_value( dizel_heat.water.config.temp_min, "WaterMinTemperature", Input, "" ); + extract_value( dizel_heat.water.config.temp_max, "WaterMaxTemperature", Input, "" ); + extract_value( dizel_heat.water.config.temp_flow, "WaterFlowTemperature", Input, "" ); + extract_value( dizel_heat.water.config.temp_cooling, "WaterCoolingTemperature", Input, "" ); + extract_value( dizel_heat.water.config.shutters, "WaterShutters", Input, "" ); + extract_value( dizel_heat.auxiliary_water_circuit, "WaterAuxCircuit", Input, "" ); + extract_value( dizel_heat.water_aux.config.temp_min, "WaterAuxMinTemperature", Input, "" ); + extract_value( dizel_heat.water_aux.config.temp_max, "WaterAuxMaxTemperature", Input, "" ); + extract_value( dizel_heat.water_aux.config.temp_cooling, "WaterAuxCoolingTemperature", Input, "" ); + extract_value( dizel_heat.water_aux.config.shutters, "WaterAuxShutters", Input, "" ); + extract_value( dizel_heat.oil.config.temp_min, "OilMinTemperature", Input, "" ); + extract_value( dizel_heat.oil.config.temp_max, "OilMaxTemperature", Input, "" ); + // water heater + extract_value( WaterHeater.config.temp_min, "HeaterMinTemperature", Input, "" ); + extract_value( WaterHeater.config.temp_max, "HeaterMaxTemperature", Input, "" ); + } } void TMoverParameters::LoadFIZ_Switches( std::string const &Input ) { @@ -9299,9 +9306,9 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C } else if (Command == "DoorOpen") /*NBMX*/ { // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów - if( ( DoorCloseCtrl == control::conductor ) - || ( DoorCloseCtrl == control::driver ) - || ( DoorCloseCtrl == control::mixed ) ) { + if( ( DoorOpenCtrl == control::conductor ) + || ( DoorOpenCtrl == control::driver ) + || ( DoorOpenCtrl == control::mixed ) ) { // ignore remote command if the door is only operated locally if( CValue2 > 0 ) { // normalne ustawienie pojazdu diff --git a/Train.cpp b/Train.cpp index bcba552d..3124b6e0 100644 --- a/Train.cpp +++ b/Train.cpp @@ -308,6 +308,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::departureannounce, &TTrain::OnCommand_departureannounce }, { user_command::hornlowactivate, &TTrain::OnCommand_hornlowactivate }, { user_command::hornhighactivate, &TTrain::OnCommand_hornhighactivate }, + { user_command::whistleactivate, &TTrain::OnCommand_whistleactivate }, { user_command::radiotoggle, &TTrain::OnCommand_radiotoggle }, { user_command::radiochannelincrease, &TTrain::OnCommand_radiochannelincrease }, { user_command::radiochanneldecrease, &TTrain::OnCommand_radiochanneldecrease }, @@ -382,25 +383,18 @@ TTrain::TTrain() { bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d) { // powiązanie ręcznego sterowania kabiną z pojazdem - // Global.pUserDynamic=NewDynamicObject; //pojazd renderowany bez trzęsienia + if( NewDynamicObject->Mechanik == nullptr ) { + ErrorLog( "Bad config: can't take control of inactive vehicle \"" + NewDynamicObject->asName + "\"" ); + return false; + } + DynamicSet(NewDynamicObject); if (!e3d) if (DynamicObject->Mechanik == NULL) return false; - // if (DynamicObject->Mechanik->AIControllFlag==AIdriver) - // return false; + DynamicObject->MechInside = true; - /* iPozSzereg=28; - for (int i=1; iMainCtrlPosNo; i++) - { - if (mvControlled->RList[i].Bn>1) - { - iPozSzereg=i-1; - i=mvControlled->MainCtrlPosNo+1; - } - } - */ MechSpring.Init(125.0); vMechVelocity = Math3D::vector3(0, 0, 0); pMechOffset = Math3D::vector3( 0, 0, 0 ); @@ -416,25 +410,6 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d) return false; } - // McZapkie: w razie wykolejenia - // dsbDerailment=TSoundsManager::GetFromName("derail.wav"); - // McZapkie: jazda luzem: - // dsbRunningNoise=TSoundsManager::GetFromName("runningnoise.wav"); - - // McZapkie? - dzwieki slyszalne tylko wewnatrz kabiny - generowane przez - // obiekt sterowany: - - // McZapkie-080302 sWentylatory.Init("wenton.wav","went.wav","wentoff.wav"); - // McZapkie-010302 - // sCompressor.Init("compressor-start.wav","compressor.wav","compressor-stop.wav"); - - // sHorn1.Init("horn1.wav",0.3); - // sHorn2.Init("horn2.wav",0.3); - - // sHorn1.Init("horn1-start.wav","horn1.wav","horn1-stop.wav"); - // sHorn2.Init("horn2-start.wav","horn2.wav","horn2-stop.wav"); - - // sConverter.Init("converter.wav",1.5); //NBMX obsluga przez AdvSound iCabn = 0; // Ra: taka proteza - przesłanie kierunku do członów connected if (mvControlled->ActiveDir > 0) @@ -3895,6 +3870,32 @@ void TTrain::OnCommand_hornhighactivate( TTrain *Train, command_data const &Comm } } +void TTrain::OnCommand_whistleactivate( TTrain *Train, command_data const &Command ) { + + if( Train->ggWhistleButton.SubModel == nullptr ) { + if( Command.action == GLFW_PRESS ) { + WriteLog( "Whistle button is missing, or wasn't defined" ); + } + return; + } + + if( Command.action == GLFW_PRESS ) { + // only need to react to press, sound will continue until stopped + if( false == TestFlag( Train->mvOccupied->WarningSignal, 4 ) ) { + // turn on + Train->mvOccupied->WarningSignal |= 4; + // visual feedback + Train->ggWhistleButton.UpdateValue( 1.0 ); + } + } + else if( Command.action == GLFW_RELEASE ) { + // turn off + Train->mvOccupied->WarningSignal &= ~4; + // visual feedback + Train->ggWhistleButton.UpdateValue( 0.0 ); + } +} + void TTrain::OnCommand_radiotoggle( TTrain *Train, command_data const &Command ) { if( Train->ggRadioButton.SubModel == nullptr ) { @@ -4530,30 +4531,34 @@ bool TTrain::Update( double const Deltatime ) if ((TestFlag(mvControlled->Couplers[0].CouplingFlag, ctrain_controll)) && (mvOccupied->ActiveCab == -1)) tmp = DynamicObject->PrevConnected; - if (tmp) - if (tmp->MoverParameters->Power > 0) - { - if (ggI1B.SubModel) - { - ggI1B.UpdateValue(tmp->MoverParameters->ShowCurrent(1)); + if( tmp ) { + if( tmp->MoverParameters->Power > 0 ) { + if( ggI1B.SubModel ) { + ggI1B.UpdateValue( tmp->MoverParameters->ShowCurrent( 1 ) ); ggI1B.Update(); } - if (ggI2B.SubModel) - { - ggI2B.UpdateValue(tmp->MoverParameters->ShowCurrent(2)); + if( ggI2B.SubModel ) { + ggI2B.UpdateValue( tmp->MoverParameters->ShowCurrent( 2 ) ); ggI2B.Update(); } - if (ggI3B.SubModel) - { - ggI3B.UpdateValue(tmp->MoverParameters->ShowCurrent(3)); + if( ggI3B.SubModel ) { + ggI3B.UpdateValue( tmp->MoverParameters->ShowCurrent( 3 ) ); ggI3B.Update(); } - if (ggItotalB.SubModel) - { - ggItotalB.UpdateValue(tmp->MoverParameters->ShowCurrent(0)); + if( ggItotalB.SubModel ) { + ggItotalB.UpdateValue( tmp->MoverParameters->ShowCurrent( 0 ) ); ggItotalB.Update(); } + if( ggWater1TempB.SubModel ) { + ggWater1TempB.UpdateValue( tmp->MoverParameters->dizel_heat.temperatura1 ); + ggWater1TempB.Update(); + } + if( ggOilPressB.SubModel ) { + ggOilPressB.UpdateValue( tmp->MoverParameters->OilPump.pressure_present ); + ggOilPressB.Update(); + } } + } } // McZapkie-300302: zegarek if (ggClockMInd.SubModel) @@ -5213,6 +5218,7 @@ bool TTrain::Update( double const Deltatime ) ggHornButton.Update(); ggHornLowButton.Update(); ggHornHighButton.Update(); + ggWhistleButton.Update(); for( auto &universal : ggUniversals ) { universal.Update(); } @@ -6235,6 +6241,7 @@ void TTrain::clear_cab_controls() ggHornButton.Clear(); ggHornLowButton.Clear(); ggHornHighButton.Clear(); + ggWhistleButton.Clear(); ggNextCurrentButton.Clear(); for( auto &universal : ggUniversals ) { universal.Clear(); @@ -6272,6 +6279,8 @@ void TTrain::clear_cab_controls() ggI2B.Clear(); ggI3B.Clear(); ggItotalB.Clear(); + ggOilPressB.Clear(); + ggWater1TempB.Clear(); ggClockSInd.Clear(); ggClockMInd.Clear(); @@ -6741,6 +6750,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "horn_bt:", ggHornButton }, { "hornlow_bt:", ggHornLowButton }, { "hornhigh_bt:", ggHornHighButton }, + { "whistle_bt:", ggHornHighButton }, { "fuse_bt:", ggFuseButton }, { "converterfuse_bt:", ggConverterFuseButton }, { "stlinoff_bt:", ggStLinOffButton }, @@ -6769,9 +6779,11 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "waterpump_sw:", ggWaterPumpButton }, { "waterheaterbreaker_sw:", ggWaterHeaterBreakerButton }, { "waterheater_sw:", ggWaterHeaterButton }, + { "water1tempb:", ggWater1TempB }, { "watercircuitslink_sw:", ggWaterCircuitsLinkButton }, { "fuelpump_sw:", ggFuelPumpButton }, { "oilpump_sw:", ggOilPumpButton }, + { "oilpressb:", ggOilPressB }, { "radio_sw:", ggRadioButton }, { "radiochannel_sw:", ggRadioChannelSelector }, { "radiochannelprev_sw:", ggRadioChannelPrevious }, diff --git a/Train.h b/Train.h index 5880dc47..b5bbd429 100644 --- a/Train.h +++ b/Train.h @@ -299,6 +299,7 @@ class TTrain static void OnCommand_departureannounce( TTrain *Train, command_data const &Command ); static void OnCommand_hornlowactivate( TTrain *Train, command_data const &Command ); static void OnCommand_hornhighactivate( TTrain *Train, command_data const &Command ); + static void OnCommand_whistleactivate( TTrain *Train, command_data const &Command ); static void OnCommand_radiotoggle( TTrain *Train, command_data const &Command ); static void OnCommand_radiochannelincrease( TTrain *Train, command_data const &Command ); static void OnCommand_radiochanneldecrease( TTrain *Train, command_data const &Command ); @@ -336,6 +337,9 @@ public: // reszta może by?publiczna TGauge ggI3B; TGauge ggItotalB; + TGauge ggOilPressB; + TGauge ggWater1TempB; + // McZapkie: definicje regulatorow TGauge ggMainCtrl; TGauge ggMainCtrlAct; @@ -395,6 +399,7 @@ public: // reszta może by?publiczna TGauge ggHornButton; TGauge ggHornLowButton; TGauge ggHornHighButton; + TGauge ggWhistleButton; TGauge ggNextCurrentButton; std::array ggUniversals; // NOTE: temporary arrangement until we have dynamically built control table diff --git a/World.cpp b/World.cpp index 014967e7..0e3f20ea 100644 --- a/World.cpp +++ b/World.cpp @@ -263,6 +263,7 @@ bool TWorld::Init( GLFWwindow *Window ) { FreeFlyModeFlag = true; // Ra: automatycznie włączone latanie Controlled = NULL; mvControlled = NULL; + SafeDelete( Train ); Camera.Type = tp_Free; } } diff --git a/command.cpp b/command.cpp index 657e99b8..bcc640d7 100644 --- a/command.cpp +++ b/command.cpp @@ -115,6 +115,7 @@ commanddescription_sequence Commands_descriptions = { { "alerteracknowledge", command_target::vehicle }, { "hornlowactivate", command_target::vehicle }, { "hornhighactivate", command_target::vehicle }, + { "whistleactivate", command_target::vehicle }, { "radiotoggle", command_target::vehicle }, { "radiochannelincrease", command_target::vehicle }, { "radiochanneldecrease", command_target::vehicle }, diff --git a/command.h b/command.h index 96ecefd5..547ea93c 100644 --- a/command.h +++ b/command.h @@ -109,6 +109,7 @@ enum class user_command { alerteracknowledge, hornlowactivate, hornhighactivate, + whistleactivate, radiotoggle, radiochannelincrease, radiochanneldecrease, diff --git a/keyboardinput.cpp b/keyboardinput.cpp index e092e5c9..e12d1072 100644 --- a/keyboardinput.cpp +++ b/keyboardinput.cpp @@ -358,7 +358,9 @@ keyboard_input::default_bindings() { // hornlowactivate { GLFW_KEY_A }, // hornhighactivate - { GLFW_KEY_A | keymodifier::shift }, + { GLFW_KEY_S }, + // whistleactivate + { GLFW_KEY_Z }, // radiotoggle { GLFW_KEY_R | keymodifier::control }, // radiochannelincrease diff --git a/mouseinput.cpp b/mouseinput.cpp index 6d8bbda2..ba9e7288 100644 --- a/mouseinput.cpp +++ b/mouseinput.cpp @@ -291,6 +291,9 @@ mouse_input::default_bindings() { { "hornhigh_bt:", { user_command::hornhighactivate, user_command::none } }, + { "whistle_bt:", { + user_command::whistleactivate, + user_command::none } }, { "fuse_bt:", { user_command::motoroverloadrelayreset, user_command::none } }, diff --git a/translation.h b/translation.h index d48cd8ce..5c35b97c 100644 --- a/translation.h +++ b/translation.h @@ -46,6 +46,7 @@ static std::unordered_map m_cabcontrols = { { "horn_bt:", "horn" }, { "hornlow_bt:", "low tone horn" }, { "hornhigh_bt:", "high tone horn" }, + { "whistle_bt:", "whistle" }, { "fuse_bt:", "motor overload relay reset" }, { "converterfuse_bt:", "converter overload relay reset" }, { "stlinoff_bt:", "motor connectors" }, diff --git a/version.h b/version.h index 96a56e56..6e8f9b75 100644 --- a/version.h +++ b/version.h @@ -1,5 +1,5 @@ #pragma once #define VERSION_MAJOR 18 -#define VERSION_MINOR 505 +#define VERSION_MINOR 508 #define VERSION_REVISION 0