mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 19:09:18 +02:00
additional door control types, door operation tweaks, load exchange procedure enhancements, load exchange sounds
This commit is contained in:
181
Driver.cpp
181
Driver.cpp
@@ -869,53 +869,15 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
// jeśli długość peronu ((sSpeedTable[i].evEvent->ValueGet(2)) nie podana,
|
// jeśli długość peronu ((sSpeedTable[i].evEvent->ValueGet(2)) nie podana,
|
||||||
// przyjąć odległość fMinProximityDist
|
// przyjąć odległość fMinProximityDist
|
||||||
{ // 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) // AI tylko sobie otwiera drzwi
|
if( !AIControllFlag ) {
|
||||||
iDrivigFlags &= ~moveStopCloser; // w razie przełączenia na AI ma
|
// w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko
|
||||||
// nie podciągać do W4, gdy
|
iDrivigFlags &= ~moveStopCloser;
|
||||||
// użytkownik zatrzymał za daleko
|
}
|
||||||
if ((iDrivigFlags & moveDoorOpened) == 0)
|
|
||||||
{ // drzwi otwierać jednorazowo
|
if( ( iDrivigFlags & moveDoorOpened ) == 0 ) {
|
||||||
|
// drzwi otwierać jednorazowo
|
||||||
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
|
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
|
||||||
if (mvOccupied->DoorOpenCtrl == 1) //(mvOccupied->TrainType==dt_EZT)
|
Doors( true, static_cast<int>( std::floor( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ) ) % 10 );
|
||||||
{ // otwieranie drzwi w EZT
|
|
||||||
if (AIControllFlag) // tylko AI otwiera drzwi EZT, użytkownik
|
|
||||||
// musi samodzielnie
|
|
||||||
if (!mvOccupied->DoorLeftOpened &&
|
|
||||||
!mvOccupied->DoorRightOpened)
|
|
||||||
{ // otwieranie drzwi
|
|
||||||
int p2 =
|
|
||||||
int(floor(sSpeedTable[i].evEvent->ValueGet(2))) %
|
|
||||||
10; // p7=platform side (1:left, 2:right, 3:both)
|
|
||||||
int lewe = (iDirection > 0) ? 1 : 2; // jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
|
|
||||||
int prawe = (iDirection > 0) ? 2 : 1;
|
|
||||||
if (p2 & lewe)
|
|
||||||
mvOccupied->DoorLeft(true);
|
|
||||||
if (p2 & prawe)
|
|
||||||
mvOccupied->DoorRight(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // otwieranie drzwi w składach wagonowych - docelowo wysyłać komendę zezwolenia na otwarcie drzwi
|
|
||||||
int p7, lewe, prawe; // p7=platform side (1:left, 2:right, 3:both)
|
|
||||||
// tu będzie jeszcze długość peronu zaokrąglona do 10m
|
|
||||||
// (20m bezpieczniej, bo nie modyfikuje bitu 1)
|
|
||||||
p7 = int(std::floor(sSpeedTable[i].evEvent->ValueGet(2))) % 10;
|
|
||||||
TDynamicObject *p = pVehicles[0]; // pojazd na czole składu
|
|
||||||
while (p)
|
|
||||||
{ // otwieranie drzwi w pojazdach - flaga zezwolenia była by lepsza
|
|
||||||
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
|
|
||||||
lewe = (p->DirectionGet() > 0) ? 1 : 2;
|
|
||||||
prawe = 3 - lewe;
|
|
||||||
// wagony muszą mieć baterię załączoną do otwarcia drzwi...
|
|
||||||
p->MoverParameters->BatterySwitch(true);
|
|
||||||
if (p7 & lewe)
|
|
||||||
p->MoverParameters->DoorLeft(true);
|
|
||||||
if (p7 & prawe)
|
|
||||||
p->MoverParameters->DoorRight(true);
|
|
||||||
// pojazd podłączony z tyłu (patrząc od czoła)
|
|
||||||
p = p->Next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (TrainParams->UpdateMTable( simulation::Time, asNextStop) ) {
|
if (TrainParams->UpdateMTable( simulation::Time, asNextStop) ) {
|
||||||
// to się wykona tylko raz po zatrzymaniu na W4
|
// to się wykona tylko raz po zatrzymaniu na W4
|
||||||
@@ -925,23 +887,9 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
iDrivigFlags &= ~( moveStartHorn | moveStartHornNow );
|
iDrivigFlags &= ~( moveStartHorn | moveStartHornNow );
|
||||||
}
|
}
|
||||||
// perform loading/unloading
|
// perform loading/unloading
|
||||||
auto const exchangetime { simulation::Station.update_load( pVehicles[ 0 ], *TrainParams ) };
|
auto const platformside = static_cast<int>( std::floor( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ) ) % 10;
|
||||||
// TBD: adjust time to load exchange size
|
auto const exchangetime = simulation::Station.update_load( pVehicles[ 0 ], *TrainParams, platformside );
|
||||||
if( fStopTime > -55 ) {
|
WaitingSet( std::max( -fStopTime, exchangetime ) ); // na końcu rozkładu się ustawia 60s i tu by było skrócenie
|
||||||
// na końcu rozkładu się ustawia 60s i tu by było skrócenie
|
|
||||||
// WaitingSet( 15.0 + Random( 15.0 ) ); // 10 sekund (wziąć z rozkładu????) - czekanie
|
|
||||||
// with door open on both sides calculated loading time is halved
|
|
||||||
// p7=platform side (1:left, 2:right, 3:both)
|
|
||||||
auto const platformside = static_cast<int>( std::floor( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ) ) % 10;
|
|
||||||
WaitingSet(
|
|
||||||
platformside == 3 ?
|
|
||||||
exchangetime * 0.5 :
|
|
||||||
exchangetime );
|
|
||||||
}
|
|
||||||
// update brake settings and ai braking tables
|
|
||||||
// NOTE: this calculation is run after completing loading/unloading
|
|
||||||
// remember to move it to a more fitting spot, when loading/unloading taks some actual time
|
|
||||||
AutoRewident(); // nastawianie hamulca do jazdy pociągowej
|
|
||||||
|
|
||||||
if( TrainParams->CheckTrainLatency() < 0.0 ) {
|
if( TrainParams->CheckTrainLatency() < 0.0 ) {
|
||||||
// odnotowano spóźnienie
|
// odnotowano spóźnienie
|
||||||
@@ -1012,6 +960,10 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
+ ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute)
|
+ ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute)
|
||||||
+ " next " + asNextStop); // informacja
|
+ " next " + asNextStop); // informacja
|
||||||
#endif
|
#endif
|
||||||
|
// update brake settings and ai braking tables
|
||||||
|
// NOTE: this calculation is expected to run after completing loading/unloading
|
||||||
|
AutoRewident(); // nastawianie hamulca do jazdy pociągowej
|
||||||
|
|
||||||
if( int( floor( sSpeedTable[ i ].evEvent->ValueGet( 1 ) ) ) & 1 ) {
|
if( int( floor( sSpeedTable[ i ].evEvent->ValueGet( 1 ) ) ) & 1 ) {
|
||||||
// nie podjeżdżać do semafora, jeśli droga nie jest wolna
|
// nie podjeżdżać do semafora, jeśli droga nie jest wolna
|
||||||
iDrivigFlags |= moveStopHere;
|
iDrivigFlags |= moveStopHere;
|
||||||
@@ -2401,7 +2353,7 @@ bool TController::ReleaseEngine()
|
|||||||
ReactionTime = PrepareTime;
|
ReactionTime = PrepareTime;
|
||||||
if (AIControllFlag)
|
if (AIControllFlag)
|
||||||
{ // jeśli steruje komputer
|
{ // jeśli steruje komputer
|
||||||
if (mvOccupied->DoorOpenCtrl == 1)
|
if (mvOccupied->DoorCloseCtrl == control::driver)
|
||||||
{ // zamykanie drzwi
|
{ // zamykanie drzwi
|
||||||
if (mvOccupied->DoorLeftOpened)
|
if (mvOccupied->DoorLeftOpened)
|
||||||
mvOccupied->DoorLeft(false);
|
mvOccupied->DoorLeft(false);
|
||||||
@@ -3051,50 +3003,66 @@ void TController::SpeedSet()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void TController::Doors(bool what)
|
// otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT
|
||||||
{ // otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT
|
void TController::Doors( bool const Open, int const Side ) {
|
||||||
if (what)
|
|
||||||
{ // otwarcie
|
if( true == Open ) {
|
||||||
}
|
// otwieranie drzwi
|
||||||
else
|
// otwieranie drzwi w składach wagonowych - docelowo wysyłać komendę zezwolenia na otwarcie drzwi
|
||||||
{ // zamykanie
|
// tu będzie jeszcze długość peronu zaokrąglona do 10m (20m bezpieczniej, bo nie modyfikuje bitu 1)
|
||||||
if (mvOccupied->DoorOpenCtrl == 1)
|
// p7=platform side (1:left, 2:right, 3:both)
|
||||||
{ // jeśli drzwi sterowane z kabiny
|
auto *vehicle = pVehicles[0]; // pojazd na czole składu
|
||||||
if( AIControllFlag ) {
|
while( vehicle != nullptr ) {
|
||||||
if( mvOccupied->DoorLeftOpened || mvOccupied->DoorRightOpened ) {
|
// wagony muszą mieć baterię załączoną do otwarcia drzwi...
|
||||||
// AI zamyka drzwi przed odjazdem
|
vehicle->MoverParameters->BatterySwitch( true );
|
||||||
if( ( true == mvOccupied->DoorClosureWarning )
|
// otwieranie drzwi w pojazdach - flaga zezwolenia była by lepsza
|
||||||
&& ( false == mvOccupied->DepartureSignal )
|
if( vehicle->MoverParameters->DoorOpenCtrl != control::passenger ) {
|
||||||
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
// if the door are controlled by the driver, we let the user operate them...
|
||||||
mvOccupied->signal_departure( true ); // załącenie bzyczka
|
if( true == AIControllFlag ) {
|
||||||
fActionTime = -3.0 - 0.1 * Random( 10 ); // 3-4 second wait
|
// ...unless this user is an ai
|
||||||
}
|
// p7=platform side (1:left, 2:right, 3:both)
|
||||||
if( fActionTime > -0.5 ) {
|
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
|
||||||
// Ra: trzeba by ustawić jakiś czas oczekiwania na zamknięcie się drzwi
|
auto const lewe = ( vehicle->DirectionGet() > 0 ) ? 1 : 2;
|
||||||
mvOccupied->DoorLeft( false ); // zamykanie drzwi
|
auto const prawe = 3 - lewe;
|
||||||
mvOccupied->DoorRight( false );
|
if( Side & lewe )
|
||||||
iDrivigFlags &= ~moveDoorOpened;
|
vehicle->MoverParameters->DoorLeft( true, range::local );
|
||||||
// 1.5-2.5 sec wait, +potentially 0.5 remaining
|
if( Side & prawe )
|
||||||
fActionTime = -1.5 - 0.1 * Random( 10 );
|
vehicle->MoverParameters->DoorRight( true, range::local );
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// pojazd podłączony z tyłu (patrząc od czoła)
|
||||||
|
vehicle = vehicle->Next();
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{ // jeśli nie, to zamykanie w składzie wagonowym
|
else {
|
||||||
TDynamicObject *p = pVehicles[0]; // pojazd na czole składu
|
// zamykanie
|
||||||
while (p)
|
if( AIControllFlag ) {
|
||||||
{ // zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
|
if( ( true == mvOccupied->DoorClosureWarning )
|
||||||
p->MoverParameters->DoorLeft(false); // w lokomotywie można by nie zamykać...
|
&& ( false == mvOccupied->DepartureSignal )
|
||||||
p->MoverParameters->DoorRight(false);
|
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
||||||
p = p->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
|
mvOccupied->signal_departure( true ); // załącenie bzyczka
|
||||||
|
fActionTime = -3.0 - 0.1 * Random( 10 ); // 3-4 second wait
|
||||||
}
|
}
|
||||||
// WaitingSet(5); //10 sekund tu to za długo, opóźnia odjazd o pół minuty
|
}
|
||||||
fActionTime = -3.0 - 0.1 * Random(10); // czekanie sekundę, może trochę dłużej
|
|
||||||
|
if( ( true == TestFlag( iDrivigFlags, moveDoorOpened ) )
|
||||||
|
&& ( ( fActionTime > -0.5 )
|
||||||
|
|| ( false == AIControllFlag ) ) ) {
|
||||||
|
// ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things
|
||||||
|
auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu
|
||||||
|
while( vehicle != nullptr ) {
|
||||||
|
// zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
|
||||||
|
if( vehicle->MoverParameters->DoorCloseCtrl != control::passenger ) {
|
||||||
|
vehicle->MoverParameters->DoorLeft( false, range::local ); // w lokomotywie można by nie zamykać...
|
||||||
|
vehicle->MoverParameters->DoorRight( false, range::local );
|
||||||
|
}
|
||||||
|
vehicle = vehicle->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
|
||||||
|
}
|
||||||
|
fActionTime = -2.5 - 0.1 * Random( 10 ); // 2.5-3.5 sec wait, +potentially 0.5 remaining
|
||||||
iDrivigFlags &= ~moveDoorOpened; // zostały zamknięte - nie wykonywać drugi raz
|
iDrivigFlags &= ~moveDoorOpened; // zostały zamknięte - nie wykonywać drugi raz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
void TController::RecognizeCommand()
|
void TController::RecognizeCommand()
|
||||||
{ // odczytuje i wykonuje komendę przekazaną lokomotywie
|
{ // odczytuje i wykonuje komendę przekazaną lokomotywie
|
||||||
@@ -3632,7 +3600,7 @@ TController::UpdateSituation(double dt) {
|
|||||||
// for human-controlled vehicles with no door control and dynamic brake auto-activating with door open
|
// for human-controlled vehicles with no door control and dynamic brake auto-activating with door open
|
||||||
if( ( false == AIControllFlag )
|
if( ( false == AIControllFlag )
|
||||||
&& ( iDrivigFlags & moveDoorOpened )
|
&& ( iDrivigFlags & moveDoorOpened )
|
||||||
&& ( mvOccupied->DoorOpenCtrl != 1 )
|
&& ( mvOccupied->DoorCloseCtrl != control::driver )
|
||||||
&& ( mvControlling->MainCtrlPos > 0 ) ) {
|
&& ( mvControlling->MainCtrlPos > 0 ) ) {
|
||||||
Doors( false );
|
Doors( false );
|
||||||
}
|
}
|
||||||
@@ -4098,7 +4066,10 @@ TController::UpdateSituation(double dt) {
|
|||||||
iDrivigFlags |= movePress; // następnie będzie dociskanie
|
iDrivigFlags |= movePress; // następnie będzie dociskanie
|
||||||
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na przeciwny (dociskanie)
|
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na przeciwny (dociskanie)
|
||||||
CheckVehicles(); // od razu zmienić światła (zgasić) - bez tego się nie odczepi
|
CheckVehicles(); // od razu zmienić światła (zgasić) - bez tego się nie odczepi
|
||||||
|
/*
|
||||||
|
// NOTE: disabled to prevent closing the door before passengers can disembark
|
||||||
fStopTime = 0.0; // nie ma na co czekać z odczepianiem
|
fStopTime = 0.0; // nie ma na co czekać z odczepianiem
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -4247,8 +4218,8 @@ TController::UpdateSituation(double dt) {
|
|||||||
&& ( false == TestFlag( iDrivigFlags, movePress ) )
|
&& ( false == TestFlag( iDrivigFlags, movePress ) )
|
||||||
&& ( iCoupler == 0 )
|
&& ( iCoupler == 0 )
|
||||||
// && ( mvOccupied->Vel > 0.0 )
|
// && ( mvOccupied->Vel > 0.0 )
|
||||||
&& ( pVehicle->PrevConnected == nullptr )
|
&& ( pVehicle->MoverParameters->Couplers[ side::front ].CouplingFlag == coupling::faux )
|
||||||
&& ( pVehicle->NextConnected == nullptr ) ) {
|
&& ( pVehicle->MoverParameters->Couplers[ side::rear ].CouplingFlag == coupling::faux ) ) {
|
||||||
SetVelocity(0, 0, stopJoin); // 1. faza odczepiania: zatrzymanie
|
SetVelocity(0, 0, stopJoin); // 1. faza odczepiania: zatrzymanie
|
||||||
// WriteLog("Zatrzymanie w celu odczepienia");
|
// WriteLog("Zatrzymanie w celu odczepienia");
|
||||||
AccPreferred = std::min( 0.0, AccPreferred );
|
AccPreferred = std::min( 0.0, AccPreferred );
|
||||||
@@ -5040,7 +5011,7 @@ TController::UpdateSituation(double dt) {
|
|||||||
fMinProximityDist : // cars are allowed to move within min proximity distance
|
fMinProximityDist : // cars are allowed to move within min proximity distance
|
||||||
fMaxProximityDist ) ? // other vehicle types keep wider margin
|
fMaxProximityDist ) ? // other vehicle types keep wider margin
|
||||||
true :
|
true :
|
||||||
vel < VelNext ) ) {
|
( vel + 1.0 ) < VelNext ) ) {
|
||||||
// to można przyspieszyć
|
// to można przyspieszyć
|
||||||
IncSpeed();
|
IncSpeed();
|
||||||
}
|
}
|
||||||
|
|||||||
2
Driver.h
2
Driver.h
@@ -303,7 +303,7 @@ private:
|
|||||||
bool IncSpeed();
|
bool IncSpeed();
|
||||||
bool DecSpeed(bool force = false);
|
bool DecSpeed(bool force = false);
|
||||||
void SpeedSet();
|
void SpeedSet();
|
||||||
void Doors(bool what);
|
void Doors(bool const Open, int const Side = 0);
|
||||||
void RecognizeCommand(); // odczytuje komende przekazana lokomotywie
|
void RecognizeCommand(); // odczytuje komende przekazana lokomotywie
|
||||||
void Activation(); // umieszczenie obsady w odpowiednim członie
|
void Activation(); // umieszczenie obsady w odpowiednim członie
|
||||||
void ControllingSet(); // znajduje człon do sterowania
|
void ControllingSet(); // znajduje człon do sterowania
|
||||||
|
|||||||
181
DynObj.cpp
181
DynObj.cpp
@@ -1924,37 +1924,49 @@ 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.substr( 0, 2 ) == "WF" ) ) {
|
&& ( ActPar[ 0 ] == 'W' ) ) {
|
||||||
// wheel flat
|
// wheel
|
||||||
// TODO: convert this whole mess to something more elegant one day
|
ActPar.erase( 0, 1 );
|
||||||
ActPar.erase( 0, 2 );
|
|
||||||
auto fixedflatsize { 0 };
|
auto fixedflatsize { 0 };
|
||||||
{
|
|
||||||
// fixed size flat
|
|
||||||
auto const indexend { ActPar.find_first_not_of( "1234567890", 0 ) };
|
|
||||||
fixedflatsize = std::atoi( ActPar.substr( 0, indexend ).c_str() );
|
|
||||||
ActPar.erase( 0, indexend );
|
|
||||||
}
|
|
||||||
// optional parameters
|
|
||||||
auto randomflatsize { 0 };
|
auto randomflatsize { 0 };
|
||||||
auto randomflatchance { 100 };
|
auto flatchance { 100 };
|
||||||
|
|
||||||
while( false == ActPar.empty() ) {
|
while( false == ActPar.empty() ) {
|
||||||
if( ActPar[ 0 ] == 'R' ) {
|
// TODO: convert this whole copy and paste mess to something more elegant one day
|
||||||
// random flat size
|
switch( ActPar[ 0 ] ) {
|
||||||
auto const indexstart { 1 };
|
case 'F': {
|
||||||
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
|
// fixed flat size
|
||||||
randomflatsize = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
|
auto const indexstart { 1 };
|
||||||
ActPar.erase( 0, indexend );
|
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
|
||||||
}
|
fixedflatsize = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
|
||||||
else if( ActPar[ 0 ] == 'P' ) {
|
ActPar.erase( 0, indexend );
|
||||||
// random flat probability
|
break;
|
||||||
auto const indexstart { 1 };
|
}
|
||||||
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
|
case 'R': {
|
||||||
randomflatchance = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
|
// random flat size
|
||||||
ActPar.erase( 0, indexend );
|
auto const indexstart { 1 };
|
||||||
|
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
|
||||||
|
randomflatsize = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
|
||||||
|
ActPar.erase( 0, indexend );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'P': {
|
||||||
|
// random flat probability
|
||||||
|
auto const indexstart { 1 };
|
||||||
|
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
|
||||||
|
flatchance = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
|
||||||
|
ActPar.erase( 0, indexend );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// unrecognized key
|
||||||
|
ActPar.erase( 0, 1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( Random(0, 100) <= randomflatchance ) {
|
if( Random( 0, 100 ) <= flatchance ) {
|
||||||
MoverParameters->WheelFlat += fixedflatsize + Random( 0, randomflatsize );
|
MoverParameters->WheelFlat += fixedflatsize + Random( 0, randomflatsize );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2476,6 +2488,87 @@ bool TDynamicObject::UpdateForce(double dt, double dt1, bool FullVer)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initiates load change by specified amounts, with a platform on specified side
|
||||||
|
void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int const Platform ) {
|
||||||
|
|
||||||
|
if( ( MoverParameters->DoorOpenCtrl == control::passenger )
|
||||||
|
|| ( MoverParameters->DoorOpenCtrl == control::mixed ) ) {
|
||||||
|
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
|
||||||
|
auto const lewe = ( DirectionGet() > 0 ) ? 1 : 2;
|
||||||
|
auto const prawe = 3 - lewe;
|
||||||
|
if( Platform & lewe ) {
|
||||||
|
MoverParameters->DoorLeft( true, range::local );
|
||||||
|
}
|
||||||
|
if( Platform & prawe ) {
|
||||||
|
MoverParameters->DoorRight( true, range::local );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_exchange.unload_count += Disembark;
|
||||||
|
m_exchange.load_count += Embark;
|
||||||
|
m_exchange.speed_factor = (
|
||||||
|
Platform == 3 ?
|
||||||
|
2.0 :
|
||||||
|
1.0 );
|
||||||
|
m_exchange.time = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update state of load exchange operation
|
||||||
|
void TDynamicObject::update_exchange( double const Deltatime ) {
|
||||||
|
|
||||||
|
if( ( m_exchange.unload_count < 0.01 ) && ( m_exchange.load_count < 0.01 ) ) { return; }
|
||||||
|
|
||||||
|
if( ( MoverParameters->Vel < 2.0 )
|
||||||
|
&& ( ( true == MoverParameters->DoorLeftOpened )
|
||||||
|
|| ( true == MoverParameters->DoorRightOpened ) ) ) {
|
||||||
|
|
||||||
|
m_exchange.time += Deltatime;
|
||||||
|
while( ( m_exchange.unload_count > 0.01 )
|
||||||
|
&& ( m_exchange.time >= 1.0 ) ) {
|
||||||
|
|
||||||
|
m_exchange.time -= 1.0;
|
||||||
|
auto const exchangesize = std::min( m_exchange.unload_count, MoverParameters->UnLoadSpeed * m_exchange.speed_factor );
|
||||||
|
m_exchange.unload_count -= exchangesize;
|
||||||
|
MoverParameters->LoadStatus = 1;
|
||||||
|
MoverParameters->Load = std::max( 0.f, MoverParameters->Load - exchangesize );
|
||||||
|
update_load_visibility();
|
||||||
|
}
|
||||||
|
if( m_exchange.unload_count < 0.01 ) {
|
||||||
|
// finish any potential unloading operation before adding new load
|
||||||
|
// don't load more than can fit
|
||||||
|
m_exchange.load_count = std::min( m_exchange.load_count, MoverParameters->MaxLoad - MoverParameters->Load );
|
||||||
|
while( ( m_exchange.load_count > 0.01 )
|
||||||
|
&& ( m_exchange.time >= 1.0 ) ) {
|
||||||
|
|
||||||
|
m_exchange.time -= 1.0;
|
||||||
|
auto const exchangesize = std::min( m_exchange.load_count, MoverParameters->LoadSpeed * m_exchange.speed_factor );
|
||||||
|
m_exchange.load_count -= exchangesize;
|
||||||
|
MoverParameters->LoadStatus = 2;
|
||||||
|
MoverParameters->Load = std::min( MoverParameters->MaxLoad, MoverParameters->Load + exchangesize ); // std::max not strictly needed but, eh
|
||||||
|
update_load_visibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( MoverParameters->Vel > 2.0 ) {
|
||||||
|
// if the vehicle moves too fast cancel the exchange
|
||||||
|
m_exchange.unload_count = 0;
|
||||||
|
m_exchange.load_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( m_exchange.unload_count < 0.01 )
|
||||||
|
&& ( m_exchange.load_count < 0.01 ) ) {
|
||||||
|
|
||||||
|
MoverParameters->LoadStatus = 0;
|
||||||
|
// if the exchange is completed (or canceled) close the door, if applicable
|
||||||
|
if( ( MoverParameters->DoorCloseCtrl == control::passenger )
|
||||||
|
|| ( MoverParameters->DoorCloseCtrl == control::mixed ) ) {
|
||||||
|
|
||||||
|
MoverParameters->DoorLeft( false, range::local );
|
||||||
|
MoverParameters->DoorRight( false, range::local );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TDynamicObject::LoadUpdate() {
|
void TDynamicObject::LoadUpdate() {
|
||||||
// przeładowanie modelu ładunku
|
// przeładowanie modelu ładunku
|
||||||
// Ra: nie próbujemy wczytywać modeli miliony razy podczas renderowania!!!
|
// Ra: nie próbujemy wczytywać modeli miliony razy podczas renderowania!!!
|
||||||
@@ -2494,7 +2587,11 @@ void TDynamicObject::LoadUpdate() {
|
|||||||
}
|
}
|
||||||
if( mdLoad == nullptr ) {
|
if( mdLoad == nullptr ) {
|
||||||
// if this fails, try generic load model
|
// if this fails, try generic load model
|
||||||
mdLoad = TModelsManager::GetModel( asBaseDir + MoverParameters->LoadType, true );
|
auto const genericloadfilename { asBaseDir + MoverParameters->LoadType };
|
||||||
|
if( ( true == FileExists( genericloadfilename + ".e3d" ) )
|
||||||
|
|| ( true == FileExists( genericloadfilename + ".t3d" ) ) ) {
|
||||||
|
mdLoad = TModelsManager::GetModel( genericloadfilename, true );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( mdLoad != nullptr ) {
|
if( mdLoad != nullptr ) {
|
||||||
// TODO: discern from vehicle component which merely uses vehicle directory and has no animations, so it can be initialized outright
|
// TODO: discern from vehicle component which merely uses vehicle directory and has no animations, so it can be initialized outright
|
||||||
@@ -2539,11 +2636,11 @@ TDynamicObject::update_load_sections() {
|
|||||||
|
|
||||||
void
|
void
|
||||||
TDynamicObject::update_load_visibility() {
|
TDynamicObject::update_load_visibility() {
|
||||||
|
/*
|
||||||
if( Random() < 0.25 ) {
|
if( Random() < 0.25 ) {
|
||||||
shuffle_load_sections();
|
shuffle_load_sections();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
auto loadpercentage { (
|
auto loadpercentage { (
|
||||||
MoverParameters->MaxLoad == 0.0 ?
|
MoverParameters->MaxLoad == 0.0 ?
|
||||||
0.0 :
|
0.0 :
|
||||||
@@ -3521,6 +3618,8 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
}
|
}
|
||||||
MoverParameters->DerailReason = 0; //żeby tylko raz
|
MoverParameters->DerailReason = 0; //żeby tylko raz
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_exchange( dt );
|
||||||
if (MoverParameters->LoadStatus)
|
if (MoverParameters->LoadStatus)
|
||||||
LoadUpdate(); // zmiana modelu ładunku
|
LoadUpdate(); // zmiana modelu ładunku
|
||||||
|
|
||||||
@@ -3561,6 +3660,7 @@ bool TDynamicObject::FastUpdate(double dt)
|
|||||||
// ResetdMoveLen();
|
// ResetdMoveLen();
|
||||||
FastMove(dDOMoveLen);
|
FastMove(dDOMoveLen);
|
||||||
|
|
||||||
|
update_exchange( dt );
|
||||||
if (MoverParameters->LoadStatus)
|
if (MoverParameters->LoadStatus)
|
||||||
LoadUpdate(); // zmiana modelu ładunku
|
LoadUpdate(); // zmiana modelu ładunku
|
||||||
return true; // Ra: chyba tak?
|
return true; // Ra: chyba tak?
|
||||||
@@ -3757,6 +3857,19 @@ void TDynamicObject::RenderSounds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// other sounds
|
// other sounds
|
||||||
|
// load exchange
|
||||||
|
if( MoverParameters->LoadStatus & 1 ) {
|
||||||
|
m_exchangesounds.unloading.play( sound_flags::exclusive );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_exchangesounds.unloading.stop();
|
||||||
|
}
|
||||||
|
if( MoverParameters->LoadStatus & 2 ) {
|
||||||
|
m_exchangesounds.loading.play( sound_flags::exclusive );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_exchangesounds.loading.stop();
|
||||||
|
}
|
||||||
// NBMX sygnal odjazdu
|
// NBMX sygnal odjazdu
|
||||||
if( MoverParameters->DoorClosureWarning ) {
|
if( MoverParameters->DoorClosureWarning ) {
|
||||||
if( MoverParameters->DepartureSignal ) {
|
if( MoverParameters->DepartureSignal ) {
|
||||||
@@ -4878,6 +4991,16 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if( token == "unloading:" ) {
|
||||||
|
m_exchangesounds.unloading.deserialize( parser, sound_type::single );
|
||||||
|
m_exchangesounds.unloading.owner( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
else if( token == "loading:" ) {
|
||||||
|
m_exchangesounds.loading.deserialize( parser, sound_type::single );
|
||||||
|
m_exchangesounds.loading.owner( this );
|
||||||
|
}
|
||||||
|
|
||||||
else if( token == "sand:" ) {
|
else if( token == "sand:" ) {
|
||||||
sSand.deserialize( parser, sound_type::multipart, sound_parameters::range );
|
sSand.deserialize( parser, sound_type::multipart, sound_parameters::range );
|
||||||
sSand.owner( this );
|
sSand.owner( this );
|
||||||
|
|||||||
20
DynObj.h
20
DynObj.h
@@ -264,6 +264,13 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// types
|
// types
|
||||||
|
struct exchange_data {
|
||||||
|
float unload_count { 0.f }; // amount to unload
|
||||||
|
float load_count { 0.f }; // amount to load
|
||||||
|
float speed_factor { 1.f }; // operation speed modifier
|
||||||
|
float time { 0.f }; // time spent on the operation
|
||||||
|
};
|
||||||
|
|
||||||
struct coupler_sounds {
|
struct coupler_sounds {
|
||||||
sound_source dsbCouplerAttach { sound_placement::external }; // moved from cab
|
sound_source dsbCouplerAttach { sound_placement::external }; // moved from cab
|
||||||
sound_source dsbCouplerDetach { sound_placement::external }; // moved from cab
|
sound_source dsbCouplerDetach { sound_placement::external }; // moved from cab
|
||||||
@@ -282,6 +289,11 @@ private:
|
|||||||
sound_source rsDoorClose { sound_placement::general, 25.f };
|
sound_source rsDoorClose { sound_placement::general, 25.f };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct exchange_sounds {
|
||||||
|
sound_source loading { sound_placement::general };
|
||||||
|
sound_source unloading { sound_placement::general };
|
||||||
|
};
|
||||||
|
|
||||||
struct axle_sounds {
|
struct axle_sounds {
|
||||||
double distance; // distance to rail joint
|
double distance; // distance to rail joint
|
||||||
double offset; // axle offset from centre of the vehicle
|
double offset; // axle offset from centre of the vehicle
|
||||||
@@ -318,6 +330,8 @@ private:
|
|||||||
void ABuBogies();
|
void ABuBogies();
|
||||||
void ABuModelRoll();
|
void ABuModelRoll();
|
||||||
void TurnOff();
|
void TurnOff();
|
||||||
|
// update state of load exchange operation
|
||||||
|
void update_exchange( double const Deltatime );
|
||||||
|
|
||||||
// members
|
// members
|
||||||
TButton btCoupler1; // sprzegi
|
TButton btCoupler1; // sprzegi
|
||||||
@@ -385,6 +399,9 @@ private:
|
|||||||
sound_source rscurve { sound_placement::external, EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; // youBy
|
sound_source rscurve { sound_placement::external, EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; // youBy
|
||||||
sound_source rsDerailment { sound_placement::external, 250.f }; // McZapkie-051202
|
sound_source rsDerailment { sound_placement::external, 250.f }; // McZapkie-051202
|
||||||
|
|
||||||
|
exchange_data m_exchange; // state of active load exchange procedure, if any
|
||||||
|
exchange_sounds m_exchangesounds; // sounds associated with the load exchange
|
||||||
|
|
||||||
Math3D::vector3 modelShake;
|
Math3D::vector3 modelShake;
|
||||||
|
|
||||||
bool renderme; // yB - czy renderowac
|
bool renderme; // yB - czy renderowac
|
||||||
@@ -466,6 +483,8 @@ private:
|
|||||||
void create_controller( std::string const Type, bool const Trainset );
|
void create_controller( std::string const Type, bool const Trainset );
|
||||||
void AttachPrev(TDynamicObject *Object, int iType = 1);
|
void AttachPrev(TDynamicObject *Object, int iType = 1);
|
||||||
bool UpdateForce(double dt, double dt1, bool FullVer);
|
bool UpdateForce(double dt, double dt1, bool FullVer);
|
||||||
|
// initiates load change by specified amounts, with a platform on specified side
|
||||||
|
void LoadExchange( int const Disembark, int const Embark, int const Platform );
|
||||||
void LoadUpdate();
|
void LoadUpdate();
|
||||||
void update_load_sections();
|
void update_load_sections();
|
||||||
void update_load_visibility();
|
void update_load_visibility();
|
||||||
@@ -553,6 +572,7 @@ private:
|
|||||||
void DestinationSet(std::string to, std::string numer);
|
void DestinationSet(std::string to, std::string numer);
|
||||||
std::string TextureTest(std::string const &name);
|
std::string TextureTest(std::string const &name);
|
||||||
void OverheadTrack(float o);
|
void OverheadTrack(float o);
|
||||||
|
|
||||||
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 ];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ enum coupling {
|
|||||||
gangway = 0x10,
|
gangway = 0x10,
|
||||||
mainhose = 0x20,
|
mainhose = 0x20,
|
||||||
heating = 0x40,
|
heating = 0x40,
|
||||||
permanent = 0x80
|
permanent = 0x80,
|
||||||
|
uic = 0x100
|
||||||
};
|
};
|
||||||
// possible effect ranges for control commands; exclusive
|
// possible effect ranges for control commands; exclusive
|
||||||
enum range {
|
enum range {
|
||||||
@@ -176,6 +177,15 @@ enum light {
|
|||||||
redmarker_right = 0x20,
|
redmarker_right = 0x20,
|
||||||
rearendsignals = 0x40
|
rearendsignals = 0x40
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// door operation methods; exclusive
|
||||||
|
enum control {
|
||||||
|
passenger, // local, opened/closed for duration of loading
|
||||||
|
driver, // remote, operated by the driver
|
||||||
|
autonomous, // local, closed when vehicle moves and/or after timeout
|
||||||
|
conductor, // remote, operated by the conductor
|
||||||
|
mixed // primary manual but answers also to remote control
|
||||||
|
};
|
||||||
/*typ hamulca elektrodynamicznego*/
|
/*typ hamulca elektrodynamicznego*/
|
||||||
static int const dbrake_none = 0;
|
static int const dbrake_none = 0;
|
||||||
static int const dbrake_passive = 1;
|
static int const dbrake_passive = 1;
|
||||||
@@ -307,7 +317,7 @@ struct TCommand
|
|||||||
std::string Command; /*komenda*/
|
std::string Command; /*komenda*/
|
||||||
double Value1 = 0.0; /*argumenty komendy*/
|
double Value1 = 0.0; /*argumenty komendy*/
|
||||||
double Value2 = 0.0;
|
double Value2 = 0.0;
|
||||||
int Coupling{ ctrain_controll }; // coupler flag used to determine command propagation
|
int Coupling { coupling::control }; // coupler flag used to determine command propagation
|
||||||
TLocation Location;
|
TLocation Location;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -821,10 +831,10 @@ public:
|
|||||||
static std::vector<std::string> const eimc_labels;
|
static std::vector<std::string> const eimc_labels;
|
||||||
double InverterFrequency { 0.0 }; // current frequency of power inverters
|
double InverterFrequency { 0.0 }; // current frequency of power inverters
|
||||||
/*-dla wagonow*/
|
/*-dla wagonow*/
|
||||||
double MaxLoad = 0.0; /*masa w T lub ilosc w sztukach - ladownosc*/
|
float MaxLoad = 0.f; /*masa w T lub ilosc w sztukach - ladownosc*/
|
||||||
std::string LoadAccepted; std::string LoadQuantity; /*co moze byc zaladowane, jednostki miary*/
|
std::string LoadAccepted; std::string LoadQuantity; /*co moze byc zaladowane, jednostki miary*/
|
||||||
double OverLoadFactor = 0.0; /*ile razy moze byc przekroczona ladownosc*/
|
double OverLoadFactor = 0.0; /*ile razy moze byc przekroczona ladownosc*/
|
||||||
double LoadSpeed = 0.0; double UnLoadSpeed = 0.0;/*szybkosc na- i rozladunku jednostki/s*/
|
float LoadSpeed = 0.f; float UnLoadSpeed = 0.f;/*szybkosc na- i rozladunku jednostki/s*/
|
||||||
int DoorOpenCtrl = 0; int DoorCloseCtrl = 0; /*0: przez pasazera, 1: przez maszyniste, 2: samoczynne (zamykanie)*/
|
int DoorOpenCtrl = 0; int DoorCloseCtrl = 0; /*0: przez pasazera, 1: przez maszyniste, 2: samoczynne (zamykanie)*/
|
||||||
double DoorStayOpen = 0.0; /*jak dlugo otwarte w przypadku DoorCloseCtrl=2*/
|
double DoorStayOpen = 0.0; /*jak dlugo otwarte w przypadku DoorCloseCtrl=2*/
|
||||||
bool DoorClosureWarning = false; /*czy jest ostrzeganie przed zamknieciem*/
|
bool DoorClosureWarning = false; /*czy jest ostrzeganie przed zamknieciem*/
|
||||||
@@ -887,7 +897,7 @@ public:
|
|||||||
bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere)
|
bool CompressorAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere)
|
||||||
bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure
|
bool CompressorGovernorLock{ false }; // indicates whether compressor pressure switch was activated due to reaching cut-out pressure
|
||||||
// TODO converter parameters, for when we start cleaning up mover parameters
|
// TODO converter parameters, for when we start cleaning up mover parameters
|
||||||
start ConverterStart{ manual }; // whether converter is started manually, or by other means
|
start ConverterStart{ start::manual }; // whether converter is started manually, or by other means
|
||||||
float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met
|
float ConverterStartDelay{ 0.0f }; // delay (in seconds) before the converter is started, once its activation conditions are met
|
||||||
double ConverterStartDelayTimer{ 0.0 }; // helper, for tracking whether converter start delay passed
|
double ConverterStartDelayTimer{ 0.0 }; // helper, for tracking whether converter start delay passed
|
||||||
bool ConverterAllow = false; /*zezwolenie na prace przetwornicy NBMX*/
|
bool ConverterAllow = false; /*zezwolenie na prace przetwornicy NBMX*/
|
||||||
@@ -1024,7 +1034,7 @@ public:
|
|||||||
double eAngle = M_PI * 0.5;
|
double eAngle = M_PI * 0.5;
|
||||||
|
|
||||||
/*-dla wagonow*/
|
/*-dla wagonow*/
|
||||||
double Load = 0.0; /*masa w T lub ilosc w sztukach - zaladowane*/
|
float Load = 0.f; /*masa w T lub ilosc w sztukach - zaladowane*/
|
||||||
std::string LoadType; /*co jest zaladowane*/
|
std::string LoadType; /*co jest zaladowane*/
|
||||||
int LoadStatus = 0; //+1=trwa rozladunek,+2=trwa zaladunek,+4=zakończono,0=zaktualizowany model
|
int LoadStatus = 0; //+1=trwa rozladunek,+2=trwa zaladunek,+4=zakończono,0=zaktualizowany model
|
||||||
double LastLoadChangeTime = 0.0; //raz (roz)ładowania
|
double LastLoadChangeTime = 0.0; //raz (roz)ładowania
|
||||||
@@ -1220,8 +1230,8 @@ public:
|
|||||||
|
|
||||||
/* funckje dla wagonow*/
|
/* funckje dla wagonow*/
|
||||||
bool LoadingDone(double LSpeed, std::string LoadInit);
|
bool LoadingDone(double LSpeed, std::string LoadInit);
|
||||||
bool DoorLeft(bool State); //obsluga drzwi lewych
|
bool DoorLeft(bool State, int const Notify = range::consist ); //obsluga drzwi lewych
|
||||||
bool DoorRight(bool State); //obsluga drzwi prawych
|
bool DoorRight(bool State, int const Notify = range::consist ); //obsluga drzwi prawych
|
||||||
bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi
|
bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi
|
||||||
bool signal_departure( bool const State, int const Notify = range::consist ); // toggles departure warning
|
bool signal_departure( bool const State, int const Notify = range::consist ); // toggles departure warning
|
||||||
|
|
||||||
|
|||||||
@@ -6006,65 +6006,80 @@ bool TMoverParameters::DoorBlockedFlag(void)
|
|||||||
// Q: 20160713
|
// Q: 20160713
|
||||||
// Otwiera / zamyka lewe drzwi
|
// Otwiera / zamyka lewe drzwi
|
||||||
// *************************************************************************************************
|
// *************************************************************************************************
|
||||||
bool TMoverParameters::DoorLeft(bool State)
|
// NOTE: door methods work regardless of vehicle door control type,
|
||||||
{
|
// but commands issued through the command system work only for vehicles which accept remote door control
|
||||||
bool DL = false;
|
bool TMoverParameters::DoorLeft(bool State, int const Notify ) {
|
||||||
if ((DoorLeftOpened != State) && (DoorBlockedFlag() == false) && (Battery == true))
|
|
||||||
{
|
if( DoorLeftOpened == State ) {
|
||||||
DL = true;
|
// TBD: should the command be passed to other vehicles regardless of whether it affected the primary target?
|
||||||
DoorLeftOpened = State;
|
// (for the time being no, methods are often invoked blindly which would lead to commands spam)
|
||||||
if (State == true)
|
return false;
|
||||||
{
|
|
||||||
if (CabNo > 0)
|
|
||||||
SendCtrlToNext("DoorOpen", 1, CabNo); // 1=lewe, 2=prawe
|
|
||||||
else
|
|
||||||
SendCtrlToNext("DoorOpen", 2, CabNo); // zamiana
|
|
||||||
CompressedVolume -= 0.003;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (CabNo > 0)
|
|
||||||
SendCtrlToNext("DoorClose", 1, CabNo);
|
|
||||||
else
|
|
||||||
SendCtrlToNext("DoorClose", 2, CabNo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
DL = false;
|
bool result { false };
|
||||||
return DL;
|
|
||||||
|
if( ( Battery == true )
|
||||||
|
&& ( DoorBlockedFlag() == false ) ) {
|
||||||
|
|
||||||
|
DoorLeftOpened = State;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
if( Notify != range::local ) {
|
||||||
|
|
||||||
|
SendCtrlToNext(
|
||||||
|
( State == true ?
|
||||||
|
"DoorOpen" :
|
||||||
|
"DoorClose" ),
|
||||||
|
( CabNo > 0 ? // 1=lewe, 2=prawe (swap if reversed)
|
||||||
|
1 :
|
||||||
|
2 ),
|
||||||
|
CabNo,
|
||||||
|
( Notify == range::unit ?
|
||||||
|
coupling::control | coupling::permanent :
|
||||||
|
coupling::control ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// *************************************************************************************************
|
// *************************************************************************************************
|
||||||
// Q: 20160713
|
// Q: 20160713
|
||||||
// Otwiera / zamyka prawe drzwi
|
// Otwiera / zamyka prawe drzwi
|
||||||
// *************************************************************************************************
|
// *************************************************************************************************
|
||||||
bool TMoverParameters::DoorRight(bool State)
|
// NOTE: door methods work regardless of vehicle door control type,
|
||||||
{
|
// but commands issued through the command system work only for vehicles which accept remote door control
|
||||||
bool DR = false;
|
bool TMoverParameters::DoorRight(bool State, int const Notify ) {
|
||||||
if ((DoorRightOpened != State) && (DoorBlockedFlag() == false) && (Battery == true))
|
|
||||||
{
|
|
||||||
DR = true;
|
|
||||||
DoorRightOpened = State;
|
|
||||||
if (State == true)
|
|
||||||
{
|
|
||||||
if (CabNo > 0)
|
|
||||||
SendCtrlToNext("DoorOpen", 2, CabNo); // 1=lewe, 2=prawe
|
|
||||||
else
|
|
||||||
SendCtrlToNext("DoorOpen", 1, CabNo); // zamiana
|
|
||||||
CompressedVolume -= 0.003;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (CabNo > 0)
|
|
||||||
SendCtrlToNext("DoorClose", 2, CabNo);
|
|
||||||
else
|
|
||||||
SendCtrlToNext("DoorClose", 1, CabNo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
DR = false;
|
|
||||||
|
|
||||||
return DR;
|
if( DoorRightOpened == State ) {
|
||||||
|
// TBD: should the command be passed to other vehicles regardless of whether it affected the primary target?
|
||||||
|
// (for the time being no, methods are often invoked blindly which would lead to commands spam)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result { false };
|
||||||
|
|
||||||
|
if( ( Battery == true )
|
||||||
|
&& ( DoorBlockedFlag() == false ) ) {
|
||||||
|
|
||||||
|
DoorRightOpened = State;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
if( Notify != range::local ) {
|
||||||
|
|
||||||
|
SendCtrlToNext(
|
||||||
|
( State == true ?
|
||||||
|
"DoorOpen" :
|
||||||
|
"DoorClose" ),
|
||||||
|
( CabNo > 0 ? // 1=lewe, 2=prawe (swap if reversed)
|
||||||
|
2 :
|
||||||
|
1 ),
|
||||||
|
CabNo,
|
||||||
|
( Notify == range::unit ?
|
||||||
|
coupling::control | coupling::permanent :
|
||||||
|
coupling::control ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// toggles departure warning
|
// toggles departure warning
|
||||||
@@ -6086,8 +6101,8 @@ TMoverParameters::signal_departure( bool const State, int const Notify ) {
|
|||||||
0 ),
|
0 ),
|
||||||
CabNo,
|
CabNo,
|
||||||
( Notify == range::unit ?
|
( Notify == range::unit ?
|
||||||
ctrain_controll | ctrain_depot :
|
coupling::control | coupling::permanent :
|
||||||
ctrain_controll ) );
|
coupling::control ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -7184,8 +7199,8 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) {
|
|||||||
auto lookup = compressorpowers.find( extract_value( "CompressorPower", line ) );
|
auto lookup = compressorpowers.find( extract_value( "CompressorPower", line ) );
|
||||||
CompressorPower =
|
CompressorPower =
|
||||||
lookup != compressorpowers.end() ?
|
lookup != compressorpowers.end() ?
|
||||||
lookup->second :
|
lookup->second :
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( true == extract_value( AirLeakRate, "AirLeakRate", line, "" ) ) {
|
if( true == extract_value( AirLeakRate, "AirLeakRate", line, "" ) ) {
|
||||||
@@ -7196,16 +7211,31 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) {
|
|||||||
|
|
||||||
void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
|
void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
|
||||||
|
|
||||||
DoorOpenCtrl = 0;
|
std::map<std::string, int> doorcontrols {
|
||||||
std::string openctrl; extract_value( openctrl, "OpenCtrl", line, "" );
|
{ "Passenger", control::passenger },
|
||||||
if( openctrl == "DriverCtrl" ) { DoorOpenCtrl = 1; }
|
{ "AutomaticCtrl", control::autonomous },
|
||||||
|
{ "DriverCtrl", control::driver },
|
||||||
DoorCloseCtrl = 0;
|
{ "Conductor", control::conductor },
|
||||||
std::string closectrl; extract_value( closectrl, "CloseCtrl", line, "" );
|
{ "Mixed", control::mixed }
|
||||||
if( closectrl == "DriverCtrl" ) { DoorCloseCtrl = 1; }
|
};
|
||||||
else if( closectrl == "AutomaticCtrl" ) { DoorCloseCtrl = 2; }
|
// opening method
|
||||||
|
{
|
||||||
if( DoorCloseCtrl == 2 ) { extract_value( DoorStayOpen, "DoorStayOpen", line, "" ); }
|
auto lookup = doorcontrols.find( extract_value( "OpenCtrl", line ) );
|
||||||
|
DoorOpenCtrl =
|
||||||
|
lookup != doorcontrols.end() ?
|
||||||
|
lookup->second :
|
||||||
|
control::passenger;
|
||||||
|
}
|
||||||
|
// closing method
|
||||||
|
{
|
||||||
|
auto lookup = doorcontrols.find( extract_value( "CloseCtrl", line ) );
|
||||||
|
DoorCloseCtrl =
|
||||||
|
lookup != doorcontrols.end() ?
|
||||||
|
lookup->second :
|
||||||
|
control::passenger;
|
||||||
|
}
|
||||||
|
// automatic closing timer
|
||||||
|
if( DoorCloseCtrl == control::autonomous ) { extract_value( DoorStayOpen, "DoorStayOpen", line, "" ); }
|
||||||
|
|
||||||
extract_value( DoorOpenSpeed, "OpenSpeed", line, "" );
|
extract_value( DoorOpenSpeed, "OpenSpeed", line, "" );
|
||||||
extract_value( DoorCloseSpeed, "CloseSpeed", line, "" );
|
extract_value( DoorCloseSpeed, "CloseSpeed", line, "" );
|
||||||
@@ -8315,6 +8345,7 @@ bool TMoverParameters::SendCtrlToNext( std::string const CtrlCommand, double con
|
|||||||
// musi być wybrana niezerowa kabina
|
// musi być wybrana niezerowa kabina
|
||||||
if( ( Couplers[ d ].Connected != nullptr )
|
if( ( Couplers[ d ].Connected != nullptr )
|
||||||
&& ( TestFlag( Couplers[ d ].CouplingFlag, Couplertype ) ) ) {
|
&& ( TestFlag( Couplers[ d ].CouplingFlag, Couplertype ) ) ) {
|
||||||
|
|
||||||
if( Couplers[ d ].ConnectedNr != d ) {
|
if( Couplers[ d ].ConnectedNr != d ) {
|
||||||
// jeśli ten nastpęny jest zgodny z aktualnym
|
// jeśli ten nastpęny jest zgodny z aktualnym
|
||||||
if( Couplers[ d ].Connected->SetInternalCommand( CtrlCommand, ctrlvalue, dir, Couplertype ) )
|
if( Couplers[ d ].Connected->SetInternalCommand( CtrlCommand, ctrlvalue, dir, Couplertype ) )
|
||||||
@@ -8473,38 +8504,48 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
|||||||
}
|
}
|
||||||
else if (Command == "DoorOpen") /*NBMX*/
|
else if (Command == "DoorOpen") /*NBMX*/
|
||||||
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
|
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
|
||||||
if ((CValue2 > 0))
|
if( ( DoorCloseCtrl == control::conductor )
|
||||||
{ // normalne ustawienie pojazdu
|
|| ( DoorCloseCtrl == control::driver )
|
||||||
if ((CValue1 == 1) || (CValue1 == 3))
|
|| ( DoorCloseCtrl == control::mixed ) ) {
|
||||||
DoorLeftOpened = true;
|
// ignore remote command if the door is only operated locally
|
||||||
if ((CValue1 == 2) || (CValue1 == 3))
|
if( CValue2 > 0 ) {
|
||||||
DoorRightOpened = true;
|
// normalne ustawienie pojazdu
|
||||||
}
|
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
|
||||||
else
|
DoorLeftOpened = true;
|
||||||
{ // odwrotne ustawienie pojazdu
|
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
|
||||||
if ((CValue1 == 2) || (CValue1 == 3))
|
DoorRightOpened = true;
|
||||||
DoorLeftOpened = true;
|
}
|
||||||
if ((CValue1 == 1) || (CValue1 == 3))
|
else {
|
||||||
DoorRightOpened = true;
|
// odwrotne ustawienie pojazdu
|
||||||
}
|
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
|
||||||
|
DoorLeftOpened = true;
|
||||||
|
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
|
||||||
|
DoorRightOpened = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||||
}
|
}
|
||||||
else if (Command == "DoorClose") /*NBMX*/
|
else if (Command == "DoorClose") /*NBMX*/
|
||||||
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
|
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
|
||||||
if ((CValue2 > 0))
|
if( ( DoorCloseCtrl == control::conductor )
|
||||||
{ // normalne ustawienie pojazdu
|
|| ( DoorCloseCtrl == control::driver )
|
||||||
if ((CValue1 == 1) || (CValue1 == 3))
|
|| ( DoorCloseCtrl == control::mixed ) ) {
|
||||||
DoorLeftOpened = false;
|
// ignore remote command if the door is only operated locally
|
||||||
if ((CValue1 == 2) || (CValue1 == 3))
|
if( CValue2 > 0 ) {
|
||||||
DoorRightOpened = false;
|
// normalne ustawienie pojazdu
|
||||||
}
|
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
|
||||||
else
|
DoorLeftOpened = false;
|
||||||
{ // odwrotne ustawienie pojazdu
|
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
|
||||||
if ((CValue1 == 2) || (CValue1 == 3))
|
DoorRightOpened = false;
|
||||||
DoorLeftOpened = false;
|
}
|
||||||
if ((CValue1 == 1) || (CValue1 == 3))
|
else {
|
||||||
DoorRightOpened = false;
|
// odwrotne ustawienie pojazdu
|
||||||
}
|
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
|
||||||
|
DoorLeftOpened = false;
|
||||||
|
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
|
||||||
|
DoorRightOpened = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||||
}
|
}
|
||||||
else if( Command == "DepartureSignal" ) {
|
else if( Command == "DepartureSignal" ) {
|
||||||
|
|||||||
75
Train.cpp
75
Train.cpp
@@ -375,12 +375,12 @@ bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
MechSpring.Init(250);
|
MechSpring.Init(125.0);
|
||||||
vMechVelocity = Math3D::vector3(0, 0, 0);
|
vMechVelocity = Math3D::vector3(0, 0, 0);
|
||||||
pMechOffset = Math3D::vector3( 0, 0, 0 );
|
pMechOffset = Math3D::vector3( 0, 0, 0 );
|
||||||
fMechSpringX = 1;
|
fMechSpringX = 0.2;
|
||||||
fMechSpringY = 0.5;
|
fMechSpringY = 0.2;
|
||||||
fMechSpringZ = 0.5;
|
fMechSpringZ = 0.1;
|
||||||
fMechMaxSpring = 0.15;
|
fMechMaxSpring = 0.15;
|
||||||
fMechRoll = 0.05;
|
fMechRoll = 0.05;
|
||||||
fMechPitch = 0.1;
|
fMechPitch = 0.1;
|
||||||
@@ -3283,9 +3283,6 @@ void TTrain::OnCommand_doorlocktoggle( TTrain *Train, command_data const &Comman
|
|||||||
|
|
||||||
void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Command ) {
|
void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Command ) {
|
||||||
|
|
||||||
if( Train->mvOccupied->DoorOpenCtrl != 1 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if( Command.action == GLFW_PRESS ) {
|
if( Command.action == GLFW_PRESS ) {
|
||||||
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
|
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
|
||||||
if( false == (
|
if( false == (
|
||||||
@@ -3293,76 +3290,74 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman
|
|||||||
Train->mvOccupied->DoorLeftOpened :
|
Train->mvOccupied->DoorLeftOpened :
|
||||||
Train->mvOccupied->DoorRightOpened ) ) {
|
Train->mvOccupied->DoorRightOpened ) ) {
|
||||||
// open
|
// open
|
||||||
|
if( Train->mvOccupied->DoorOpenCtrl != control::driver ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if( Train->mvOccupied->ActiveCab == 1 ) {
|
if( Train->mvOccupied->ActiveCab == 1 ) {
|
||||||
if( Train->mvOccupied->DoorLeft( true ) ) {
|
Train->mvOccupied->DoorLeft( true );
|
||||||
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// in the rear cab sides are reversed...
|
// in the rear cab sides are reversed...
|
||||||
if( Train->mvOccupied->DoorRight( true ) ) {
|
Train->mvOccupied->DoorRight( true );
|
||||||
// ...but so are the switches
|
|
||||||
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// visual feedback
|
||||||
|
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// close
|
// close
|
||||||
|
if( Train->mvOccupied->DoorCloseCtrl != control::driver ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: move door opening/closing to the update, so the switch animation doesn't hinge on door working
|
||||||
if( Train->mvOccupied->ActiveCab == 1 ) {
|
if( Train->mvOccupied->ActiveCab == 1 ) {
|
||||||
if( Train->mvOccupied->DoorLeft( false ) ) {
|
Train->mvOccupied->DoorLeft( false );
|
||||||
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// in the rear cab sides are reversed...
|
// in the rear cab sides are reversed...
|
||||||
if( Train->mvOccupied->DoorRight( false ) ) {
|
Train->mvOccupied->DoorRight( false );
|
||||||
// ...but so are the switches
|
|
||||||
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// visual feedback
|
||||||
|
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Command ) {
|
void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Command ) {
|
||||||
|
|
||||||
if( Train->mvOccupied->DoorOpenCtrl != 1 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if( Command.action == GLFW_PRESS ) {
|
if( Command.action == GLFW_PRESS ) {
|
||||||
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
|
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
|
||||||
if( false == (
|
if( false == (
|
||||||
Train->mvOccupied->ActiveCab == 1 ?
|
Train->mvOccupied->ActiveCab == 1 ?
|
||||||
Train->mvOccupied->DoorRightOpened :
|
Train->mvOccupied->DoorRightOpened :
|
||||||
Train->mvOccupied->DoorLeftOpened ) ) {
|
Train->mvOccupied->DoorLeftOpened ) ) {
|
||||||
// open
|
// open
|
||||||
|
if( Train->mvOccupied->DoorOpenCtrl != control::driver ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if( Train->mvOccupied->ActiveCab == 1 ) {
|
if( Train->mvOccupied->ActiveCab == 1 ) {
|
||||||
if( Train->mvOccupied->DoorRight( true ) ) {
|
Train->mvOccupied->DoorRight( true );
|
||||||
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// in the rear cab sides are reversed...
|
// in the rear cab sides are reversed...
|
||||||
if( Train->mvOccupied->DoorLeft( true ) ) {
|
Train->mvOccupied->DoorLeft( true );
|
||||||
// ...but so are the switches
|
|
||||||
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// visual feedback
|
||||||
|
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// close
|
// close
|
||||||
|
if( Train->mvOccupied->DoorCloseCtrl != control::driver ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if( Train->mvOccupied->ActiveCab == 1 ) {
|
if( Train->mvOccupied->ActiveCab == 1 ) {
|
||||||
if( Train->mvOccupied->DoorRight( false ) ) {
|
Train->mvOccupied->DoorRight( false );
|
||||||
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// in the rear cab sides are reversed...
|
// in the rear cab sides are reversed...
|
||||||
if( Train->mvOccupied->DoorLeft( false ) ) {
|
Train->mvOccupied->DoorLeft( false );
|
||||||
// ...but so are the switches
|
|
||||||
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// visual feedback
|
||||||
|
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
station.cpp
29
station.cpp
@@ -15,7 +15,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
// exchanges load with consist attached to specified vehicle, operating on specified schedule
|
// exchanges load with consist attached to specified vehicle, operating on specified schedule
|
||||||
double
|
double
|
||||||
basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule ) {
|
basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule, int const Platform ) {
|
||||||
|
|
||||||
auto const firststop { Schedule.StationIndex == 1 };
|
auto const firststop { Schedule.StationIndex == 1 };
|
||||||
auto const laststop { Schedule.StationIndex == Schedule.StationCount };
|
auto const laststop { Schedule.StationIndex == Schedule.StationCount };
|
||||||
@@ -30,7 +30,13 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
|
|||||||
auto const stationsizemodifier { ( trainstop ? 1.0 : 2.0 ) };
|
auto const stationsizemodifier { ( trainstop ? 1.0 : 2.0 ) };
|
||||||
// go through all vehicles and update their load
|
// go through all vehicles and update their load
|
||||||
// NOTE: for the time being we limit ourselves to passenger-carrying cars only
|
// NOTE: for the time being we limit ourselves to passenger-carrying cars only
|
||||||
auto exchangetime { 0.0 };
|
auto exchangetime { 0.f };
|
||||||
|
// platform (1:left, 2:right, 3:both)
|
||||||
|
// with exchange performed on both sides waiting times are halved
|
||||||
|
auto const exchangetimemodifier { (
|
||||||
|
Platform == 3 ?
|
||||||
|
0.5f :
|
||||||
|
1.0f ) };
|
||||||
|
|
||||||
auto *vehicle { First };
|
auto *vehicle { First };
|
||||||
while( vehicle != nullptr ) {
|
while( vehicle != nullptr ) {
|
||||||
@@ -47,24 +53,29 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
|
|||||||
// NOTE: for the time being we're doing simple, random load change calculation
|
// NOTE: for the time being we're doing simple, random load change calculation
|
||||||
// TODO: exchange driven by station parameters and time of the day
|
// TODO: exchange driven by station parameters and time of the day
|
||||||
auto unloadcount = static_cast<int>(
|
auto unloadcount = static_cast<int>(
|
||||||
firststop ? 0 :
|
|
||||||
laststop ? parameters.Load :
|
laststop ? parameters.Load :
|
||||||
std::min(
|
firststop ? 0 :
|
||||||
|
std::min<float>(
|
||||||
parameters.Load,
|
parameters.Load,
|
||||||
Random( parameters.MaxLoad * 0.10 * stationsizemodifier ) ) );
|
Random( parameters.MaxLoad * 0.10 * stationsizemodifier ) ) );
|
||||||
auto loadcount = static_cast<int>(
|
auto loadcount = static_cast<int>(
|
||||||
laststop ?
|
laststop ?
|
||||||
0 :
|
0 :
|
||||||
Random( parameters.MaxLoad * 0.15 * stationsizemodifier ) );
|
Random( parameters.MaxLoad * 0.15f * stationsizemodifier ) );
|
||||||
if( true == firststop ) {
|
if( true == firststop ) {
|
||||||
// slightly larger group at the initial station
|
// slightly larger group at the initial station
|
||||||
loadcount *= 2;
|
loadcount *= 2;
|
||||||
}
|
}
|
||||||
parameters.Load = std::min( parameters.MaxLoad, parameters.Load - unloadcount + loadcount );
|
|
||||||
vehicle->LoadUpdate();
|
|
||||||
vehicle->update_load_visibility();
|
|
||||||
|
|
||||||
exchangetime = std::max( exchangetime, unloadcount / parameters.UnLoadSpeed + loadcount / parameters.LoadSpeed);
|
if( ( unloadcount > 0 ) || ( loadcount > 0 ) ) {
|
||||||
|
|
||||||
|
vehicle->LoadExchange( unloadcount, loadcount, Platform );
|
||||||
|
/*
|
||||||
|
vehicle->LoadUpdate();
|
||||||
|
vehicle->update_load_visibility();
|
||||||
|
*/
|
||||||
|
exchangetime = std::max( exchangetime, exchangetimemodifier * ( unloadcount / parameters.UnLoadSpeed + loadcount / parameters.LoadSpeed ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
vehicle = vehicle->Next();
|
vehicle = vehicle->Next();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,5 +18,5 @@ public:
|
|||||||
// methods
|
// methods
|
||||||
// exchanges load with consist attached to specified vehicle, operating on specified schedule; returns: time needed for exchange, in seconds
|
// exchanges load with consist attached to specified vehicle, operating on specified schedule; returns: time needed for exchange, in seconds
|
||||||
double
|
double
|
||||||
update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule );
|
update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule, int const Platform );
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user