mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 23:49:17 +02:00
build 210424. soundproofing enhancement, battery sound, heating command propagation, memory cell command retrieval logic enhancement, coupling mode logic enhancement, motor overload relay threshold cab control animation fix, cab control fallback sound activation fixes,
This commit is contained in:
75
Driver.cpp
75
Driver.cpp
@@ -1676,11 +1676,15 @@ TController::TableUpdateEvent( double &Velocity, TCommandType &Command, TSpeedPo
|
||||
else if( Point.evEvent->is_command() ) {
|
||||
// jeśli prędkość jest zerowa, a komórka zawiera komendę
|
||||
eSignNext = Point.evEvent; // dla informacji
|
||||
// make sure the command isn't for someone else
|
||||
// TBD, TODO: revise this check for bank/loose_shunt; we might want to ignore obstacles with no owner in these modes
|
||||
if( Point.fDist < Obstacle.distance ) {
|
||||
if( true == TestFlag( iDrivigFlags, moveStopHere ) ) {
|
||||
// jeśli ma stać, dostaje komendę od razu
|
||||
Command = TCommandType::cm_Command; // komenda z komórki, do wykonania po zatrzymaniu
|
||||
}
|
||||
else if( Point.fDist <= fMaxProximityDist ) {
|
||||
// NOTE: human drivers are likely to stop wherever and expect things to still work, so we give them more leeway
|
||||
else if( Point.fDist <= ( AIControllFlag ? fMaxProximityDist : std::max( 250.0, fMaxProximityDist ) ) ) {
|
||||
// jeśli ma dociągnąć, to niech dociąga
|
||||
// (moveStopCloser dotyczy dociągania do W4, nie semafora)
|
||||
Command = TCommandType::cm_Command; // komenda z komórki, do wykonania po zatrzymaniu
|
||||
@@ -1688,6 +1692,7 @@ TController::TableUpdateEvent( double &Velocity, TCommandType &Command, TSpeedPo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // jeśli nie ma zawalidrogi
|
||||
|
||||
return false;
|
||||
@@ -1928,9 +1933,13 @@ TController::~TController()
|
||||
// zamiana kodu rozkazu na opis
|
||||
std::string TController::Order2Str(TOrders Order) const {
|
||||
|
||||
if( Order & Change_direction ) {
|
||||
if( ( ( Order & Change_direction ) != 0 )
|
||||
&& ( Order != Change_direction ) ) {
|
||||
// może być nałożona na inną i wtedy ma priorytet
|
||||
return "Change_direction";
|
||||
return
|
||||
Order2Str( Change_direction )
|
||||
+ " + "
|
||||
+ Order2Str( static_cast<TOrders>( Order & ~Change_direction ) );
|
||||
}
|
||||
switch( Order ) {
|
||||
case Wait_for_orders: return "Wait_for_orders";
|
||||
@@ -1953,11 +1962,15 @@ std::array<char, 64> orderbuffer;
|
||||
std::string TController::OrderCurrent() const
|
||||
{ // pobranie aktualnego rozkazu celem wyświetlenia
|
||||
auto const order { OrderCurrentGet() };
|
||||
// generally prioritize direction change...
|
||||
if( order & Change_direction ) {
|
||||
// ...but not in the middle of coupling operation
|
||||
if( false == TestFlag( iDrivigFlags, moveConnect ) ) {
|
||||
return locale::strings[ locale::string::driver_scenario_changedirection ];
|
||||
}
|
||||
}
|
||||
|
||||
switch( OrderList[ OrderPos ] ) {
|
||||
switch( static_cast<TOrders>( order & ~Change_direction ) ) {
|
||||
case Wait_for_orders: { return locale::strings[ locale::string::driver_scenario_waitfororders ]; }
|
||||
case Prepare_engine: { return locale::strings[ locale::string::driver_scenario_prepareengine ]; }
|
||||
case Release_engine: { return locale::strings[ locale::string::driver_scenario_releaseengine ]; }
|
||||
@@ -4927,17 +4940,20 @@ TController::PrepareDirection() {
|
||||
locale::string::driver_hint_directionbackward );
|
||||
}
|
||||
|
||||
void TController::JumpToNextOrder()
|
||||
void TController::JumpToNextOrder( bool const Ignoremergedchangedirection )
|
||||
{ // wykonanie kolejnej komendy z tablicy rozkazów
|
||||
if (OrderList[OrderPos] != Wait_for_orders)
|
||||
{
|
||||
if (OrderList[OrderPos] & Change_direction) // jeśli zmiana kierunku
|
||||
if (OrderList[OrderPos] != Change_direction) // ale nałożona na coś
|
||||
{
|
||||
OrderList[OrderPos] = TOrders(OrderList[OrderPos] & ~Change_direction); // usunięcie zmiany kierunku z innej komendy
|
||||
if( ( ( OrderList[ OrderPos ] & Change_direction ) != 0 ) // jeśli zmiana kierunku
|
||||
&& ( OrderList[ OrderPos ] != Change_direction ) ) { // ale nałożona na coś
|
||||
|
||||
if( false == Ignoremergedchangedirection ) {
|
||||
// usunięcie zmiany kierunku z innej komendy
|
||||
OrderList[ OrderPos ] = TOrders( OrderList[ OrderPos ] & ~Change_direction );
|
||||
OrderCheck();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (OrderPos < maxorders - 1)
|
||||
++OrderPos;
|
||||
else
|
||||
@@ -6701,9 +6717,9 @@ TController::UpdateConnect() {
|
||||
// podłączanie do składu
|
||||
if (iDrivigFlags & moveConnect) {
|
||||
// sprzęgi sprawdzamy w pierwszej kolejności, bo jak połączony, to koniec
|
||||
auto *vehicle { pVehicles[ end::front ] };
|
||||
auto *vehicle { iCouplingVehicle.value().first };
|
||||
auto const couplingend { iCouplingVehicle.value().second };
|
||||
auto *vehicleparameters { vehicle->MoverParameters };
|
||||
auto const couplingend { ( vehicle->DirectionGet() > 0 ? end::front : end::rear ) };
|
||||
if( vehicleparameters->Couplers[ couplingend ].CouplingFlag != iCoupler ) {
|
||||
auto const &neighbour { vehicleparameters->Neighbours[ couplingend ] };
|
||||
if( neighbour.vehicle != nullptr ) {
|
||||
@@ -6736,17 +6752,27 @@ TController::UpdateConnect() {
|
||||
CheckVehicles( Connect ); // sprawdzić światła nowego składu
|
||||
|
||||
iCoupler = 0; // dalsza jazda manewrowa już bez łączenia
|
||||
iCouplingVehicle.reset();
|
||||
iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania
|
||||
JumpToNextOrder(); // wykonanie następnej komendy
|
||||
JumpToNextOrder( true ); // wykonanie następnej komendy
|
||||
}
|
||||
} // moveConnect
|
||||
else {
|
||||
if( Obstacle.distance <= 20.0 ) {
|
||||
// początek podczepiania, z wyłączeniem sprawdzania fTrackBlock
|
||||
if( Obstacle.distance <= 20.0 ) {
|
||||
if( !iCouplingVehicle ) {
|
||||
// write down which vehicle should be coupled with the target consist,
|
||||
// so we don't lose track of it if the user does something unexpected
|
||||
iCouplingVehicle = {
|
||||
pVehicles[ end::front ],
|
||||
( pVehicles[ end::front ]->DirectionGet() > 0 ?
|
||||
end::front :
|
||||
end::rear ) };
|
||||
iDrivigFlags |= moveConnect;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
TController::unit_count( int const Threshold ) const {
|
||||
@@ -6885,9 +6911,7 @@ TController::UpdateDisconnect() {
|
||||
// 5th stage: clean up and move on to next order
|
||||
if( iDirection == iDirectionOrder ) {
|
||||
iDrivigFlags &= ~movePress; // koniec dociskania
|
||||
while( ( OrderCurrentGet() & Disconnect ) != 0 ) {
|
||||
JumpToNextOrder(); // zmieni światła
|
||||
}
|
||||
JumpToNextOrder( true ); // zmieni światła
|
||||
TableClear(); // skanowanie od nowa
|
||||
iDrivigFlags &= ~moveStartHorn; // bez trąbienia przed ruszeniem
|
||||
}
|
||||
@@ -6957,6 +6981,11 @@ TController::handle_orders() {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// special case, change_direction potentially received during partially completed coupling operation
|
||||
// this is unlikely to happen for the AI, but can happen for a (slower) human user
|
||||
if( TestFlag( iDrivigFlags, moveConnect ) ) {
|
||||
UpdateConnect();
|
||||
}
|
||||
break;
|
||||
}
|
||||
} // switch OrderList[OrderPos]
|
||||
@@ -7949,13 +7978,18 @@ TController::check_route_ahead( double const Range ) {
|
||||
void
|
||||
TController::check_route_behind( double const Range ) {
|
||||
|
||||
if( VelNext != 0.0 ) { return; }
|
||||
if( VelNext != 0.0 ) { return; } // not if we can move ahead
|
||||
if( TestFlag( iDrivigFlags, moveConnect ) ) { return; } // not if we're in middle of coupling operation
|
||||
|
||||
if( !( OrderCurrentGet() & ~( Shunt | Loose_shunt | Connect ) ) ) {
|
||||
if( ( OrderCurrentGet() & ~( Shunt | Loose_shunt | Connect ) ) == 0 ) {
|
||||
// jedzie w Shunt albo Connect, albo Wait_for_orders
|
||||
// w trybie Connect skanować do tyłu tylko jeśli przed kolejnym sygnałem nie ma taboru do podłączenia
|
||||
if( ( ( OrderCurrentGet() & Connect ) == 0 )
|
||||
|| ( Obstacle.distance > std::min( 2000.0, FirstSemaphorDist ) ) ) {
|
||||
auto const couplinginprogress {
|
||||
( TestFlag( OrderCurrentGet(), Connect ) )
|
||||
&& ( ( Obstacle.distance < std::min( 2000.0, FirstSemaphorDist ) )
|
||||
|| ( TestFlag( iDrivigFlags, moveConnect ) ) ) };
|
||||
if( couplinginprogress ) { return; }
|
||||
|
||||
auto const comm { BackwardScan( Range ) };
|
||||
if( comm != TCommandType::cm_Unknown ) {
|
||||
// jeśli w drugą można jechać
|
||||
@@ -7972,7 +8006,6 @@ TController::check_route_behind( double const Range ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TController::UpdateBrakingHelper() {
|
||||
|
||||
3
Driver.h
3
Driver.h
@@ -383,6 +383,7 @@ private:
|
||||
int iDirection = 0; // kierunek jazdy względem sprzęgów pojazdu, w którym siedzi AI (1=przód,-1=tył)
|
||||
int iDirectionOrder = 0; //żadany kierunek jazdy (służy do zmiany kierunku)
|
||||
std::optional<int> iDirectionBackup; // consist direction to be restored after coupling/uncoupling and similar direction-changing operations
|
||||
std::optional<std::pair<TDynamicObject*,int>> iCouplingVehicle; // <vehicle, coupler> to be coupled with another consist in current coupling operation
|
||||
int iVehicleCount = -2; // wartość neutralna // ilość pojazdów do odłączenia albo zabrania ze składu (-1=wszystkie)
|
||||
int iCoupler = 0; // maska sprzęgu, jaką należy użyć przy łączeniu (po osiągnięciu trybu Connect), 0 gdy jazda bez łączenia
|
||||
int iDriverFailCount = 0; // licznik błędów AI
|
||||
@@ -446,7 +447,7 @@ public:
|
||||
std::string OrderCurrent() const;
|
||||
private:
|
||||
void RecognizeCommand(); // odczytuje komende przekazana lokomotywie
|
||||
void JumpToNextOrder();
|
||||
void JumpToNextOrder( bool const Skipmergedchangedirection = false );
|
||||
void JumpToFirstOrder();
|
||||
void OrderPush( TOrders NewOrder );
|
||||
void OrderNext( TOrders NewOrder );
|
||||
|
||||
16
DynObj.cpp
16
DynObj.cpp
@@ -4122,6 +4122,14 @@ void TDynamicObject::RenderSounds() {
|
||||
sHeater.stop();
|
||||
}
|
||||
|
||||
// battery sound
|
||||
if( MoverParameters->Battery ) {
|
||||
m_batterysound.play( sound_flags::exclusive | sound_flags::looping );
|
||||
}
|
||||
else {
|
||||
m_batterysound.stop();
|
||||
}
|
||||
|
||||
// brake system and braking sounds:
|
||||
|
||||
// brake cylinder piston
|
||||
@@ -5763,6 +5771,12 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
sHeater.owner( this );
|
||||
}
|
||||
|
||||
else if( token == "battery:" ) {
|
||||
// train heating device
|
||||
m_batterysound.deserialize( parser, sound_type::single );
|
||||
m_batterysound.owner( this );
|
||||
}
|
||||
|
||||
else if( token == "turbo:" ) {
|
||||
// pliki z turbogeneratorem
|
||||
m_powertrainsounds.engine_turbo.deserialize( parser, sound_type::multipart, sound_parameters::range );
|
||||
@@ -6484,7 +6498,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
||||
// other engine compartment sounds
|
||||
auto const nullvector { glm::vec3() };
|
||||
std::vector<sound_source *> enginesounds = {
|
||||
&sConverter, &sCompressor, &sCompressorIdle, &sSmallCompressor, &sHeater
|
||||
&sConverter, &sCompressor, &sCompressorIdle, &sSmallCompressor, &sHeater, &m_batterysound
|
||||
};
|
||||
for( auto sound : enginesounds ) {
|
||||
if( sound->offset() == nullvector ) {
|
||||
|
||||
1
DynObj.h
1
DynObj.h
@@ -480,6 +480,7 @@ private:
|
||||
sound_source sCompressorIdle { sound_placement::engine };
|
||||
sound_source sSmallCompressor { sound_placement::engine };
|
||||
sound_source sHeater { sound_placement::engine };
|
||||
sound_source m_batterysound { sound_placement::engine };
|
||||
// braking sounds
|
||||
sound_source dsbPneumaticRelay { sound_placement::external };
|
||||
sound_source rsBrake { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // moved from cab
|
||||
|
||||
13
Event.cpp
13
Event.cpp
@@ -538,10 +538,10 @@ updatevalues_event::run_() {
|
||||
auto const location { targetcell->location() };
|
||||
for( auto vehicle : targetcell->Track->Dynamics ) {
|
||||
if( vehicle->Mechanik ) {
|
||||
WriteLog( " Vehicle: [" + vehicle->name() + "]" );
|
||||
targetcell->PutCommand(
|
||||
vehicle->Mechanik,
|
||||
&location );
|
||||
WriteLog( " Vehicle: [" + vehicle->name() + "]" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -775,10 +775,9 @@ putvalues_event::run_() {
|
||||
m_input.location.z,
|
||||
m_input.location.y };
|
||||
|
||||
std::string vehiclename;
|
||||
if( m_activator->Mechanik ) {
|
||||
// przekazanie rozkazu do AI
|
||||
vehiclename = m_activator->Mechanik->Vehicle()->name();
|
||||
WriteLog( " Vehicle: [" + m_activator->Mechanik->Vehicle()->name() + "]" );
|
||||
m_activator->Mechanik->PutCommand(
|
||||
m_input.data_text,
|
||||
m_input.data_value_1,
|
||||
@@ -790,7 +789,7 @@ putvalues_event::run_() {
|
||||
// send the command to consist owner,
|
||||
// we're acting on presumption there's hardly ever need to issue command to unmanned vehicle
|
||||
// and the intended recipient moved between vehicles after the event was queued
|
||||
vehiclename = m_activator->ctOwner->Vehicle()->name();
|
||||
WriteLog( " Vehicle: [" + m_activator->ctOwner->Vehicle()->name() + "]" );
|
||||
m_activator->ctOwner->PutCommand(
|
||||
m_input.data_text,
|
||||
m_input.data_value_1,
|
||||
@@ -799,15 +798,13 @@ putvalues_event::run_() {
|
||||
}
|
||||
else {
|
||||
// przekazanie do pojazdu
|
||||
vehiclename = m_activator->name();
|
||||
WriteLog( " Vehicle: [" + m_activator->name() +"]" );
|
||||
m_activator->MoverParameters->PutCommand(
|
||||
m_input.data_text,
|
||||
m_input.data_value_1,
|
||||
m_input.data_value_2,
|
||||
loc );
|
||||
}
|
||||
|
||||
WriteLog( " Vehicle: [" + vehiclename + "]" );
|
||||
}
|
||||
|
||||
// export_as_text() subclass details
|
||||
@@ -944,10 +941,10 @@ copyvalues_event::run_() {
|
||||
auto const location { targetcell->location() };
|
||||
for( auto vehicle : targetcell->Track->Dynamics ) {
|
||||
if( vehicle->Mechanik ) {
|
||||
WriteLog( " Vehicle: [" + vehicle->name() + "]" );
|
||||
targetcell->PutCommand(
|
||||
vehicle->Mechanik,
|
||||
&location );
|
||||
WriteLog( " Vehicle: [" + vehicle->name() + "]" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
Gauge.cpp
53
Gauge.cpp
@@ -141,9 +141,33 @@ void TGauge::Load( cParser &Parser, TDynamicObject const *Owner, double const mu
|
||||
>> endscale;
|
||||
}
|
||||
// new, variable length section
|
||||
while( true == Load_mapping( Parser ) ) {
|
||||
{
|
||||
scratch_data scratchpad;
|
||||
while( true == Load_mapping( Parser, scratchpad ) ) {
|
||||
; // all work done by while()
|
||||
}
|
||||
// post-deserialization cleanup
|
||||
// set provided custom soundproofing to assigned sounds (for sounds without their own custom soundproofing)
|
||||
if( scratchpad.soundproofing ) {
|
||||
if( !m_soundfxincrease.soundproofing() ) {
|
||||
m_soundfxincrease.soundproofing() = scratchpad.soundproofing;
|
||||
}
|
||||
if( !m_soundfxdecrease.soundproofing() ) {
|
||||
m_soundfxdecrease.soundproofing() = scratchpad.soundproofing;
|
||||
}
|
||||
if( !m_soundfxon.soundproofing() ) {
|
||||
m_soundfxon.soundproofing() = scratchpad.soundproofing;
|
||||
}
|
||||
if( !m_soundfxoff.soundproofing() ) {
|
||||
m_soundfxoff.soundproofing() = scratchpad.soundproofing;
|
||||
}
|
||||
for( auto &soundfxrecord : m_soundfxvalues ) {
|
||||
if( !soundfxrecord.second.soundproofing() ) {
|
||||
soundfxrecord.second.soundproofing() = scratchpad.soundproofing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bind defined sounds with the button owner
|
||||
@@ -207,7 +231,7 @@ void TGauge::Load( cParser &Parser, TDynamicObject const *Owner, double const mu
|
||||
};
|
||||
|
||||
bool
|
||||
TGauge::Load_mapping( cParser &Input ) {
|
||||
TGauge::Load_mapping( cParser &Input, TGauge::scratch_data &Scratchpad ) {
|
||||
|
||||
// token can be a key or block end
|
||||
auto const key { Input.getToken<std::string>( true, "\n\r\t ,;" ) };
|
||||
@@ -236,8 +260,21 @@ TGauge::Load_mapping( cParser &Input ) {
|
||||
else if( key == "soundoff:" ) {
|
||||
m_soundfxoff.deserialize( Input, sound_type::single );
|
||||
}
|
||||
else if( key.compare( 0, std::min<std::size_t>( key.size(), 5 ), "sound" ) == 0 ) {
|
||||
// sounds assigned to specific gauge values, defined by key soundFoo: where Foo = value
|
||||
else if( key == "soundproofing:" ) {
|
||||
// custom soundproofing in format [ p1, p2, p3, p4, p5, p6 ]
|
||||
Input.getTokens( 6, false, "\n\r\t ,;[]" );
|
||||
std::array<float, 6> soundproofing;
|
||||
Input
|
||||
>> soundproofing[ 0 ]
|
||||
>> soundproofing[ 1 ]
|
||||
>> soundproofing[ 2 ]
|
||||
>> soundproofing[ 3 ]
|
||||
>> soundproofing[ 4 ]
|
||||
>> soundproofing[ 5 ];
|
||||
Scratchpad.soundproofing = soundproofing;
|
||||
}
|
||||
else if( starts_with( key, "sound" ) ) {
|
||||
// sounds assigned to specific gauge values, defined by key soundX: where X = value
|
||||
auto const indexstart { key.find_first_of( "-1234567890" ) };
|
||||
auto const indexend { key.find_first_not_of( "-1234567890", indexstart ) };
|
||||
if( indexstart != std::string::npos ) {
|
||||
@@ -290,13 +327,19 @@ TGauge::UpdateValue( float fNewDesired, sound_source *Fallbacksound ) {
|
||||
// HACK: crude way to discern controls with continuous and quantized value range
|
||||
if( currentvalue < fNewDesired ) {
|
||||
// shift up
|
||||
if( false == m_soundfxincrease.empty() ) {
|
||||
m_soundfxincrease.play( m_soundtype );
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( currentvalue > fNewDesired ) {
|
||||
// shift down
|
||||
if( false == m_soundfxdecrease.empty() ) {
|
||||
m_soundfxdecrease.play( m_soundtype );
|
||||
return;
|
||||
}
|
||||
else if( Fallbacksound != nullptr ) {
|
||||
}
|
||||
if( Fallbacksound != nullptr ) {
|
||||
// ...and if that fails too, try the provided fallback sound from legacy system
|
||||
Fallbacksound->play( m_soundtype );
|
||||
}
|
||||
|
||||
6
Gauge.h
6
Gauge.h
@@ -71,10 +71,14 @@ public:
|
||||
*SubModelOn { nullptr }; // optional submodel visible when the state input is set
|
||||
|
||||
private:
|
||||
// types
|
||||
struct scratch_data {
|
||||
std::optional< std::array<float, 6> > soundproofing;
|
||||
};
|
||||
// methods
|
||||
// imports member data pair from the config file
|
||||
bool
|
||||
Load_mapping( cParser &Input );
|
||||
Load_mapping( cParser &Input, TGauge::scratch_data &Scratchpad );
|
||||
void
|
||||
UpdateValue( float fNewDesired, sound_source *Fallbacksound );
|
||||
float
|
||||
|
||||
@@ -1046,7 +1046,7 @@ public:
|
||||
double EngineHeatingRPM { 0.0 }; // guaranteed engine revolutions with heating enabled
|
||||
double LightPower = 0.0; /*moc pobierana na ogrzewanie/oswietlenie*/
|
||||
double BatteryVoltage = 0.0; /*Winger - baterie w elektrykach*/
|
||||
bool Battery = false; /*Czy sa zalavzone baterie*/
|
||||
bool Battery = false; /*Czy sa zalaczone baterie*/
|
||||
start_t BatteryStart = start_t::manual;
|
||||
bool EpFuse = true; /*Czy sa zalavzone baterie*/
|
||||
bool Signalling = false; /*Czy jest zalaczona sygnalizacja hamowania ostatniego wagonu*/
|
||||
@@ -1805,6 +1805,8 @@ public:
|
||||
bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/
|
||||
bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/
|
||||
bool ChangeCompressorPreset( int const Change, range_t const Notify = range_t::consist );
|
||||
bool HeatingSwitch( bool const State, range_t const Notify = range_t::consist );
|
||||
void HeatingSwitch_( bool const State );
|
||||
|
||||
/*-funkcje typowe dla lokomotywy elektrycznej*/
|
||||
void LowVoltagePowerCheck( double const Deltatime );
|
||||
|
||||
@@ -647,10 +647,12 @@ bool TMoverParameters::ChangeCab(int direction)
|
||||
// rozruch wysoki (true) albo niski (false)
|
||||
bool
|
||||
TMoverParameters::CurrentSwitch(bool const State) {
|
||||
// Ra: przeniosłem z Train.cpp, nie wiem czy ma to sens
|
||||
|
||||
if( MaxCurrentSwitch( State ) ) {
|
||||
if (TrainType != dt_EZT)
|
||||
return (MinCurrentSwitch(State));
|
||||
if( TrainType != dt_EZT ) {
|
||||
( MinCurrentSwitch( State ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// TBD, TODO: split off shunt mode toggle into a separate command? It doesn't make much sense to have these two together like that
|
||||
// dla 2Ls150
|
||||
@@ -3641,6 +3643,33 @@ bool TMoverParameters::ChangeCompressorPreset( int const State, range_t const No
|
||||
return ( CompressorListPos != initialstate );
|
||||
}
|
||||
|
||||
bool TMoverParameters::HeatingSwitch( bool const State, range_t const Notify ) {
|
||||
|
||||
bool const initialstate { HeatingAllow };
|
||||
|
||||
HeatingSwitch_( State );
|
||||
|
||||
if( Notify != range_t::local ) {
|
||||
// pass the command to other vehicles
|
||||
// TBD: pass the requested state, or the actual state?
|
||||
SendCtrlToNext(
|
||||
"HeatingSwitch",
|
||||
( State ? 1 : 0 ),
|
||||
CabActive,
|
||||
( Notify == range_t::unit ?
|
||||
coupling::control | coupling::permanent :
|
||||
coupling::control ) );
|
||||
}
|
||||
|
||||
return ( HeatingAllow != initialstate );
|
||||
}
|
||||
|
||||
void TMoverParameters::HeatingSwitch_( bool const State ) {
|
||||
|
||||
// TBD, TODO: activation dependencies?
|
||||
HeatingAllow = State;
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// Q: 20160711
|
||||
// zwiększenie nastawy hamulca
|
||||
@@ -6550,12 +6579,14 @@ bool TMoverParameters::MaxCurrentSwitch(bool State)
|
||||
if (State && (Imax == ImaxLo) && (RList[MainCtrlPos].Bn < 2) &&
|
||||
!((TrainType == dt_ET42) && (MainCtrlPos > 0)))
|
||||
{
|
||||
|
||||
Imax = ImaxHi;
|
||||
MCS = true;
|
||||
if (CabActive != 0)
|
||||
SendCtrlToNext("MaxCurrentSwitch", 1, CabActive);
|
||||
}
|
||||
if (!State)
|
||||
|
||||
if (Imax == ImaxHi)
|
||||
if (!((TrainType == dt_ET42) && (MainCtrlPos > 0)))
|
||||
{
|
||||
@@ -11771,6 +11802,11 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
MainSwitch_( CValue1 > 0.0 );
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if (Command == "HeatingSwitch")
|
||||
{
|
||||
HeatingSwitch_( CValue1 > 0.0 );
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if (Command == "Direction")
|
||||
{
|
||||
DirActive = static_cast<int>(floor(CValue1));
|
||||
|
||||
24
Train.cpp
24
Train.cpp
@@ -4859,7 +4859,7 @@ void TTrain::OnCommand_heatingenable( TTrain *Train, command_data const &Command
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
Train->mvControlled->HeatingAllow = true;
|
||||
Train->mvOccupied->HeatingSwitch( true );
|
||||
// visual feedback
|
||||
Train->ggTrainHeatingButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
@@ -4869,7 +4869,7 @@ void TTrain::OnCommand_heatingdisable( TTrain *Train, command_data const &Comman
|
||||
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
Train->mvControlled->HeatingAllow = false;
|
||||
Train->mvOccupied->HeatingSwitch( false );
|
||||
// visual feedback
|
||||
Train->ggTrainHeatingButton.UpdateValue(
|
||||
( Train->ggTrainHeatingButton.type() == TGaugeType::push ?
|
||||
@@ -7101,7 +7101,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
}
|
||||
ggMainCtrl.Update();
|
||||
}
|
||||
if (ggMainCtrlAct.SubModel)
|
||||
if (ggMainCtrlAct.SubModel != nullptr )
|
||||
{
|
||||
if (mvControlled->CoupledCtrl)
|
||||
ggMainCtrlAct.UpdateValue(
|
||||
@@ -7110,7 +7110,7 @@ bool TTrain::Update( double const Deltatime )
|
||||
ggMainCtrlAct.UpdateValue(double(mvControlled->MainCtrlActualPos));
|
||||
ggMainCtrlAct.Update();
|
||||
}
|
||||
if (ggScndCtrl.SubModel) {
|
||||
if (ggScndCtrl.SubModel != nullptr ) {
|
||||
// Ra: od byte odejmowane boolean i konwertowane potem na double?
|
||||
ggScndCtrl.UpdateValue(
|
||||
double( mvControlled->ScndCtrlPos
|
||||
@@ -7118,26 +7118,34 @@ bool TTrain::Update( double const Deltatime )
|
||||
dsbNastawnikBocz );
|
||||
ggScndCtrl.Update();
|
||||
}
|
||||
if( ggScndCtrlButton.SubModel != nullptr ) {
|
||||
if( ggScndCtrlButton.is_toggle() ) {
|
||||
ggScndCtrlButton.UpdateValue(
|
||||
( ( mvControlled->ScndCtrlPos > 0 ) ? 1.f : 0.f ),
|
||||
dsbSwitch );
|
||||
}
|
||||
ggScndCtrlButton.Update( lowvoltagepower );
|
||||
}
|
||||
if( ggScndCtrlOffButton.SubModel != nullptr ) {
|
||||
ggScndCtrlOffButton.Update( lowvoltagepower );
|
||||
}
|
||||
if( ggDistanceCounterButton.SubModel != nullptr ) {
|
||||
ggDistanceCounterButton.Update();
|
||||
if (ggDirKey.SubModel) {
|
||||
if (mvControlled->TrainType != dt_EZT)
|
||||
}
|
||||
if (ggDirKey.SubModel != nullptr ) {
|
||||
if( mvControlled->TrainType != dt_EZT ) {
|
||||
ggDirKey.UpdateValue(
|
||||
double( mvControlled->DirActive ),
|
||||
dsbReverserKey );
|
||||
else
|
||||
}
|
||||
else {
|
||||
ggDirKey.UpdateValue(
|
||||
double( mvControlled->DirActive ) + double( mvControlled->Imin == mvControlled->IminHi ),
|
||||
dsbReverserKey );
|
||||
}
|
||||
ggDirKey.Update();
|
||||
}
|
||||
if (ggBrakeCtrl.SubModel)
|
||||
if (ggBrakeCtrl.SubModel != nullptr )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (DynamicObject->Mechanik ?
|
||||
|
||||
@@ -1147,24 +1147,24 @@ TController::cue_action( locale::string const Action, float const Actionparamete
|
||||
// consist heating
|
||||
case locale::string::driver_hint_consistheatingon: {
|
||||
if( AIControllFlag ) {
|
||||
mvControlling->HeatingAllow = true;
|
||||
mvOccupied->HeatingSwitch( true );
|
||||
}
|
||||
remove_hint( locale::string::driver_hint_consistheatingoff );
|
||||
hint(
|
||||
Action,
|
||||
[this](float const Parameter) -> bool {
|
||||
return ( mvControlling->HeatingAllow == true ); } );
|
||||
return ( mvOccupied->HeatingAllow == true ); } );
|
||||
break;
|
||||
}
|
||||
case locale::string::driver_hint_consistheatingoff: {
|
||||
if( AIControllFlag ) {
|
||||
mvControlling->HeatingAllow = false;
|
||||
mvOccupied->HeatingSwitch( false );
|
||||
}
|
||||
remove_hint( locale::string::driver_hint_consistheatingon );
|
||||
hint(
|
||||
Action,
|
||||
[this](float const Parameter) -> bool {
|
||||
return ( mvControlling->HeatingAllow == false ); } );
|
||||
return ( mvOccupied->HeatingAllow == false ); } );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1088,7 +1088,7 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
|
||||
// biezaca komenda dla AI
|
||||
auto textline =
|
||||
"Current order: [" + std::to_string( mechanik.OrderPos ) + "] "
|
||||
+ mechanik.OrderCurrent();
|
||||
+ mechanik.Order2Str( mechanik.OrderCurrentGet() );
|
||||
|
||||
if( mechanik.fStopTime < 0.0 ) {
|
||||
textline += "\n stop time: " + to_string( std::abs( mechanik.fStopTime ), 1 );
|
||||
|
||||
37
sound.cpp
37
sound.cpp
@@ -171,10 +171,23 @@ sound_source::deserialize_mapping( cParser &Input ) {
|
||||
else if( key == "soundend:" ) {
|
||||
sound( sound_id::end ).buffer = audio::renderer.fetch_buffer( deserialize_random_set( Input, "\n\r\t ,;" ) );
|
||||
}
|
||||
else if( key.compare( 0, std::min<std::size_t>( key.size(), 5 ), "sound" ) == 0 ) {
|
||||
else if( key == "soundproofing:" ) {
|
||||
// custom soundproofing in format [ p1, p2, p3, p4, p5, p6 ]
|
||||
Input.getTokens( 6, false, "\n\r\t ,;[]" );
|
||||
std::array<float, 6> soundproofing;
|
||||
Input
|
||||
>> soundproofing[ 0 ]
|
||||
>> soundproofing[ 1 ]
|
||||
>> soundproofing[ 2 ]
|
||||
>> soundproofing[ 3 ]
|
||||
>> soundproofing[ 4 ]
|
||||
>> soundproofing[ 5 ];
|
||||
m_soundproofing = soundproofing;
|
||||
}
|
||||
else if( starts_with( key, "sound" ) ) {
|
||||
// sound chunks, defined with key soundX where X = activation threshold
|
||||
auto const indexstart { key.find_first_of( "1234567890" ) };
|
||||
auto const indexend { key.find_first_not_of( "1234567890", indexstart ) };
|
||||
auto const indexstart { key.find_first_of( "-1234567890" ) };
|
||||
auto const indexend { key.find_first_not_of( "-1234567890", indexstart ) };
|
||||
if( indexstart != std::string::npos ) {
|
||||
// NOTE: we'll sort the chunks at the end of deserialization
|
||||
m_soundchunks.emplace_back(
|
||||
@@ -202,10 +215,10 @@ sound_source::deserialize_mapping( cParser &Input ) {
|
||||
Input.getToken<float>( false, "\n\r\t ,;" ),
|
||||
0.0f, 1.0f );
|
||||
}
|
||||
else if( key.compare( 0, std::min<std::size_t>( key.size(), 5 ), "pitch" ) == 0 ) {
|
||||
else if( starts_with( key, "pitch" ) ) {
|
||||
// sound chunk pitch, defined with key pitchX where X = activation threshold
|
||||
auto const indexstart { key.find_first_of( "1234567890" ) };
|
||||
auto const indexend { key.find_first_not_of( "1234567890", indexstart ) };
|
||||
auto const indexstart { key.find_first_of( "-1234567890" ) };
|
||||
auto const indexend { key.find_first_not_of( "-1234567890", indexstart ) };
|
||||
if( indexstart != std::string::npos ) {
|
||||
auto const index { std::stoi( key.substr( indexstart, indexend - indexstart ) ) };
|
||||
auto const pitch { Input.getToken<float>( false, "\n\r\t ,;" ) };
|
||||
@@ -962,12 +975,14 @@ sound_source::update_soundproofing() {
|
||||
auto const isambient { ( ( m_placement == sound_placement::external ) && ( m_owner == nullptr ) && ( m_range < -1 ) ? 1 : 0 ) };
|
||||
auto const placement { ( isambient ? sound_placement::external_ambient : m_placement ) };
|
||||
if( m_owner != nullptr ) {
|
||||
m_properties.soundproofing =
|
||||
m_owner->soundproofing(
|
||||
static_cast<int>( placement ),
|
||||
( m_owner != listenervehicle ?
|
||||
auto const listenerlocation { (
|
||||
m_owner != listenervehicle ?
|
||||
4 : // part of two-stage calculation owner->outside->listener, or single stage owner->outside one
|
||||
occupiedcab ) );
|
||||
occupiedcab ) };
|
||||
m_properties.soundproofing = (
|
||||
m_soundproofing ? // custom soundproofing has higher priority than that of the owner
|
||||
m_soundproofing.value()[ listenerlocation + 1 ] : // cab indices start from -1 so we have to account for this
|
||||
m_owner->soundproofing( static_cast<int>( placement ), listenerlocation ) );
|
||||
}
|
||||
if( ( listenervehicle ) && ( listenervehicle != m_owner ) ) {
|
||||
// if the listener is located in another vehicle, calculate additional proofing of the sound coming from outside
|
||||
|
||||
10
sound.h
10
sound.h
@@ -116,6 +116,11 @@ public:
|
||||
start( float const Offset );
|
||||
float const &
|
||||
start() const;
|
||||
// custom soundproofing setter/getter
|
||||
auto &
|
||||
soundproofing();
|
||||
auto const &
|
||||
soundproofing() const;
|
||||
// returns true if there isn't any sound buffer associated with the object, false otherwise
|
||||
bool
|
||||
empty() const;
|
||||
@@ -231,6 +236,7 @@ private:
|
||||
std::vector<soundchunk_pair> m_soundchunks; // table of samples activated when associated variable is within certain range
|
||||
bool m_soundchunksempty { true }; // helper, cached check whether sample table is linked with any actual samples
|
||||
int m_crossfaderange {}; // range of transition from one chunk to another
|
||||
std::optional< std::array<float, 6> > m_soundproofing; // custom soundproofing parameters
|
||||
};
|
||||
|
||||
// owner setter/getter
|
||||
@@ -245,6 +251,10 @@ inline std::string const & sound_source::name() const { return m_name; }
|
||||
// playback starting point shift setter/getter
|
||||
inline void sound_source::start( float const Offset ) { m_startoffset = Offset; }
|
||||
inline float const & sound_source::start() const { return m_startoffset; }
|
||||
// custom soundproofing setter/getter
|
||||
inline auto & sound_source::soundproofing() { return m_soundproofing; }
|
||||
inline auto const & sound_source::soundproofing() const { return m_soundproofing; }
|
||||
|
||||
|
||||
// collection of sound sources present in the scene
|
||||
class sound_table : public basic_table<sound_source> {
|
||||
|
||||
@@ -393,15 +393,15 @@ init() {
|
||||
"Wylaczyc przetwornice",
|
||||
"Odblokowac przekaznik nadmiarowy przetwornicy",
|
||||
"Odblokowac przekaznik roznicowy obwodu glownego",
|
||||
"Odblokowac przekaznik nadmiarowy motorow trakcyjnych",
|
||||
"Odblokowac przekaznik nadmiarowy silnikow trakcyjnych",
|
||||
"Zamknac wylacznik szybki",
|
||||
"Otworzyc wylacznik szybki",
|
||||
"Zalaczyc sprezarke",
|
||||
"Wylaczyc sprezarke",
|
||||
"Zalaczyc wentylatory przednich motorow trakcyjnych",
|
||||
"Wylaczyc wentylatory przednich motorow trakcyjnych",
|
||||
"Zalaczyc wentylatory tylnych motorow trakcyjnych",
|
||||
"Wylaczyc wentylatory tylnych motorow trakcyjnych",
|
||||
"Zalaczyc wentylatory przednich silnikow trakcyjnych",
|
||||
"Wylaczyc wentylatory przednich silnikow trakcyjnych",
|
||||
"Zalaczyc wentylatory tylnych silnikow trakcyjnych",
|
||||
"Wylaczyc wentylatory tylnych silnikow trakcyjnych",
|
||||
"Zalaczyc hamulec sprezynowy",
|
||||
"Zwolnic hamules sprezynowy",
|
||||
"Zalaczyc hamulec reczny",
|
||||
|
||||
@@ -77,7 +77,7 @@ ui_layer::init( GLFWwindow *Window ) {
|
||||
|
||||
static ImWchar const glyphranges[] = {
|
||||
0x0020, 0x00FF, // ascii + extension
|
||||
0x0100, 0x017F, // latin extended-a
|
||||
// 0x0100, 0x017F, // latin extended-a
|
||||
0x2070, 0x2079, // superscript
|
||||
0x2500, 0x256C, // box drawings
|
||||
0,
|
||||
|
||||
Reference in New Issue
Block a user