mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01: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,
|
||||
// przyjąć odległość fMinProximityDist
|
||||
{ // jeśli się zatrzymał przy W4, albo stał w momencie zobaczenia W4
|
||||
if (!AIControllFlag) // AI tylko sobie otwiera drzwi
|
||||
iDrivigFlags &= ~moveStopCloser; // w razie przełączenia na AI ma
|
||||
// nie podciągać do W4, gdy
|
||||
// użytkownik zatrzymał za daleko
|
||||
if ((iDrivigFlags & moveDoorOpened) == 0)
|
||||
{ // drzwi otwierać jednorazowo
|
||||
if( !AIControllFlag ) {
|
||||
// w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko
|
||||
iDrivigFlags &= ~moveStopCloser;
|
||||
}
|
||||
|
||||
if( ( iDrivigFlags & moveDoorOpened ) == 0 ) {
|
||||
// drzwi otwierać jednorazowo
|
||||
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
|
||||
if (mvOccupied->DoorOpenCtrl == 1) //(mvOccupied->TrainType==dt_EZT)
|
||||
{ // 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();
|
||||
}
|
||||
}
|
||||
Doors( true, static_cast<int>( std::floor( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ) ) % 10 );
|
||||
}
|
||||
if (TrainParams->UpdateMTable( simulation::Time, asNextStop) ) {
|
||||
// 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 );
|
||||
}
|
||||
// perform loading/unloading
|
||||
auto const exchangetime { simulation::Station.update_load( pVehicles[ 0 ], *TrainParams ) };
|
||||
// TBD: adjust time to load exchange size
|
||||
if( fStopTime > -55 ) {
|
||||
// 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
|
||||
auto const platformside = static_cast<int>( std::floor( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ) ) % 10;
|
||||
auto const exchangetime = simulation::Station.update_load( pVehicles[ 0 ], *TrainParams, platformside );
|
||||
WaitingSet( std::max( -fStopTime, exchangetime ) ); // na końcu rozkładu się ustawia 60s i tu by było skrócenie
|
||||
|
||||
if( TrainParams->CheckTrainLatency() < 0.0 ) {
|
||||
// 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)
|
||||
+ " next " + asNextStop); // informacja
|
||||
#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 ) {
|
||||
// nie podjeżdżać do semafora, jeśli droga nie jest wolna
|
||||
iDrivigFlags |= moveStopHere;
|
||||
@@ -2401,7 +2353,7 @@ bool TController::ReleaseEngine()
|
||||
ReactionTime = PrepareTime;
|
||||
if (AIControllFlag)
|
||||
{ // jeśli steruje komputer
|
||||
if (mvOccupied->DoorOpenCtrl == 1)
|
||||
if (mvOccupied->DoorCloseCtrl == control::driver)
|
||||
{ // zamykanie drzwi
|
||||
if (mvOccupied->DoorLeftOpened)
|
||||
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
|
||||
if (what)
|
||||
{ // otwarcie
|
||||
}
|
||||
else
|
||||
{ // zamykanie
|
||||
if (mvOccupied->DoorOpenCtrl == 1)
|
||||
{ // jeśli drzwi sterowane z kabiny
|
||||
if( AIControllFlag ) {
|
||||
if( mvOccupied->DoorLeftOpened || mvOccupied->DoorRightOpened ) {
|
||||
// AI zamyka drzwi przed odjazdem
|
||||
if( ( true == mvOccupied->DoorClosureWarning )
|
||||
&& ( false == mvOccupied->DepartureSignal )
|
||||
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
||||
mvOccupied->signal_departure( true ); // załącenie bzyczka
|
||||
fActionTime = -3.0 - 0.1 * Random( 10 ); // 3-4 second wait
|
||||
}
|
||||
if( fActionTime > -0.5 ) {
|
||||
// Ra: trzeba by ustawić jakiś czas oczekiwania na zamknięcie się drzwi
|
||||
mvOccupied->DoorLeft( false ); // zamykanie drzwi
|
||||
mvOccupied->DoorRight( false );
|
||||
iDrivigFlags &= ~moveDoorOpened;
|
||||
// 1.5-2.5 sec wait, +potentially 0.5 remaining
|
||||
fActionTime = -1.5 - 0.1 * Random( 10 );
|
||||
}
|
||||
// otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT
|
||||
void TController::Doors( bool const Open, int const Side ) {
|
||||
|
||||
if( true == Open ) {
|
||||
// otwieranie drzwi
|
||||
// otwieranie drzwi w składach wagonowych - docelowo wysyłać komendę zezwolenia na otwarcie drzwi
|
||||
// tu będzie jeszcze długość peronu zaokrąglona do 10m (20m bezpieczniej, bo nie modyfikuje bitu 1)
|
||||
// p7=platform side (1:left, 2:right, 3:both)
|
||||
auto *vehicle = pVehicles[0]; // pojazd na czole składu
|
||||
while( vehicle != nullptr ) {
|
||||
// wagony muszą mieć baterię załączoną do otwarcia drzwi...
|
||||
vehicle->MoverParameters->BatterySwitch( true );
|
||||
// otwieranie drzwi w pojazdach - flaga zezwolenia była by lepsza
|
||||
if( vehicle->MoverParameters->DoorOpenCtrl != control::passenger ) {
|
||||
// if the door are controlled by the driver, we let the user operate them...
|
||||
if( true == AIControllFlag ) {
|
||||
// ...unless this user is an ai
|
||||
// p7=platform side (1:left, 2:right, 3:both)
|
||||
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
|
||||
auto const lewe = ( vehicle->DirectionGet() > 0 ) ? 1 : 2;
|
||||
auto const prawe = 3 - lewe;
|
||||
if( Side & lewe )
|
||||
vehicle->MoverParameters->DoorLeft( true, range::local );
|
||||
if( Side & prawe )
|
||||
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
|
||||
TDynamicObject *p = pVehicles[0]; // pojazd na czole składu
|
||||
while (p)
|
||||
{ // zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
|
||||
p->MoverParameters->DoorLeft(false); // w lokomotywie można by nie zamykać...
|
||||
p->MoverParameters->DoorRight(false);
|
||||
p = p->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
|
||||
}
|
||||
else {
|
||||
// zamykanie
|
||||
if( AIControllFlag ) {
|
||||
if( ( true == mvOccupied->DoorClosureWarning )
|
||||
&& ( false == mvOccupied->DepartureSignal )
|
||||
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
|
||||
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
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void TController::RecognizeCommand()
|
||||
{ // 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
|
||||
if( ( false == AIControllFlag )
|
||||
&& ( iDrivigFlags & moveDoorOpened )
|
||||
&& ( mvOccupied->DoorOpenCtrl != 1 )
|
||||
&& ( mvOccupied->DoorCloseCtrl != control::driver )
|
||||
&& ( mvControlling->MainCtrlPos > 0 ) ) {
|
||||
Doors( false );
|
||||
}
|
||||
@@ -4098,7 +4066,10 @@ TController::UpdateSituation(double dt) {
|
||||
iDrivigFlags |= movePress; // następnie będzie dociskanie
|
||||
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na przeciwny (dociskanie)
|
||||
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
|
||||
*/
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -4247,8 +4218,8 @@ TController::UpdateSituation(double dt) {
|
||||
&& ( false == TestFlag( iDrivigFlags, movePress ) )
|
||||
&& ( iCoupler == 0 )
|
||||
// && ( mvOccupied->Vel > 0.0 )
|
||||
&& ( pVehicle->PrevConnected == nullptr )
|
||||
&& ( pVehicle->NextConnected == nullptr ) ) {
|
||||
&& ( pVehicle->MoverParameters->Couplers[ side::front ].CouplingFlag == coupling::faux )
|
||||
&& ( pVehicle->MoverParameters->Couplers[ side::rear ].CouplingFlag == coupling::faux ) ) {
|
||||
SetVelocity(0, 0, stopJoin); // 1. faza odczepiania: zatrzymanie
|
||||
// WriteLog("Zatrzymanie w celu odczepienia");
|
||||
AccPreferred = std::min( 0.0, AccPreferred );
|
||||
@@ -5040,7 +5011,7 @@ TController::UpdateSituation(double dt) {
|
||||
fMinProximityDist : // cars are allowed to move within min proximity distance
|
||||
fMaxProximityDist ) ? // other vehicle types keep wider margin
|
||||
true :
|
||||
vel < VelNext ) ) {
|
||||
( vel + 1.0 ) < VelNext ) ) {
|
||||
// to można przyspieszyć
|
||||
IncSpeed();
|
||||
}
|
||||
|
||||
2
Driver.h
2
Driver.h
@@ -303,7 +303,7 @@ private:
|
||||
bool IncSpeed();
|
||||
bool DecSpeed(bool force = false);
|
||||
void SpeedSet();
|
||||
void Doors(bool what);
|
||||
void Doors(bool const Open, int const Side = 0);
|
||||
void RecognizeCommand(); // odczytuje komende przekazana lokomotywie
|
||||
void Activation(); // umieszczenie obsady w odpowiednim członie
|
||||
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
|
||||
else if( ( ActPar.size() >= 3 )
|
||||
&& ( ActPar.substr( 0, 2 ) == "WF" ) ) {
|
||||
// wheel flat
|
||||
// TODO: convert this whole mess to something more elegant one day
|
||||
ActPar.erase( 0, 2 );
|
||||
&& ( ActPar[ 0 ] == 'W' ) ) {
|
||||
// wheel
|
||||
ActPar.erase( 0, 1 );
|
||||
|
||||
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 randomflatchance { 100 };
|
||||
auto flatchance { 100 };
|
||||
|
||||
while( false == ActPar.empty() ) {
|
||||
if( ActPar[ 0 ] == 'R' ) {
|
||||
// random flat size
|
||||
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 );
|
||||
}
|
||||
else if( ActPar[ 0 ] == 'P' ) {
|
||||
// random flat probability
|
||||
auto const indexstart { 1 };
|
||||
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
|
||||
randomflatchance = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
|
||||
ActPar.erase( 0, indexend );
|
||||
// TODO: convert this whole copy and paste mess to something more elegant one day
|
||||
switch( ActPar[ 0 ] ) {
|
||||
case 'F': {
|
||||
// fixed flat size
|
||||
auto const indexstart { 1 };
|
||||
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
|
||||
fixedflatsize = std::atoi( ActPar.substr( indexstart, indexend ).c_str() );
|
||||
ActPar.erase( 0, indexend );
|
||||
break;
|
||||
}
|
||||
case 'R': {
|
||||
// random flat size
|
||||
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 );
|
||||
}
|
||||
}
|
||||
@@ -2476,6 +2488,87 @@ bool TDynamicObject::UpdateForce(double dt, double dt1, bool FullVer)
|
||||
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() {
|
||||
// przeładowanie modelu ładunku
|
||||
// Ra: nie próbujemy wczytywać modeli miliony razy podczas renderowania!!!
|
||||
@@ -2494,7 +2587,11 @@ void TDynamicObject::LoadUpdate() {
|
||||
}
|
||||
if( mdLoad == nullptr ) {
|
||||
// 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 ) {
|
||||
// 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
|
||||
TDynamicObject::update_load_visibility() {
|
||||
|
||||
/*
|
||||
if( Random() < 0.25 ) {
|
||||
shuffle_load_sections();
|
||||
}
|
||||
|
||||
*/
|
||||
auto loadpercentage { (
|
||||
MoverParameters->MaxLoad == 0.0 ?
|
||||
0.0 :
|
||||
@@ -3521,6 +3618,8 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
}
|
||||
MoverParameters->DerailReason = 0; //żeby tylko raz
|
||||
}
|
||||
|
||||
update_exchange( dt );
|
||||
if (MoverParameters->LoadStatus)
|
||||
LoadUpdate(); // zmiana modelu ładunku
|
||||
|
||||
@@ -3561,6 +3660,7 @@ bool TDynamicObject::FastUpdate(double dt)
|
||||
// ResetdMoveLen();
|
||||
FastMove(dDOMoveLen);
|
||||
|
||||
update_exchange( dt );
|
||||
if (MoverParameters->LoadStatus)
|
||||
LoadUpdate(); // zmiana modelu ładunku
|
||||
return true; // Ra: chyba tak?
|
||||
@@ -3757,6 +3857,19 @@ void TDynamicObject::RenderSounds() {
|
||||
}
|
||||
|
||||
// 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
|
||||
if( MoverParameters->DoorClosureWarning ) {
|
||||
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:" ) {
|
||||
sSand.deserialize( parser, sound_type::multipart, sound_parameters::range );
|
||||
sSand.owner( this );
|
||||
|
||||
20
DynObj.h
20
DynObj.h
@@ -264,6 +264,13 @@ private:
|
||||
|
||||
private:
|
||||
// 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 {
|
||||
sound_source dsbCouplerAttach { 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 };
|
||||
};
|
||||
|
||||
struct exchange_sounds {
|
||||
sound_source loading { sound_placement::general };
|
||||
sound_source unloading { sound_placement::general };
|
||||
};
|
||||
|
||||
struct axle_sounds {
|
||||
double distance; // distance to rail joint
|
||||
double offset; // axle offset from centre of the vehicle
|
||||
@@ -318,6 +330,8 @@ private:
|
||||
void ABuBogies();
|
||||
void ABuModelRoll();
|
||||
void TurnOff();
|
||||
// update state of load exchange operation
|
||||
void update_exchange( double const Deltatime );
|
||||
|
||||
// members
|
||||
TButton btCoupler1; // sprzegi
|
||||
@@ -385,6 +399,9 @@ private:
|
||||
sound_source rscurve { sound_placement::external, EU07_SOUND_RUNNINGNOISECUTOFFRANGE }; // youBy
|
||||
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;
|
||||
|
||||
bool renderme; // yB - czy renderowac
|
||||
@@ -466,6 +483,8 @@ private:
|
||||
void create_controller( std::string const Type, bool const Trainset );
|
||||
void AttachPrev(TDynamicObject *Object, int iType = 1);
|
||||
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 update_load_sections();
|
||||
void update_load_visibility();
|
||||
@@ -553,6 +572,7 @@ private:
|
||||
void DestinationSet(std::string to, std::string numer);
|
||||
std::string TextureTest(std::string const &name);
|
||||
void OverheadTrack(float o);
|
||||
|
||||
double MED[9][8]; // lista zmiennych do debugowania hamulca ED
|
||||
static std::string const MED_labels[ 8 ];
|
||||
};
|
||||
|
||||
@@ -153,7 +153,8 @@ enum coupling {
|
||||
gangway = 0x10,
|
||||
mainhose = 0x20,
|
||||
heating = 0x40,
|
||||
permanent = 0x80
|
||||
permanent = 0x80,
|
||||
uic = 0x100
|
||||
};
|
||||
// possible effect ranges for control commands; exclusive
|
||||
enum range {
|
||||
@@ -176,6 +177,15 @@ enum light {
|
||||
redmarker_right = 0x20,
|
||||
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*/
|
||||
static int const dbrake_none = 0;
|
||||
static int const dbrake_passive = 1;
|
||||
@@ -307,7 +317,7 @@ struct TCommand
|
||||
std::string Command; /*komenda*/
|
||||
double Value1 = 0.0; /*argumenty komendy*/
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -821,10 +831,10 @@ public:
|
||||
static std::vector<std::string> const eimc_labels;
|
||||
double InverterFrequency { 0.0 }; // current frequency of power inverters
|
||||
/*-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*/
|
||||
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)*/
|
||||
double DoorStayOpen = 0.0; /*jak dlugo otwarte w przypadku DoorCloseCtrl=2*/
|
||||
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 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
|
||||
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
|
||||
double ConverterStartDelayTimer{ 0.0 }; // helper, for tracking whether converter start delay passed
|
||||
bool ConverterAllow = false; /*zezwolenie na prace przetwornicy NBMX*/
|
||||
@@ -1024,7 +1034,7 @@ public:
|
||||
double eAngle = M_PI * 0.5;
|
||||
|
||||
/*-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*/
|
||||
int LoadStatus = 0; //+1=trwa rozladunek,+2=trwa zaladunek,+4=zakończono,0=zaktualizowany model
|
||||
double LastLoadChangeTime = 0.0; //raz (roz)ładowania
|
||||
@@ -1220,8 +1230,8 @@ public:
|
||||
|
||||
/* funckje dla wagonow*/
|
||||
bool LoadingDone(double LSpeed, std::string LoadInit);
|
||||
bool DoorLeft(bool State); //obsluga drzwi lewych
|
||||
bool DoorRight(bool State); //obsluga drzwi prawych
|
||||
bool DoorLeft(bool State, int const Notify = range::consist ); //obsluga drzwi lewych
|
||||
bool DoorRight(bool State, int const Notify = range::consist ); //obsluga drzwi prawych
|
||||
bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi
|
||||
bool signal_departure( bool const State, int const Notify = range::consist ); // toggles departure warning
|
||||
|
||||
|
||||
@@ -6006,65 +6006,80 @@ bool TMoverParameters::DoorBlockedFlag(void)
|
||||
// Q: 20160713
|
||||
// Otwiera / zamyka lewe drzwi
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::DoorLeft(bool State)
|
||||
{
|
||||
bool DL = false;
|
||||
if ((DoorLeftOpened != State) && (DoorBlockedFlag() == false) && (Battery == true))
|
||||
{
|
||||
DL = true;
|
||||
DoorLeftOpened = State;
|
||||
if (State == true)
|
||||
{
|
||||
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);
|
||||
}
|
||||
// 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 TMoverParameters::DoorLeft(bool State, int const Notify ) {
|
||||
|
||||
if( DoorLeftOpened == 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;
|
||||
}
|
||||
else
|
||||
DL = false;
|
||||
return DL;
|
||||
|
||||
bool result { false };
|
||||
|
||||
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
|
||||
// Otwiera / zamyka prawe drzwi
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::DoorRight(bool State)
|
||||
{
|
||||
bool DR = false;
|
||||
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;
|
||||
// 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 TMoverParameters::DoorRight(bool State, int const Notify ) {
|
||||
|
||||
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
|
||||
@@ -6086,8 +6101,8 @@ TMoverParameters::signal_departure( bool const State, int const Notify ) {
|
||||
0 ),
|
||||
CabNo,
|
||||
( Notify == range::unit ?
|
||||
ctrain_controll | ctrain_depot :
|
||||
ctrain_controll ) );
|
||||
coupling::control | coupling::permanent :
|
||||
coupling::control ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -7184,8 +7199,8 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) {
|
||||
auto lookup = compressorpowers.find( extract_value( "CompressorPower", line ) );
|
||||
CompressorPower =
|
||||
lookup != compressorpowers.end() ?
|
||||
lookup->second :
|
||||
1;
|
||||
lookup->second :
|
||||
1;
|
||||
}
|
||||
|
||||
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 ) {
|
||||
|
||||
DoorOpenCtrl = 0;
|
||||
std::string openctrl; extract_value( openctrl, "OpenCtrl", line, "" );
|
||||
if( openctrl == "DriverCtrl" ) { DoorOpenCtrl = 1; }
|
||||
|
||||
DoorCloseCtrl = 0;
|
||||
std::string closectrl; extract_value( closectrl, "CloseCtrl", line, "" );
|
||||
if( closectrl == "DriverCtrl" ) { DoorCloseCtrl = 1; }
|
||||
else if( closectrl == "AutomaticCtrl" ) { DoorCloseCtrl = 2; }
|
||||
|
||||
if( DoorCloseCtrl == 2 ) { extract_value( DoorStayOpen, "DoorStayOpen", line, "" ); }
|
||||
std::map<std::string, int> doorcontrols {
|
||||
{ "Passenger", control::passenger },
|
||||
{ "AutomaticCtrl", control::autonomous },
|
||||
{ "DriverCtrl", control::driver },
|
||||
{ "Conductor", control::conductor },
|
||||
{ "Mixed", control::mixed }
|
||||
};
|
||||
// opening method
|
||||
{
|
||||
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( DoorCloseSpeed, "CloseSpeed", line, "" );
|
||||
@@ -8315,6 +8345,7 @@ bool TMoverParameters::SendCtrlToNext( std::string const CtrlCommand, double con
|
||||
// musi być wybrana niezerowa kabina
|
||||
if( ( Couplers[ d ].Connected != nullptr )
|
||||
&& ( TestFlag( Couplers[ d ].CouplingFlag, Couplertype ) ) ) {
|
||||
|
||||
if( Couplers[ d ].ConnectedNr != d ) {
|
||||
// jeśli ten nastpęny jest zgodny z aktualnym
|
||||
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*/
|
||||
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
|
||||
if ((CValue2 > 0))
|
||||
{ // normalne ustawienie pojazdu
|
||||
if ((CValue1 == 1) || (CValue1 == 3))
|
||||
DoorLeftOpened = true;
|
||||
if ((CValue1 == 2) || (CValue1 == 3))
|
||||
DoorRightOpened = true;
|
||||
}
|
||||
else
|
||||
{ // odwrotne ustawienie pojazdu
|
||||
if ((CValue1 == 2) || (CValue1 == 3))
|
||||
DoorLeftOpened = true;
|
||||
if ((CValue1 == 1) || (CValue1 == 3))
|
||||
DoorRightOpened = true;
|
||||
}
|
||||
if( ( DoorCloseCtrl == control::conductor )
|
||||
|| ( DoorCloseCtrl == control::driver )
|
||||
|| ( DoorCloseCtrl == control::mixed ) ) {
|
||||
// ignore remote command if the door is only operated locally
|
||||
if( CValue2 > 0 ) {
|
||||
// normalne ustawienie pojazdu
|
||||
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
|
||||
DoorLeftOpened = true;
|
||||
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
|
||||
DoorRightOpened = true;
|
||||
}
|
||||
else {
|
||||
// odwrotne ustawienie pojazdu
|
||||
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
|
||||
DoorLeftOpened = true;
|
||||
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
|
||||
DoorRightOpened = true;
|
||||
}
|
||||
}
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
else if (Command == "DoorClose") /*NBMX*/
|
||||
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
|
||||
if ((CValue2 > 0))
|
||||
{ // normalne ustawienie pojazdu
|
||||
if ((CValue1 == 1) || (CValue1 == 3))
|
||||
DoorLeftOpened = false;
|
||||
if ((CValue1 == 2) || (CValue1 == 3))
|
||||
DoorRightOpened = false;
|
||||
}
|
||||
else
|
||||
{ // odwrotne ustawienie pojazdu
|
||||
if ((CValue1 == 2) || (CValue1 == 3))
|
||||
DoorLeftOpened = false;
|
||||
if ((CValue1 == 1) || (CValue1 == 3))
|
||||
DoorRightOpened = false;
|
||||
}
|
||||
if( ( DoorCloseCtrl == control::conductor )
|
||||
|| ( DoorCloseCtrl == control::driver )
|
||||
|| ( DoorCloseCtrl == control::mixed ) ) {
|
||||
// ignore remote command if the door is only operated locally
|
||||
if( CValue2 > 0 ) {
|
||||
// normalne ustawienie pojazdu
|
||||
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
|
||||
DoorLeftOpened = false;
|
||||
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
|
||||
DoorRightOpened = false;
|
||||
}
|
||||
else {
|
||||
// odwrotne ustawienie pojazdu
|
||||
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
|
||||
DoorLeftOpened = false;
|
||||
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
|
||||
DoorRightOpened = false;
|
||||
}
|
||||
}
|
||||
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
|
||||
}
|
||||
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);
|
||||
pMechOffset = Math3D::vector3( 0, 0, 0 );
|
||||
fMechSpringX = 1;
|
||||
fMechSpringY = 0.5;
|
||||
fMechSpringZ = 0.5;
|
||||
fMechSpringX = 0.2;
|
||||
fMechSpringY = 0.2;
|
||||
fMechSpringZ = 0.1;
|
||||
fMechMaxSpring = 0.15;
|
||||
fMechRoll = 0.05;
|
||||
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 ) {
|
||||
|
||||
if( Train->mvOccupied->DoorOpenCtrl != 1 ) {
|
||||
return;
|
||||
}
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
|
||||
if( false == (
|
||||
@@ -3293,76 +3290,74 @@ void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Comman
|
||||
Train->mvOccupied->DoorLeftOpened :
|
||||
Train->mvOccupied->DoorRightOpened ) ) {
|
||||
// open
|
||||
if( Train->mvOccupied->DoorOpenCtrl != control::driver ) {
|
||||
return;
|
||||
}
|
||||
if( Train->mvOccupied->ActiveCab == 1 ) {
|
||||
if( Train->mvOccupied->DoorLeft( true ) ) {
|
||||
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
Train->mvOccupied->DoorLeft( true );
|
||||
}
|
||||
else {
|
||||
// in the rear cab sides are reversed...
|
||||
if( Train->mvOccupied->DoorRight( true ) ) {
|
||||
// ...but so are the switches
|
||||
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
Train->mvOccupied->DoorRight( true );
|
||||
}
|
||||
// visual feedback
|
||||
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
else {
|
||||
// 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->DoorLeft( false ) ) {
|
||||
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
}
|
||||
Train->mvOccupied->DoorLeft( false );
|
||||
}
|
||||
else {
|
||||
// in the rear cab sides are reversed...
|
||||
if( Train->mvOccupied->DoorRight( false ) ) {
|
||||
// ...but so are the switches
|
||||
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
}
|
||||
Train->mvOccupied->DoorRight( false );
|
||||
}
|
||||
// visual feedback
|
||||
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Command ) {
|
||||
|
||||
if( Train->mvOccupied->DoorOpenCtrl != 1 ) {
|
||||
return;
|
||||
}
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
|
||||
if( false == (
|
||||
Train->mvOccupied->ActiveCab == 1 ?
|
||||
Train->mvOccupied->DoorRightOpened :
|
||||
Train->mvOccupied->DoorLeftOpened ) ) {
|
||||
Train->mvOccupied->DoorRightOpened :
|
||||
Train->mvOccupied->DoorLeftOpened ) ) {
|
||||
// open
|
||||
if( Train->mvOccupied->DoorOpenCtrl != control::driver ) {
|
||||
return;
|
||||
}
|
||||
if( Train->mvOccupied->ActiveCab == 1 ) {
|
||||
if( Train->mvOccupied->DoorRight( true ) ) {
|
||||
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
Train->mvOccupied->DoorRight( true );
|
||||
}
|
||||
else {
|
||||
// in the rear cab sides are reversed...
|
||||
if( Train->mvOccupied->DoorLeft( true ) ) {
|
||||
// ...but so are the switches
|
||||
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
Train->mvOccupied->DoorLeft( true );
|
||||
}
|
||||
// visual feedback
|
||||
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
else {
|
||||
// close
|
||||
if( Train->mvOccupied->DoorCloseCtrl != control::driver ) {
|
||||
return;
|
||||
}
|
||||
if( Train->mvOccupied->ActiveCab == 1 ) {
|
||||
if( Train->mvOccupied->DoorRight( false ) ) {
|
||||
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
}
|
||||
Train->mvOccupied->DoorRight( false );
|
||||
}
|
||||
else {
|
||||
// in the rear cab sides are reversed...
|
||||
if( Train->mvOccupied->DoorLeft( false ) ) {
|
||||
// ...but so are the switches
|
||||
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
||||
}
|
||||
Train->mvOccupied->DoorLeft( false );
|
||||
}
|
||||
// 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
|
||||
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 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 ) };
|
||||
// go through all vehicles and update their load
|
||||
// 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 };
|
||||
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
|
||||
// TODO: exchange driven by station parameters and time of the day
|
||||
auto unloadcount = static_cast<int>(
|
||||
firststop ? 0 :
|
||||
laststop ? parameters.Load :
|
||||
std::min(
|
||||
firststop ? 0 :
|
||||
std::min<float>(
|
||||
parameters.Load,
|
||||
Random( parameters.MaxLoad * 0.10 * stationsizemodifier ) ) );
|
||||
auto loadcount = static_cast<int>(
|
||||
laststop ?
|
||||
0 :
|
||||
Random( parameters.MaxLoad * 0.15 * stationsizemodifier ) );
|
||||
Random( parameters.MaxLoad * 0.15f * stationsizemodifier ) );
|
||||
if( true == firststop ) {
|
||||
// slightly larger group at the initial station
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -18,5 +18,5 @@ public:
|
||||
// methods
|
||||
// exchanges load with consist attached to specified vehicle, operating on specified schedule; returns: time needed for exchange, in seconds
|
||||
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