mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 16:19:19 +02:00
build 200728. basic train passenger information system, event condition diagnostics enhancement, ai door control logic fix
This commit is contained in:
54
Driver.cpp
54
Driver.cpp
@@ -986,6 +986,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
if( mvOccupied->Vel > 0.3 ) {
|
if( mvOccupied->Vel > 0.3 ) {
|
||||||
// jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie
|
// jeśli jedzie (nie trzeba czekać, aż się drgania wytłumią - drzwi zamykane od 1.0) to będzie zatrzymanie
|
||||||
sSpeedTable[ i ].fVelNext = 0;
|
sSpeedTable[ i ].fVelNext = 0;
|
||||||
|
// potentially announce pending stop
|
||||||
|
if( ( m_lastannouncement != announcement_t::approaching )
|
||||||
|
&& ( sSpeedTable[ i ].fDist < 750 )
|
||||||
|
&& ( sSpeedTable[ i ].fDist > 250 ) ) {
|
||||||
|
announce( announcement_t::approaching );
|
||||||
|
}
|
||||||
} else if( true == IsAtPassengerStop ) {
|
} else if( true == IsAtPassengerStop ) {
|
||||||
// jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4
|
// jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4
|
||||||
if( !AIControllFlag ) {
|
if( !AIControllFlag ) {
|
||||||
@@ -1009,18 +1015,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
auto const platformside = static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10;
|
auto const platformside = static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10;
|
||||||
auto const exchangetime = simulation::Station.update_load( pVehicles[ 0 ], TrainParams, platformside );
|
auto const exchangetime = simulation::Station.update_load( pVehicles[ 0 ], TrainParams, platformside );
|
||||||
WaitingSet( exchangetime );
|
WaitingSet( exchangetime );
|
||||||
|
// announce the stop name while at it
|
||||||
|
announce( announcement_t::current );
|
||||||
m_lastexchangestop = asNextStop;
|
m_lastexchangestop = asNextStop;
|
||||||
|
m_makenextstopannouncement = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( false == TrainParams.IsMaintenance() )
|
|
||||||
// && ( ( iDrivigFlags & moveDoorOpened ) == 0 ) )
|
|
||||||
{
|
|
||||||
// drzwi otwierać jednorazowo
|
|
||||||
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
|
|
||||||
Doors( true, static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (TrainParams.DirectionChange()) {
|
if (TrainParams.DirectionChange()) {
|
||||||
// jeśli "@" w rozkładzie, to wykonanie dalszych komend
|
// jeśli "@" w rozkładzie, to wykonanie dalszych komend
|
||||||
// wykonanie kolejnej komendy, nie dotyczy ostatniej stacji
|
// wykonanie kolejnej komendy, nie dotyczy ostatniej stacji
|
||||||
@@ -1053,6 +1053,13 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( ( false == TrainParams.IsMaintenance() )
|
||||||
|
&& ( ( false == TestFlag( iDrivigFlags, moveDoorOpened ) )
|
||||||
|
|| ( true == DoesAnyDoorNeedOpening ) ) ) {
|
||||||
|
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
|
||||||
|
Doors( true, static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10 );
|
||||||
|
}
|
||||||
|
|
||||||
if (OrderCurrentGet() & ( Shunt | Loose_shunt )) {
|
if (OrderCurrentGet() & ( Shunt | Loose_shunt )) {
|
||||||
OrderNext(Obey_train); // uruchomić jazdę pociągową
|
OrderNext(Obey_train); // uruchomić jazdę pociągową
|
||||||
CheckVehicles(); // zmienić światła
|
CheckVehicles(); // zmienić światła
|
||||||
@@ -4184,6 +4191,23 @@ TController::doors_permit_active() const {
|
|||||||
|| IsAnyDoorPermitActive[ side::left ] );
|
|| IsAnyDoorPermitActive[ side::left ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TController::announce( announcement_t const Announcement ) {
|
||||||
|
|
||||||
|
m_lastannouncement = Announcement;
|
||||||
|
|
||||||
|
if( IsCargoTrain ) {
|
||||||
|
// cargo trains aren't likely to have announcement systems, so we can skip the procedure altogether
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *vehicle { pVehicles[ end::front ] };
|
||||||
|
while( vehicle ) {
|
||||||
|
vehicle->announce( Announcement );
|
||||||
|
vehicle = vehicle->Next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TController::RecognizeCommand()
|
void TController::RecognizeCommand()
|
||||||
{ // odczytuje i wykonuje komendę przekazaną lokomotywie
|
{ // odczytuje i wykonuje komendę przekazaną lokomotywie
|
||||||
TCommand *c = &mvOccupied->CommandIn;
|
TCommand *c = &mvOccupied->CommandIn;
|
||||||
@@ -4268,6 +4292,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
|||||||
TrainParams.StationIndexInc(); // przejście do następnej
|
TrainParams.StationIndexInc(); // przejście do następnej
|
||||||
iStationStart = TrainParams.StationIndex;
|
iStationStart = TrainParams.StationIndex;
|
||||||
asNextStop = TrainParams.NextStop();
|
asNextStop = TrainParams.NextStop();
|
||||||
|
m_lastannouncement = announcement_t::idle;
|
||||||
iDrivigFlags |= movePrimary; // skoro dostał rozkład, to jest teraz głównym
|
iDrivigFlags |= movePrimary; // skoro dostał rozkład, to jest teraz głównym
|
||||||
// NewCommand = Global.asCurrentSceneryPath + NewCommand;
|
// NewCommand = Global.asCurrentSceneryPath + NewCommand;
|
||||||
auto lookup =
|
auto lookup =
|
||||||
@@ -4294,7 +4319,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
|||||||
NewCommand = TrainParams.Relation2; // relacja docelowa z rozkładu
|
NewCommand = TrainParams.Relation2; // relacja docelowa z rozkładu
|
||||||
}
|
}
|
||||||
// jeszcze poustawiać tekstury na wyświetlaczach
|
// jeszcze poustawiać tekstury na wyświetlaczach
|
||||||
TDynamicObject *p = pVehicles[0];
|
TDynamicObject *p = pVehicles[end::front];
|
||||||
while (p)
|
while (p)
|
||||||
{
|
{
|
||||||
p->DestinationSet(NewCommand, TrainParams.TrainName); // relacja docelowa
|
p->DestinationSet(NewCommand, TrainParams.TrainName); // relacja docelowa
|
||||||
@@ -4726,6 +4751,10 @@ TController::UpdateSituation(double dt) {
|
|||||||
// zaktualizować wyświetlanie rozkładu
|
// zaktualizować wyświetlanie rozkładu
|
||||||
iStationStart = TrainParams.StationIndex;
|
iStationStart = TrainParams.StationIndex;
|
||||||
fLastStopExpDist = -1.0; // usunąć licznik
|
fLastStopExpDist = -1.0; // usunąć licznik
|
||||||
|
if( true == m_makenextstopannouncement ) {
|
||||||
|
announce( announcement_t::next );
|
||||||
|
m_makenextstopannouncement = false; // keep next stop announcements suppressed until another scheduled stop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ABu-160305 testowanie gotowości do jazdy
|
// ABu-160305 testowanie gotowości do jazdy
|
||||||
@@ -5960,6 +5989,7 @@ TController::UpdateSituation(double dt) {
|
|||||||
VelforDriver );
|
VelforDriver );
|
||||||
}
|
}
|
||||||
// recalculate potential load exchange duration
|
// recalculate potential load exchange duration
|
||||||
|
DoesAnyDoorNeedOpening = false;
|
||||||
ExchangeTime = 0.f;
|
ExchangeTime = 0.f;
|
||||||
if( fStopTime < 0 ) {
|
if( fStopTime < 0 ) {
|
||||||
// czas postoju przed dalszą jazdą (np. na przystanku)
|
// czas postoju przed dalszą jazdą (np. na przystanku)
|
||||||
@@ -5967,7 +5997,9 @@ TController::UpdateSituation(double dt) {
|
|||||||
// verify progress of load exchange
|
// verify progress of load exchange
|
||||||
auto *vehicle { pVehicles[ 0 ] };
|
auto *vehicle { pVehicles[ 0 ] };
|
||||||
while( vehicle != nullptr ) {
|
while( vehicle != nullptr ) {
|
||||||
ExchangeTime = std::max( ExchangeTime, vehicle->LoadExchangeTime() );
|
auto const vehicleexchangetime { vehicle->LoadExchangeTime() };
|
||||||
|
DoesAnyDoorNeedOpening |= ( ( vehicleexchangetime > 0 ) && ( vehicle->LoadExchangeSpeed() == 0 ) );
|
||||||
|
ExchangeTime = std::max( ExchangeTime, vehicleexchangetime );
|
||||||
vehicle = vehicle->Next();
|
vehicle = vehicle->Next();
|
||||||
}
|
}
|
||||||
if( ( ExchangeTime > 0 )
|
if( ( ExchangeTime > 0 )
|
||||||
|
|||||||
4
Driver.h
4
Driver.h
@@ -454,6 +454,8 @@ private:
|
|||||||
int iRadioChannel = 1; // numer aktualnego kanału radiowego
|
int iRadioChannel = 1; // numer aktualnego kanału radiowego
|
||||||
int iGuardRadio = 0; // numer kanału radiowego kierownika (0, gdy nie używa radia)
|
int iGuardRadio = 0; // numer kanału radiowego kierownika (0, gdy nie używa radia)
|
||||||
sound_source tsGuardSignal{ sound_placement::internal };
|
sound_source tsGuardSignal{ sound_placement::internal };
|
||||||
|
announcement_t m_lastannouncement{ announcement_t::idle };
|
||||||
|
bool m_makenextstopannouncement{ false };
|
||||||
|
|
||||||
// consist
|
// consist
|
||||||
// methods
|
// methods
|
||||||
@@ -468,6 +470,7 @@ private:
|
|||||||
bool doors_permit_active() const;
|
bool doors_permit_active() const;
|
||||||
void AutoRewident(); // ustawia hamulce w składzie
|
void AutoRewident(); // ustawia hamulce w składzie
|
||||||
void UpdatePantographs();
|
void UpdatePantographs();
|
||||||
|
void announce( announcement_t const Announcement );
|
||||||
// members
|
// members
|
||||||
double fLength = 0.0; // długość składu (do wyciągania z ograniczeń)
|
double fLength = 0.0; // długość składu (do wyciągania z ograniczeń)
|
||||||
double fMass = 0.0; // całkowita masa do liczenia stycznej składowej grawitacji
|
double fMass = 0.0; // całkowita masa do liczenia stycznej składowej grawitacji
|
||||||
@@ -482,6 +485,7 @@ private:
|
|||||||
bool Ready = false; // ABu: stan gotowosci do odjazdu - sprawdzenie odhamowania wagonow
|
bool Ready = false; // ABu: stan gotowosci do odjazdu - sprawdzenie odhamowania wagonow
|
||||||
double ConsistShade{ 1.0 }; // averaged amount of sunlight received by the consist
|
double ConsistShade{ 1.0 }; // averaged amount of sunlight received by the consist
|
||||||
TDynamicObject *pVehicles[ 2 ]; // skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane)
|
TDynamicObject *pVehicles[ 2 ]; // skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane)
|
||||||
|
bool DoesAnyDoorNeedOpening{ false };
|
||||||
bool IsAnyDoorOpen[ 2 ]; // state of door in the consist
|
bool IsAnyDoorOpen[ 2 ]; // state of door in the consist
|
||||||
bool IsAnyDoorPermitActive[ 2 ]; // state of door permit in the consist
|
bool IsAnyDoorPermitActive[ 2 ]; // state of door permit in the consist
|
||||||
bool IsAnyLineBreakerOpen{ false }; // state of line breaker in all powered vehicles under control
|
bool IsAnyLineBreakerOpen{ false }; // state of line breaker in all powered vehicles under control
|
||||||
|
|||||||
144
DynObj.cpp
144
DynObj.cpp
@@ -29,6 +29,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
#include "uitranscripts.h"
|
#include "uitranscripts.h"
|
||||||
#include "messaging.h"
|
#include "messaging.h"
|
||||||
|
#include "Driver.h"
|
||||||
|
|
||||||
// Ra: taki zapis funkcjonuje lepiej, ale może nie jest optymalny
|
// Ra: taki zapis funkcjonuje lepiej, ale może nie jest optymalny
|
||||||
#define vWorldFront Math3D::vector3(0, 0, 1)
|
#define vWorldFront Math3D::vector3(0, 0, 1)
|
||||||
@@ -2022,7 +2023,7 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
}
|
}
|
||||||
} // koniec hamulce
|
} // koniec hamulce
|
||||||
else if( ( ActPar.size() >= 3 )
|
else if( ( ActPar.size() >= 3 )
|
||||||
&& ( ActPar[ 0 ] == 'W' ) ) {
|
&& ( ActPar.front() == 'W' ) ) {
|
||||||
// wheel
|
// wheel
|
||||||
ActPar.erase( 0, 1 );
|
ActPar.erase( 0, 1 );
|
||||||
|
|
||||||
@@ -2032,7 +2033,7 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
|
|
||||||
while( false == ActPar.empty() ) {
|
while( false == ActPar.empty() ) {
|
||||||
// TODO: convert this whole copy and paste mess to something more elegant one day
|
// TODO: convert this whole copy and paste mess to something more elegant one day
|
||||||
switch( ActPar[ 0 ] ) {
|
switch( ActPar.front() ) {
|
||||||
case 'F': {
|
case 'F': {
|
||||||
// fixed flat size
|
// fixed flat size
|
||||||
auto const indexstart { 1 };
|
auto const indexstart { 1 };
|
||||||
@@ -2078,14 +2079,14 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
}
|
}
|
||||||
} // wheel
|
} // wheel
|
||||||
else if( ( ActPar.size() >= 2 )
|
else if( ( ActPar.size() >= 2 )
|
||||||
&& ( ActPar[ 0 ] == 'T' ) ) {
|
&& ( ActPar.front() == 'T' ) ) {
|
||||||
// temperature
|
// temperature
|
||||||
ActPar.erase( 0, 1 );
|
ActPar.erase( 0, 1 );
|
||||||
|
|
||||||
auto setambient { false };
|
auto setambient { false };
|
||||||
|
|
||||||
while( false == ActPar.empty() ) {
|
while( false == ActPar.empty() ) {
|
||||||
switch( ActPar[ 0 ] ) {
|
switch( ActPar.front() ) {
|
||||||
case 'A': {
|
case 'A': {
|
||||||
// cold start, set all temperatures to ambient level
|
// cold start, set all temperatures to ambient level
|
||||||
setambient = true;
|
setambient = true;
|
||||||
@@ -4304,7 +4305,7 @@ void TDynamicObject::RenderSounds() {
|
|||||||
// NBMX sygnal odjazdu
|
// NBMX sygnal odjazdu
|
||||||
if( MoverParameters->Doors.has_warning ) {
|
if( MoverParameters->Doors.has_warning ) {
|
||||||
auto const lowvoltagepower { MoverParameters->Power24vIsAvailable || MoverParameters->Power110vIsAvailable };
|
auto const lowvoltagepower { MoverParameters->Power24vIsAvailable || MoverParameters->Power110vIsAvailable };
|
||||||
for( auto &departuresignalsound : m_departuresignalsounds ) {
|
for( auto &speaker : m_speakers ) {
|
||||||
// TBD, TODO: per-location door state triggers?
|
// TBD, TODO: per-location door state triggers?
|
||||||
if( ( MoverParameters->DepartureSignal )
|
if( ( MoverParameters->DepartureSignal )
|
||||||
&& ( lowvoltagepower )
|
&& ( lowvoltagepower )
|
||||||
@@ -4316,13 +4317,32 @@ void TDynamicObject::RenderSounds() {
|
|||||||
) {
|
) {
|
||||||
// for the autonomous doors play the warning automatically whenever a door is closing
|
// for the autonomous doors play the warning automatically whenever a door is closing
|
||||||
// MC: pod warunkiem ze jest zdefiniowane w chk
|
// MC: pod warunkiem ze jest zdefiniowane w chk
|
||||||
departuresignalsound.play( sound_flags::exclusive | sound_flags::looping );
|
speaker.departure_signal.play( sound_flags::exclusive | sound_flags::looping );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
departuresignalsound.stop();
|
speaker.departure_signal.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// announcements
|
||||||
|
for( auto &speaker : m_speakers ) {
|
||||||
|
auto const lowvoltagepower { MoverParameters->Power24vIsAvailable || MoverParameters->Power110vIsAvailable };
|
||||||
|
if( lowvoltagepower ) {
|
||||||
|
// speaker is powered up, can play queued announcements
|
||||||
|
if( speaker.announcement.is_playing() ) { continue; }
|
||||||
|
if( speaker.announcement_queue.empty() ) { continue; }
|
||||||
|
// pull first sound from the queue
|
||||||
|
speaker.announcement = speaker.announcement_queue.front();
|
||||||
|
speaker.announcement.owner( this );
|
||||||
|
speaker.announcement.offset( speaker.offset );
|
||||||
|
speaker.announcement.play();
|
||||||
|
speaker.announcement_queue.pop_front();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
speaker.announcement.stop();
|
||||||
|
speaker.announcement_queue.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
// NBMX Obsluga drzwi, MC: zuniwersalnione
|
// NBMX Obsluga drzwi, MC: zuniwersalnione
|
||||||
std::array<side, 2> const sides { side::right, side::left };
|
std::array<side, 2> const sides { side::right, side::left };
|
||||||
for( auto const side : sides ) {
|
for( auto const side : sides ) {
|
||||||
@@ -4747,15 +4767,13 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
parser.getTokens();
|
parser.getTokens();
|
||||||
parser >> asModel;
|
parser >> asModel;
|
||||||
replace_slashes( asModel );
|
replace_slashes( asModel );
|
||||||
if( asModel[asModel.size() - 1] == '#' ) // Ra 2015-01: nie podoba mi siê to
|
if( asModel.back() == '#' ) // Ra 2015-01: nie podoba mi siê to
|
||||||
{ // model wymaga wielu tekstur wymiennych
|
{ // model wymaga wielu tekstur wymiennych
|
||||||
m_materialdata.multi_textures = 1;
|
m_materialdata.multi_textures = 1;
|
||||||
asModel.erase( asModel.length() - 1 );
|
asModel.erase( asModel.length() - 1 );
|
||||||
}
|
}
|
||||||
// name can contain leading slash, erase it to avoid creation of double slashes when the name is combined with current directory
|
// name can contain leading slash, erase it to avoid creation of double slashes when the name is combined with current directory
|
||||||
if( asModel[ 0 ] == '/' ) {
|
erase_leading_slashes( asModel );
|
||||||
asModel.erase( 0, 1 );
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
// never really used, may as well get rid of it
|
// never really used, may as well get rid of it
|
||||||
std::size_t i = asModel.find( ',' );
|
std::size_t i = asModel.find( ',' );
|
||||||
@@ -4871,7 +4889,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
// value can be optionally set of values enclosed in "[]" in which case one value will be picked randomly
|
// value can be optionally set of values enclosed in "[]" in which case one value will be picked randomly
|
||||||
while( ( ( token = parser.getToken<std::string>() ) != "" )
|
while( ( ( token = parser.getToken<std::string>() ) != "" )
|
||||||
&& ( token != "}" ) ) {
|
&& ( token != "}" ) ) {
|
||||||
if( token[ token.size() - 1 ] == ':' ) {
|
if( token.back() == ':' ) {
|
||||||
auto loadmodel { deserialize_random_set( parser ) };
|
auto loadmodel { deserialize_random_set( parser ) };
|
||||||
replace_slashes( loadmodel );
|
replace_slashes( loadmodel );
|
||||||
LoadModelOverrides.emplace( token.erase( token.size() - 1 ), loadmodel );
|
LoadModelOverrides.emplace( token.erase( token.size() - 1 ), loadmodel );
|
||||||
@@ -5694,14 +5712,12 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
|
|
||||||
else if( token == "departuresignal:" ) {
|
else if( token == "departuresignal:" ) {
|
||||||
// pliki z sygnalem odjazdu
|
// pliki z sygnalem odjazdu
|
||||||
sound_source soundtemplate { sound_placement::general };
|
sound_source soundtemplate { sound_placement::general, 25.f };
|
||||||
soundtemplate.deserialize( parser, sound_type::multipart, sound_parameters::range );
|
soundtemplate.deserialize( parser, sound_type::multipart, sound_parameters::range );
|
||||||
soundtemplate.owner( this );
|
soundtemplate.owner( this );
|
||||||
for( auto &departuresignalsound : m_departuresignalsounds ) {
|
for( auto &speaker : m_speakers ) {
|
||||||
// apply configuration to all defined doors, but preserve their individual offsets
|
speaker.departure_signal = soundtemplate;
|
||||||
auto const soundoffset { departuresignalsound.offset() };
|
speaker.departure_signal.offset( speaker.offset );
|
||||||
departuresignalsound = soundtemplate;
|
|
||||||
departuresignalsound.offset( soundoffset );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5844,6 +5860,38 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
m_wheelflat.owner( this );
|
m_wheelflat.owner( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if(token == "announcements:") {
|
||||||
|
// announcement sounds
|
||||||
|
// content provided as "key: value" pairs together enclosed in "{}"
|
||||||
|
// value can be optionally set of values enclosed in "[]" in which case one value will be picked randomly
|
||||||
|
std::array<sound_source, static_cast<int>( announcement_t::end )> announcementsounds;
|
||||||
|
std::unordered_map<std::string, announcement_t> const announcements = {
|
||||||
|
{ "near_stop:", announcement_t::approaching },
|
||||||
|
{ "stop:", announcement_t::current },
|
||||||
|
{ "next_stop:", announcement_t::next },
|
||||||
|
{ "destination:", announcement_t::destination } };
|
||||||
|
while( ( ( token = parser.getToken<std::string>() ) != "" )
|
||||||
|
&& ( token != "}" ) ) {
|
||||||
|
if( token.back() == ':' ) {
|
||||||
|
auto const lookup { announcements.find( token ) };
|
||||||
|
auto const announcementtype { (
|
||||||
|
lookup != announcements.end() ?
|
||||||
|
lookup->second :
|
||||||
|
announcement_t::idle ) };
|
||||||
|
// NOTE: we retrieve key value for all keys, not just recognized ones
|
||||||
|
auto announcementsound{ deserialize_random_set( parser ) };
|
||||||
|
replace_slashes( announcementsound );
|
||||||
|
if( announcementtype == announcement_t::idle ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sound_source soundtemplate { sound_placement::general, EU07_SOUND_CABANNOUNCEMENTCUTOFFRANGE };
|
||||||
|
soundtemplate.deserialize( announcementsound, sound_type::single );
|
||||||
|
soundtemplate.owner( this );
|
||||||
|
m_announcements[ static_cast<int>( announcementtype ) ] = soundtemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} while( ( token != "" )
|
} while( ( token != "" )
|
||||||
&& ( token != "endsounds" ) );
|
&& ( token != "endsounds" ) );
|
||||||
|
|
||||||
@@ -5891,10 +5939,11 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
door.step_open.offset( location );
|
door.step_open.offset( location );
|
||||||
m_doorsounds.emplace_back( door );
|
m_doorsounds.emplace_back( door );
|
||||||
}
|
}
|
||||||
// potential departure sound, one per door (pair) on vehicle centreline
|
m_speakers.emplace_back(
|
||||||
sound_source departuresignalsound { sound_placement::general, 25.f };
|
speaker_sounds {
|
||||||
departuresignalsound.offset( glm::vec3{ 0.f, 3.f, offset } );
|
{ 0.f, 3.f, offset },
|
||||||
m_departuresignalsounds.emplace_back( departuresignalsound );
|
{},
|
||||||
|
{} } );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7009,6 +7058,57 @@ material_handle TDynamicObject::DestinationFind( std::string Destination ) {
|
|||||||
return destinationhandle;
|
return destinationhandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TDynamicObject::announce( announcement_t const Announcement ) {
|
||||||
|
|
||||||
|
if( m_speakers.empty() ) { return; }
|
||||||
|
|
||||||
|
auto const *driver { (
|
||||||
|
ctOwner != nullptr ?
|
||||||
|
ctOwner :
|
||||||
|
Mechanik ) };
|
||||||
|
if( driver == nullptr ) { return; }
|
||||||
|
|
||||||
|
auto const &timetable { driver->TrainTimetable() };
|
||||||
|
|
||||||
|
if( m_announcements[ static_cast<int>( Announcement ) ].empty() ) {
|
||||||
|
goto followup;
|
||||||
|
}
|
||||||
|
// if the announcement sound was defined queue playback
|
||||||
|
{
|
||||||
|
sound_source stopnamesound;
|
||||||
|
switch( Announcement ) {
|
||||||
|
case announcement_t::approaching:
|
||||||
|
case announcement_t::next: {
|
||||||
|
stopnamesound = timetable.next_stop_sound();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case announcement_t::current: {
|
||||||
|
stopnamesound = timetable.current_stop_sound();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case announcement_t::destination: {
|
||||||
|
stopnamesound = timetable.last_stop_sound();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( stopnamesound.empty() ) {
|
||||||
|
goto followup;
|
||||||
|
}
|
||||||
|
for( auto &speaker : m_speakers ) {
|
||||||
|
speaker.announcement_queue.emplace_back( m_announcements[ static_cast<int>( Announcement ) ] );
|
||||||
|
speaker.announcement_queue.emplace_back( stopnamesound );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
followup:
|
||||||
|
// potentially follow up with another announcement
|
||||||
|
if( Announcement == announcement_t::next ) {
|
||||||
|
announce( announcement_t::destination );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TDynamicObject::OverheadTrack(float o)
|
void TDynamicObject::OverheadTrack(float o)
|
||||||
{ // ewentualne wymuszanie jazdy
|
{ // ewentualne wymuszanie jazdy
|
||||||
// bezprądowej z powodu informacji
|
// bezprądowej z powodu informacji
|
||||||
|
|||||||
21
DynObj.h
21
DynObj.h
@@ -150,6 +150,15 @@ public:
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
enum class announcement_t : int {
|
||||||
|
idle = 0,
|
||||||
|
approaching,
|
||||||
|
current,
|
||||||
|
next,
|
||||||
|
destination,
|
||||||
|
end
|
||||||
|
};
|
||||||
|
|
||||||
// parameters for the material object, as currently used by various simulator models
|
// parameters for the material object, as currently used by various simulator models
|
||||||
struct material_data {
|
struct material_data {
|
||||||
|
|
||||||
@@ -395,6 +404,13 @@ private:
|
|||||||
void position( glm::vec3 const Location );
|
void position( glm::vec3 const Location );
|
||||||
void render( TMoverParameters const &Vehicle, double const Deltatime );
|
void render( TMoverParameters const &Vehicle, double const Deltatime );
|
||||||
};
|
};
|
||||||
|
// single source per door (pair) on the centreline
|
||||||
|
struct speaker_sounds {
|
||||||
|
glm::vec3 offset;
|
||||||
|
sound_source departure_signal;
|
||||||
|
sound_source announcement;
|
||||||
|
std::deque<sound_source> announcement_queue; // fifo queue
|
||||||
|
};
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
void ABuLittleUpdate(double ObjSqrDist);
|
void ABuLittleUpdate(double ObjSqrDist);
|
||||||
@@ -476,7 +492,6 @@ private:
|
|||||||
std::array<coupler_sounds, 2> m_couplersounds; // always front and rear
|
std::array<coupler_sounds, 2> m_couplersounds; // always front and rear
|
||||||
std::vector<pantograph_sounds> m_pantographsounds; // typically 2 but can be less (or more?)
|
std::vector<pantograph_sounds> m_pantographsounds; // typically 2 but can be less (or more?)
|
||||||
std::vector<door_sounds> m_doorsounds; // can expect symmetrical arrangement, but don't count on it
|
std::vector<door_sounds> m_doorsounds; // can expect symmetrical arrangement, but don't count on it
|
||||||
std::vector<sound_source> m_departuresignalsounds; // single source per door (pair) on the centreline
|
|
||||||
bool m_doorlocks { false }; // sound helper, current state of door locks
|
bool m_doorlocks { false }; // sound helper, current state of door locks
|
||||||
sound_source sHorn1 { sound_placement::external, 5 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE };
|
sound_source sHorn1 { sound_placement::external, 5 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE };
|
||||||
sound_source sHorn2 { sound_placement::external, 5 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE };
|
sound_source sHorn2 { sound_placement::external, 5 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE };
|
||||||
@@ -493,6 +508,9 @@ private:
|
|||||||
exchange_data m_exchange; // state of active load exchange procedure, if any
|
exchange_data m_exchange; // state of active load exchange procedure, if any
|
||||||
exchange_sounds m_exchangesounds; // sounds associated with the load exchange
|
exchange_sounds m_exchangesounds; // sounds associated with the load exchange
|
||||||
|
|
||||||
|
std::vector<speaker_sounds> m_speakers;
|
||||||
|
std::array<sound_source, static_cast<int>( announcement_t::end )> m_announcements;
|
||||||
|
|
||||||
coupleradapter_data m_coupleradapter;
|
coupleradapter_data m_coupleradapter;
|
||||||
|
|
||||||
bool renderme; // yB - czy renderowac
|
bool renderme; // yB - czy renderowac
|
||||||
@@ -702,6 +720,7 @@ private:
|
|||||||
void OverheadTrack(float o);
|
void OverheadTrack(float o);
|
||||||
glm::dvec3 get_future_movement() const;
|
glm::dvec3 get_future_movement() const;
|
||||||
void move_set(double distance);
|
void move_set(double distance);
|
||||||
|
void announce( announcement_t const Announcement );
|
||||||
|
|
||||||
double MED[9][8]; // lista zmiennych do debugowania hamulca ED
|
double MED[9][8]; // lista zmiennych do debugowania hamulca ED
|
||||||
static std::string const MED_labels[ 8 ];
|
static std::string const MED_labels[ 8 ];
|
||||||
|
|||||||
37
Event.cpp
37
Event.cpp
@@ -74,18 +74,51 @@ basic_event::event_conditions::test() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( flags & flags::track_busy ) {
|
if( flags & flags::track_busy ) {
|
||||||
|
auto trackbusyresult { true };
|
||||||
|
std::string trackbusylog { "Test: Track busy - " };
|
||||||
for( auto *track : tracks ) {
|
for( auto *track : tracks ) {
|
||||||
if( true == track->IsEmpty() ) {
|
if( true == track->IsEmpty() ) {
|
||||||
return false;
|
trackbusylog += "[" + track->name() + "]";
|
||||||
|
trackbusyresult = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
auto const &vehicles { track->Dynamics };
|
||||||
|
if( trackbusylog.back() == ']' ) {
|
||||||
|
trackbusylog += ", ";
|
||||||
|
}
|
||||||
|
trackbusylog += "[" + vehicles.front()->asName + "] @ [" + track->name() + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteLog(
|
||||||
|
trackbusylog
|
||||||
|
+ " - "
|
||||||
|
+ ( trackbusyresult ? "Pass" : "Fail" ) );
|
||||||
|
|
||||||
|
if( false == trackbusyresult ) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( flags & flags::track_free ) {
|
if( flags & flags::track_free ) {
|
||||||
|
auto trackfreeresult { true };
|
||||||
|
std::string trackfreelog{ "Test: Track free - " };
|
||||||
for( auto *track : tracks ) {
|
for( auto *track : tracks ) {
|
||||||
if( false == track->IsEmpty() ) {
|
if( false == track->IsEmpty() ) {
|
||||||
return false;
|
auto const &vehicles { track->Dynamics };
|
||||||
|
trackfreelog += "[" + vehicles.front()->asName + "] @ [" + track->name() + "] - ";
|
||||||
|
trackfreeresult = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WriteLog(
|
||||||
|
trackfreelog
|
||||||
|
+ ( trackfreeresult ? "Pass" : "Fail" ) );
|
||||||
|
|
||||||
|
if( false == trackfreeresult ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( flags & ( flags::text | flags::value1 | flags::value2 ) ) {
|
if( flags & ( flags::text | flags::value1 | flags::value2 ) ) {
|
||||||
// porównanie wartości
|
// porównanie wartości
|
||||||
|
|||||||
@@ -9146,7 +9146,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( inputline[ 0 ] == ' ' ) {
|
if( !inputline.empty() && inputline.front() == ' ' ) {
|
||||||
// guard against malformed config files with leading spaces
|
// guard against malformed config files with leading spaces
|
||||||
inputline.erase( 0, inputline.find_first_not_of( ' ' ) );
|
inputline.erase( 0, inputline.find_first_not_of( ' ' ) );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -511,7 +511,7 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
|
|||||||
// zapewni to jakąś zgodność wstecz, bo zamiast liczby będzie ciąg, którego
|
// zapewni to jakąś zgodność wstecz, bo zamiast liczby będzie ciąg, którego
|
||||||
// wartość powinna być uznana jako zerowa
|
// wartość powinna być uznana jako zerowa
|
||||||
// parser.getToken(iNumVerts);
|
// parser.getToken(iNumVerts);
|
||||||
if (token[0] == '*')
|
if (token.front() == '*')
|
||||||
{ // jeśli pierwszy znak jest gwiazdką, poszukać
|
{ // jeśli pierwszy znak jest gwiazdką, poszukać
|
||||||
// submodelu o nazwie bez tej gwiazdki i wziąć z
|
// submodelu o nazwie bez tej gwiazdki i wziąć z
|
||||||
// niego wierzchołki
|
// niego wierzchołki
|
||||||
|
|||||||
@@ -1181,7 +1181,7 @@ texture_manager::create( std::string Filename, bool const Loadnow, GLint Formath
|
|||||||
replace_slashes( Filename );
|
replace_slashes( Filename );
|
||||||
erase_leading_slashes( Filename );
|
erase_leading_slashes( Filename );
|
||||||
// temporary code for legacy assets -- textures with names beginning with # are to be sharpened
|
// temporary code for legacy assets -- textures with names beginning with # are to be sharpened
|
||||||
if( ( Filename[ 0 ] == '#' )
|
if( ( Filename.front() == '#' )
|
||||||
|| ( Filename.find( "/#" ) != std::string::npos ) ) {
|
|| ( Filename.find( "/#" ) != std::string::npos ) ) {
|
||||||
traits += '#';
|
traits += '#';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7926,9 +7926,7 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
|||||||
// szukaj kabinę jako oddzielny model
|
// szukaj kabinę jako oddzielny model
|
||||||
// name can contain leading slash, erase it to avoid creation of double slashes when the name is combined with current directory
|
// name can contain leading slash, erase it to avoid creation of double slashes when the name is combined with current directory
|
||||||
replace_slashes( token );
|
replace_slashes( token );
|
||||||
if( token[ 0 ] == '/' ) {
|
erase_leading_slashes( token );
|
||||||
token.erase( 0, 1 );
|
|
||||||
}
|
|
||||||
TModel3d *kabina = TModelsManager::GetModel(DynamicObject->asBaseDir + token, true);
|
TModel3d *kabina = TModelsManager::GetModel(DynamicObject->asBaseDir + token, true);
|
||||||
// z powrotem defaultowa sciezka do tekstur
|
// z powrotem defaultowa sciezka do tekstur
|
||||||
Global.asCurrentTexturePath = szTexturePath;
|
Global.asCurrentTexturePath = szTexturePath;
|
||||||
|
|||||||
110
mtable.cpp
110
mtable.cpp
@@ -42,28 +42,65 @@ std::string TTrainParameters::NextStop() const
|
|||||||
return "[End of route]"; //że niby koniec
|
return "[End of route]"; //że niby koniec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sound_source
|
||||||
|
TTrainParameters::next_stop_sound() const {
|
||||||
|
if( StationIndex > StationCount ) {
|
||||||
|
return { sound_placement::general };
|
||||||
|
}
|
||||||
|
for( auto stationidx { StationIndex }; stationidx < StationCount + 1; ++stationidx ) {
|
||||||
|
auto &station{ TimeTable[ stationidx ] };
|
||||||
|
if( station.Ah == -1 ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// specified arrival time means it's a scheduled stop
|
||||||
|
return station.name_sound;
|
||||||
|
}
|
||||||
|
// shouldn't normally get here, unless the timetable is malformed
|
||||||
|
return { sound_placement::general };
|
||||||
|
}
|
||||||
|
|
||||||
|
sound_source
|
||||||
|
TTrainParameters::last_stop_sound() const {
|
||||||
|
|
||||||
|
return TimeTable[ StationCount ].name_sound;
|
||||||
|
}
|
||||||
|
|
||||||
bool TTrainParameters::IsStop() const
|
bool TTrainParameters::IsStop() const
|
||||||
{ // zapytanie, czy zatrzymywać na następnym punkcie rozkładu
|
{ // zapytanie, czy zatrzymywać na następnym punkcie rozkładu
|
||||||
if ((StationIndex < StationCount))
|
if ((StationIndex <= StationCount))
|
||||||
return TimeTable[StationIndex].Ah >= 0; //-1 to brak postoju
|
return TimeTable[StationIndex].Ah >= 0; //-1 to brak postoju
|
||||||
else
|
else
|
||||||
return true; // na ostatnim się zatrzymać zawsze
|
return true; // na ostatnim się zatrzymać zawsze
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TTrainParameters::IsLastStop() const {
|
||||||
|
|
||||||
|
return ( StationIndex >= StationCount );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TTrainParameters::IsMaintenance() const {
|
bool TTrainParameters::IsMaintenance() const {
|
||||||
if( ( StationIndex < StationCount ) )
|
if( ( StationIndex <= StationCount ) )
|
||||||
return TimeTable[ StationIndex ].is_maintenance;
|
return TimeTable[ StationIndex ].is_maintenance;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TTrainParameters::radio_channel() const {
|
int TTrainParameters::radio_channel() const {
|
||||||
if( ( StationIndex < StationCount ) )
|
if( ( StationIndex <= StationCount ) )
|
||||||
return TimeTable[ StationIndex ].radio_channel;
|
return TimeTable[ StationIndex ].radio_channel;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns: sound file associated with current station, or -1
|
||||||
|
sound_source TTrainParameters::current_stop_sound() const {
|
||||||
|
if( ( StationIndex <= StationCount ) )
|
||||||
|
return TimeTable[ StationIndex ].name_sound;
|
||||||
|
else
|
||||||
|
return { sound_placement::general };
|
||||||
|
}
|
||||||
|
|
||||||
bool TTrainParameters::UpdateMTable( scenario_time const &Time, std::string const &NewName ) {
|
bool TTrainParameters::UpdateMTable( scenario_time const &Time, std::string const &NewName ) {
|
||||||
|
|
||||||
return UpdateMTable( Time.data().wHour, Time.data().wMinute + Time.data().wSecond * 0.0167, NewName );
|
return UpdateMTable( Time.data().wHour, Time.data().wMinute + Time.data().wSecond * 0.0167, NewName );
|
||||||
@@ -421,7 +458,7 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
|
|||||||
{
|
{
|
||||||
auto const stationware { Split( record->StationWare, ',' ) };
|
auto const stationware { Split( record->StationWare, ',' ) };
|
||||||
for( auto const &entry : stationware ) {
|
for( auto const &entry : stationware ) {
|
||||||
if( entry[ 0 ] == 'R' ) {
|
if( entry.front() == 'R' ) {
|
||||||
auto const entrysplit { split_string_and_number( entry ) };
|
auto const entrysplit { split_string_and_number( entry ) };
|
||||||
if( ( entrysplit.first == "R" )
|
if( ( entrysplit.first == "R" )
|
||||||
&& ( entrysplit.second <= 10 ) ) {
|
&& ( entrysplit.second <= 10 ) ) {
|
||||||
@@ -507,9 +544,10 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
|
|||||||
TimeTable[1].Ah = TimeTable[1].Dh;
|
TimeTable[1].Ah = TimeTable[1].Dh;
|
||||||
TimeTable[1].Am = TimeTable[1].Dm;
|
TimeTable[1].Am = TimeTable[1].Dm;
|
||||||
}
|
}
|
||||||
// NextStationName:=TimeTable[1].StationName;
|
|
||||||
/* TTVmax:=TimeTable[1].vmax; */
|
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
load_sounds();
|
||||||
|
// potentially offset table times
|
||||||
auto const timeoffset { static_cast<int>( Global.ScenarioTimeOffset * 60 ) + iPlus };
|
auto const timeoffset { static_cast<int>( Global.ScenarioTimeOffset * 60 ) + iPlus };
|
||||||
if( timeoffset != 0 ) // jeżeli jest przesunięcie rozkładu
|
if( timeoffset != 0 ) // jeżeli jest przesunięcie rozkładu
|
||||||
{
|
{
|
||||||
@@ -534,24 +572,31 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
|
|||||||
return ConversionError == 0;
|
return ConversionError == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMTableTime::UpdateMTableTime(double deltaT)
|
void
|
||||||
// dodanie czasu (deltaT) w sekundach, z przeliczeniem godziny
|
TTrainParameters::load_sounds() {
|
||||||
{
|
|
||||||
mr += deltaT; // dodawanie sekund
|
for( auto stationidx = 1; stationidx < StationCount + 1; ++stationidx ) {
|
||||||
while (mr >= 60.0) // przeliczenie sekund do właściwego przedziału
|
auto &station { TimeTable[ stationidx ] };
|
||||||
{
|
if( station.Ah == -1 ) {
|
||||||
mr -= 60.0;
|
continue;
|
||||||
++mm;
|
|
||||||
}
|
}
|
||||||
while (mm > 59) // przeliczenie minut do właściwego przedziału
|
// specified arrival time means it's a scheduled stop
|
||||||
{
|
auto const stationname { (
|
||||||
mm -= 60;
|
ends_with( station.StationName, "_po" ) ?
|
||||||
++hh;
|
station.StationName.substr( 0, station.StationName.size() - 3 ) :
|
||||||
|
station.StationName ) };
|
||||||
|
|
||||||
|
auto const lookup {
|
||||||
|
FileExists(
|
||||||
|
{ Global.asCurrentSceneryPath + stationname, std::string{ szSoundPath } + "sip/" + stationname },
|
||||||
|
{ ".ogg", ".flac", ".wav" } ) };
|
||||||
|
if( lookup.first.empty() ) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
while (hh > 23) // przeliczenie godzin do właściwego przedziału
|
// wczytanie dźwięku odjazdu w wersji radiowej (słychać tylko w kabinie)
|
||||||
{
|
station.name_sound =
|
||||||
hh -= 24;
|
sound_source{ sound_placement::general, EU07_SOUND_CABANNOUNCEMENTCUTOFFRANGE }
|
||||||
++dd; // zwiększenie numeru dnia
|
.deserialize( lookup.first + lookup.second, sound_type::single );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -592,3 +637,24 @@ void TTrainParameters::serialize( dictionary_source *Output ) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TMTableTime::UpdateMTableTime(double deltaT)
|
||||||
|
// dodanie czasu (deltaT) w sekundach, z przeliczeniem godziny
|
||||||
|
{
|
||||||
|
mr += deltaT; // dodawanie sekund
|
||||||
|
while (mr >= 60.0) // przeliczenie sekund do właściwego przedziału
|
||||||
|
{
|
||||||
|
mr -= 60.0;
|
||||||
|
++mm;
|
||||||
|
}
|
||||||
|
while (mm > 59) // przeliczenie minut do właściwego przedziału
|
||||||
|
{
|
||||||
|
mm -= 60;
|
||||||
|
++hh;
|
||||||
|
}
|
||||||
|
while (hh > 23) // przeliczenie godzin do właściwego przedziału
|
||||||
|
{
|
||||||
|
hh -= 24;
|
||||||
|
++dd; // zwiększenie numeru dnia
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
9
mtable.h
9
mtable.h
@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Classes.h"
|
#include "Classes.h"
|
||||||
|
#include "sound.h"
|
||||||
|
|
||||||
namespace Mtable
|
namespace Mtable
|
||||||
{
|
{
|
||||||
@@ -38,6 +39,7 @@ struct TMTableLine
|
|||||||
float tm{ 0.f }; // czas jazdy do tej stacji w min. (z kolumny)
|
float tm{ 0.f }; // czas jazdy do tej stacji w min. (z kolumny)
|
||||||
bool is_maintenance{ false };
|
bool is_maintenance{ false };
|
||||||
int radio_channel{ -1 };
|
int radio_channel{ -1 };
|
||||||
|
sound_source name_sound{ sound_placement::internal };
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef TMTableLine TMTable[MaxTTableSize + 1];
|
typedef TMTableLine TMTable[MaxTTableSize + 1];
|
||||||
@@ -65,7 +67,10 @@ class TTrainParameters
|
|||||||
std::string ShowRelation() const;
|
std::string ShowRelation() const;
|
||||||
double WatchMTable(double DistCounter);
|
double WatchMTable(double DistCounter);
|
||||||
std::string NextStop() const;
|
std::string NextStop() const;
|
||||||
|
sound_source next_stop_sound() const;
|
||||||
|
sound_source last_stop_sound() const;
|
||||||
bool IsStop() const;
|
bool IsStop() const;
|
||||||
|
bool IsLastStop() const;
|
||||||
bool IsMaintenance() const;
|
bool IsMaintenance() const;
|
||||||
bool IsTimeToGo(double hh, double mm);
|
bool IsTimeToGo(double hh, double mm);
|
||||||
bool UpdateMTable(double hh, double mm, std::string const &NewName);
|
bool UpdateMTable(double hh, double mm, std::string const &NewName);
|
||||||
@@ -80,6 +85,10 @@ class TTrainParameters
|
|||||||
void serialize( dictionary_source *Output ) const;
|
void serialize( dictionary_source *Output ) const;
|
||||||
// returns: radio channel associated with current station, or -1
|
// returns: radio channel associated with current station, or -1
|
||||||
int radio_channel() const;
|
int radio_channel() const;
|
||||||
|
// returns: sound file associated with current station, or -1
|
||||||
|
sound_source current_stop_sound() const;
|
||||||
|
private:
|
||||||
|
void load_sounds();
|
||||||
};
|
};
|
||||||
|
|
||||||
class TMTableTime
|
class TMTableTime
|
||||||
|
|||||||
3
sound.h
3
sound.h
@@ -15,6 +15,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
float const EU07_SOUND_GLOBALRANGE { -1.f };
|
float const EU07_SOUND_GLOBALRANGE { -1.f };
|
||||||
float const EU07_SOUND_CABCONTROLSCUTOFFRANGE { 7.5f };
|
float const EU07_SOUND_CABCONTROLSCUTOFFRANGE { 7.5f };
|
||||||
|
float const EU07_SOUND_CABANNOUNCEMENTCUTOFFRANGE{ 30.f };
|
||||||
float const EU07_SOUND_BRAKINGCUTOFFRANGE { 100.f };
|
float const EU07_SOUND_BRAKINGCUTOFFRANGE { 100.f };
|
||||||
float const EU07_SOUND_RUNNINGNOISECUTOFFRANGE { 200.f };
|
float const EU07_SOUND_RUNNINGNOISECUTOFFRANGE { 200.f };
|
||||||
float const EU07_SOUND_HANDHELDRADIORANGE { 3500.f };
|
float const EU07_SOUND_HANDHELDRADIORANGE { 3500.f };
|
||||||
@@ -50,7 +51,7 @@ class sound_source {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// constructors
|
// constructors
|
||||||
sound_source( sound_placement const Placement, float const Range = 50.f );
|
sound_source( sound_placement const Placement = sound_placement::general, float const Range = 50.f );
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
~sound_source();
|
~sound_source();
|
||||||
|
|||||||
@@ -459,6 +459,14 @@ len_common_prefix( std::string const &Left, std::string const &Right ) {
|
|||||||
std::distance( left, std::mismatch( left, left + Left.size(), right ).first ) );
|
std::distance( left, std::mismatch( left, left + Left.size(), right ).first ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns true if provided string ends with another provided string
|
||||||
|
bool
|
||||||
|
ends_with( std::string const &String, std::string const &Suffix ) {
|
||||||
|
|
||||||
|
return ( String.size() >= Suffix.size() )
|
||||||
|
&& ( 0 == String.compare( String.size() - Suffix.size(), Suffix.size(), Suffix ) );
|
||||||
|
}
|
||||||
|
|
||||||
// helper, restores content of a 3d vector from provided input stream
|
// helper, restores content of a 3d vector from provided input stream
|
||||||
// TODO: review and clean up the helper routines, there's likely some redundant ones
|
// TODO: review and clean up the helper routines, there's likely some redundant ones
|
||||||
glm::dvec3 LoadPoint( cParser &Input ) {
|
glm::dvec3 LoadPoint( cParser &Input ) {
|
||||||
|
|||||||
@@ -216,6 +216,9 @@ std::string substr_path( std::string const &Filename );
|
|||||||
// returns common prefix of two provided strings
|
// returns common prefix of two provided strings
|
||||||
std::ptrdiff_t len_common_prefix( std::string const &Left, std::string const &Right );
|
std::ptrdiff_t len_common_prefix( std::string const &Left, std::string const &Right );
|
||||||
|
|
||||||
|
// returns true if provided string ends with another provided string
|
||||||
|
bool ends_with( std::string const &String, std::string const &Suffix );
|
||||||
|
|
||||||
template <typename Type_>
|
template <typename Type_>
|
||||||
void SafeDelete( Type_ &Pointer ) {
|
void SafeDelete( Type_ &Pointer ) {
|
||||||
delete Pointer;
|
delete Pointer;
|
||||||
|
|||||||
Reference in New Issue
Block a user