16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 17:29:18 +02:00

build 210508. spring brake sound support, internaldata sounds update fix, minor bug fixes

This commit is contained in:
tmj-fstate
2021-05-09 02:01:16 +02:00
parent fa9136e333
commit 51415ef71f
8 changed files with 494 additions and 543 deletions

View File

@@ -2709,10 +2709,11 @@ bool TController::PrepareEngine()
cue_action( locale::string::driver_hint_pantographcompressoroff ); // sprężarkę pantografów można już wyłączyć
}
}
// TODO: make pantograph setup a part of control_pantographs() and call it here instead
if( ( fOverhead2 == -1.0 ) && ( iOverheadDown == 0 ) ) {
cue_action( locale::string::driver_hint_pantographsvalveon );
cue_action( locale::string::driver_hint_frontpantographvalveon );
cue_action( locale::string::driver_hint_rearpantographvalveon );
cue_action( locale::string::driver_hint_frontpantographvalveon, ( iDirection >= 0 ? 5 : 0 ) );
cue_action( locale::string::driver_hint_rearpantographvalveon, ( iDirection >= 0 ? 0 : 5 ) );
}
}

View File

@@ -4209,7 +4209,7 @@ void TDynamicObject::RenderSounds() {
}
// Dzwiek odluzniacza
if( MoverParameters->Hamulec->GetStatus() & b_rls ) {
if( MoverParameters->Hamulec->Releaser() ) {
sReleaser
.gain(
clamp<float>(
@@ -4294,6 +4294,19 @@ void TDynamicObject::RenderSounds() {
rsPisk.stop();
}
// spring brake
if( m_springbrakesounds.state != MoverParameters->SpringBrake.Activate ) {
m_springbrakesounds.state = MoverParameters->SpringBrake.Activate;
if( m_springbrakesounds.state ) {
m_springbrakesounds.activate.play( sound_flags::exclusive );
m_springbrakesounds.release.stop();
}
else {
m_springbrakesounds.activate.stop();
m_springbrakesounds.release.play( sound_flags::exclusive );
}
}
// other sounds
// load exchange
if( MoverParameters->LoadStatus & 1 ) {
@@ -5702,6 +5715,15 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
rsUnbrake.deserialize( parser, sound_type::single, sound_parameters::range );
rsUnbrake.owner( this );
}
// spring brake sounds
else if( token == "springbrake:" ) {
m_springbrakesounds.activate.deserialize( parser, sound_type::single );
m_springbrakesounds.activate.owner( this );
}
else if( token == "springbrakeoff:" ) {
m_springbrakesounds.release.deserialize( parser, sound_type::single );
m_springbrakesounds.release.owner( this );
}
else if( token == "derail:" ) {
// dzwiek przy wykolejeniu

View File

@@ -421,6 +421,12 @@ private:
sound_source announcement;
std::deque<sound_source> announcement_queue; // fifo queue
};
struct springbrake_sounds {
sound_source activate { sound_placement::external };
sound_source release { sound_placement::external };
bool state { false };
};
// methods
void ABuLittleUpdate(double ObjSqrDist);
@@ -496,6 +502,7 @@ private:
sound_source m_emergencybrake { sound_placement::engine };
double m_emergencybrakeflow{ 0.f };
sound_source sReleaser { sound_placement::external };
springbrake_sounds m_springbrakesounds;
sound_source rsSlippery { sound_placement::external, EU07_SOUND_BRAKINGCUTOFFRANGE }; // moved from cab
sound_source sSand { sound_placement::external };
// moving part and other external sounds

View File

@@ -286,25 +286,25 @@ TGauge::Load_mapping( cParser &Input, TGauge::scratch_data &Scratchpad ) {
return true; // return value marks a key: value pair was extracted, nothing about whether it's recognized
}
void
TGauge::UpdateValue( float fNewDesired ) {
return UpdateValue( fNewDesired, nullptr );
}
void
TGauge::UpdateValue( float fNewDesired, sound_source &Fallbacksound ) {
return UpdateValue( fNewDesired, &Fallbacksound );
}
// ustawienie wartości docelowej. plays provided fallback sound, if no sound was defined in the control itself
void
TGauge::UpdateValue( float fNewDesired, sound_source *Fallbacksound ) {
bool
TGauge::UpdateValue( float fNewDesired, std::optional<sound_source> &Fallbacksound ) {
if( false == UpdateValue( fNewDesired ) ) {
if( Fallbacksound ) {
Fallbacksound->play( m_soundtype );
return true;
}
}
return false;
}
bool
TGauge::UpdateValue( float fNewDesired ) {
auto const desiredtimes100 = static_cast<int>( std::round( 100.0 * fNewDesired ) );
if( desiredtimes100 == static_cast<int>( std::round( 100.0 * m_targetvalue ) ) ) {
return;
return true;
}
m_targetvalue = fNewDesired;
// if there's any sound associated with new requested value, play it
@@ -315,7 +315,7 @@ TGauge::UpdateValue( float fNewDesired, sound_source *Fallbacksound ) {
auto const lookup = m_soundfxvalues.find( desiredtimes100 / 100 );
if( lookup != m_soundfxvalues.end() ) {
lookup->second.play();
return;
return true;
}
}
else {
@@ -329,20 +329,17 @@ TGauge::UpdateValue( float fNewDesired, sound_source *Fallbacksound ) {
// shift up
if( false == m_soundfxincrease.empty() ) {
m_soundfxincrease.play( m_soundtype );
return;
return true;
}
}
else if( currentvalue > fNewDesired ) {
// shift down
if( false == m_soundfxdecrease.empty() ) {
m_soundfxdecrease.play( m_soundtype );
return;
return true;
}
}
if( Fallbacksound != nullptr ) {
// ...and if that fails too, try the provided fallback sound from legacy system
Fallbacksound->play( m_soundtype );
}
return false; // no suitable sound was found
};
void TGauge::PutValue(float fNewDesired)

View File

@@ -43,8 +43,8 @@ public:
*this = TGauge(); }
void Init(TSubModel *Submodel, TSubModel *Submodelon, TGaugeAnimation Type, float Scale = 1, float Offset = 0, float Friction = 0, float Value = 0, float const Endvalue = -1.0, float const Endscale = -1.0, bool const Interpolate = false );
void Load(cParser &Parser, TDynamicObject const *Owner, double const mul = 1.0);
void UpdateValue( float fNewDesired );
void UpdateValue( float fNewDesired, sound_source &Fallbacksound );
bool UpdateValue( float fNewDesired );
bool UpdateValue( float fNewDesired, std::optional<sound_source> &Fallbacksound );
void PutValue(float fNewDesired);
float GetValue() const;
float GetDesiredValue() const;
@@ -79,8 +79,6 @@ private:
// imports member data pair from the config file
bool
Load_mapping( cParser &Input, TGauge::scratch_data &Scratchpad );
void
UpdateValue( float fNewDesired, sound_source *Fallbacksound );
float
GetScaledValue() const;
void

652
Train.cpp
View File

@@ -671,32 +671,33 @@ dictionary_source *TTrain::GetTrainState( dictionary_source const &Extraparamete
for( int j = 0; j < 10; ++j )
dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] );
for( int i = 0; i < 8; ++i ) {
auto const idx { std::to_string( i + 1 ) };
for( int j = 0; j < 10; ++j )
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] );
dict->insert( ( "eimp_c" + idx + "_" + std::string( TXTC[ j ] ) ), fEIMParams[ i + 1 ][ j ] );
for (int j = 0; j < 10; ++j)
dict->insert(("diesel_param_" + std::to_string(i + 1) + "_" + std::string(TXTD[j])), fDieselParams[i + 1][j]);
dict->insert(("diesel_param_" + idx + "_" + std::string(TXTD[j])), fDieselParams[i + 1][j]);
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_ms" ), bMains[ i ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_cv" ), fCntVol[ i ] );
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pf" ), bPants[ i ][ 0 ] );
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_pr" ), bPants[ i ][ 1 ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_fuse" ), bFuse[ i ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_batt" ), bBatt[ i ] );
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_conv" ), bConv[ i ] );
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_comp_a" ), bComp[ i ][ 0 ] );
dict->insert( ( "eimp_u" + std::to_string( i + 1 ) + "_comp_w" ), bComp[ i ][ 1 ] );
//dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_comp_a" ), bComp[ i ][ 2 ]);
//dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_comp_w" ), bComp[ i ][ 3 ]);
dict->insert( ( "eimp_c" + std::to_string( i + 1 ) + "_heat" ), bHeat[ i ] );
dict->insert( ( "eimp_c" + idx + "_ms" ), bMains[ i ] );
dict->insert( ( "eimp_c" + idx + "_cv" ), fCntVol[ i ] );
dict->insert( ( "eimp_c" + idx + "_fuse" ), bFuse[ i ] );
dict->insert( ( "eimp_c" + idx + "_batt" ), bBatt[ i ] );
dict->insert( ( "eimp_c" + idx + "_conv" ), bConv[ i ] );
dict->insert( ( "eimp_c" + idx + "_heat" ), bHeat[ i ] );
dict->insert( ( "eimp_u" + idx + "_pf" ), bPants[ i ][ 0 ] );
dict->insert( ( "eimp_u" + idx + "_pr" ), bPants[ i ][ 1 ] );
dict->insert( ( "eimp_u" + idx + "_comp_a" ), bComp[ i ][ 0 ] );
dict->insert( ( "eimp_u" + idx + "_comp_w" ), bComp[ i ][ 1 ] );
}
dict->insert( "compressors_no", (int)bCompressors.size() );
for (int i = 0; i < bCompressors.size(); i++)
{
dict->insert("compressors_" + std::to_string(i + 1) + "_allow", std::get<0>(bCompressors[i]));
dict->insert("compressors_" + std::to_string(i + 1) + "_work", std::get<1>(bCompressors[i]));
dict->insert("compressors_" + std::to_string(i + 1) + "_car_no", std::get<2>(bCompressors[i]));
auto const idx { std::to_string( i + 1 ) };
dict->insert("compressors_" + idx + "_allow", std::get<0>(bCompressors[i]));
dict->insert("compressors_" + idx + "_work", std::get<1>(bCompressors[i]));
dict->insert("compressors_" + idx + "_car_no", std::get<2>(bCompressors[i]));
}
@@ -856,7 +857,9 @@ void TTrain::set_train_brake( double const Position ) {
( ( originalbrakeposition / 100 == 0 ) || ( originalbrakeposition / 100 >= 5 ) )
&& ( ( mvOccupied->BrakeCtrlPos == 0 ) || ( mvOccupied->BrakeCtrlPos >= 5 ) ) ) ) ) {
// sound feedback if the lever movement activates one of the switches
dsbPneumaticSwitch.play();
if( dsbPneumaticSwitch ) {
dsbPneumaticSwitch->play();
}
}
}
@@ -1839,7 +1842,9 @@ void TTrain::OnCommand_epbrakecontroltoggle( TTrain *Train, command_data const &
// turn on
if( Train->mvOccupied->EpFuseSwitch( true ) ) {
// audio feedback
Train->dsbPneumaticSwitch.play();
if( Train->dsbPneumaticSwitch ) {
Train->dsbPneumaticSwitch->play();
}
};
}
else {
@@ -1851,7 +1856,9 @@ void TTrain::OnCommand_epbrakecontroltoggle( TTrain *Train, command_data const &
// potentially turn on
if( Train->mvOccupied->EpFuseSwitch( true ) ) {
// audio feedback
Train->dsbPneumaticSwitch.play();
if( Train->dsbPneumaticSwitch ) {
Train->dsbPneumaticSwitch->play();
}
};
}
// visual feedback
@@ -6379,23 +6386,27 @@ bool TTrain::Update( double const Deltatime )
bPants[iUnitNo - 1][end::front] = ( bPants[iUnitNo - 1][end::front] || p->MoverParameters->Pantographs[end::front].is_active );
bPants[iUnitNo - 1][end::rear] = ( bPants[iUnitNo - 1][end::rear] || p->MoverParameters->Pantographs[end::rear].is_active );
}
// TBD, TODO: clean up compressor data arrangement?
if( iUnitNo <= 8 ) {
bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow || (p->MoverParameters->CompressorStart == start_t::automatic));
bSlip[i] = p->MoverParameters->SlippingWheels;
}
if (p->MoverParameters->CompressorSpeed > 0.00001)
{
if( iUnitNo <= 8 ) {
bComp[iUnitNo - 1][1] = (bComp[iUnitNo - 1][1] || p->MoverParameters->CompressorFlag);
}
bCompressors.emplace_back(
p->MoverParameters->CompressorAllow || (p->MoverParameters->CompressorStart == start_t::automatic),
p->MoverParameters->CompressorFlag,
i);
}
bSlip[i] = p->MoverParameters->SlippingWheels;
if ((in < 8) && (p->MoverParameters->eimc[eimc_p_Pmax] > 1))
{
fEIMParams[1 + in][0] = p->MoverParameters->eimv[eimv_Fmax];
fEIMParams[1 + in][1] = Max0R(fEIMParams[1 + in][0], 0);
fEIMParams[1 + in][2] = -Min0R(fEIMParams[1 + in][0], 0);
fEIMParams[1 + in][3] = p->MoverParameters->eimv[eimv_Fmax] /
Max0R(p->MoverParameters->eimv[eimv_Fful], 1);
fEIMParams[1 + in][3] = p->MoverParameters->eimv[eimv_Fmax] / Max0R(p->MoverParameters->eimv[eimv_Fful], 1);
fEIMParams[1 + in][4] = Max0R(fEIMParams[1 + in][3], 0);
fEIMParams[1 + in][5] = -Min0R(fEIMParams[1 + in][3], 0);
fEIMParams[1 + in][6] = p->MoverParameters->eimv[eimv_If];
@@ -6437,10 +6448,9 @@ bool TTrain::Update( double const Deltatime )
in++;
iPowerNo = in;
}
// p = p->NextC(4); //prev
if ((kier ? p->NextC(128) : p->PrevC(128)) != (kier ? p->NextC(4) : p->PrevC(4)))
if ((kier ? p->NextC(coupling::permanent) : p->PrevC(coupling::permanent)) != (kier ? p->NextC(coupling::control) : p->PrevC(coupling::control)))
iUnitNo++;
p = (kier ? p->NextC(4) : p->PrevC(4));
p = (kier ? p->NextC(coupling::control) : p->PrevC(coupling::control));
iCarNo = i + 1;
}
else
@@ -7437,32 +7447,34 @@ TTrain::update_sounds( double const Deltatime ) {
}
m_lastlocalbrakepressure = mvOccupied->LocBrakePress;
// local brake, release
if( rsSBHiss ) {
if( ( m_localbrakepressurechange < -0.05f )
&& ( mvOccupied->LocBrakePress > mvOccupied->BrakePress - 0.05 ) ) {
rsSBHiss
.gain( clamp( rsSBHiss.m_amplitudeoffset + rsSBHiss.m_amplitudefactor * -m_localbrakepressurechange * 0.05, 0.0, 1.5 ) )
.play( sound_flags::exclusive | sound_flags::looping );
rsSBHiss->gain( clamp( rsSBHiss->m_amplitudeoffset + rsSBHiss->m_amplitudefactor * -m_localbrakepressurechange * 0.05, 0.0, 1.5 ) );
rsSBHiss->play( sound_flags::exclusive | sound_flags::looping );
}
else {
// don't stop the sound too abruptly
volume = std::max( 0.0, rsSBHiss.gain() - 0.1 * Deltatime );
rsSBHiss.gain( volume );
volume = std::max( 0.0, rsSBHiss->gain() - 0.1 * Deltatime );
rsSBHiss->gain( volume );
if( volume < 0.05 ) {
rsSBHiss.stop();
rsSBHiss->stop();
}
}
}
// local brake, engage
if( rsSBHissU ) {
if( m_localbrakepressurechange > 0.05f ) {
rsSBHissU
.gain( clamp( rsSBHissU.m_amplitudeoffset + rsSBHissU.m_amplitudefactor * m_localbrakepressurechange * 0.05, 0.0, 1.5 ) )
.play( sound_flags::exclusive | sound_flags::looping );
rsSBHissU->gain( clamp( rsSBHissU->m_amplitudeoffset + rsSBHissU->m_amplitudefactor * m_localbrakepressurechange * 0.05, 0.0, 1.5 ) );
rsSBHissU->play( sound_flags::exclusive | sound_flags::looping );
}
else {
// don't stop the sound too abruptly
volume = std::max( 0.0, rsSBHissU.gain() - 0.1 * Deltatime );
rsSBHissU.gain( volume );
volume = std::max( 0.0, rsSBHissU->gain() - 0.1 * Deltatime );
rsSBHissU->gain( volume );
if( volume < 0.05 ) {
rsSBHissU.stop();
rsSBHissU->stop();
}
}
}
@@ -7471,97 +7483,105 @@ TTrain::update_sounds( double const Deltatime ) {
if( ( mvOccupied->BrakeHandle == TBrakeHandle::FV4a )
|| ( mvOccupied->BrakeHandle == TBrakeHandle::FVel6 ) ) {
// upuszczanie z PG
if( rsHiss ) {
fPPress = interpolate( fPPress, static_cast<float>( mvOccupied->Handle->GetSound( s_fv4a_b ) ), 0.05f );
volume = (
fPPress > 0 ?
rsHiss.m_amplitudefactor * fPPress * 0.25 :
rsHiss->m_amplitudefactor * fPPress * 0.25 :
0 );
if( volume * brakevolumescale > 0.05 ) {
rsHiss
.gain( volume * brakevolumescale )
.play( sound_flags::exclusive | sound_flags::looping );
rsHiss->gain( volume * brakevolumescale );
rsHiss->play( sound_flags::exclusive | sound_flags::looping );
}
else {
rsHiss.stop();
rsHiss->stop();
}
}
// napelnianie PG
if( rsHissU ) {
fNPress = interpolate( fNPress, static_cast<float>( mvOccupied->Handle->GetSound( s_fv4a_u ) ), 0.25f );
volume = (
fNPress > 0 ?
rsHissU.m_amplitudefactor * fNPress :
rsHissU->m_amplitudefactor * fNPress :
0 );
if( volume * brakevolumescale > 0.05 ) {
rsHissU
.gain( volume * brakevolumescale )
.play( sound_flags::exclusive | sound_flags::looping );
rsHissU->gain( volume * brakevolumescale );
rsHissU->play( sound_flags::exclusive | sound_flags::looping );
}
else {
rsHissU.stop();
rsHissU->stop();
}
}
// upuszczanie przy naglym
volume = mvOccupied->Handle->GetSound( s_fv4a_e ) * rsHissE.m_amplitudefactor;
if( rsHissE ) {
volume = mvOccupied->Handle->GetSound( s_fv4a_e ) * rsHissE->m_amplitudefactor;
if( volume * brakevolumescale > 0.05 ) {
rsHissE
.gain( volume * brakevolumescale )
.play( sound_flags::exclusive | sound_flags::looping );
rsHissE->gain( volume * brakevolumescale );
rsHissE->play( sound_flags::exclusive | sound_flags::looping );
}
else {
rsHissE.stop();
rsHissE->stop();
}
}
// upuszczanie sterujacego fala
volume = mvOccupied->Handle->GetSound( s_fv4a_x ) * rsHissX.m_amplitudefactor;
if( rsHissX ) {
volume = mvOccupied->Handle->GetSound( s_fv4a_x ) * rsHissX->m_amplitudefactor;
if( volume * brakevolumescale > 0.05 ) {
rsHissX
.gain( volume * brakevolumescale )
.play( sound_flags::exclusive | sound_flags::looping );
rsHissX->gain( volume * brakevolumescale );
rsHissX->play( sound_flags::exclusive | sound_flags::looping );
}
else {
rsHissX.stop();
rsHissX->stop();
}
}
// upuszczanie z czasowego
volume = mvOccupied->Handle->GetSound( s_fv4a_t ) * rsHissT.m_amplitudefactor;
if( rsHissT ) {
volume = mvOccupied->Handle->GetSound( s_fv4a_t ) * rsHissT->m_amplitudefactor;
if( volume * brakevolumescale > 0.05 ) {
rsHissT
.gain( volume * brakevolumescale )
.play( sound_flags::exclusive | sound_flags::looping );
rsHissT->gain( volume * brakevolumescale );
rsHissT->play( sound_flags::exclusive | sound_flags::looping );
}
else {
rsHissT.stop();
rsHissT->stop();
}
}
} else {
// jesli nie FV4a
// upuszczanie z PG
if( rsHiss ) {
fPPress = ( 4.0f * fPPress + std::max( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
volume = (
fPPress > 0.0f ?
2.0 * rsHiss.m_amplitudefactor * fPPress :
2.0 * rsHiss->m_amplitudefactor * fPPress :
0.0 );
if( volume > 0.05 ) {
rsHiss
.gain( volume )
.play( sound_flags::exclusive | sound_flags::looping );
rsHiss->gain( volume );
rsHiss->play( sound_flags::exclusive | sound_flags::looping );
}
else {
rsHiss.stop();
rsHiss->stop();
}
}
// napelnianie PG
if( rsHissU ) {
fNPress = ( 4.0f * fNPress + Min0R( mvOccupied->dpLocalValve, mvOccupied->dpMainValve ) ) / ( 4.0f + 1.0f );
volume = (
fNPress < 0.0f ?
-1.0 * rsHissU.m_amplitudefactor * fNPress :
-1.0 * rsHissU->m_amplitudefactor * fNPress :
0.0 );
if( volume > 0.01 ) {
rsHissU
.gain( volume )
.play( sound_flags::exclusive | sound_flags::looping );
rsHissU->gain( volume );
rsHissU->play( sound_flags::exclusive | sound_flags::looping );
}
else {
rsHissU.stop();
rsHissU->stop();
}
}
} // koniec nie FV4a
// brakes
if( rsBrake ) {
if( ( mvOccupied->UnitBrakeForce > 10.0 )
&& ( mvOccupied->Vel > 0.05 ) ) {
@@ -7573,49 +7593,54 @@ TTrain::update_sounds( double const Deltatime ) {
volume = (
FreeFlyModeFlag ?
0.0 :
rsBrake.m_amplitudeoffset
+ std::sqrt( brakeforceratio * interpolate( 0.4, 1.0, ( mvOccupied->Vel / ( 1 + mvOccupied->Vmax ) ) ) ) * rsBrake.m_amplitudefactor );
rsBrake
.pitch( rsBrake.m_frequencyoffset + mvOccupied->Vel * rsBrake.m_frequencyfactor )
.gain( volume )
.play( sound_flags::exclusive | sound_flags::looping );
rsBrake->m_amplitudeoffset
+ std::sqrt( brakeforceratio * interpolate( 0.4, 1.0, ( mvOccupied->Vel / ( 1 + mvOccupied->Vmax ) ) ) ) * rsBrake->m_amplitudefactor );
rsBrake->pitch( rsBrake->m_frequencyoffset + mvOccupied->Vel * rsBrake->m_frequencyfactor );
rsBrake->gain( volume );
rsBrake->play( sound_flags::exclusive | sound_flags::looping );
}
else {
rsBrake.stop();
rsBrake->stop();
}
}
// ambient sound
// since it's typically ticking of the clock we can center it on tachometer or on middle of compartment bounding area
rsFadeSound.play( sound_flags::exclusive | sound_flags::looping );
if( rsFadeSound ) {
rsFadeSound->play( sound_flags::exclusive | sound_flags::looping );
}
if( mvControlled->TrainType == dt_181 ) {
if( dsbSlipAlarm ) {
// alarm przy poslizgu dla 181/182 - BOMBARDIER
if( ( mvControlled->SlippingWheels )
&& ( DynamicObject->GetVelocity() > 1.0 ) ) {
dsbSlipAlarm.play( sound_flags::exclusive | sound_flags::looping );
dsbSlipAlarm->play( sound_flags::exclusive | sound_flags::looping );
}
else {
dsbSlipAlarm.stop();
dsbSlipAlarm->stop();
}
}
// szum w czasie jazdy
if( rsRunningNoise ) {
if( ( false == FreeFlyModeFlag )
&& ( false == Global.CabWindowOpen )
&& ( DynamicObject->GetVelocity() > 0.5 ) ) {
update_sounds_runningnoise( rsRunningNoise );
update_sounds_runningnoise( *rsRunningNoise );
}
else {
// don't play the optional ending sound if the listener switches views
rsRunningNoise.stop( true == FreeFlyModeFlag );
rsRunningNoise->stop( true == FreeFlyModeFlag );
}
}
// hunting oscillation noise
if( rsHuntingNoise ) {
if( ( false == FreeFlyModeFlag )
&& ( false == Global.CabWindowOpen )
&& ( DynamicObject->GetVelocity() > 0.5 )
&& ( DynamicObject->IsHunting ) ) {
update_sounds_runningnoise( rsHuntingNoise );
update_sounds_runningnoise( *rsHuntingNoise );
// modify calculated sound volume by hunting amount
auto const huntingamount =
interpolate(
@@ -7624,63 +7649,68 @@ TTrain::update_sounds( double const Deltatime ) {
( mvOccupied->Vel - DynamicObject->HuntingShake.fadein_begin ) / ( DynamicObject->HuntingShake.fadein_end - DynamicObject->HuntingShake.fadein_begin ),
0.0, 1.0 ) );
rsHuntingNoise.gain( rsHuntingNoise.gain() * huntingamount );
rsHuntingNoise->gain( rsHuntingNoise->gain() * huntingamount );
}
else {
// don't play the optional ending sound if the listener switches views
rsHuntingNoise.stop( true == FreeFlyModeFlag );
rsHuntingNoise->stop( true == FreeFlyModeFlag );
}
}
// rain sound
if( m_rainsound ) {
if( ( false == FreeFlyModeFlag )
&& ( false == Global.CabWindowOpen )
&& ( Global.Weather == "rain:" ) ) {
if( m_rainsound.is_combined() ) {
m_rainsound.pitch( Global.Overcast - 1.0 );
if( m_rainsound->is_combined() ) {
m_rainsound->pitch( Global.Overcast - 1.0 );
}
m_rainsound
.gain( m_rainsound.m_amplitudeoffset + m_rainsound.m_amplitudefactor * 1.f )
.play( sound_flags::exclusive | sound_flags::looping );
m_rainsound->gain( m_rainsound->m_amplitudeoffset + m_rainsound->m_amplitudefactor * 1.f );
m_rainsound->play( sound_flags::exclusive | sound_flags::looping );
}
else {
m_rainsound.stop();
m_rainsound->stop();
}
}
if( dsbHasler ) {
if( fTachoCount >= 3.f ) {
auto const frequency{ (
true == dsbHasler.is_combined() ?
true == dsbHasler->is_combined() ?
fTachoVelocity * 0.01 :
dsbHasler.m_frequencyoffset + dsbHasler.m_frequencyfactor ) };
dsbHasler
.pitch( frequency )
.gain( dsbHasler.m_amplitudeoffset + dsbHasler.m_amplitudefactor )
.play( sound_flags::exclusive | sound_flags::looping );
dsbHasler->m_frequencyoffset + dsbHasler->m_frequencyfactor ) };
dsbHasler->pitch( frequency );
dsbHasler->gain( dsbHasler->m_amplitudeoffset + dsbHasler->m_amplitudefactor );
dsbHasler->play( sound_flags::exclusive | sound_flags::looping );
}
else if( fTachoCount < 1.f ) {
dsbHasler.stop();
dsbHasler->stop();
}
}
// power-reliant sounds
if( mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable ) {
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
// hunter-091012: rozdzielenie alarmow
if( dsbBuzzer ) {
if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm )
|| TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) {
if( false == dsbBuzzer.is_playing() ) {
dsbBuzzer
.pitch( dsbBuzzer.m_frequencyoffset + dsbBuzzer.m_frequencyfactor )
.gain( dsbBuzzer.m_amplitudeoffset + dsbBuzzer.m_amplitudefactor )
.play( sound_flags::looping );
if( false == dsbBuzzer->is_playing() ) {
dsbBuzzer->pitch( dsbBuzzer->m_frequencyoffset + dsbBuzzer->m_frequencyfactor );
dsbBuzzer->gain( dsbBuzzer->m_amplitudeoffset + dsbBuzzer->m_amplitudefactor );
dsbBuzzer->play( sound_flags::looping );
Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
}
else {
if( true == dsbBuzzer.is_playing() ) {
dsbBuzzer.stop();
if( true == dsbBuzzer->is_playing() ) {
dsbBuzzer->stop();
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
}
}
// distance meter alert
if( m_distancecounterclear ) {
auto const *owner{ (
DynamicObject->ctOwner != nullptr ?
DynamicObject->ctOwner :
@@ -7689,19 +7719,23 @@ TTrain::update_sounds( double const Deltatime ) {
// play assigned sound if the train travelled its full length since meter activation
// TBD: check all combinations of directions and active cab
m_distancecounter = -1.f; // turn off the meter after its task is done
m_distancecounterclear
.pitch( m_distancecounterclear.m_frequencyoffset + m_distancecounterclear.m_frequencyfactor )
.gain( m_distancecounterclear.m_amplitudeoffset + m_distancecounterclear.m_amplitudefactor )
.play( sound_flags::exclusive );
m_distancecounterclear->pitch( m_distancecounterclear->m_frequencyoffset + m_distancecounterclear->m_frequencyfactor );
m_distancecounterclear->gain( m_distancecounterclear->m_amplitudeoffset + m_distancecounterclear->m_amplitudefactor );
m_distancecounterclear->play( sound_flags::exclusive );
}
}
}
else {
// stop power-reliant sounds if power is cut
if( true == dsbBuzzer.is_playing() ) {
dsbBuzzer.stop();
if( dsbBuzzer ) {
if( true == dsbBuzzer->is_playing() ) {
dsbBuzzer->stop();
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
m_distancecounterclear.stop();
}
if( m_distancecounterclear ) {
m_distancecounterclear->stop();
}
}
update_sounds_radio();
@@ -7784,12 +7818,14 @@ void TTrain::update_sounds_radio() {
message.second->gain( volume );
}
// radiostop
if( m_radiostop ) {
if( ( true == radioenabled )
&& ( true == mvOccupied->RadioStopFlag ) ) {
m_radiostop.play( sound_flags::exclusive | sound_flags::looping );
m_radiostop->play( sound_flags::exclusive | sound_flags::looping );
}
else {
m_radiostop.stop();
m_radiostop->stop();
}
}
}
@@ -7832,10 +7868,43 @@ bool TTrain::CabChange(int iDirection)
// wczytywanie pliku z danymi multimedialnymi (dzwieki, kontrolki, kabiny)
bool TTrain::LoadMMediaFile(std::string const &asFileName)
{
// initialize sounds so potential entries from previous vehicle don't stick around
std::unordered_map<
std::string,
std::tuple<std::optional<sound_source> &, sound_placement, float, sound_type, int, double>>
internalsounds = {
{"ctrl:", {dsbNastawnikJazdy, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"ctrlscnd:", {dsbNastawnikBocz, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"reverserkey:", {dsbReverserKey, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"buzzer:", {dsbBuzzer, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"radiostop:", {m_radiostop, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"slipalarm:", {dsbSlipAlarm, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"distancecounter:", {m_distancecounterclear, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"tachoclock:", {dsbHasler, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"switch:", {dsbSwitch, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"pneumaticswitch:", {dsbPneumaticSwitch, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"airsound:", {rsHiss, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"airsound2:", {rsHissU, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"airsound3:", {rsHissE, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"airsound4:", {rsHissX, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"airsound5:", {rsHissT, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"localbrakesound:", {rsSBHiss, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"localbrakesound2:", {rsSBHissU, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, sound_parameters::amplitude, 100.0}},
{"brakesound:", {rsBrake, sound_placement::internal, -1, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, 100.0}},
{"fadesound:", {rsFadeSound, sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE, sound_type::single, 0, 100.0}},
{"runningnoise:", {rsRunningNoise, sound_placement::internal, EU07_SOUND_GLOBALRANGE, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, mvOccupied->Vmax }},
{"huntingnoise:", {rsHuntingNoise, sound_placement::internal, EU07_SOUND_GLOBALRANGE, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, mvOccupied->Vmax }},
{"rainsound:", {m_rainsound, sound_placement::internal, -1, sound_type::single, 0, 100.0}},
};
for( auto &soundconfig : internalsounds ) {
std::get<std::optional<sound_source> &>( soundconfig.second ).reset();
}
// NOTE: since radiosound is an incomplete template not using std::optional it gets a special treatment
m_radiosound.owner( DynamicObject );
cParser parser( asFileName, cParser::buffer_FILE, DynamicObject->asBaseDir );
// NOTE: yaml-style comments are disabled until conflict in use of # is resolved
// parser.addCommentStyle( "#", "\n" );
std::string token;
do
{
@@ -7844,145 +7913,56 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName)
parser >> token;
} while ((token != "") && (token != "internaldata:"));
if (token == "internaldata:")
{
do
{
if (token == "internaldata:") {
do {
token = "";
parser.getTokens();
parser >> token;
// SEKCJA DZWIEKOW
if (token == "ctrl:") {
// nastawnik:
dsbNastawnikJazdy.deserialize( parser, sound_type::single );
dsbNastawnikJazdy.owner( DynamicObject );
auto lookup { internalsounds.find( token ) };
if( lookup == internalsounds.end() ) { continue; }
auto const soundconfig { lookup->second };
sound_source sound {
std::get<sound_placement>( soundconfig ),
std::get<float>( soundconfig ) };
sound.deserialize(
parser,
std::get<sound_type>( soundconfig ),
std::get<int>( soundconfig ),
std::get<double>( soundconfig ) );
sound.owner( DynamicObject );
std::get<std::optional<sound_source> &>( soundconfig ) = sound;
} while( token != "" );
// assign default samples to sound emitters which weren't included in the config file
if( !m_rainsound ) {
sound_source rainsound;
rainsound.deserialize( "rainsound_default", sound_type::single );
rainsound.owner( DynamicObject );
m_rainsound = rainsound;
}
else if (token == "ctrlscnd:") {
// hunter-081211: nastawnik bocznikowania
dsbNastawnikBocz.deserialize( parser, sound_type::single );
dsbNastawnikBocz.owner( DynamicObject );
}
else if (token == "reverserkey:") {
// hunter-131211: dzwiek kierunkowego
dsbReverserKey.deserialize( parser, sound_type::single );
dsbReverserKey.owner( DynamicObject );
}
else if (token == "buzzer:") {
// bzyczek shp:
dsbBuzzer.deserialize( parser, sound_type::single );
dsbBuzzer.owner( DynamicObject );
}
else if( token == "radiostop:" ) {
// radiostop
m_radiostop.deserialize( parser, sound_type::single );
m_radiostop.owner( DynamicObject );
}
else if (token == "slipalarm:") {
// Bombardier 011010: alarm przy poslizgu:
dsbSlipAlarm.deserialize( parser, sound_type::single );
dsbSlipAlarm.owner( DynamicObject );
}
else if (token == "distancecounter:") {
// distance meter 'good to go' sound
m_distancecounterclear.deserialize( parser, sound_type::single );
m_distancecounterclear.owner( DynamicObject );
}
else if (token == "tachoclock:") {
// cykanie rejestratora:
dsbHasler.deserialize( parser, sound_type::single );
dsbHasler.owner( DynamicObject );
}
else if (token == "switch:") {
// przelaczniki:
dsbSwitch.deserialize( parser, sound_type::single );
dsbSwitch.owner( DynamicObject );
}
else if (token == "pneumaticswitch:") {
// stycznik EP:
dsbPneumaticSwitch.deserialize( parser, sound_type::single );
dsbPneumaticSwitch.owner( DynamicObject );
}
else if (token == "airsound:") {
// syk:
rsHiss.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHiss.owner( DynamicObject );
if( true == rsSBHiss.empty() ) {
if (!rsSBHiss) {
// fallback for vehicles without defined local brake hiss sound
rsSBHiss = rsHiss;
}
}
else if (token == "airsound2:") {
// syk:
rsHissU.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHissU.owner( DynamicObject );
if( true == rsSBHissU.empty() ) {
if (!rsSBHissU) {
// fallback for vehicles without defined local brake hiss sound
rsSBHissU = rsHissU;
}
if (rsBrake) {
rsBrake->m_frequencyfactor /= (1 + mvOccupied->Vmax);
}
else if (token == "airsound3:") {
// syk:
rsHissE.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHissE.owner( DynamicObject );
if (rsRunningNoise) {
rsRunningNoise->m_frequencyfactor /= (1 + mvOccupied->Vmax);
}
else if (token == "airsound4:") {
// syk:
rsHissX.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHissX.owner( DynamicObject );
if (rsHuntingNoise) {
rsHuntingNoise->m_frequencyfactor /= (1 + mvOccupied->Vmax);
}
else if (token == "airsound5:") {
// syk:
rsHissT.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsHissT.owner( DynamicObject );
}
else if (token == "localbrakesound:") {
// syk:
rsSBHiss.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsSBHiss.owner( DynamicObject );
}
else if( token == "localbrakesound2:" ) {
// syk:
rsSBHissU.deserialize( parser, sound_type::single, sound_parameters::amplitude );
rsSBHissU.owner( DynamicObject );
}
else if( token == "brakesound:" ) {
// the sound of vehicle body vibrations etc, when brakes are engaged
rsBrake.deserialize( parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency );
rsBrake.owner( DynamicObject );
// NOTE: can't pre-calculate amplitude normalization based on max brake force, as this varies depending on vehicle speed
rsBrake.m_frequencyfactor /= ( 1 + mvOccupied->Vmax );
}
else if (token == "fadesound:") {
// ambient sound:
rsFadeSound.deserialize( parser, sound_type::single );
rsFadeSound.owner( DynamicObject );
}
else if( token == "runningnoise:" ) {
// szum podczas jazdy:
rsRunningNoise.deserialize( parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, mvOccupied->Vmax );
rsRunningNoise.owner( DynamicObject );
rsRunningNoise.m_frequencyfactor /= ( 1 + mvOccupied->Vmax );
}
else if( token == "huntingnoise:" ) {
// hunting oscillation sound:
rsHuntingNoise.deserialize( parser, sound_type::single, sound_parameters::amplitude | sound_parameters::frequency, mvOccupied->Vmax );
rsHuntingNoise.owner( DynamicObject );
rsHuntingNoise.m_frequencyfactor /= ( 1 + mvOccupied->Vmax );
}
else if( token == "rainsound:" ) {
// precipitation sound:
m_rainsound.deserialize( parser, sound_type::single );
m_rainsound.owner( DynamicObject );
}
} while (token != "");
}
/*
else
{
return false;
} // nie znalazl sekcji internal
*/
return true;
}
@@ -7991,19 +7971,21 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
m_controlmapper.clear();
// clear python screens
m_screens.clear();
// reset sound positions and owner
// reset sound positions
auto const nullvector { glm::vec3() };
std::vector<sound_source *> sounds = {
&dsbReverserKey, &dsbNastawnikJazdy, &dsbNastawnikBocz,
&dsbSwitch, &dsbPneumaticSwitch,
&rsHiss, &rsHissU, &rsHissE, &rsHissX, &rsHissT, &rsSBHiss, &rsSBHissU,
&rsFadeSound, &rsRunningNoise, &rsHuntingNoise,
&dsbHasler, &dsbBuzzer, &dsbSlipAlarm, &m_distancecounterclear, &m_radiosound, &m_radiostop
std::vector<std::reference_wrapper<std::optional<sound_source>>> sounds = {
dsbReverserKey, dsbNastawnikJazdy, dsbNastawnikBocz,
dsbSwitch, dsbPneumaticSwitch,
rsHiss, rsHissU, rsHissE, rsHissX, rsHissT, rsSBHiss, rsSBHissU,
rsFadeSound, rsRunningNoise, rsHuntingNoise,
dsbHasler, dsbBuzzer, dsbSlipAlarm, m_distancecounterclear, m_rainsound, m_radiostop
};
for( auto sound : sounds ) {
sound->offset( nullvector );
sound->owner( DynamicObject );
for( auto &sound : sounds ) {
if( sound.get() ) {
sound.get()->offset( nullvector );
}
}
m_radiosound.offset( nullvector );
// reset view angles
pMechViewAngle = { 0.0, 0.0 };
@@ -8011,7 +7993,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
bool parse = false;
int cabindex = 0;
DynamicObject->mdKabina = NULL; // likwidacja wskaźnika na dotychczasową kabinę
DynamicObject->mdKabina = nullptr; // likwidacja wskaźnika na dotychczasową kabinę
switch (NewCabNo)
{ // ustalenie numeru kabiny do wczytania
case -1:
@@ -8038,59 +8020,8 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
token = "";
parser.getTokens();
parser >> token;
/*
if( token == "locations:" ) {
do {
token = "";
parser.getTokens(); parser >> token;
if( token == "radio:" ) {
// point in 3d space, in format [ x, y, z ]
glm::vec3 radiolocation;
parser.getTokens( 3, false, "\n\r\t ,;[]" );
parser
>> radiolocation.x
>> radiolocation.y
>> radiolocation.z;
radiolocation *= glm::vec3( NewCabNo, 1, NewCabNo );
m_radiosound.offset( radiolocation );
}
else if( token == "alerter:" ) {
// point in 3d space, in format [ x, y, z ]
glm::vec3 alerterlocation;
parser.getTokens( 3, false, "\n\r\t ,;[]" );
parser
>> alerterlocation.x
>> alerterlocation.y
>> alerterlocation.z;
alerterlocation *= glm::vec3( NewCabNo, 1, NewCabNo );
dsbBuzzer.offset( alerterlocation );
}
} while( ( token != "" )
&& ( token != "endlocations" ) );
} // locations:
*/
} while ((token != "") && (token != cabstr));
/*
if ((cabindex != 1) && (token != cabstr))
{
// jeśli nie znaleziony wpis kabiny, próba szukania kabiny 1
cabstr = "cab1definition:";
// crude way to start parsing from beginning
parser = std::make_shared<cParser>(asFileName, cParser::buffer_FILE);
// NOTE: yaml-style comments are disabled until conflict in use of # is resolved
// parser.addCommentStyle( "#", "\n" );
do
{
token = "";
parser.getTokens();
parser >> token;
} while ((token != "") && (token != cabstr));
}
*/
if (token == cabstr)
{
// jeśli znaleziony wpis kabiny
@@ -8288,63 +8219,53 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
if (DynamicObject->mdKabina)
{
*/
// assign default samples to sound emitters which weren't included in the config file
if( m_rainsound.empty() ) {
m_rainsound.deserialize( "rainsound_default", sound_type::single );
m_rainsound.owner( DynamicObject );
}
// configure placement of sound emitters which aren't bound with any device model, and weren't placed manually
// try first to bind sounds to location of possible devices
if( dsbReverserKey.offset() == nullvector ) {
dsbReverserKey.offset( ggDirKey.model_offset() );
}
if( dsbNastawnikJazdy.offset() == nullvector ) {
dsbNastawnikJazdy.offset( ggJointCtrl.model_offset() );
}
if( dsbNastawnikJazdy.offset() == nullvector ) {
dsbNastawnikJazdy.offset( ggMainCtrl.model_offset() );
}
if( dsbNastawnikBocz.offset() == nullvector ) {
dsbNastawnikBocz.offset( ggScndCtrl.model_offset() );
}
if( dsbBuzzer.offset() == nullvector ) {
dsbBuzzer.offset( btLampkaCzuwaka.model_offset() );
}
// HACK: alerter is likely to be located somewhere near computer displays
if( m_distancecounterclear.offset() == nullvector ) {
m_distancecounterclear.offset( btLampkaCzuwaka.model_offset() );
}
// radio has two potential items which can provide the position
auto const caboffset { glm::dvec3 { ( Cabine[ cabindex ].CabPos1 + Cabine[ cabindex ].CabPos2 ) * 0.5 } +glm::dvec3 { 0, 1, 0 } };
// NOTE: since radiosound is an incomplete template not using std::optional it gets a special treatment
if( m_radiosound.offset() == nullvector ) {
m_radiosound.offset( btLampkaRadio.model_offset() );
}
if( m_radiostop.offset() == nullvector ) {
m_radiostop.offset( m_radiosound.offset() );
if( m_radiosound.offset() == nullvector ) {
m_radiosound.offset( caboffset );
}
auto const localbrakeoffset { ggLocalBrake.model_offset() };
std::vector<sound_source *> localbrakesounds = {
&rsSBHiss, &rsSBHissU
std::vector<std::pair<std::reference_wrapper<std::optional<sound_source>>, glm::vec3>>
soundlocations = {
{dsbReverserKey, ggDirKey.model_offset()},
{dsbNastawnikJazdy, ggJointCtrl.model_offset()},
{dsbNastawnikJazdy, ggMainCtrl.model_offset()}, // NOTE: fallback for vehicles without universal controller
{dsbNastawnikBocz, ggScndCtrl.model_offset()},
{dsbSwitch, caboffset},
{dsbPneumaticSwitch, caboffset},
{rsHiss, ggBrakeCtrl.model_offset()},
{rsHissU, ggBrakeCtrl.model_offset()},
{rsHissE, ggBrakeCtrl.model_offset()},
{rsHissX, ggBrakeCtrl.model_offset()},
{rsHissT, ggBrakeCtrl.model_offset()},
{rsSBHiss, ggLocalBrake.model_offset()},
{rsSBHiss, ggBrakeCtrl.model_offset()}, // NOTE: fallback if the local brake model can't be located
{rsSBHissU, ggLocalBrake.model_offset()},
{rsSBHissU, ggBrakeCtrl.model_offset()}, // NOTE: fallback if the local brake model can't be located
{rsFadeSound, caboffset},
{rsRunningNoise, caboffset},
{rsHuntingNoise, caboffset},
{dsbHasler, caboffset},
{dsbBuzzer, btLampkaCzuwaka.model_offset()},
{dsbSlipAlarm, caboffset},
{m_distancecounterclear, btLampkaCzuwaka.model_offset()},
{m_rainsound, caboffset},
{m_radiostop, m_radiosound.offset()},
};
for( auto sound : localbrakesounds ) {
if( sound->offset() == nullvector ) {
sound->offset( localbrakeoffset );
for( auto & sound : soundlocations ) {
if( ( sound.first.get() )
&& ( sound.first.get()->offset() == nullvector ) ) {
sound.first.get()->offset( sound.second );
}
}
// NOTE: if the local brake model can't be located the emitter will also be assigned location of main brake
auto const brakeoffset { ggBrakeCtrl.model_offset() };
std::vector<sound_source *> brakesounds = {
&rsHiss, &rsHissU, &rsHissE, &rsHissX, &rsHissT, &rsSBHiss, &rsSBHissU,
};
for( auto sound : brakesounds ) {
if( sound->offset() == nullvector ) {
sound->offset( brakeoffset );
}
}
// for whatever is left fallback on generic location, centre of the cab
auto const caboffset { glm::dvec3 { ( Cabine[ cabindex ].CabPos1 + Cabine[ cabindex ].CabPos2 ) * 0.5 } + glm::dvec3 { 0, 1, 0 } };
for( auto sound : sounds ) {
if( sound->offset() == nullvector ) {
sound->offset( caboffset );
// second pass, in case some items received no positioning due to missing submodels etc
for( auto & sound : soundlocations ) {
if( ( sound.first.get() )
&& ( sound.first.get()->offset() == nullvector ) ) {
sound.first.get()->offset( caboffset );
}
}
@@ -8521,9 +8442,13 @@ TTrain::MoveToVehicle(TDynamicObject *target) {
DynamicSet(target);
}
{
auto const filename { Occupied()->TypeName + ".mmd" };
LoadMMediaFile( filename );
InitializeCab(
Occupied()->CabActive,
Occupied()->TypeName + ".mmd" );
filename );
}
Dynamic()->ABuSetModelShake( {} ); // zerowanie przesunięcia przed powrotem?
@@ -9544,8 +9469,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
gauge.Load(Parser, DynamicObject);
gauge.AssignFloat(&fTachoVelocityJump);
// bind tachometer sound location to the meter
if( dsbHasler.offset() == glm::vec3() ) {
dsbHasler.offset( gauge.model_offset() );
if( dsbHasler
&& dsbHasler->offset() == glm::vec3() ) {
dsbHasler->offset( gauge.model_offset() );
}
}
else if (Label == "tachometern:")
@@ -9555,8 +9481,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
gauge.Load(Parser, DynamicObject);
gauge.AssignFloat(&fTachoVelocity);
// bind tachometer sound location to the meter
if( dsbHasler.offset() == glm::vec3() ) {
dsbHasler.offset( gauge.model_offset() );
if( dsbHasler
&& dsbHasler->offset() == glm::vec3() ) {
dsbHasler->offset( gauge.model_offset() );
}
}
else if (Label == "tachometerd:")
@@ -9566,8 +9493,9 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
gauge.Load(Parser, DynamicObject);
gauge.AssignFloat(&fTachoVelocity);
// bind tachometer sound location to the meter
if( dsbHasler.offset() == glm::vec3() ) {
dsbHasler.offset( gauge.model_offset() );
if( dsbHasler
&& dsbHasler->offset() == glm::vec3() ) {
dsbHasler->offset( gauge.model_offset() );
}
}
else if ((Label == "hvcurrent1:") || (Label == "hvcurrent1b:"))

52
Train.h
View File

@@ -728,35 +728,33 @@ public: // reszta może by?publiczna
TButton btHaslerBrakes; // ciśnienie w cylindrach
TButton btHaslerCurrent; // prąd na silnikach
sound_source dsbReverserKey { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // hunter-121211
sound_source dsbNastawnikJazdy { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source dsbNastawnikBocz { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // hunter-081211
sound_source dsbSwitch { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source dsbPneumaticSwitch { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source rsHiss { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // upuszczanie
sound_source rsHissU { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // napelnianie
sound_source rsHissE { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // nagle
sound_source rsHissX { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // fala
sound_source rsHissT { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // czasowy
sound_source rsSBHiss { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // local
sound_source rsSBHissU { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // local, engage brakes
float m_lastlocalbrakepressure { -1.f }; // helper, cached level of pressure in local brake cylinder
float m_localbrakepressurechange { 0.f }; // recent change of pressure in local brake cylinder
sound_source rsBrake { sound_placement::internal, -1 };
sound_source rsFadeSound { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source rsRunningNoise{ sound_placement::internal, EU07_SOUND_GLOBALRANGE };
sound_source rsHuntingNoise{ sound_placement::internal, EU07_SOUND_GLOBALRANGE };
sound_source m_rainsound { sound_placement::internal, -1 };
sound_source dsbHasler { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source dsbBuzzer { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source dsbSlipAlarm { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // Bombardier 011010: alarm przy poslizgu dla 181/182
std::optional<sound_source>
dsbNastawnikJazdy,
dsbNastawnikBocz,
dsbReverserKey,
dsbBuzzer,
m_radiostop,
dsbSlipAlarm,
m_distancecounterclear,
dsbHasler,
dsbSwitch,
dsbPneumaticSwitch,
rsHiss,
rsHissU,
rsHissE,
rsHissX,
rsHissT,
rsSBHiss,
rsSBHissU,
rsBrake,
rsFadeSound,
rsRunningNoise,
rsHuntingNoise,
m_rainsound;
sound_source m_radiosound { sound_placement::internal, 2 * EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // cached template for radio messages
std::vector<std::pair<int, std::shared_ptr<sound_source>>> m_radiomessages; // list of currently played radio messages
sound_source m_radiostop { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source m_distancecounterclear { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // distance meter 'good to go' alert
float m_lastlocalbrakepressure { -1.f }; // helper, cached level of pressure in local brake cylinder
float m_localbrakepressurechange { 0.f }; // recent change of pressure in local brake cylinder
/*
int iCabLightFlag; // McZapkie:120503: oswietlenie kabiny (0: wyl, 1: przyciemnione, 2: pelne)
bool bCabLight; // hunter-091012: czy swiatlo jest zapalone?

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 21
#define VERSION_MINOR 426
#define VERSION_MINOR 508
#define VERSION_REVISION 0