From c75f7138b82c6bb889678c666c3601d57c2a0aea Mon Sep 17 00:00:00 2001 From: tmj-fstate Date: Mon, 12 Feb 2018 16:19:53 +0100 Subject: [PATCH] basic weather-based texture selection, additional control commands, minor line breaker logic fixes --- McZapkie/Mover.cpp | 67 +++++++---- Train.cpp | 289 +++++++++++++++++++++++++++++---------------- Train.h | 8 +- World.cpp | 17 +++ World.h | 2 + command.cpp | 4 + command.h | 4 + keyboardinput.cpp | 8 ++ simulation.cpp | 3 + 9 files changed, 271 insertions(+), 131 deletions(-) diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 49507441..d2e01f42 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -5282,34 +5282,46 @@ bool TMoverParameters::AutoRelayCheck(void) && ( MainCtrlPos > 0 ) && ( MainCtrlPos != MainCtrlPosNo ) && ( FastSerialCircuit == 1 ) ) { - + // szybkie wchodzenie na bezoporowa (303E) + // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: ++MainCtrlActualPos; - // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: - // szybkie wchodzenie na bezoporowa (303E) - OK = true; - SetFlag(SoundFlag, sound::parallel | sound::loud); + if( MainCtrlPos - MainCtrlActualPos == 1 ) { + // HACK: ensure we play only single sound of basic relays for entire trasition; return false + // for all but last step despite configuration change, to prevent playback of the basic relay sound + // TBD, TODO: move the basic sound event here and enable it with call parameter + OK = true; + } + if( RList[ MainCtrlActualPos ].R == 0 ) { + SetFlag( SoundFlag, sound::parallel | sound::loud ); + OK = true; + } } else if ((LastRelayTime > CtrlDelay) && (ARFASI)) { // WriteLog("LRT = " + FloatToStr(LastRelayTime) + ", " + // FloatToStr(CtrlDelay)); - if ((TrainType == dt_ET22) && (MainCtrlPos > 1) && - ((RList[MainCtrlActualPos].Bn < RList[MainCtrlActualPos + 1].Bn) || - (DelayCtrlFlag))) // et22 z walem grupowym - if (!DelayCtrlFlag) // najpierw przejscie + if( ( TrainType == dt_ET22 ) + && ( MainCtrlPos > 1 ) + && ( ( RList[ MainCtrlActualPos ].Bn < RList[ MainCtrlActualPos + 1 ].Bn ) + || ( DelayCtrlFlag ) ) ) { + // et22 z walem grupowym + if( !DelayCtrlFlag ) // najpierw przejscie { ++MainCtrlActualPos; DelayCtrlFlag = true; // tryb przejscia OK = true; } - else if (LastRelayTime > 4 * CtrlDelay) // przejscie + else if( LastRelayTime > 4 * CtrlDelay ) // przejscie { DelayCtrlFlag = false; OK = true; } +/* else ; +*/ + } else // nie ET22 z wałem grupowym { ++MainCtrlActualPos; @@ -5317,30 +5329,33 @@ bool TMoverParameters::AutoRelayCheck(void) } //--------- // hunter-111211: poprawki - if (MainCtrlActualPos > 0) - if ((RList[MainCtrlActualPos].R == 0) && - (!(MainCtrlActualPos == MainCtrlPosNo))) // wejscie na bezoporowa - { - SetFlag(SoundFlag, sound::parallel | sound::loud); + if( MainCtrlActualPos > 0 ) { + if( ( RList[ MainCtrlActualPos ].R == 0 ) + && ( MainCtrlActualPos != MainCtrlPosNo ) ) { + // wejscie na bezoporowa + SetFlag( SoundFlag, sound::parallel | sound::loud ); } - else if ((RList[MainCtrlActualPos].R > 0) && - (RList[MainCtrlActualPos - 1].R == - 0)) // wejscie na drugi uklad - { - SetFlag(SoundFlag, sound::parallel); + else if( ( RList[ MainCtrlActualPos ].R > 0 ) + && ( RList[ MainCtrlActualPos - 1 ].R == 0 ) ) { + // wejscie na drugi uklad + SetFlag( SoundFlag, sound::parallel ); } + } } } else if (RList[MainCtrlActualPos].Relay > MainCtrlPos) { - if ((RList[MainCtrlPos].R == 0) && (MainCtrlPos > 0) && - (!(MainCtrlPos == MainCtrlPosNo)) && (FastSerialCircuit == 1)) - { + if( ( RList[ MainCtrlPos ].R == 0 ) + && ( MainCtrlPos > 0 ) + && ( !( MainCtrlPos == MainCtrlPosNo ) ) + && ( FastSerialCircuit == 1 ) ) { + // szybkie wchodzenie na bezoporowa (303E) + // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: --MainCtrlActualPos; - // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: - // szybkie wchodzenie na bezoporowa (303E) OK = true; - SetFlag(SoundFlag, sound::parallel); + if( RList[ MainCtrlActualPos ].R == 0 ) { + SetFlag( SoundFlag, sound::parallel ); + } } else if (LastRelayTime > CtrlDownDelay) { diff --git a/Train.cpp b/Train.cpp index e746e52d..413c6f1d 100644 --- a/Train.cpp +++ b/Train.cpp @@ -250,7 +250,11 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = { { user_command::headlightenableupper, &TTrain::OnCommand_headlightenableupper }, { user_command::headlightdisableupper, &TTrain::OnCommand_headlightdisableupper }, { user_command::redmarkertoggleleft, &TTrain::OnCommand_redmarkertoggleleft }, + { user_command::redmarkerenableleft, &TTrain::OnCommand_redmarkerenableleft }, + { user_command::redmarkerdisableleft, &TTrain::OnCommand_redmarkerdisableleft }, { user_command::redmarkertoggleright, &TTrain::OnCommand_redmarkertoggleright }, + { user_command::redmarkerenableright, &TTrain::OnCommand_redmarkerenableright }, + { user_command::redmarkerdisableright, &TTrain::OnCommand_redmarkerdisableright }, { user_command::headlighttogglerearleft, &TTrain::OnCommand_headlighttogglerearleft }, { user_command::headlighttogglerearright, &TTrain::OnCommand_headlighttogglerearright }, { user_command::headlighttogglerearupper, &TTrain::OnCommand_headlighttogglerearupper }, @@ -1791,7 +1795,7 @@ void TTrain::OnCommand_pantographcompressoractivate( TTrain *Train, command_data void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Command ) { - if( Command.action != GLFW_RELEASE ) { + if( Command.action == GLFW_PRESS ) { // press or hold... if( Train->m_linebreakerstate == 0 ) { // ...to close the circuit @@ -1803,24 +1807,28 @@ void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Com OnCommand_linebreakeropen( Train, Command ); } } - else { + else if( Command.action == GLFW_RELEASE ) { // release... - if( Train->m_linebreakerstate <= 0 ) { - // ...after opening circuit, or holding for too short time to close it - OnCommand_linebreakeropen( Train, Command ); - } - else { - // ...after closing the circuit - // NOTE: bit of a dirty shortcut here - OnCommand_linebreakerclose( Train, Command ); + if( ( Train->ggMainOnButton.SubModel != nullptr ) + || ( Train->mvControlled->TrainType == dt_EZT ) ) { + // only impulse switches react to release events; since we don't have switch type definition for the line breaker, + // we detect it from presence of relevant button, or presume such switch arrangement for EMUs + if( Train->m_linebreakerstate == 0 ) { + // ...after opening circuit, or holding for too short time to close it + OnCommand_linebreakeropen( Train, Command ); + } + else { + // ...after closing the circuit + // NOTE: bit of a dirty shortcut here + OnCommand_linebreakerclose( Train, Command ); + } } } } void TTrain::OnCommand_linebreakeropen( TTrain *Train, command_data const &Command ) { - if( Command.action != GLFW_RELEASE ) { - // press or hold... + if( Command.action == GLFW_PRESS ) { // visual feedback if( Train->ggMainOffButton.SubModel != nullptr ) { // two separate switches to close and break the circuit @@ -1838,6 +1846,10 @@ void TTrain::OnCommand_linebreakeropen( TTrain *Train, command_data const &Comma Train->ggMainButton.UpdateValue( 0.0, Train->dsbSwitch ); } } + else { + // fallback for cabs with no submodel + Train->ggMainButton.UpdateValue( 0.0, Train->dsbSwitch ); + } // play sound immediately when the switch is hit, not after release Train->fMainRelayTimer = 0.0f; @@ -1851,11 +1863,11 @@ void TTrain::OnCommand_linebreakeropen( TTrain *Train, command_data const &Comma } if( true == Train->mvControlled->MainSwitch( false ) ) { - Train->m_linebreakerstate = -1; + Train->m_linebreakerstate = 0; } } - else { - // release... + else if( Command.action == GLFW_RELEASE ) { + // visual feedback // we don't exactly know which of the two buttons was used, so reset both // for setup with two separate swiches if( Train->ggMainOnButton.SubModel != nullptr ) { @@ -1866,22 +1878,14 @@ void TTrain::OnCommand_linebreakeropen( TTrain *Train, command_data const &Comma } // and the two-state switch too, for good measure if( Train->ggMainButton.SubModel != nullptr ) { - // visual feedback Train->ggMainButton.UpdateValue( 0.0, Train->dsbSwitch ); } - if( Train->m_linebreakerstate < 0 ) { - // finalize state change of the line breaker - Train->m_linebreakerstate = 0; - } - // on button release reset the closing timer - Train->fMainRelayTimer = 0.0f; } } void TTrain::OnCommand_linebreakerclose( TTrain *Train, command_data const &Command ) { if( Command.action == GLFW_PRESS ) { - // press... // visual feedback if( Train->ggMainOnButton.SubModel != nullptr ) { // two separate switches to close and break the circuit @@ -1891,10 +1895,14 @@ void TTrain::OnCommand_linebreakerclose( TTrain *Train, command_data const &Comm // single two-state switch Train->ggMainButton.UpdateValue( 1.0, Train->dsbSwitch ); } + else { + // fallback for cabs with no submodel + Train->ggMainButton.UpdateValue( 1.0, Train->dsbSwitch ); + } + // the actual closing of the line breaker is handled in the train update routine } else if( Command.action == GLFW_RELEASE ) { - // release... // visual feedback if( Train->ggMainOnButton.SubModel != nullptr ) { // setup with two separate switches @@ -1905,7 +1913,6 @@ void TTrain::OnCommand_linebreakerclose( TTrain *Train, command_data const &Comm // TODO: have proper switch type config for all switches, and put it in the cab switch descriptions, not in the .fiz if( Train->mvControlled->TrainType == dt_EZT ) { if( Train->ggMainButton.SubModel != nullptr ) { - // visual feedback Train->ggMainButton.UpdateValue( 0.0, Train->dsbSwitch ); } } @@ -1913,17 +1920,17 @@ void TTrain::OnCommand_linebreakerclose( TTrain *Train, command_data const &Comm if( Train->m_linebreakerstate == 1 ) { return; } // already in the desired state if( Train->m_linebreakerstate > 1 ) { - // we don't need to start the diesel twice, but the other types still need to be launched + // we don't need to start the diesel twice, but the other types (with impulse switch setup) still need to be launched if( ( Train->mvControlled->EngineType != DieselEngine ) && ( Train->mvControlled->EngineType != DieselElectric ) ) { if( Train->mvControlled->MainSwitch( true ) ) { // side-effects Train->mvControlled->ConverterSwitch( ( Train->ggConverterButton.GetValue() > 0.5 ) || ( Train->mvControlled->ConverterStart == start::automatic ) ); Train->mvControlled->CompressorSwitch( Train->ggCompressorButton.GetValue() > 0.5 ); + // finalize state change of the line breaker + Train->m_linebreakerstate = 1; } } - // finalize state change of the line breaker - Train->m_linebreakerstate = 1; } // on button release reset the closing timer Train->fMainRelayTimer = 0.0f; @@ -2606,90 +2613,160 @@ void TTrain::OnCommand_headlightdisableupper( TTrain *Train, command_data const void TTrain::OnCommand_redmarkertoggleleft( TTrain *Train, command_data const &Command ) { + if( Command.action == GLFW_PRESS ) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + side::front : + side::rear ); + + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) == 0 ) { + // turn on + OnCommand_redmarkerenableleft( Train, Command ); + } + else { + //turn off + OnCommand_redmarkerdisableleft( Train, Command ); + } + } +} + +void TTrain::OnCommand_redmarkerenableleft( TTrain *Train, command_data const &Command ) { + if( Train->mvOccupied->LightsPosNo > 0 ) { // lights are controlled by preset selector return; } - int const vehicleside = - ( Train->mvOccupied->ActiveCab == 1 ? - side::front : - side::rear ); + if( Command.action == GLFW_PRESS ) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + side::front : + side::rear ); + + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) != 0 ) { return; } // already enabled + + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_left; + // visual feedback + if( Train->ggLeftEndLightButton.SubModel != nullptr ) { + Train->ggLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); + } + else { + // we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch + // this is crude, but for now will do + Train->ggLeftLightButton.UpdateValue( -1.0, Train->dsbSwitch ); + // if the light is controlled by 3-way switch, disable the headlight + Train->DynamicObject->iLights[ vehicleside ] &= ~light::headlight_left; + } + } +} + +void TTrain::OnCommand_redmarkerdisableleft( TTrain *Train, command_data const &Command ) { + + if( Train->mvOccupied->LightsPosNo > 0 ) { + // lights are controlled by preset selector + return; + } if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) == 0 ) { - // turn on - Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_left; - // visual feedback - if( Train->ggLeftEndLightButton.SubModel != nullptr ) { - Train->ggLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); - } - else { - // we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch - // this is crude, but for now will do - Train->ggLeftLightButton.UpdateValue( -1.0, Train->dsbSwitch ); - // if the light is controlled by 3-way switch, disable the headlight - Train->DynamicObject->iLights[ vehicleside ] &= ~light::headlight_left; - } + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + side::front : + side::rear ); + + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_left ) == 0 ) { return; } // already disabled + + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_left; + // visual feedback + if( Train->ggLeftEndLightButton.SubModel != nullptr ) { + Train->ggLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } else { - //turn off - Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_left; - // visual feedback - if( Train->ggLeftEndLightButton.SubModel != nullptr ) { - Train->ggLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); - } - else { - // we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch - // this is crude, but for now will do - Train->ggLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch ); - } + // we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch + // this is crude, but for now will do + Train->ggLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } } } void TTrain::OnCommand_redmarkertoggleright( TTrain *Train, command_data const &Command ) { + if( Command.action == GLFW_PRESS ) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + side::front : + side::rear ); + + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) == 0 ) { + // turn on + OnCommand_redmarkerenableright( Train, Command ); + } + else { + //turn off + OnCommand_redmarkerdisableright( Train, Command ); + } + } +} + +void TTrain::OnCommand_redmarkerenableright( TTrain *Train, command_data const &Command ) { + if( Train->mvOccupied->LightsPosNo > 0 ) { // lights are controlled by preset selector return; } - int const vehicleside = - ( Train->mvOccupied->ActiveCab == 1 ? - side::front : - side::rear ); + if( Command.action == GLFW_PRESS ) { + // only reacting to press, so the switch doesn't flip back and forth if key is held down + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + side::front : + side::rear ); + + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) != 0 ) { return; } // already enabled + + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_right; + // visual feedback + if( Train->ggRightEndLightButton.SubModel != nullptr ) { + Train->ggRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); + } + else { + // we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch + // this is crude, but for now will do + Train->ggRightLightButton.UpdateValue( -1.0, Train->dsbSwitch ); + // if the light is controlled by 3-way switch, disable the headlight + Train->DynamicObject->iLights[ vehicleside ] &= ~light::headlight_right; + } + } +} + +void TTrain::OnCommand_redmarkerdisableright( TTrain *Train, command_data const &Command ) { + + if( Train->mvOccupied->LightsPosNo > 0 ) { + // lights are controlled by preset selector + return; + } if( Command.action == GLFW_PRESS ) { // only reacting to press, so the switch doesn't flip back and forth if key is held down - if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) == 0 ) { - // turn on - Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_right; - // visual feedback - if( Train->ggRightEndLightButton.SubModel != nullptr ) { - Train->ggRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch ); - } - else { - // we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch - // this is crude, but for now will do - Train->ggRightLightButton.UpdateValue( -1.0, Train->dsbSwitch ); - // if the light is controlled by 3-way switch, disable the headlight - Train->DynamicObject->iLights[ vehicleside ] &= ~light::headlight_right; - } + int const vehicleside = + ( Train->mvOccupied->ActiveCab == 1 ? + side::front : + side::rear ); + + if( ( Train->DynamicObject->iLights[ vehicleside ] & light::redmarker_right ) == 0 ) { return; } // already disabled + + Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_right; + // visual feedback + if( Train->ggRightEndLightButton.SubModel != nullptr ) { + Train->ggRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } else { - //turn off - Train->DynamicObject->iLights[ vehicleside ] ^= light::redmarker_right; - // visual feedback - if( Train->ggRightEndLightButton.SubModel != nullptr ) { - Train->ggRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch ); - } - else { - // we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch - // this is crude, but for now will do - Train->ggRightLightButton.UpdateValue( 0.0, Train->dsbSwitch ); - } + // we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch + // this is crude, but for now will do + Train->ggRightLightButton.UpdateValue( 0.0, Train->dsbSwitch ); } } } @@ -3697,6 +3774,7 @@ bool TTrain::Update( double const Deltatime ) m_linebreakerstate = 0; } } + if( ( ggMainButton.GetDesiredValue() > 0.95 ) || ( ggMainOnButton.GetDesiredValue() > 0.95 ) ) { // keep track of period the line breaker button is held down, to determine when/if circuit closes @@ -3708,23 +3786,6 @@ bool TTrain::Update( double const Deltatime ) // TODO: consider whether it makes sense for diesel engines and such fMainRelayTimer += Deltatime; } - if( m_linebreakerstate < 1 ) { - - if( fMainRelayTimer > mvControlled->InitialCtrlDelay ) { - // wlaczanie WSa z opoznieniem - m_linebreakerstate = 2; - // for diesels, we complete the engine start here - // TODO: consider arranging a better way to start the diesel engines - if( ( mvControlled->EngineType == DieselEngine ) - || ( mvControlled->EngineType == DieselElectric ) ) { - if( mvControlled->MainSwitch( true ) ) { - // side-effects - mvControlled->ConverterSwitch( ( ggConverterButton.GetDesiredValue() > 0.95 ) || ( mvControlled->ConverterStart == start::automatic ) ); - mvControlled->CompressorSwitch( ggCompressorButton.GetDesiredValue() > 0.95 ); - } - } - } - } } else { // button isn't down, reset the timer @@ -3734,6 +3795,28 @@ bool TTrain::Update( double const Deltatime ) // if the button disconnecting the line breaker is down prevent the timer from accumulating fMainRelayTimer = 0.0f; } + if( m_linebreakerstate == 0 ) { + if( fMainRelayTimer > mvControlled->InitialCtrlDelay ) { + // wlaczanie WSa z opoznieniem + // mark the line breaker as ready to close; for electric vehicles with impulse switch the setup is completed on button release + m_linebreakerstate = 2; + } + } + if( m_linebreakerstate == 2 ) { + // for diesels and/or vehicles with toggle switch setup we complete the engine start here + // TBD, TODO: arrange a better way to start the diesel engines + if( ( ggMainOffButton.SubModel == nullptr ) + || ( ( mvControlled->EngineType == DieselEngine ) + || ( mvControlled->EngineType == DieselElectric ) ) ) { + if( mvControlled->MainSwitch( true ) ) { + // side-effects + mvControlled->ConverterSwitch( ( ggConverterButton.GetDesiredValue() > 0.95 ) || ( mvControlled->ConverterStart == start::automatic ) ); + mvControlled->CompressorSwitch( ggCompressorButton.GetDesiredValue() > 0.95 ); + // finalize state change of the line breaker + m_linebreakerstate = 1; + } + } + } // check for received user commands // NOTE: this is a temporary arrangement, for the transition period from old command setup to the new one diff --git a/Train.h b/Train.h index 4b300e42..df9f2ac3 100644 --- a/Train.h +++ b/Train.h @@ -240,7 +240,11 @@ class TTrain static void OnCommand_headlightenableupper( TTrain *Train, command_data const &Command ); static void OnCommand_headlightdisableupper( TTrain *Train, command_data const &Command ); static void OnCommand_redmarkertoggleleft( TTrain *Train, command_data const &Command ); + static void OnCommand_redmarkerenableleft( TTrain *Train, command_data const &Command ); + static void OnCommand_redmarkerdisableleft( TTrain *Train, command_data const &Command ); static void OnCommand_redmarkertoggleright( TTrain *Train, command_data const &Command ); + static void OnCommand_redmarkerenableright( TTrain *Train, command_data const &Command ); + static void OnCommand_redmarkerdisableright( TTrain *Train, command_data const &Command ); static void OnCommand_headlighttogglerearleft( TTrain *Train, command_data const &Command ); static void OnCommand_headlighttogglerearright( TTrain *Train, command_data const &Command ); static void OnCommand_headlighttogglerearupper( TTrain *Train, command_data const &Command ); @@ -284,7 +288,7 @@ class TTrain TMoverParameters *mvSecond; // drugi człon (ET40, ET41, ET42, ukrotnienia) TMoverParameters *mvThird; // trzeci człon (SN61) // helper variable, to prevent immediate switch between closing and opening line breaker circuit - int m_linebreakerstate { 0 }; // -1: freshly open, 0: open, 1: closed, 2: freshly closed (and yes this is awful way to go about it) + int m_linebreakerstate { 0 }; // 0: open, 1: closed, 2: freshly closed (and yes this is awful way to go about it) static const commandhandler_map m_commandhandlers; control_mapper m_controlmapper; @@ -577,7 +581,7 @@ private: float fPress[20][3]; // cisnienia dla wszystkich czlonow static std::vector const fPress_labels; float fEIMParams[9][10]; // parametry dla silnikow asynchronicznych - int RadioChannel() { return iRadioChannel; }; + int RadioChannel() const { return iRadioChannel; }; // plays provided sound from position of the radio void radio_message( sound_source *Message, int const Channel ); inline TDynamicObject *Dynamic() { return DynamicObject; }; diff --git a/World.cpp b/World.cpp index 5ad41330..5c5533f5 100644 --- a/World.cpp +++ b/World.cpp @@ -1317,6 +1317,11 @@ TWorld::Update_UI() { uitextline2 += ( vehicle->MoverParameters->ConvOvldFlag ? "!" : "." ); uitextline2 += ( false == vehicle->MoverParameters->CompressorAllowLocal ? "-" : ( ( vehicle->MoverParameters->CompressorAllow || vehicle->MoverParameters->CompressorPower > 1 ) ? ( vehicle->MoverParameters->CompressorFlag ? "C" : "c" ) : "." ) ); uitextline2 += ( vehicle->MoverParameters->CompressorGovernorLock ? "!" : "." ); + + auto const train { Global.pWorld->train() }; + if( ( train != nullptr ) && ( train->Dynamic() == vehicle ) ) { + uitextline2 += " R: " + std::to_string( train->RadioChannel() ); + } /* uitextline2 += " AnlgB: " + to_string( tmp->MoverParameters->AnPos, 1 ) @@ -2124,9 +2129,21 @@ TWorld::compute_season( int const Yearday ) const { return Left.first < Right; } ); Global.Season = lookup->second + ":"; + // season can affect the weather so if it changes, re-calculate weather as well + compute_weather(); } +// calculates current weather +void +TWorld::compute_weather() const { + Global.Weather = ( + Global.Overcast < 0.25 ? "clear:" : + Global.Overcast < 1.0 ? "cloudy:" : + ( Global.Season != "winter:" ? + "rain:" : + "snow:" ) ); +} void world_environment::init() { diff --git a/World.h b/World.h index 56736115..c9654100 100644 --- a/World.h +++ b/World.h @@ -110,6 +110,8 @@ TWorld(); void ToggleDaylight(); // calculates current season of the year based on set simulation date void compute_season( int const Yearday ) const; + // calculates current weather + void compute_weather() const; // members diff --git a/command.cpp b/command.cpp index aa60c905..d249c849 100644 --- a/command.cpp +++ b/command.cpp @@ -140,7 +140,11 @@ commanddescription_sequence Commands_descriptions = { { "headlightenableupper", command_target::vehicle }, { "headlightdisableupper", command_target::vehicle }, { "redmarkertoggleleft", command_target::vehicle }, + { "redmarkerenableleft", command_target::vehicle }, + { "redmarkerdisableleft", command_target::vehicle }, { "redmarkertoggleright", command_target::vehicle }, + { "redmarkerenableright", command_target::vehicle }, + { "redmarkerdisableright", command_target::vehicle }, { "headlighttogglerearleft", command_target::vehicle }, { "headlighttogglerearright", command_target::vehicle }, { "headlighttogglerearupper", command_target::vehicle }, diff --git a/command.h b/command.h index 380df31e..d9695d37 100644 --- a/command.h +++ b/command.h @@ -133,7 +133,11 @@ enum class user_command { headlightenableupper, headlightdisableupper, redmarkertoggleleft, + redmarkerenableleft, + redmarkerdisableleft, redmarkertoggleright, + redmarkerenableright, + redmarkerdisableright, headlighttogglerearleft, headlighttogglerearright, headlighttogglerearupper, diff --git a/keyboardinput.cpp b/keyboardinput.cpp index 74dc998a..76f9a6ef 100644 --- a/keyboardinput.cpp +++ b/keyboardinput.cpp @@ -403,8 +403,16 @@ keyboard_input::default_bindings() { { -1 }, // redmarkertoggleleft { GLFW_KEY_Y | keymodifier::shift }, + // redmarkerenableleft + { -1 }, + // redmarkerdisableleft + { -1 }, // redmarkertoggleright { GLFW_KEY_I | keymodifier::shift }, + // redmarkerenableright + { -1 }, + // redmarkerdisableright + { -1 }, // headlighttogglerearleft { GLFW_KEY_Y | keymodifier::control }, // headlighttogglerearright diff --git a/simulation.cpp b/simulation.cpp index d9c2b8b3..1251ac4f 100644 --- a/simulation.cpp +++ b/simulation.cpp @@ -167,6 +167,9 @@ state_manager::deserialize_atmo( cParser &Input, scene::scratch_data &Scratchpad if( token != "endatmo" ) { // optional overcast parameter Global.Overcast = clamp( std::stof( token ), 0.f, 2.f ); + // overcast drives weather so do a calculation here + // NOTE: ugly, clean it up when we're done with world refactoring + Global.pWorld->compute_weather(); } while( ( false == token.empty() ) && ( token != "endatmo" ) ) {