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

build 190129. door control system enhancements, minor bug fixes

This commit is contained in:
tmj-fstate
2019-01-29 16:29:37 +01:00
parent 753cf7ee5d
commit e71db46de0
20 changed files with 1225 additions and 1000 deletions

View File

@@ -1009,21 +1009,6 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
continue; continue;
} }
} }
else {
// sitting at passenger stop
if( fStopTime < 0 ) {
// verify progress of load exchange
auto exchangetime { 0.f };
auto *vehicle { pVehicles[ 0 ] };
while( vehicle != nullptr ) {
exchangetime = std::max( exchangetime, vehicle->LoadExchangeTime() );
vehicle = vehicle->Next();
}
if( exchangetime > 0 ) {
WaitingSet( exchangetime );
}
}
}
if (OrderCurrentGet() & Shunt) { if (OrderCurrentGet() & Shunt) {
OrderNext(Obey_train); // uruchomić jazdę pociągową OrderNext(Obey_train); // uruchomić jazdę pociągową
@@ -2089,8 +2074,8 @@ bool TController::CheckVehicles(TOrders user)
{ {
// HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi... // HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi...
if( ( p != pVehicle ) if( ( p != pVehicle )
&& ( ( p->MoverParameters->Couplers[ side::front ].CouplingFlag & ( coupling::control | coupling::permanent ) ) == 0 ) && ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control | coupling::permanent ) ) == 0 )
&& ( ( p->MoverParameters->Couplers[ side::rear ].CouplingFlag & ( coupling::control | coupling::permanent ) ) == 0 ) ) { && ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control | coupling::permanent ) ) == 0 ) ) {
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly // NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
p->MoverParameters->BatterySwitch( true ); p->MoverParameters->BatterySwitch( true );
} }
@@ -2114,12 +2099,12 @@ bool TController::CheckVehicles(TOrders user)
// jeśli jazda pociągowa // jeśli jazda pociągowa
// światła pociągowe (Pc1) i końcówki (Pc5) // światła pociągowe (Pc1) i końcówki (Pc5)
auto const frontlights { ( auto const frontlights { (
( m_lighthints[ side::front ] != -1 ) ? ( m_lighthints[ end::front ] != -1 ) ?
m_lighthints[ side::front ] : m_lighthints[ end::front ] :
light::headlight_left | light::headlight_right | light::headlight_upper ) }; light::headlight_left | light::headlight_right | light::headlight_upper ) };
auto const rearlights { ( auto const rearlights { (
( m_lighthints[ side::rear ] != -1 ) ? ( m_lighthints[ end::rear ] != -1 ) ?
m_lighthints[ side::rear ] : m_lighthints[ end::rear ] :
light::redmarker_left | light::redmarker_right | light::rearendsignals ) }; light::redmarker_left | light::redmarker_right | light::rearendsignals ) };
Lights( Lights(
frontlights, frontlights,
@@ -2156,9 +2141,12 @@ bool TController::CheckVehicles(TOrders user)
Lights( 0, light::headlight_right ); Lights( 0, light::headlight_right );
} }
} }
// nastawianie hamulca do jazdy pociągowej
if( OrderCurrentGet() & ( Obey_train | Shunt ) ) { if( OrderCurrentGet() & ( Obey_train | Shunt ) ) {
// nastawianie hamulca do jazdy pociągowej
AutoRewident(); AutoRewident();
// enable door locks
mvOccupied->LockDoors( true );
} }
} }
else { // gdy człowiek i gdy nastąpiło połącznie albo rozłączenie else { // gdy człowiek i gdy nastąpiło połącznie albo rozłączenie
@@ -2473,10 +2461,10 @@ bool TController::PrepareEngine()
// w EN57 sprężarka w ra jest zasilana z silnikowego // w EN57 sprężarka w ra jest zasilana z silnikowego
mvOccupied->CompressorSwitch( true ); mvOccupied->CompressorSwitch( true );
// enable motor blowers // enable motor blowers
mvOccupied->MotorBlowersSwitchOff( false, side::front ); mvOccupied->MotorBlowersSwitchOff( false, end::front );
mvOccupied->MotorBlowersSwitch( true, side::front ); mvOccupied->MotorBlowersSwitch( true, end::front );
mvOccupied->MotorBlowersSwitchOff( false, side::rear ); mvOccupied->MotorBlowersSwitchOff( false, end::rear );
mvOccupied->MotorBlowersSwitch( true, side::rear ); mvOccupied->MotorBlowersSwitch( true, end::rear );
} }
} }
else else
@@ -2558,15 +2546,9 @@ bool TController::ReleaseEngine() {
while( ( mvOccupied->ActiveDir > 0 ) && ( mvOccupied->DirectionBackward() ) ) { ; } while( ( mvOccupied->ActiveDir > 0 ) && ( mvOccupied->DirectionBackward() ) ) { ; }
while( ( mvOccupied->ActiveDir < 0 ) && ( mvOccupied->DirectionForward() ) ) { ; } while( ( mvOccupied->ActiveDir < 0 ) && ( mvOccupied->DirectionForward() ) ) { ; }
if( mvOccupied->DoorCloseCtrl == control_t::driver ) {
// zamykanie drzwi // zamykanie drzwi
if( mvOccupied->DoorLeftOpened ) { mvOccupied->OperateDoors( side::right, false );
mvOccupied->DoorLeft( false ); mvOccupied->OperateDoors( side::left, false );
}
if( mvOccupied->DoorRightOpened ) {
mvOccupied->DoorRight( false );
}
}
if( true == mvControlling->Mains ) { if( true == mvControlling->Mains ) {
mvControlling->CompressorSwitch( false ); mvControlling->CompressorSwitch( false );
@@ -3238,36 +3220,40 @@ void TController::Doors( bool const Open, int const Side ) {
// otwieranie drzwi // otwieranie drzwi
// otwieranie drzwi w składach wagonowych - docelowo wysyłać komendę zezwolenia na otwarcie 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) // tu będzie jeszcze długość peronu zaokrąglona do 10m (20m bezpieczniej, bo nie modyfikuje bitu 1)
auto *vehicle = pVehicles[0]; // pojazd na czole składu auto const lewe = ( pVehicle->DirectionGet() > 0 ) ? 1 : 2;
while( vehicle != nullptr ) {
// otwieranie drzwi w pojazdach - flaga zezwolenia była by lepsza
if( vehicle->MoverParameters->DoorOpenCtrl != control_t::passenger ) {
// if the door are controlled by the driver, we let the user operate them...
if( true == AIControllFlag ) {
// ...unless this user is an ai
// Side=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; auto const prawe = 3 - lewe;
if( Side & lewe )
vehicle->MoverParameters->DoorLeft( true, range_t::local ); if( ( pVehicle->MoverParameters->Doors.open_permit == false )
&& ( true == AIControllFlag ) ) {
// grant door control permission if it's not automatic
// TBD: stricter requirements?
if( Side & prawe ) if( Side & prawe )
vehicle->MoverParameters->DoorRight( true, range_t::local ); pVehicle->MoverParameters->PermitDoors( side::right );
if( Side & lewe )
pVehicle->MoverParameters->PermitDoors( side::left );
} }
}
// pojazd podłączony z tyłu (patrząc od czoła) if( ( pVehicle->MoverParameters->Doors.open_control == control_t::conductor )
vehicle = vehicle->Next(); || ( ( true == AIControllFlag )
&& ( ( pVehicle->MoverParameters->Doors.open_control == control_t::driver )
|| ( pVehicle->MoverParameters->Doors.open_control == control_t::mixed ) ) ) ) {
// if the door can be operated by the driver we let the user operate them unless this user is an ai
// the train conductor, if present, handles door operation also for human-driven trains
if( Side & prawe )
pVehicle->MoverParameters->OperateDoors( side::right, true );
if( Side & lewe )
pVehicle->MoverParameters->OperateDoors( side::left, true );
} }
} }
else { else {
// zamykanie // zamykanie
if( false == doors_open() ) { if( ( true == pVehicle->MoverParameters->Doors.open_permit ) && ( false == doors_open() ) ) {
// the doors are already closed, we can skip all hard work // the doors are already closed and we don't have to revoke control permit, we can skip all hard work
iDrivigFlags &= ~moveDoorOpened; iDrivigFlags &= ~moveDoorOpened;
} }
if( AIControllFlag ) { if( AIControllFlag ) {
if( ( true == mvOccupied->DoorClosureWarning ) if( ( true == mvOccupied->Doors.has_autowarning )
&& ( false == mvOccupied->DepartureSignal ) && ( false == mvOccupied->DepartureSignal )
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) { && ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
mvOccupied->signal_departure( true ); // załącenie bzyczka mvOccupied->signal_departure( true ); // załącenie bzyczka
@@ -3279,12 +3265,22 @@ void TController::Doors( bool const Open, int const Side ) {
&& ( ( fActionTime > -0.5 ) && ( ( fActionTime > -0.5 )
|| ( false == AIControllFlag ) ) ) { || ( false == AIControllFlag ) ) ) {
// ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things // ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things
if( ( pVehicle->MoverParameters->Doors.open_control == control_t::conductor )
|| ( ( true == AIControllFlag )
&& ( ( pVehicle->MoverParameters->Doors.open_control == control_t::driver )
|| ( pVehicle->MoverParameters->Doors.open_control == control_t::mixed ) ) ) ) {
// if the door are controlled by the driver, we let the user operate them unless this user is an ai
// the train conductor, if present, handles door operation also for human-driven trains
pVehicle->MoverParameters->OperateDoors( side::right, false );
pVehicle->MoverParameters->OperateDoors( side::left, false );
}
auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu
while( vehicle != nullptr ) { while( vehicle != nullptr ) {
// zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza // zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
if( vehicle->MoverParameters->DoorCloseCtrl != control_t::autonomous ) { if( vehicle->MoverParameters->Doors.auto_velocity < 0.f ) {
vehicle->MoverParameters->DoorLeft( false, range_t::local ); // w lokomotywie można by nie zamykać... vehicle->MoverParameters->OperateDoors( side::right, false, range_t::local ); // w lokomotywie można by nie zamykać...
vehicle->MoverParameters->DoorRight( false, range_t::local ); vehicle->MoverParameters->OperateDoors( side::left, false, range_t::local );
} }
vehicle = vehicle->Next(); // pojazd podłączony z tyłu (patrząc od czoła) vehicle = vehicle->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
} }
@@ -3307,8 +3303,8 @@ TController::doors_open() const {
auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu
while( vehicle != nullptr ) { while( vehicle != nullptr ) {
if( ( vehicle->MoverParameters->DoorRightOpened == true ) if( ( false == vehicle->MoverParameters->Doors.instances[side::right].is_closed )
|| ( vehicle->MoverParameters->DoorLeftOpened == true ) ) { || ( false == vehicle->MoverParameters->Doors.instances[side::left].is_closed ) ) {
// any open door is enough // any open door is enough
return true; return true;
} }
@@ -3725,8 +3721,8 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
if( NewCommand == "SetLights" ) { if( NewCommand == "SetLights" ) {
// set consist lights pattern hints // set consist lights pattern hints
m_lighthints[ side::front ] = static_cast<int>( NewValue1 ); m_lighthints[ end::front ] = static_cast<int>( NewValue1 );
m_lighthints[ side::rear ] = static_cast<int>( NewValue2 ); m_lighthints[ end::rear ] = static_cast<int>( NewValue2 );
if( true == TestFlag( OrderCurrentGet(), Obey_train ) ) { if( true == TestFlag( OrderCurrentGet(), Obey_train ) ) {
// light hints only apply in the obey_train mode // light hints only apply in the obey_train mode
CheckVehicles(); CheckVehicles();
@@ -3846,6 +3842,7 @@ TController::UpdateSituation(double dt) {
fAccGravity = 0.0; // przyspieszenie wynikające z pochylenia fAccGravity = 0.0; // przyspieszenie wynikające z pochylenia
double dy; // składowa styczna grawitacji, w przedziale <0,1> double dy; // składowa styczna grawitacji, w przedziale <0,1>
double AbsAccS = 0; double AbsAccS = 0;
IsAnyDoorOpen[ side::right ] = IsAnyDoorOpen[ side::left ] = false;
TDynamicObject *p = pVehicles[0]; // pojazd na czole składu TDynamicObject *p = pVehicles[0]; // pojazd na czole składu
while (p) while (p)
{ // sprawdzenie odhamowania wszystkich połączonych pojazdów { // sprawdzenie odhamowania wszystkich połączonych pojazdów
@@ -3879,6 +3876,15 @@ TController::UpdateSituation(double dt) {
&& ( vehicle->FuseFlag ) ) { // wywalony nadmiarowy && ( vehicle->FuseFlag ) ) { // wywalony nadmiarowy
Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego
} }
// check door state
auto const switchsides { p->DirectionGet() <= 0 };
IsAnyDoorOpen[ side::right ] =
IsAnyDoorOpen[ side::right ]
|| ( false == vehicle->Doors.instances[ ( switchsides ? side::left : side::right ) ].is_closed );
IsAnyDoorOpen[ side::left ] =
IsAnyDoorOpen[ side::left ]
|| ( false == vehicle->Doors.instances[ ( switchsides ? side::right : side::left ) ].is_closed );
p = p->Next(); // pojazd podłączony z tyłu (patrząc od czoła) p = p->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
} }
@@ -3938,7 +3944,7 @@ TController::UpdateSituation(double dt) {
// TODO: check if this situation still happens and the hack is still needed // TODO: check if this situation still happens and the hack is still needed
if( ( false == AIControllFlag ) if( ( false == AIControllFlag )
&& ( iDrivigFlags & moveDoorOpened ) && ( iDrivigFlags & moveDoorOpened )
&& ( mvOccupied->DoorCloseCtrl != control_t::driver ) && ( mvOccupied->Doors.close_control != control_t::driver )
&& ( mvControlling->MainCtrlPos > ( mvControlling->EngineType != TEngineType::DieselEngine ? 0 : 1 ) ) ) { // for diesel 1st position is effectively 0 && ( mvControlling->MainCtrlPos > ( mvControlling->EngineType != TEngineType::DieselEngine ? 0 : 1 ) ) ) { // for diesel 1st position is effectively 0
Doors( false ); Doors( false );
} }
@@ -4470,8 +4476,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->MoverParameters->Couplers[ side::front ].CouplingFlag == coupling::faux ) && ( pVehicle->MoverParameters->Couplers[ end::front ].CouplingFlag == coupling::faux )
&& ( pVehicle->MoverParameters->Couplers[ side::rear ].CouplingFlag == coupling::faux ) ) { && ( pVehicle->MoverParameters->Couplers[ end::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 );
@@ -4925,6 +4931,16 @@ TController::UpdateSituation(double dt) {
if( fStopTime < 0 ) { if( fStopTime < 0 ) {
// czas postoju przed dalszą jazdą (np. na przystanku) // czas postoju przed dalszą jazdą (np. na przystanku)
VelDesired = 0.0; // jak ma czekać, to nie ma jazdy VelDesired = 0.0; // jak ma czekać, to nie ma jazdy
// verify progress of load exchange
auto exchangetime { 0.f };
auto *vehicle { pVehicles[ 0 ] };
while( vehicle != nullptr ) {
exchangetime = std::max( exchangetime, vehicle->LoadExchangeTime() );
vehicle = vehicle->Next();
}
if( exchangetime > 0 ) {
WaitingSet( exchangetime );
}
} }
if( ( OrderCurrentGet() & Obey_train ) != 0 ) { if( ( OrderCurrentGet() & Obey_train ) != 0 ) {
@@ -5686,7 +5702,7 @@ void TController::OrderCheck()
if( OrderList[ OrderPos ] != Obey_train ) { if( OrderList[ OrderPos ] != Obey_train ) {
// reset light hints // reset light hints
m_lighthints[ side::front ] = m_lighthints[ side::rear ] = -1; m_lighthints[ end::front ] = m_lighthints[ end::rear ] = -1;
} }
if( OrderList[ OrderPos ] & ( Shunt | Connect | Obey_train ) ) { if( OrderList[ OrderPos ] & ( Shunt | Connect | Obey_train ) ) {
CheckVehicles(); // sprawdzić światła CheckVehicles(); // sprawdzić światła
@@ -6327,7 +6343,7 @@ bool TController::IsStop() const
double double
TController::TrackBlock() const { TController::TrackBlock() const {
return pVehicles[ side::front ]->fTrackBlock; return pVehicles[ end::front ]->fTrackBlock;
} }
void TController::MoveTo(TDynamicObject *to) void TController::MoveTo(TDynamicObject *to)

View File

@@ -422,6 +422,7 @@ private:
double fReady = 0.0; // poziom odhamowania wagonów double fReady = 0.0; // poziom odhamowania wagonów
bool Ready = false; // ABu: stan gotowosci do odjazdu - sprawdzenie odhamowania wagonow bool Ready = false; // ABu: stan gotowosci do odjazdu - sprawdzenie odhamowania wagonow
TDynamicObject *pVehicles[ 2 ]; // skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane) TDynamicObject *pVehicles[ 2 ]; // skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane)
bool IsAnyDoorOpen[ 2 ]; // state of door in the consist
// logs // logs
// methods // methods
@@ -436,7 +437,7 @@ private:
public: public:
TDynamicObject const *Vehicle() const { TDynamicObject const *Vehicle() const {
return pVehicle; } return pVehicle; }
TDynamicObject *Vehicle( side const Side ) const { TDynamicObject *Vehicle( end const Side ) const {
return pVehicles[ Side ]; } return pVehicles[ Side ]; }
private: private:
std::string OwnerName() const; std::string OwnerName() const;

View File

@@ -427,96 +427,88 @@ void TDynamicObject::UpdateBoogie(TAnim *pAnim)
pAnim->smAnimated->SetRotate(float3(1, 0, 0), *pAnim->dWheelAngle); pAnim->smAnimated->SetRotate(float3(1, 0, 0), *pAnim->dWheelAngle);
}; };
void TDynamicObject::UpdateDoorTranslate(TAnim *pAnim) // animacja drzwi - przesuw
{ // animacja drzwi - przesuw void TDynamicObject::UpdateDoorTranslate(TAnim *pAnim) {
if (pAnim->smAnimated) { if( pAnim->smAnimated == nullptr ) { return; }
auto const &door { MoverParameters->Doors.instances[ (
( pAnim->iNumber & 1 ) == 0 ?
side::right :
side::left ) ] };
if( pAnim->iNumber & 1 ) {
pAnim->smAnimated->SetTranslate( pAnim->smAnimated->SetTranslate(
Math3D::vector3{ Math3D::vector3{
0.0, 0.0,
0.0, 0.0,
dDoorMoveR } ); door.position } );
}
else {
pAnim->smAnimated->SetTranslate(
Math3D::vector3{
0.0,
0.0,
dDoorMoveL } );
}
}
}; };
void TDynamicObject::UpdateDoorRotate(TAnim *pAnim) // animacja drzwi - obrót
{ // animacja drzwi - obrót void TDynamicObject::UpdateDoorRotate(TAnim *pAnim) {
if (pAnim->smAnimated)
{ if( pAnim->smAnimated == nullptr ) { return; }
if (pAnim->iNumber & 1)
pAnim->smAnimated->SetRotate(float3(1, 0, 0), dDoorMoveR); auto const &door { MoverParameters->Doors.instances[ (
else ( pAnim->iNumber & 1 ) == 0 ?
pAnim->smAnimated->SetRotate(float3(1, 0, 0), dDoorMoveL); side::right :
} side::left ) ] };
pAnim->smAnimated->SetRotate(
float3(1, 0, 0),
door.position );
}; };
void TDynamicObject::UpdateDoorFold(TAnim *pAnim) // animacja drzwi - obrót
{ // animacja drzwi - obrót void TDynamicObject::UpdateDoorFold(TAnim *pAnim) {
if (pAnim->smAnimated)
{ if( pAnim->smAnimated == nullptr ) { return; }
if (pAnim->iNumber & 1)
{ auto const &door { MoverParameters->Doors.instances[ (
pAnim->smAnimated->SetRotate(float3(0, 0, 1), dDoorMoveR); ( pAnim->iNumber & 1 ) == 0 ?
TSubModel *sm = pAnim->smAnimated->ChildGet(); // skrzydło mniejsze side::right :
if (sm) side::left ) ] };
{
sm->SetRotate(float3(0, 0, 1), -dDoorMoveR - dDoorMoveR); // skrzydło większe // skrzydło mniejsze
pAnim->smAnimated->SetRotate(
float3(0, 0, 1),
door.position);
// skrzydło większe
auto *sm = pAnim->smAnimated->ChildGet();
if( sm == nullptr ) { return; }
sm->SetRotate(
float3(0, 0, 1),
-door.position - door.position);
// podnóżek?
sm = sm->ChildGet(); sm = sm->ChildGet();
if (sm) if( sm == nullptr ) { return; }
sm->SetRotate(float3(0, 1, 0), dDoorMoveR); // podnóżek?
} sm->SetRotate(
} float3(0, 1, 0),
else door.position);
{
pAnim->smAnimated->SetRotate(float3(0, 0, 1), dDoorMoveL);
TSubModel *sm = pAnim->smAnimated->ChildGet(); // skrzydło mniejsze
if (sm)
{
sm->SetRotate(float3(0, 0, 1), -dDoorMoveL - dDoorMoveL); // skrzydło większe
sm = sm->ChildGet();
if (sm)
sm->SetRotate(float3(0, 1, 0), dDoorMoveL); // podnóżek?
}
}
}
}; };
void TDynamicObject::UpdateDoorPlug(TAnim *pAnim) // animacja drzwi - odskokprzesuw
{ // animacja drzwi - odskokprzesuw void TDynamicObject::UpdateDoorPlug(TAnim *pAnim) {
if (pAnim->smAnimated) {
if( pAnim->smAnimated == nullptr ) { return; }
auto const &door { MoverParameters->Doors.instances[ (
( pAnim->iNumber & 1 ) == 0 ?
side::right :
side::left ) ] };
if( pAnim->iNumber & 1 ) {
pAnim->smAnimated->SetTranslate( pAnim->smAnimated->SetTranslate(
Math3D::vector3 { Math3D::vector3 {
std::min( std::min(
dDoorMoveR * 2, door.position * 2.f,
MoverParameters->DoorMaxPlugShift ), MoverParameters->Doors.range_out ),
0.0, 0.0,
std::max( std::max(
0.0, 0.f,
dDoorMoveR - MoverParameters->DoorMaxPlugShift * 0.5f ) } ); door.position - MoverParameters->Doors.range_out * 0.5f ) } );
}
else {
pAnim->smAnimated->SetTranslate(
Math3D::vector3 {
std::min(
dDoorMoveL * 2,
MoverParameters->DoorMaxPlugShift ),
0.0,
std::max(
0.0,
dDoorMoveL - MoverParameters->DoorMaxPlugShift * 0.5f ) } );
}
}
} }
void TDynamicObject::UpdatePant(TAnim *pAnim) void TDynamicObject::UpdatePant(TAnim *pAnim)
@@ -542,20 +534,16 @@ void TDynamicObject::UpdatePlatformTranslate( TAnim *pAnim ) {
if( pAnim->smAnimated == nullptr ) { return; } if( pAnim->smAnimated == nullptr ) { return; }
if( pAnim->iNumber & 1 ) { auto const &door { MoverParameters->Doors.instances[ (
( pAnim->iNumber & 1 ) == 0 ?
side::right :
side::left ) ] };
pAnim->smAnimated->SetTranslate( pAnim->smAnimated->SetTranslate(
Math3D::vector3{ Math3D::vector3{
interpolate( 0.0, MoverParameters->PlatformMaxShift, dDoorstepMoveR ), interpolate( 0.f, MoverParameters->Doors.step_range, door.step_position ),
0.0, 0.0,
0.0 } ); 0.0 } );
}
else {
pAnim->smAnimated->SetTranslate(
Math3D::vector3{
interpolate( 0.0, MoverParameters->PlatformMaxShift, dDoorstepMoveL ),
0.0,
0.0 } );
}
} }
// doorstep animation, rotate // doorstep animation, rotate
@@ -563,14 +551,14 @@ void TDynamicObject::UpdatePlatformRotate( TAnim *pAnim ) {
if( pAnim->smAnimated == nullptr ) { return; } if( pAnim->smAnimated == nullptr ) { return; }
if( pAnim->iNumber & 1 ) auto const &door { MoverParameters->Doors.instances[ (
( pAnim->iNumber & 1 ) == 0 ?
side::right :
side::left ) ] };
pAnim->smAnimated->SetRotate( pAnim->smAnimated->SetRotate(
float3( 0, 1, 0 ), float3( 0, 1, 0 ),
interpolate( 0.0, MoverParameters->PlatformMaxShift, dDoorstepMoveR ) ); interpolate( 0.f, MoverParameters->Doors.step_range, door.step_position ) );
else
pAnim->smAnimated->SetRotate(
float3( 0, 1, 0 ),
interpolate( 0.0, MoverParameters->PlatformMaxShift, dDoorstepMoveL ) );
} }
// mirror animation, rotate // mirror animation, rotate
@@ -580,8 +568,8 @@ void TDynamicObject::UpdateMirror( TAnim *pAnim ) {
// only animate the mirror if it's located on the same end of the vehicle as the active cab // only animate the mirror if it's located on the same end of the vehicle as the active cab
auto const isactive { ( auto const isactive { (
MoverParameters->ActiveCab > 0 ? ( ( pAnim->iNumber >> 4 ) == side::front ? 1.0 : 0.0 ) : MoverParameters->ActiveCab > 0 ? ( ( pAnim->iNumber >> 4 ) == end::front ? 1.0 : 0.0 ) :
MoverParameters->ActiveCab < 0 ? ( ( pAnim->iNumber >> 4 ) == side::rear ? 1.0 : 0.0 ) : MoverParameters->ActiveCab < 0 ? ( ( pAnim->iNumber >> 4 ) == end::rear ? 1.0 : 0.0 ) :
0.0 ) }; 0.0 ) };
if( pAnim->iNumber & 1 ) if( pAnim->iNumber & 1 )
@@ -955,13 +943,13 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
} }
} }
// tablice blaszane: // tablice blaszane:
if (TestFlag(iLights[side::front], light::rearendsignals)) if (TestFlag(iLights[end::front], light::rearendsignals))
{ {
btEndSignalsTab1.Turn( true ); btEndSignalsTab1.Turn( true );
btnOn = true; btnOn = true;
} }
// else btEndSignalsTab1.TurnOff(); // else btEndSignalsTab1.TurnOff();
if (TestFlag(iLights[side::rear], light::rearendsignals)) if (TestFlag(iLights[end::rear], light::rearendsignals))
{ {
btEndSignalsTab2.Turn( true ); btEndSignalsTab2.Turn( true );
btnOn = true; btnOn = true;
@@ -1396,7 +1384,7 @@ TDynamicObject::couple( int const Side ) {
MoverParameters->Couplers[ Side ].Connected, MoverParameters->Couplers[ Side ].Connected,
( MoverParameters->Couplers[ Side ].CouplingFlag | coupling::brakehose ) ) ) { ( MoverParameters->Couplers[ Side ].CouplingFlag | coupling::brakehose ) ) ) {
SetPneumatic( Side != 0, true ); SetPneumatic( Side != 0, true );
if( Side == side::front ) { if( Side == end::front ) {
PrevConnected->SetPneumatic( Side != 0, true ); PrevConnected->SetPneumatic( Side != 0, true );
} }
else { else {
@@ -1417,7 +1405,7 @@ TDynamicObject::couple( int const Side ) {
MoverParameters->Couplers[ Side ].Connected, MoverParameters->Couplers[ Side ].Connected,
( MoverParameters->Couplers[ Side ].CouplingFlag | coupling::mainhose ) ) ) { ( MoverParameters->Couplers[ Side ].CouplingFlag | coupling::mainhose ) ) ) {
SetPneumatic( Side != 0, false ); SetPneumatic( Side != 0, false );
if( Side == side::front ) { if( Side == end::front ) {
PrevConnected->SetPneumatic( Side != 0, false ); PrevConnected->SetPneumatic( Side != 0, false );
} }
else { else {
@@ -1492,21 +1480,21 @@ void TDynamicObject::CouplersDettach(double MinDist, int MyScanDir) {
if (MyScanDir > 0) { if (MyScanDir > 0) {
// pojazd od strony sprzęgu 0 // pojazd od strony sprzęgu 0
if( ( PrevConnected != nullptr ) if( ( PrevConnected != nullptr )
&& ( MoverParameters->Couplers[ side::front ].CoupleDist > MinDist ) ) { && ( MoverParameters->Couplers[ end::front ].CoupleDist > MinDist ) ) {
// sprzęgi wirtualne zawsze przekraczają // sprzęgi wirtualne zawsze przekraczają
if( ( PrevConnectedNo == side::front ? if( ( PrevConnectedNo == end::front ?
PrevConnected->PrevConnected : PrevConnected->PrevConnected :
PrevConnected->NextConnected ) PrevConnected->NextConnected )
== this ) { == this ) {
// Ra: nie rozłączamy znalezionego, jeżeli nie do nas podłączony // Ra: nie rozłączamy znalezionego, jeżeli nie do nas podłączony
// (może jechać w innym kierunku) // (może jechać w innym kierunku)
PrevConnected->MoverParameters->Couplers[PrevConnectedNo].Connected = nullptr; PrevConnected->MoverParameters->Couplers[PrevConnectedNo].Connected = nullptr;
if( PrevConnectedNo == side::front ) { if( PrevConnectedNo == end::front ) {
// sprzęg 0 nie podłączony // sprzęg 0 nie podłączony
PrevConnected->PrevConnectedNo = 2; PrevConnected->PrevConnectedNo = 2;
PrevConnected->PrevConnected = nullptr; PrevConnected->PrevConnected = nullptr;
} }
else if( PrevConnectedNo == side::rear ) { else if( PrevConnectedNo == end::rear ) {
// sprzęg 1 nie podłączony // sprzęg 1 nie podłączony
PrevConnected->NextConnectedNo = 2; PrevConnected->NextConnectedNo = 2;
PrevConnected->NextConnected = nullptr; PrevConnected->NextConnected = nullptr;
@@ -1515,27 +1503,27 @@ void TDynamicObject::CouplersDettach(double MinDist, int MyScanDir) {
// za to zawsze odłączamy siebie // za to zawsze odłączamy siebie
PrevConnected = nullptr; PrevConnected = nullptr;
PrevConnectedNo = 2; // sprzęg 0 nie podłączony PrevConnectedNo = 2; // sprzęg 0 nie podłączony
MoverParameters->Couplers[ side::front ].Connected = nullptr; MoverParameters->Couplers[ end::front ].Connected = nullptr;
} }
} }
else { else {
// pojazd od strony sprzęgu 1 // pojazd od strony sprzęgu 1
if( ( NextConnected != nullptr ) if( ( NextConnected != nullptr )
&& ( MoverParameters->Couplers[ side::rear ].CoupleDist > MinDist ) ) { && ( MoverParameters->Couplers[ end::rear ].CoupleDist > MinDist ) ) {
// sprzęgi wirtualne zawsze przekraczają // sprzęgi wirtualne zawsze przekraczają
if( ( NextConnectedNo == side::front ? if( ( NextConnectedNo == end::front ?
NextConnected->PrevConnected : NextConnected->PrevConnected :
NextConnected->NextConnected ) NextConnected->NextConnected )
== this) { == this) {
// Ra: nie rozłączamy znalezionego, jeżeli nie do nas podłączony // Ra: nie rozłączamy znalezionego, jeżeli nie do nas podłączony
// (może jechać w innym kierunku) // (może jechać w innym kierunku)
NextConnected->MoverParameters->Couplers[ NextConnectedNo ].Connected = nullptr; NextConnected->MoverParameters->Couplers[ NextConnectedNo ].Connected = nullptr;
if( NextConnectedNo == side::front ) { if( NextConnectedNo == end::front ) {
// sprzęg 0 nie podłączony // sprzęg 0 nie podłączony
NextConnected->PrevConnectedNo = 2; NextConnected->PrevConnectedNo = 2;
NextConnected->PrevConnected = nullptr; NextConnected->PrevConnected = nullptr;
} }
else if( NextConnectedNo == side::rear ) { else if( NextConnectedNo == end::rear ) {
// sprzęg 1 nie podłączony // sprzęg 1 nie podłączony
NextConnected->NextConnectedNo = 2; NextConnected->NextConnectedNo = 2;
NextConnected->NextConnected = nullptr; NextConnected->NextConnected = nullptr;
@@ -1627,7 +1615,7 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance )
// siebie można bezpiecznie podłączyć jednostronnie do znalezionego // siebie można bezpiecznie podłączyć jednostronnie do znalezionego
MoverParameters->Attach( mycoupler, foundcoupler, foundobject->MoverParameters, coupling::faux ); MoverParameters->Attach( mycoupler, foundcoupler, foundobject->MoverParameters, coupling::faux );
// MoverParameters->Couplers[MyCouplFound].Render=false; //wirtualnego nie renderujemy // MoverParameters->Couplers[MyCouplFound].Render=false; //wirtualnego nie renderujemy
if( mycoupler == side::front ) { if( mycoupler == end::front ) {
PrevConnected = foundobject; // pojazd od strony sprzęgu 0 PrevConnected = foundobject; // pojazd od strony sprzęgu 0
PrevConnectedNo = foundcoupler; PrevConnectedNo = foundcoupler;
} }
@@ -1638,7 +1626,7 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance )
if( foundobject->MoverParameters->Couplers[ foundcoupler ].CouplingFlag == coupling::faux ) { if( foundobject->MoverParameters->Couplers[ foundcoupler ].CouplingFlag == coupling::faux ) {
// Ra: wpinamy się wirtualnym tylko jeśli znaleziony ma wirtualny sprzęg // Ra: wpinamy się wirtualnym tylko jeśli znaleziony ma wirtualny sprzęg
if( ( foundcoupler == side::front ? if( ( foundcoupler == end::front ?
foundobject->PrevConnected : foundobject->PrevConnected :
foundobject->NextConnected ) foundobject->NextConnected )
!= this ) { != this ) {
@@ -1646,13 +1634,13 @@ void TDynamicObject::ABuScanObjects( int Direction, double Distance )
// otherwise we risk leaving the target's connected vehicle with active one-side connection // otherwise we risk leaving the target's connected vehicle with active one-side connection
foundobject->CouplersDettach( foundobject->CouplersDettach(
1.0, 1.0,
( foundcoupler == side::front ? ( foundcoupler == end::front ?
1 : 1 :
-1 ) ); -1 ) );
} }
foundobject->MoverParameters->Attach( foundcoupler, mycoupler, this->MoverParameters, coupling::faux ); foundobject->MoverParameters->Attach( foundcoupler, mycoupler, this->MoverParameters, coupling::faux );
if( foundcoupler == side::front ) { if( foundcoupler == end::front ) {
// jeśli widoczny sprzęg 0 znalezionego // jeśli widoczny sprzęg 0 znalezionego
if( ( DebugModeFlag ) if( ( DebugModeFlag )
&& ( foundobject->PrevConnected ) && ( foundobject->PrevConnected )
@@ -1728,8 +1716,6 @@ TDynamicObject::TDynamicObject() {
// Winger 160204 - pantografy // Winger 160204 - pantografy
// PantVolume = 3.5; // PantVolume = 3.5;
NoVoltTime = 0; NoVoltTime = 0;
dDoorMoveL = 0.0;
dDoorMoveR = 0.0;
mdModel = NULL; mdModel = NULL;
mdKabina = NULL; mdKabina = NULL;
// smWiazary[0]=smWiazary[1]=NULL; // smWiazary[0]=smWiazary[1]=NULL;
@@ -2147,19 +2133,19 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
btEndSignals21.Init( "endsignal23", mdModel, false); btEndSignals21.Init( "endsignal23", mdModel, false);
btEndSignals13.Init( "endsignal12", mdModel, false); btEndSignals13.Init( "endsignal12", mdModel, false);
btEndSignals23.Init( "endsignal22", mdModel, false); btEndSignals23.Init( "endsignal22", mdModel, false);
iInventory[ side::front ] |= btEndSignals11.Active() ? light::redmarker_left : 0; // informacja, czy ma poszczególne światła iInventory[ end::front ] |= btEndSignals11.Active() ? light::redmarker_left : 0; // informacja, czy ma poszczególne światła
iInventory[ side::front ] |= btEndSignals13.Active() ? light::redmarker_right : 0; iInventory[ end::front ] |= btEndSignals13.Active() ? light::redmarker_right : 0;
iInventory[ side::rear ] |= btEndSignals21.Active() ? light::redmarker_left : 0; iInventory[ end::rear ] |= btEndSignals21.Active() ? light::redmarker_left : 0;
iInventory[ side::rear ] |= btEndSignals23.Active() ? light::redmarker_right : 0; iInventory[ end::rear ] |= btEndSignals23.Active() ? light::redmarker_right : 0;
// ABu: to niestety zostawione dla kompatybilnosci modeli: // ABu: to niestety zostawione dla kompatybilnosci modeli:
btEndSignals1.Init( "endsignals1", mdModel, false); btEndSignals1.Init( "endsignals1", mdModel, false);
btEndSignals2.Init( "endsignals2", mdModel, false); btEndSignals2.Init( "endsignals2", mdModel, false);
btEndSignalsTab1.Init( "endtab1", mdModel, false); btEndSignalsTab1.Init( "endtab1", mdModel, false);
btEndSignalsTab2.Init( "endtab2", mdModel, false); btEndSignalsTab2.Init( "endtab2", mdModel, false);
iInventory[ side::front ] |= btEndSignals1.Active() ? ( light::redmarker_left | light::redmarker_right ) : 0; iInventory[ end::front ] |= btEndSignals1.Active() ? ( light::redmarker_left | light::redmarker_right ) : 0;
iInventory[ side::front ] |= btEndSignalsTab1.Active() ? light::rearendsignals : 0; // tabliczki blaszane iInventory[ end::front ] |= btEndSignalsTab1.Active() ? light::rearendsignals : 0; // tabliczki blaszane
iInventory[ side::rear ] |= btEndSignals2.Active() ? ( light::redmarker_left | light::redmarker_right ) : 0; iInventory[ end::rear ] |= btEndSignals2.Active() ? ( light::redmarker_left | light::redmarker_right ) : 0;
iInventory[ side::rear ] |= btEndSignalsTab2.Active() ? light::rearendsignals : 0; iInventory[ end::rear ] |= btEndSignalsTab2.Active() ? light::rearendsignals : 0;
// ABu Uwaga! tu zmienic w modelu! // ABu Uwaga! tu zmienic w modelu!
btHeadSignals11.Init( "headlamp13", mdModel, false); // lewe btHeadSignals11.Init( "headlamp13", mdModel, false); // lewe
btHeadSignals12.Init( "headlamp11", mdModel, false); // górne btHeadSignals12.Init( "headlamp11", mdModel, false); // górne
@@ -2167,12 +2153,12 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
btHeadSignals21.Init( "headlamp23", mdModel, false); btHeadSignals21.Init( "headlamp23", mdModel, false);
btHeadSignals22.Init( "headlamp21", mdModel, false); btHeadSignals22.Init( "headlamp21", mdModel, false);
btHeadSignals23.Init( "headlamp22", mdModel, false); btHeadSignals23.Init( "headlamp22", mdModel, false);
iInventory[ side::front ] |= btHeadSignals11.Active() ? light::headlight_left : 0; iInventory[ end::front ] |= btHeadSignals11.Active() ? light::headlight_left : 0;
iInventory[ side::front ] |= btHeadSignals12.Active() ? light::headlight_upper : 0; iInventory[ end::front ] |= btHeadSignals12.Active() ? light::headlight_upper : 0;
iInventory[ side::front ] |= btHeadSignals13.Active() ? light::headlight_right : 0; iInventory[ end::front ] |= btHeadSignals13.Active() ? light::headlight_right : 0;
iInventory[ side::rear ] |= btHeadSignals21.Active() ? light::headlight_left : 0; iInventory[ end::rear ] |= btHeadSignals21.Active() ? light::headlight_left : 0;
iInventory[ side::rear ] |= btHeadSignals22.Active() ? light::headlight_upper : 0; iInventory[ end::rear ] |= btHeadSignals22.Active() ? light::headlight_upper : 0;
iInventory[ side::rear ] |= btHeadSignals23.Active() ? light::headlight_right : 0; iInventory[ end::rear ] |= btHeadSignals23.Active() ? light::headlight_right : 0;
btMechanik1.Init( "mechanik1", mdLowPolyInt, false); btMechanik1.Init( "mechanik1", mdLowPolyInt, false);
btMechanik2.Init( "mechanik2", mdLowPolyInt, false); btMechanik2.Init( "mechanik2", mdLowPolyInt, false);
if( MoverParameters->dizel_heat.water.config.shutters ) { if( MoverParameters->dizel_heat.water.config.shutters ) {
@@ -2456,10 +2442,10 @@ void TDynamicObject::Move(double fDistance)
// MoverParameters->Loc.Z= vPosition.y; // MoverParameters->Loc.Z= vPosition.y;
// obliczanie pozycji sprzęgów do liczenia zderzeń // obliczanie pozycji sprzęgów do liczenia zderzeń
auto dir = (0.5 * MoverParameters->Dim.L) * vFront; // wektor sprzęgu auto dir = (0.5 * MoverParameters->Dim.L) * vFront; // wektor sprzęgu
vCoulpler[side::front] = vPosition + dir; // współrzędne sprzęgu na początku vCoulpler[end::front] = vPosition + dir; // współrzędne sprzęgu na początku
vCoulpler[side::rear] = vPosition - dir; // współrzędne sprzęgu na końcu vCoulpler[end::rear] = vPosition - dir; // współrzędne sprzęgu na końcu
MoverParameters->vCoulpler[side::front] = vCoulpler[side::front]; // tymczasowo kopiowane na inny poziom MoverParameters->vCoulpler[end::front] = vCoulpler[end::front]; // tymczasowo kopiowane na inny poziom
MoverParameters->vCoulpler[side::rear] = vCoulpler[side::rear]; MoverParameters->vCoulpler[end::rear] = vCoulpler[end::rear];
// bCameraNear= // bCameraNear=
// if (bCameraNear) //jeśli istotne są szczegóły (blisko kamery) // if (bCameraNear) //jeśli istotne są szczegóły (blisko kamery)
{ // przeliczenie cienia { // przeliczenie cienia
@@ -2605,19 +2591,20 @@ bool TDynamicObject::UpdateForce(double dt, double dt1, bool FullVer)
// initiates load change by specified amounts, with a platform on specified side // initiates load change by specified amounts, with a platform on specified side
void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int const Platform ) { void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int const Platform ) {
/*
if( ( MoverParameters->DoorOpenCtrl == control_t::passenger ) if( ( MoverParameters->Doors.open_control == control_t::passenger )
|| ( MoverParameters->DoorOpenCtrl == control_t::mixed ) ) { || ( MoverParameters->Doors.open_control == control_t::mixed ) ) {
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie // jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
auto const lewe = ( DirectionGet() > 0 ) ? 1 : 2; auto const lewe = ( DirectionGet() > 0 ) ? 1 : 2;
auto const prawe = 3 - lewe; auto const prawe = 3 - lewe;
if( Platform & lewe ) { if( Platform & lewe ) {
MoverParameters->DoorLeft( true, range_t::local ); MoverParameters->OperateDoors( side::left, true, range_t::local );
} }
if( Platform & prawe ) { if( Platform & prawe ) {
MoverParameters->DoorRight( true, range_t::local ); MoverParameters->OperateDoors( side::right, true, range_t::local );
} }
} }
*/
m_exchange.unload_count += Disembark; m_exchange.unload_count += Disembark;
m_exchange.load_count += Embark; m_exchange.load_count += Embark;
m_exchange.platforms = Platform; m_exchange.platforms = Platform;
@@ -2644,10 +2631,10 @@ float TDynamicObject::LoadExchangeSpeed() const {
auto const lewe { ( DirectionGet() > 0 ) ? 1 : 2 }; auto const lewe { ( DirectionGet() > 0 ) ? 1 : 2 };
auto const prawe { 3 - lewe }; auto const prawe { 3 - lewe };
if( m_exchange.platforms & lewe ) { if( m_exchange.platforms & lewe ) {
exchangespeedfactor += ( MoverParameters->DoorLeftOpened ? 1.f : 0.f ); exchangespeedfactor += ( MoverParameters->Doors.instances[side::left].is_open ? 1.f : 0.f );
} }
if( m_exchange.platforms & prawe ) { if( m_exchange.platforms & prawe ) {
exchangespeedfactor += ( MoverParameters->DoorRightOpened ? 1.f : 0.f ); exchangespeedfactor += ( MoverParameters->Doors.instances[ side::right ].is_open ? 1.f : 0.f );
} }
return exchangespeedfactor; return exchangespeedfactor;
@@ -2661,16 +2648,38 @@ void TDynamicObject::update_exchange( double const Deltatime ) {
if( ( m_exchange.unload_count < 0.01 ) && ( m_exchange.load_count < 0.01 ) ) { return; } if( ( m_exchange.unload_count < 0.01 ) && ( m_exchange.load_count < 0.01 ) ) { return; }
if( ( MoverParameters->Vel < 2.0 ) if( MoverParameters->Vel < 2.0 ) {
&& ( ( true == MoverParameters->DoorLeftOpened )
|| ( true == MoverParameters->DoorRightOpened ) ) ) { auto const exchangespeed { LoadExchangeSpeed() };
if( exchangespeed < ( m_exchange.platforms == 3 ? 2.f : 1.f ) ) {
// the exchange isn't performed at optimal rate, or at all. try to open viable vehicle doors to speed it up
auto const lewe { ( DirectionGet() > 0 ) ? 1 : 2 };
auto const prawe { 3 - lewe };
if( ( m_exchange.platforms & lewe )
&& ( false == (
MoverParameters->Doors.instances[side::left].is_open
|| MoverParameters->Doors.instances[side::left].is_opening ) ) ) {
// try to open left door
MoverParameters->OperateDoors( side::left, true, range_t::local );
}
if( ( m_exchange.platforms & prawe )
&& ( false == (
MoverParameters->Doors.instances[side::right].is_open
|| MoverParameters->Doors.instances[side::right].is_opening ) ) ) {
// try to open right door
MoverParameters->OperateDoors( side::right, true, range_t::local );
}
}
if( exchangespeed > 0.f ) {
m_exchange.time += Deltatime; m_exchange.time += Deltatime;
while( ( m_exchange.unload_count > 0.01 ) while( ( m_exchange.unload_count > 0.01 )
&& ( m_exchange.time >= 1.0 ) ) { && ( m_exchange.time >= 1.0 ) ) {
m_exchange.time -= 1.0; m_exchange.time -= 1.0;
auto const exchangesize = std::min( m_exchange.unload_count, MoverParameters->UnLoadSpeed * LoadExchangeSpeed() ); auto const exchangesize = std::min( m_exchange.unload_count, MoverParameters->UnLoadSpeed * exchangespeed );
m_exchange.unload_count -= exchangesize; m_exchange.unload_count -= exchangesize;
MoverParameters->LoadStatus = 1; MoverParameters->LoadStatus = 1;
MoverParameters->LoadAmount = std::max( 0.f, MoverParameters->LoadAmount - exchangesize ); MoverParameters->LoadAmount = std::max( 0.f, MoverParameters->LoadAmount - exchangesize );
@@ -2684,7 +2693,7 @@ void TDynamicObject::update_exchange( double const Deltatime ) {
&& ( m_exchange.time >= 1.0 ) ) { && ( m_exchange.time >= 1.0 ) ) {
m_exchange.time -= 1.0; m_exchange.time -= 1.0;
auto const exchangesize = std::min( m_exchange.load_count, MoverParameters->LoadSpeed * LoadExchangeSpeed() ); auto const exchangesize = std::min( m_exchange.load_count, MoverParameters->LoadSpeed * exchangespeed );
m_exchange.load_count -= exchangesize; m_exchange.load_count -= exchangesize;
MoverParameters->LoadStatus = 2; MoverParameters->LoadStatus = 2;
MoverParameters->LoadAmount = std::min( MoverParameters->MaxLoad, MoverParameters->LoadAmount + exchangesize ); // std::max not strictly needed but, eh MoverParameters->LoadAmount = std::min( MoverParameters->MaxLoad, MoverParameters->LoadAmount + exchangesize ); // std::max not strictly needed but, eh
@@ -2692,6 +2701,7 @@ void TDynamicObject::update_exchange( double const Deltatime ) {
} }
} }
} }
}
if( MoverParameters->Vel > 2.0 ) { if( MoverParameters->Vel > 2.0 ) {
// if the vehicle moves too fast cancel the exchange // if the vehicle moves too fast cancel the exchange
@@ -2704,18 +2714,18 @@ void TDynamicObject::update_exchange( double const Deltatime ) {
MoverParameters->LoadStatus = 0; MoverParameters->LoadStatus = 0;
// if the exchange is completed (or canceled) close the door, if applicable // if the exchange is completed (or canceled) close the door, if applicable
if( ( MoverParameters->DoorCloseCtrl == control_t::passenger ) if( ( MoverParameters->Doors.close_control == control_t::passenger )
|| ( MoverParameters->DoorCloseCtrl == control_t::mixed ) ) { || ( MoverParameters->Doors.close_control == control_t::mixed ) ) {
if( ( MoverParameters->Vel > 2.0 ) if( ( MoverParameters->Vel > 2.0 )
|| ( Random() < ( || ( Random() < (
// remotely controlled door are more likely to be left open // remotely controlled door are more likely to be left open
MoverParameters->DoorCloseCtrl == control_t::passenger ? MoverParameters->Doors.close_control == control_t::passenger ?
0.75 : 0.75 :
0.50 ) ) ) { 0.50 ) ) ) {
MoverParameters->DoorLeft( false, range_t::local ); MoverParameters->OperateDoors( side::left, false, range_t::local );
MoverParameters->DoorRight( false, range_t::local ); MoverParameters->OperateDoors( side::right, false, range_t::local );
} }
} }
} }
@@ -3044,18 +3054,20 @@ bool TDynamicObject::Update(double dt, double dt1)
RapidMult = MoverParameters->RapidMult; RapidMult = MoverParameters->RapidMult;
auto const amax = RapidMult * std::min(FmaxPN / masamax, MoverParameters->MED_amax); auto const amax = RapidMult * std::min(FmaxPN / masamax, MoverParameters->MED_amax);
auto const doorisopen {
( false == MoverParameters->Doors.instances[ side::right ].is_closed )
|| ( false == MoverParameters->Doors.instances[ side::left ].is_closed ) };
if ((MoverParameters->Vel < 0.5) && (MoverParameters->BrakePress > 0.2) || if ((MoverParameters->Vel < 0.5) && (MoverParameters->BrakePress > 0.2) || doorisopen )
(dDoorMoveL > 0.001) || (dDoorMoveR > 0.001))
{ {
MoverParameters->ShuntMode = true; MoverParameters->ShuntMode = true;
} }
if (MoverParameters->ShuntMode) if (MoverParameters->ShuntMode)
{ {
MoverParameters->ShuntModeAllow = (dDoorMoveL < 0.001) && (dDoorMoveR < 0.001) && MoverParameters->ShuntModeAllow = ( false == doorisopen ) &&
(MoverParameters->LocalBrakeRatio() < 0.01); (MoverParameters->LocalBrakeRatio() < 0.01);
} }
if ((MoverParameters->Vel > 1) && (dDoorMoveL < 0.001) && (dDoorMoveR < 0.001)) if( ( MoverParameters->Vel > 1 ) && ( false == doorisopen ) )
{ {
MoverParameters->ShuntMode = false; MoverParameters->ShuntMode = false;
MoverParameters->ShuntModeAllow = (MoverParameters->BrakePress > 0.2) && MoverParameters->ShuntModeAllow = (MoverParameters->BrakePress > 0.2) &&
@@ -3717,121 +3729,6 @@ bool TDynamicObject::Update(double dt, double dt1)
*/ */
} }
// NBMX Obsluga drzwi, MC: zuniwersalnione
// TODO: fully generalized door assembly
if( ( dDoorMoveL < MoverParameters->DoorMaxShiftL )
&& ( true == MoverParameters->DoorLeftOpened ) ) {
// open left door
if( ( MoverParameters->TrainType == dt_EZT )
|| ( MoverParameters->TrainType == dt_DMU ) ) {
// multi-unit vehicles typically open door only after unfolding the doorstep
if( ( MoverParameters->PlatformMaxShift == 0.0 ) // no wait if no doorstep
|| ( MoverParameters->PlatformOpenMethod == 2 ) // no wait for rotating doorstep
|| ( dDoorstepMoveL == 1.0 ) ) {
dDoorMoveL = std::min(
MoverParameters->DoorMaxShiftL,
dDoorMoveL + MoverParameters->DoorOpenSpeed * dt1 );
}
}
else {
dDoorMoveL = std::min(
MoverParameters->DoorMaxShiftL,
dDoorMoveL + MoverParameters->DoorOpenSpeed * dt1 );
}
DoorDelayL = 0.f;
}
if( ( dDoorMoveL > 0.0 )
&& ( false == MoverParameters->DoorLeftOpened ) ) {
// close left door
DoorDelayL += dt1;
if( DoorDelayL > MoverParameters->DoorCloseDelay ) {
dDoorMoveL -= dt1 * MoverParameters->DoorCloseSpeed;
dDoorMoveL = std::max( dDoorMoveL, 0.0 );
}
}
if( ( dDoorMoveR < MoverParameters->DoorMaxShiftR )
&& ( true == MoverParameters->DoorRightOpened ) ) {
// open right door
if( ( MoverParameters->TrainType == dt_EZT )
|| ( MoverParameters->TrainType == dt_DMU ) ) {
// multi-unit vehicles typically open door only after unfolding the doorstep
if( ( MoverParameters->PlatformMaxShift == 0.0 ) // no wait if no doorstep
|| ( MoverParameters->PlatformOpenMethod == 2 ) // no wait for rotating doorstep
|| ( dDoorstepMoveR == 1.0 ) ) {
dDoorMoveR = std::min(
MoverParameters->DoorMaxShiftR,
dDoorMoveR + MoverParameters->DoorOpenSpeed * dt1 );
}
}
else {
dDoorMoveR = std::min(
MoverParameters->DoorMaxShiftR,
dDoorMoveR + MoverParameters->DoorOpenSpeed * dt1 );
}
DoorDelayR = 0.f;
}
if( ( dDoorMoveR > 0.0 )
&& ( false == MoverParameters->DoorRightOpened ) ) {
// close right door
DoorDelayR += dt1;
if( DoorDelayR > MoverParameters->DoorCloseDelay ) {
dDoorMoveR -= dt1 * MoverParameters->DoorCloseSpeed;
dDoorMoveR = std::max( dDoorMoveR, 0.0 );
}
}
// doorsteps
if( ( dDoorstepMoveL < 1.0 )
&& ( true == MoverParameters->DoorLeftOpened ) ) {
// unfold left doorstep
dDoorstepMoveL = std::min(
1.0,
dDoorstepMoveL + MoverParameters->PlatformSpeed * dt1 );
}
if( ( dDoorstepMoveL > 0.0 )
&& ( false == MoverParameters->DoorLeftOpened )
&& ( DoorDelayL > MoverParameters->DoorCloseDelay ) ) {
// fold left doorstep
if( ( MoverParameters->TrainType == dt_EZT )
|| ( MoverParameters->TrainType == dt_DMU ) ) {
// multi-unit vehicles typically fold the doorstep only after closing the door
if( dDoorMoveL == 0.0 ) {
dDoorstepMoveL = std::max(
0.0,
dDoorstepMoveL - MoverParameters->PlatformSpeed * dt1 );
}
}
else {
dDoorstepMoveL = std::max(
0.0,
dDoorstepMoveL - MoverParameters->PlatformSpeed * dt1 );
}
}
if( ( dDoorstepMoveR < 1.0 )
&& ( true == MoverParameters->DoorRightOpened ) ) {
// unfold right doorstep
dDoorstepMoveR = std::min(
1.0,
dDoorstepMoveR + MoverParameters->PlatformSpeed * dt1 );
}
if( ( dDoorstepMoveR > 0.0 )
&& ( false == MoverParameters->DoorRightOpened )
&& ( DoorDelayR > MoverParameters->DoorCloseDelay ) ) {
// fold right doorstep
if( ( MoverParameters->TrainType == dt_EZT )
|| ( MoverParameters->TrainType == dt_DMU ) ) {
// multi-unit vehicles typically fold the doorstep only after closing the door
if( dDoorMoveR == 0.0 ) {
dDoorstepMoveR = std::max(
0.0,
dDoorstepMoveR - MoverParameters->PlatformSpeed * dt1 );
}
}
else {
dDoorstepMoveR = std::max(
0.0,
dDoorstepMoveR - MoverParameters->PlatformSpeed * dt1 );
}
}
// mirrors // mirrors
if( MoverParameters->Vel > 5.0 ) { if( MoverParameters->Vel > 5.0 ) {
// automatically fold mirrors when above velocity threshold // automatically fold mirrors when above velocity threshold
@@ -3849,13 +3746,13 @@ bool TDynamicObject::Update(double dt, double dt1)
else { else {
// unfold mirror on the side with open doors, if not moving too fast // unfold mirror on the side with open doors, if not moving too fast
if( ( dMirrorMoveL < 1.0 ) if( ( dMirrorMoveL < 1.0 )
&& ( true == MoverParameters->DoorLeftOpened ) ) { && ( true == MoverParameters->Doors.instances[side::left].is_open ) ) {
dMirrorMoveL = std::min( dMirrorMoveL = std::min(
1.0, 1.0,
dMirrorMoveL + 1.0 * dt1 ); dMirrorMoveL + 1.0 * dt1 );
} }
if( ( dMirrorMoveR < 1.0 ) if( ( dMirrorMoveR < 1.0 )
&& ( true == MoverParameters->DoorRightOpened ) ) { && ( true == MoverParameters->Doors.instances[side::right].is_open ) ) {
dMirrorMoveR = std::min( dMirrorMoveR = std::min(
1.0, 1.0,
dMirrorMoveR + 1.0 * dt1 ); dMirrorMoveR + 1.0 * dt1 );
@@ -4198,7 +4095,7 @@ void TDynamicObject::RenderSounds() {
m_exchangesounds.loading.stop(); m_exchangesounds.loading.stop();
} }
// NBMX sygnal odjazdu // NBMX sygnal odjazdu
if( MoverParameters->DoorClosureWarning ) { if( MoverParameters->Doors.has_warning ) {
for( auto &door : m_doorsounds ) { for( auto &door : m_doorsounds ) {
// TBD, TODO: per-location door state triggers? // TBD, TODO: per-location door state triggers?
if( ( MoverParameters->DepartureSignal ) if( ( MoverParameters->DepartureSignal )
@@ -4218,106 +4115,59 @@ void TDynamicObject::RenderSounds() {
} }
} }
// NBMX Obsluga drzwi, MC: zuniwersalnione // NBMX Obsluga drzwi, MC: zuniwersalnione
// TODO: fully generalized door assembly std::array<side, 2> const sides { side::right, side::left };
if( true == MoverParameters->DoorLeftOpened ) { for( auto const side : sides ) {
// open left door
// door sounds
// due to potential wait for the doorstep we play the sound only during actual animation
if( ( dDoorMoveL > 0.0 )
&& ( dDoorMoveL < MoverParameters->DoorMaxShiftL ) ) {
for( auto &door : m_doorsounds ) {
if( door.rsDoorClose.offset().x > 0.f ) {
// determine left side doors from their offset
door.rsDoorOpen.play( sound_flags::exclusive );
door.rsDoorClose.stop();
}
}
}
// doorstep sounds
if( dDoorstepMoveL < 1.0 ) {
for( auto &door : m_doorsounds ) {
if( door.step_close.offset().x > 0.f ) {
door.step_open.play( sound_flags::exclusive );
door.step_close.stop();
}
}
}
}
if( false == MoverParameters->DoorLeftOpened ) {
// close left door
// door sounds can start playing before the door begins moving
if( dDoorMoveL > 0.0 ) {
for( auto &door : m_doorsounds ) {
if( door.rsDoorClose.offset().x > 0.f ) {
// determine left side doors from their offset
door.rsDoorClose.play( sound_flags::exclusive );
door.rsDoorOpen.stop();
}
}
}
// doorstep sounds are played only when the doorstep is moving
if( ( dDoorstepMoveL > 0.0 )
&& ( dDoorstepMoveL < 1.0 ) ) {
for( auto &door : m_doorsounds ) {
if( door.step_close.offset().x > 0.f ) {
// determine left side doors from their offset
door.step_close.play( sound_flags::exclusive );
door.step_open.stop();
}
}
}
}
if( true == MoverParameters->DoorRightOpened ) { auto const &door { MoverParameters->Doors.instances[ side ] };
// open right door
if( true == door.is_opening ) {
// door sounds // door sounds
// due to potential wait for the doorstep we play the sound only during actual animation // due to potential wait for the doorstep we play the sound only during actual animation
if( ( dDoorMoveR > 0.0 ) if( door.position > 0.f ) {
&& ( dDoorMoveR < MoverParameters->DoorMaxShiftR ) ) { for( auto &doorsounds : m_doorsounds ) {
for( auto &door : m_doorsounds ) { if( doorsounds.placement == side ) {
if( door.rsDoorClose.offset().x < 0.f ) { // determine left side doors from their offset
// determine right side doors from their offset doorsounds.rsDoorOpen.play( sound_flags::exclusive );
door.rsDoorOpen.play( sound_flags::exclusive ); doorsounds.rsDoorClose.stop();
door.rsDoorClose.stop();
} }
} }
} }
// doorstep sounds // doorstep sounds
if( dDoorstepMoveR < 1.0 ) { if( door.step_position < 1.f ) {
for( auto &door : m_doorsounds ) { for( auto &doorsounds : m_doorsounds ) {
if( door.step_close.offset().x < 0.f ) { if( doorsounds.placement == side ) {
door.step_open.play( sound_flags::exclusive ); doorsounds.step_open.play( sound_flags::exclusive );
door.step_close.stop(); doorsounds.step_close.stop();
} }
} }
} }
} }
if( false == MoverParameters->DoorRightOpened ) { if( true == door.is_closing ) {
// close right door // door sounds can start playing before the door begins moving but shouldn't cease once the door closes
// door sounds can start playing before the door begins moving if( door.position > 0.f ) {
if( dDoorMoveR > 0.0 ) { for( auto &doorsounds : m_doorsounds ) {
for( auto &door : m_doorsounds ) { if( doorsounds.placement == side ) {
if( door.rsDoorClose.offset().x < 0.f ) {
// determine left side doors from their offset // determine left side doors from their offset
door.rsDoorClose.play( sound_flags::exclusive ); doorsounds.rsDoorClose.play( sound_flags::exclusive );
door.rsDoorOpen.stop(); doorsounds.rsDoorOpen.stop();
} }
} }
} }
// doorstep sounds are played only when the doorstep is moving // doorstep sounds are played only when the doorstep is moving
if( ( dDoorstepMoveR > 0.0 ) if( ( door.step_position > 0.f )
&& ( dDoorstepMoveR < 1.0 ) ) { && ( door.step_position < 1.f ) ) {
for( auto &door : m_doorsounds ) { for( auto &doorsounds : m_doorsounds ) {
if( door.step_close.offset().x < 0.f ) { if( doorsounds.placement == side ) {
// determine left side doors from their offset // determine left side doors from their offset
door.step_close.play( sound_flags::exclusive ); doorsounds.step_close.play( sound_flags::exclusive );
door.step_open.stop(); doorsounds.step_open.stop();
}
} }
} }
} }
} }
// door locks // door locks
if( MoverParameters->DoorBlockedFlag() != m_doorlocks ) { if( MoverParameters->Doors.is_locked != m_doorlocks ) {
// toggle state of the locks... // toggle state of the locks...
m_doorlocks = !m_doorlocks; m_doorlocks = !m_doorlocks;
// ...and play relevant sounds // ...and play relevant sounds
@@ -5173,7 +5023,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
if (pAnimations[i + j].smAnimated) if (pAnimations[i + j].smAnimated)
{ //++iAnimatedDoors; { //++iAnimatedDoors;
pAnimations[i + j].smAnimated->WillBeAnimated(); // wyłączenie optymalizacji transformu pAnimations[i + j].smAnimated->WillBeAnimated(); // wyłączenie optymalizacji transformu
switch (MoverParameters->DoorOpenMethod) switch( MoverParameters->Doors.type )
{ // od razu zapinamy potrzebny typ animacji { // od razu zapinamy potrzebny typ animacji
case 1: case 1:
pAnimations[ i + j ].yUpdate = std::bind( &TDynamicObject::UpdateDoorTranslate, this, std::placeholders::_1 ); pAnimations[ i + j ].yUpdate = std::bind( &TDynamicObject::UpdateDoorTranslate, this, std::placeholders::_1 );
@@ -5190,7 +5040,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
default: default:
break; break;
} }
pAnimations[i + j].iNumber = i; // parzyste działają inaczej niż nieparzyste pAnimations[i + j].iNumber = i + 1; // parzyste działają inaczej niż nieparzyste
pAnimations[i + j].fMaxDist = 300 * 300; // drzwi to z daleka widać pAnimations[i + j].fMaxDist = 300 * 300; // drzwi to z daleka widać
/* /*
// NOTE: no longer used // NOTE: no longer used
@@ -5215,7 +5065,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
if (pAnimations[i + j].smAnimated) if (pAnimations[i + j].smAnimated)
{ //++iAnimatedDoors; { //++iAnimatedDoors;
pAnimations[i + j].smAnimated->WillBeAnimated(); // wyłączenie optymalizacji transformu pAnimations[i + j].smAnimated->WillBeAnimated(); // wyłączenie optymalizacji transformu
switch (MoverParameters->PlatformOpenMethod) switch( MoverParameters->Doors.step_type )
{ // od razu zapinamy potrzebny typ animacji { // od razu zapinamy potrzebny typ animacji
case 1: // shift case 1: // shift
pAnimations[ i + j ].yUpdate = std::bind( &TDynamicObject::UpdatePlatformTranslate, this, std::placeholders::_1 ); pAnimations[ i + j ].yUpdate = std::bind( &TDynamicObject::UpdatePlatformTranslate, this, std::placeholders::_1 );
@@ -5226,7 +5076,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
default: default:
break; break;
} }
pAnimations[i + j].iNumber = i; // parzyste działają inaczej niż nieparzyste pAnimations[i + j].iNumber = i + 1; // parzyste działają inaczej niż nieparzyste
pAnimations[i + j].fMaxDist = 150 * 150; // drzwi to z daleka widać pAnimations[i + j].fMaxDist = 150 * 150; // drzwi to z daleka widać
/* /*
// NOTE: no longer used // NOTE: no longer used
@@ -5257,8 +5107,8 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
// parzyste działają inaczej niż nieparzyste // parzyste działają inaczej niż nieparzyste
pAnimations[ i + j ].iNumber = pAnimations[ i + j ].iNumber =
( ( pAnimations[ i + j ].smAnimated->offset().z > 0 ? ( ( pAnimations[ i + j ].smAnimated->offset().z > 0 ?
side::front : end::front :
side::rear ) << 4 ) end::rear ) << 4 )
+ i; + i;
pAnimations[ i + j ].fMaxDist = 150 * 150; // drzwi to z daleka widać pAnimations[ i + j ].fMaxDist = 150 * 150; // drzwi to z daleka widać
/* /*
@@ -5362,9 +5212,9 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
blowertemplate.owner( this ); blowertemplate.owner( this );
auto const amplitudedivisor = static_cast<float>( auto const amplitudedivisor = static_cast<float>(
MoverParameters->MotorBlowers[ side::front ].speed > 0.f ? MoverParameters->MotorBlowers[ end::front ].speed > 0.f ?
MoverParameters->MotorBlowers[ side::front ].speed * MoverParameters->nmax * 60 + MoverParameters->Power * 3 : MoverParameters->MotorBlowers[ end::front ].speed * MoverParameters->nmax * 60 + MoverParameters->Power * 3 :
MoverParameters->MotorBlowers[ side::front ].speed * -1 ); MoverParameters->MotorBlowers[ end::front ].speed * -1 );
blowertemplate.m_amplitudefactor /= amplitudedivisor; blowertemplate.m_amplitudefactor /= amplitudedivisor;
blowertemplate.m_frequencyfactor /= amplitudedivisor; blowertemplate.m_frequencyfactor /= amplitudedivisor;
@@ -5707,6 +5557,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|| ( sides == "left" ) ) { || ( sides == "left" ) ) {
// left... // left...
auto const location { glm::vec3 { MoverParameters->Dim.W * 0.5f, MoverParameters->Dim.H * 0.5f, offset } }; auto const location { glm::vec3 { MoverParameters->Dim.W * 0.5f, MoverParameters->Dim.H * 0.5f, offset } };
door.placement = side::left;
door.sDepartureSignal.offset( location ); door.sDepartureSignal.offset( location );
door.rsDoorClose.offset( location ); door.rsDoorClose.offset( location );
door.rsDoorOpen.offset( location ); door.rsDoorOpen.offset( location );
@@ -5720,6 +5571,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|| ( sides == "right" ) ) { || ( sides == "right" ) ) {
// ...and right // ...and right
auto const location { glm::vec3 { MoverParameters->Dim.W * -0.5f, MoverParameters->Dim.H * 0.5f, offset } }; auto const location { glm::vec3 { MoverParameters->Dim.W * -0.5f, MoverParameters->Dim.H * 0.5f, offset } };
door.placement = side::right;
door.sDepartureSignal.offset( location ); door.sDepartureSignal.offset( location );
door.rsDoorClose.offset( location ); door.rsDoorClose.offset( location );
door.rsDoorOpen.offset( location ); door.rsDoorOpen.offset( location );
@@ -6063,19 +5915,19 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
} }
// couplers // couplers
auto const frontcoupleroffset { glm::vec3{ 0.f, 1.f, MoverParameters->Dim.L * 0.5f } }; auto const frontcoupleroffset { glm::vec3{ 0.f, 1.f, MoverParameters->Dim.L * 0.5f } };
m_couplersounds[ side::front ].dsbCouplerAttach.offset( frontcoupleroffset ); m_couplersounds[ end::front ].dsbCouplerAttach.offset( frontcoupleroffset );
m_couplersounds[ side::front ].dsbCouplerDetach.offset( frontcoupleroffset ); m_couplersounds[ end::front ].dsbCouplerDetach.offset( frontcoupleroffset );
m_couplersounds[ side::front ].dsbCouplerStretch.offset( frontcoupleroffset ); m_couplersounds[ end::front ].dsbCouplerStretch.offset( frontcoupleroffset );
m_couplersounds[ side::front ].dsbCouplerStretch_loud.offset( frontcoupleroffset ); m_couplersounds[ end::front ].dsbCouplerStretch_loud.offset( frontcoupleroffset );
m_couplersounds[ side::front ].dsbBufferClamp.offset( frontcoupleroffset ); m_couplersounds[ end::front ].dsbBufferClamp.offset( frontcoupleroffset );
m_couplersounds[ side::front ].dsbBufferClamp_loud.offset( frontcoupleroffset ); m_couplersounds[ end::front ].dsbBufferClamp_loud.offset( frontcoupleroffset );
auto const rearcoupleroffset { glm::vec3{ 0.f, 1.f, MoverParameters->Dim.L * -0.5f } }; auto const rearcoupleroffset { glm::vec3{ 0.f, 1.f, MoverParameters->Dim.L * -0.5f } };
m_couplersounds[ side::rear ].dsbCouplerAttach.offset( rearcoupleroffset ); m_couplersounds[ end::rear ].dsbCouplerAttach.offset( rearcoupleroffset );
m_couplersounds[ side::rear ].dsbCouplerDetach.offset( rearcoupleroffset ); m_couplersounds[ end::rear ].dsbCouplerDetach.offset( rearcoupleroffset );
m_couplersounds[ side::rear ].dsbCouplerStretch.offset( rearcoupleroffset ); m_couplersounds[ end::rear ].dsbCouplerStretch.offset( rearcoupleroffset );
m_couplersounds[ side::rear ].dsbCouplerStretch_loud.offset( rearcoupleroffset ); m_couplersounds[ end::rear ].dsbCouplerStretch_loud.offset( rearcoupleroffset );
m_couplersounds[ side::rear ].dsbBufferClamp.offset( rearcoupleroffset ); m_couplersounds[ end::rear ].dsbBufferClamp.offset( rearcoupleroffset );
m_couplersounds[ side::rear ].dsbBufferClamp_loud.offset( rearcoupleroffset ); m_couplersounds[ end::rear ].dsbBufferClamp_loud.offset( rearcoupleroffset );
} }
TModel3d * TModel3d *
@@ -6209,8 +6061,8 @@ void TDynamicObject::RaLightsSet(int head, int rear)
if( rear == ( light::redmarker_left | light::redmarker_right | light::rearendsignals ) ) // jeśli nadal obydwie możliwości if( rear == ( light::redmarker_left | light::redmarker_right | light::rearendsignals ) ) // jeśli nadal obydwie możliwości
if( iInventory[ if( iInventory[
( iDirection ? ( iDirection ?
side::rear : end::rear :
side::front ) ] & ( light::redmarker_left | light::redmarker_right ) ) { end::front ) ] & ( light::redmarker_left | light::redmarker_right ) ) {
// czy ma jakieś światła czerowone od danej strony // czy ma jakieś światła czerowone od danej strony
rear = ( light::redmarker_left | light::redmarker_right ); // dwa światła czerwone rear = ( light::redmarker_left | light::redmarker_right ); // dwa światła czerwone
} }
@@ -6236,7 +6088,18 @@ void TDynamicObject::RaLightsSet(int head, int rear)
int TDynamicObject::DirectionSet(int d) int TDynamicObject::DirectionSet(int d)
{ // ustawienie kierunku w składzie (wykonuje AI) { // ustawienie kierunku w składzie (wykonuje AI)
auto const lastdirection { iDirection };
iDirection = d > 0 ? 1 : 0; // d:1=zgodny,-1=przeciwny; iDirection:1=zgodny,0=przeciwny; iDirection = d > 0 ? 1 : 0; // d:1=zgodny,-1=przeciwny; iDirection:1=zgodny,0=przeciwny;
if( iDirection != lastdirection ) {
// direction was flipped, switch recorded servicable platform sides for potentially ongoing load exchange
auto const left { ( lastdirection > 0 ) ? 1 : 2 };
auto const right { 3 - left };
m_exchange.platforms =
( m_exchange.platforms & left ? right : 0 )
+ ( m_exchange.platforms & right ? left : 0 );
}
if (MyTrack) if (MyTrack)
{ // podczas wczytywania wstawiane jest AI, ale może jeszcze nie { // podczas wczytywania wstawiane jest AI, ale może jeszcze nie
// być toru // być toru
@@ -6251,8 +6114,8 @@ int TDynamicObject::DirectionSet(int d)
ctrain_virtual) // brak pojazdu podpiętego? ctrain_virtual) // brak pojazdu podpiętego?
ABuScanObjects(-1, 300); ABuScanObjects(-1, 300);
} }
return 1 - (iDirection ? NextConnectedNo : PrevConnectedNo); // informacja o położeniu // informacja o położeniu następnego
// następnego return 1 - (iDirection ? NextConnectedNo : PrevConnectedNo);
}; };
TDynamicObject * TDynamicObject::PrevAny() TDynamicObject * TDynamicObject::PrevAny()
@@ -6428,7 +6291,7 @@ void TDynamicObject::ParamSet(int what, int into)
// dla 8 różnych // dla 8 różnych
if (what & 1) // na razie mamy lewe oraz prawe, czyli używamy maskę 1=lewe, if (what & 1) // na razie mamy lewe oraz prawe, czyli używamy maskę 1=lewe,
// 2=prawe, 3=wszystkie // 2=prawe, 3=wszystkie
if (MoverParameters->DoorLeftOpened) if( MoverParameters->Doors.instances[side::left].is_open )
{ // są otwarte { // są otwarte
if (!into) // jeśli zamykanie if (!into) // jeśli zamykanie
{ {
@@ -6443,7 +6306,7 @@ void TDynamicObject::ParamSet(int what, int into)
} }
} }
if (what & 2) // prawe działają niezależnie od lewych if (what & 2) // prawe działają niezależnie od lewych
if (MoverParameters->DoorRightOpened) if( MoverParameters->Doors.instances[side::right].is_open )
{ // są otwarte { // są otwarte
if (!into) // jeśli zamykanie if (!into) // jeśli zamykanie
{ {
@@ -6998,7 +6861,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
if( false == motorblowers.empty() ) { if( false == motorblowers.empty() ) {
for( auto &blowersound : motorblowers ) { for( auto &blowersound : motorblowers ) {
// match the motor blower and the sound source based on whether they're located in the front or the back of the vehicle // match the motor blower and the sound source based on whether they're located in the front or the back of the vehicle
auto const &blower { Vehicle.MotorBlowers[ ( blowersound.offset().z > 0 ? side::front : side::rear ) ] }; auto const &blower { Vehicle.MotorBlowers[ ( blowersound.offset().z > 0 ? end::front : end::rear ) ] };
if( blower.revolutions > 1 ) { if( blower.revolutions > 1 ) {
blowersound blowersound
@@ -7183,7 +7046,7 @@ vehicle_table::update_traction( TDynamicObject *Vehicle ) {
// pętla po pantografach // pętla po pantografach
auto pantograph { Vehicle->pants[ pantographindex ].fParamPants }; auto pantograph { Vehicle->pants[ pantographindex ].fParamPants };
if( true == ( if( true == (
pantographindex == side::front ? pantographindex == end::front ?
Vehicle->MoverParameters->PantFrontUp : Vehicle->MoverParameters->PantFrontUp :
Vehicle->MoverParameters->PantRearUp ) ) { Vehicle->MoverParameters->PantRearUp ) ) {
// jeśli pantograf podniesiony // jeśli pantograf podniesiony

View File

@@ -271,12 +271,6 @@ private:
public: public:
TAnim *pants; // indeks obiektu animującego dla pantografu 0 TAnim *pants; // indeks obiektu animującego dla pantografu 0
double NoVoltTime; // czas od utraty zasilania double NoVoltTime; // czas od utraty zasilania
float DoorDelayL{ 0.f }; // left side door closing delay timer
float DoorDelayR{ 0.f }; // right side door closing delay timer
double dDoorMoveL; // NBMX
double dDoorMoveR; // NBMX
double dDoorstepMoveL{ 0.0 };
double dDoorstepMoveR{ 0.0 };
double dMirrorMoveL{ 0.0 }; double dMirrorMoveL{ 0.0 };
double dMirrorMoveR{ 0.0 }; double dMirrorMoveR{ 0.0 };
TSubModel *smBrakeSet; // nastawa hamulca (wajcha) TSubModel *smBrakeSet; // nastawa hamulca (wajcha)
@@ -316,6 +310,7 @@ private:
sound_source unlock { sound_placement::general }; sound_source unlock { sound_placement::general };
sound_source step_open { sound_placement::general }; sound_source step_open { sound_placement::general };
sound_source step_close { sound_placement::general }; sound_source step_close { sound_placement::general };
side placement {};
}; };
struct exchange_sounds { struct exchange_sounds {
@@ -621,7 +616,7 @@ private:
void RadioStop(); void RadioStop();
void Damage(char flag); void Damage(char flag);
void RaLightsSet(int head, int rear); void RaLightsSet(int head, int rear);
int LightList( side const Side ) const { return iInventory[ Side ]; } int LightList( end const Side ) const { return iInventory[ Side ]; }
void set_cab_lights( int const Cab, float const Level ); void set_cab_lights( int const Cab, float const Level );
TDynamicObject * FirstFind(int &coupler_nr, int cf = 1); TDynamicObject * FirstFind(int &coupler_nr, int cf = 1);
float GetEPP(); // wyliczanie sredniego cisnienia w PG float GetEPP(); // wyliczanie sredniego cisnienia w PG

View File

@@ -138,10 +138,16 @@ static int const ctrain_scndpneumatic = 32; //przewody 8 atm (żółte; zasilani
static int const ctrain_heating = 64; //przewody ogrzewania WN static int const ctrain_heating = 64; //przewody ogrzewania WN
static int const ctrain_depot = 128; //nie rozłączalny podczas zwykłych manewrów (międzyczłonowy), we wpisie wartość ujemna static int const ctrain_depot = 128; //nie rozłączalny podczas zwykłych manewrów (międzyczłonowy), we wpisie wartość ujemna
// vehicle sides; exclusive // vehicle sides; exclusive
enum side { enum end {
front = 0, front = 0,
rear rear
}; };
enum side {
right = 0,
left = 1
};
// possible coupling types; can be combined // possible coupling types; can be combined
enum coupling { enum coupling {
faux = 0x0, faux = 0x0,
@@ -677,6 +683,54 @@ private:
bool breaker { true }; // device is allowed to operate bool breaker { true }; // device is allowed to operate
}; };
// basic approximation of doors
struct basic_door {
// config
// ld inputs
bool open_permit { false }; // door can be opened
bool local_open { false }; // local attempt to open the door
bool local_close { false }; // local attempt to close the door
bool remote_open { false }; // received remote signal to open the door
bool remote_close { false }; // received remote signal to close the door
// internal data
float auto_timer { -1.f }; // delay between activation of open state and closing state for automatic doors
float close_delay { 0.f }; // delay between activation of closing state and actual closing
float position { 0.f }; // current shift of the door from the closed position
float step_position { 0.f }; // current shift of the movable step from the retracted position
// ld outputs
bool is_closed { true }; // the door is fully closed
bool is_closing { false }; // the door is currently closing
bool is_opening { false }; // the door is currently opening
bool is_open { false }; // the door is fully open
};
struct door_data {
// config
control_t open_control { control_t::passenger };
float open_rate { 1.f };
control_t close_control { control_t::passenger };
float close_rate { 1.f };
float close_delay { 0.f };
int type { 2 };
float range { 0.f }; // extent of primary move/rotation
float range_out { 0.f }; // extent of shift outward, applicable for plug doors
int step_type { 2 };
float step_rate { 0.5f };
float step_range { 0.f };
bool has_lock { false };
bool has_warning { false };
bool has_autowarning { false };
float auto_duration { -1.f }; // automatic door closure delay period
float auto_velocity { -1.f }; // automatic door closure velocity threshold
// ld inputs
bool lock_enabled { true };
bool open_permit { true };
// vehicle parts
std::array<basic_door, 2> instances; // door on the right and left side of the vehicle
// ld outputs
bool is_locked { false };
};
struct water_heater { struct water_heater {
// config // config
struct heater_config_t { struct heater_config_t {
@@ -983,6 +1037,7 @@ public:
float MaxLoad = 0.f; /*masa w T lub ilosc w sztukach - ladownosc*/ float MaxLoad = 0.f; /*masa w T lub ilosc w sztukach - ladownosc*/
double OverLoadFactor = 0.0; /*ile razy moze byc przekroczona ladownosc*/ double OverLoadFactor = 0.0; /*ile razy moze byc przekroczona ladownosc*/
float LoadSpeed = 0.f; float UnLoadSpeed = 0.f;/*szybkosc na- i rozladunku jednostki/s*/ float LoadSpeed = 0.f; float UnLoadSpeed = 0.f;/*szybkosc na- i rozladunku jednostki/s*/
#ifdef EU07_USEOLDDOORCODE
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*/
@@ -994,6 +1049,7 @@ public:
double PlatformSpeed = 0.5; /*szybkosc stopnia*/ double PlatformSpeed = 0.5; /*szybkosc stopnia*/
double PlatformMaxShift { 0.0 }; /*wysuniecie stopnia*/ double PlatformMaxShift { 0.0 }; /*wysuniecie stopnia*/
int PlatformOpenMethod { 2 }; /*sposob animacji stopnia*/ int PlatformOpenMethod { 2 }; /*sposob animacji stopnia*/
#endif
double MirrorMaxShift { 90.0 }; double MirrorMaxShift { 90.0 };
bool ScndS = false; /*Czy jest bocznikowanie na szeregowej*/ bool ScndS = false; /*Czy jest bocznikowanie na szeregowej*/
double SpeedCtrlDelay = 2; /*opoznienie dzialania tempomatu z wybieralna predkoscia*/ double SpeedCtrlDelay = 2; /*opoznienie dzialania tempomatu z wybieralna predkoscia*/
@@ -1057,6 +1113,7 @@ public:
bool WaterCircuitsLink { false }; // optional connection between water circuits bool WaterCircuitsLink { false }; // optional connection between water circuits
heat_data dizel_heat; heat_data dizel_heat;
std::array<cooling_fan, 2> MotorBlowers; std::array<cooling_fan, 2> MotorBlowers;
door_data Doors;
int BrakeCtrlPos = -2; /*nastawa hamulca zespolonego*/ int BrakeCtrlPos = -2; /*nastawa hamulca zespolonego*/
double BrakeCtrlPosR = 0.0; /*nastawa hamulca zespolonego - plynna dla FV4a*/ double BrakeCtrlPosR = 0.0; /*nastawa hamulca zespolonego - plynna dla FV4a*/
@@ -1200,13 +1257,14 @@ public:
std::string LoadQuantity; // jednostki miary std::string LoadQuantity; // jednostki miary
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
#ifdef EU07_USEOLDDOORCODE
bool DoorBlocked = false; //Czy jest blokada drzwi bool DoorBlocked = false; //Czy jest blokada drzwi
bool DoorLockEnabled { true }; bool DoorLockEnabled { true };
bool DoorLeftOpened = false; //stan drzwi bool DoorLeftOpened = false; //stan drzwi
double DoorLeftOpenTimer { -1.0 }; // left door closing timer for automatic door type double DoorLeftOpenTimer { -1.0 }; // left door closing timer for automatic door type
bool DoorRightOpened = false; bool DoorRightOpened = false;
double DoorRightOpenTimer{ -1.0 }; // right door closing timer for automatic door type double DoorRightOpenTimer{ -1.0 }; // right door closing timer for automatic door type
#endif
bool PantFrontUp = false; //stan patykow 'Winger 160204 bool PantFrontUp = false; //stan patykow 'Winger 160204
bool PantRearUp = false; bool PantRearUp = false;
bool PantFrontSP = true; //dzwiek patykow 'Winger 010304 bool PantFrontSP = true; //dzwiek patykow 'Winger 010304
@@ -1360,8 +1418,8 @@ public:
bool FuelPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // fuel pump state toggle bool FuelPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // fuel pump state toggle
bool OilPumpSwitch( bool State, range_t const Notify = range_t::consist ); // oil pump state toggle bool OilPumpSwitch( bool State, range_t const Notify = range_t::consist ); // oil pump state toggle
bool OilPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // oil pump state toggle bool OilPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // oil pump state toggle
bool MotorBlowersSwitch( bool State, side const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle bool MotorBlowersSwitch( bool State, end const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle
bool MotorBlowersSwitchOff( bool State, side const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle bool MotorBlowersSwitchOff( bool State, end const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle
bool MainSwitch( bool const State, range_t const Notify = range_t::consist );/*! wylacznik glowny*/ bool MainSwitch( bool const State, range_t const Notify = range_t::consist );/*! wylacznik glowny*/
void MainSwitch_( bool const State ); void MainSwitch_( bool const State );
bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/ bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/
@@ -1414,11 +1472,11 @@ public:
/* funckje dla wagonow*/ /* funckje dla wagonow*/
bool AssignLoad( std::string const &Name, float const Amount = 0.f ); bool AssignLoad( std::string const &Name, float const Amount = 0.f );
bool LoadingDone(double LSpeed, std::string const &Loadname); bool LoadingDone(double LSpeed, std::string const &Loadname);
bool DoorLeft(bool State, range_t const Notify = range_t::consist ); //obsluga drzwi lewych bool PermitDoors( side const Door, range_t const Notify = range_t::consist );
bool DoorRight(bool State, range_t const Notify = range_t::consist ); //obsluga drzwi prawych bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist );
bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi bool LockDoors( bool const State, range_t const Notify = range_t::consist );
bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning
void update_autonomous_doors( double const Deltatime ); // automatic door controller update void update_doors( double const Deltatime ); // door controller update
/* funkcje dla samochodow*/ /* funkcje dla samochodow*/
bool ChangeOffsetH(double DeltaOffset); bool ChangeOffsetH(double DeltaOffset);

View File

@@ -815,8 +815,8 @@ void TMoverParameters::UpdateBatteryVoltage(double dt)
// HACK: emulate low voltage generator powered directly by the diesel engine // HACK: emulate low voltage generator powered directly by the diesel engine
auto const converteractive{ ( auto const converteractive{ (
( ConverterFlag ) ( ConverterFlag )
|| ( ( ( Couplers[ side::front ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ side::front ].Connected->ConverterFlag ) || ( ( ( Couplers[ end::front ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ end::front ].Connected->ConverterFlag )
|| ( ( ( Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ side::rear ].Connected->ConverterFlag ) ) || ( ( ( Couplers[ end::rear ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ end::rear ].Connected->ConverterFlag ) )
|| ( ( EngineType == TEngineType::DieselElectric ) && ( true == Mains ) ) || ( ( EngineType == TEngineType::DieselElectric ) && ( true == Mains ) )
|| ( ( EngineType == TEngineType::DieselEngine ) && ( true == Mains ) ) }; || ( ( EngineType == TEngineType::DieselEngine ) && ( true == Mains ) ) };
@@ -1119,7 +1119,7 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
for( int side = 0; side < 2; ++side ) { for( int side = 0; side < 2; ++side ) {
// przekazywanie napiec // przekazywanie napiec
auto const oppositeside = ( side == side::front ? side::rear : side::front ); auto const oppositeside = ( side == end::front ? end::rear : end::front );
if( ( Couplers[ side ].CouplingFlag & ctrain_power ) if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Heating ) || ( ( Heating )
@@ -1135,7 +1135,7 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
} }
} }
hvc = Couplers[ side::front ].power_high.voltage + Couplers[ side::rear ].power_high.voltage; hvc = Couplers[ end::front ].power_high.voltage + Couplers[ end::rear ].power_high.voltage;
if( std::abs( PantFrontVolt ) + std::abs( PantRearVolt ) < 1.0 ) { if( std::abs( PantFrontVolt ) + std::abs( PantRearVolt ) < 1.0 ) {
// bez napiecia... // bez napiecia...
@@ -1151,9 +1151,9 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { && ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
auto const &connectedcoupler = auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[ Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == side::front ? ( Couplers[ side ].ConnectedNr == end::front ?
side::rear : end::rear :
side::front ) ]; end::front ) ];
Couplers[ side ].power_high.current = Couplers[ side ].power_high.current =
connectedcoupler.power_high.current connectedcoupler.power_high.current
+ Itot * Couplers[ side ].power_high.voltage / hvc; // obciążenie rozkladane stosownie do napiec + Itot * Couplers[ side ].power_high.voltage / hvc; // obciążenie rozkladane stosownie do napiec
@@ -1175,9 +1175,9 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) { && ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
auto const &connectedcoupler = auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[ Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == side::front ? ( Couplers[ side ].ConnectedNr == end::front ?
side::rear : end::rear :
side::front ) ]; end::front ) ];
TotalCurrent += connectedcoupler.power_high.current; TotalCurrent += connectedcoupler.power_high.current;
Couplers[ side ].power_high.current = 0.0; Couplers[ side ].power_high.current = 0.0;
} }
@@ -1465,7 +1465,7 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
} }
BrakeSlippingTimer += Deltatime; BrakeSlippingTimer += Deltatime;
// automatic doors // automatic doors
update_autonomous_doors( Deltatime ); update_doors( Deltatime );
} }
double TMoverParameters::ShowEngineRotation(int VehN) double TMoverParameters::ShowEngineRotation(int VehN)
@@ -2643,7 +2643,7 @@ bool TMoverParameters::OilPumpSwitchOff( bool State, range_t const Notify ) {
return ( OilPump.is_disabled != initialstate ); return ( OilPump.is_disabled != initialstate );
} }
bool TMoverParameters::MotorBlowersSwitch( bool State, side const Side, range_t const Notify ) { bool TMoverParameters::MotorBlowersSwitch( bool State, end const Side, range_t const Notify ) {
auto &fan { MotorBlowers[ Side ] }; auto &fan { MotorBlowers[ Side ] };
@@ -2659,7 +2659,7 @@ bool TMoverParameters::MotorBlowersSwitch( bool State, side const Side, range_t
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
SendCtrlToNext( SendCtrlToNext(
( Side == side::front ? "MotorBlowersFrontSwitch" : "MotorBlowersRearSwitch" ), ( Side == end::front ? "MotorBlowersFrontSwitch" : "MotorBlowersRearSwitch" ),
( fan.is_enabled ? 1 : 0 ), ( fan.is_enabled ? 1 : 0 ),
CabNo, CabNo,
( Notify == range_t::unit ? ( Notify == range_t::unit ?
@@ -2670,7 +2670,7 @@ bool TMoverParameters::MotorBlowersSwitch( bool State, side const Side, range_t
return ( fan.is_enabled != initialstate ); return ( fan.is_enabled != initialstate );
} }
bool TMoverParameters::MotorBlowersSwitchOff( bool State, side const Side, range_t const Notify ) { bool TMoverParameters::MotorBlowersSwitchOff( bool State, end const Side, range_t const Notify ) {
auto &fan { MotorBlowers[ Side ] }; auto &fan { MotorBlowers[ Side ] };
@@ -2686,7 +2686,7 @@ bool TMoverParameters::MotorBlowersSwitchOff( bool State, side const Side, range
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
SendCtrlToNext( SendCtrlToNext(
( Side == side::front ? "MotorBlowersFrontSwitchOff" : "MotorBlowersRearSwitchOff" ), ( Side == end::front ? "MotorBlowersFrontSwitchOff" : "MotorBlowersRearSwitchOff" ),
( fan.is_disabled ? 1 : 0 ), ( fan.is_disabled ? 1 : 0 ),
CabNo, CabNo,
( Notify == range_t::unit ? ( Notify == range_t::unit ?
@@ -3314,11 +3314,11 @@ void TMoverParameters::CompressorCheck(double dt)
{ // sprawdzić możliwe warunki wyłączenia sprężarki { // sprawdzić możliwe warunki wyłączenia sprężarki
if (CompressorPower == 5) // jeśli zasilanie z sąsiedniego członu if (CompressorPower == 5) // jeśli zasilanie z sąsiedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if( Couplers[ side::rear ].Connected != NULL ) { if( Couplers[ end::rear ].Connected != NULL ) {
CompressorFlag = ( CompressorFlag = (
( ( Couplers[ side::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) ( ( Couplers[ end::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal ) && ( CompressorAllowLocal )
&& ( Couplers[ side::rear ].Connected->ConverterFlag ) ); && ( Couplers[ end::rear ].Connected->ConverterFlag ) );
} }
else { else {
// bez tamtego członu nie zadziała // bez tamtego członu nie zadziała
@@ -3327,11 +3327,11 @@ void TMoverParameters::CompressorCheck(double dt)
} }
else if (CompressorPower == 4) // jeśli zasilanie z poprzedniego członu else if (CompressorPower == 4) // jeśli zasilanie z poprzedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if( Couplers[ side::front ].Connected != NULL ) { if( Couplers[ end::front ].Connected != NULL ) {
CompressorFlag = ( CompressorFlag = (
( ( Couplers[ side::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) ( ( Couplers[ end::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal ) && ( CompressorAllowLocal )
&& ( Couplers[ side::front ].Connected->ConverterFlag ) ); && ( Couplers[ end::front ].Connected->ConverterFlag ) );
} }
else { else {
CompressorFlag = false; // bez tamtego członu nie zadziała CompressorFlag = false; // bez tamtego członu nie zadziała
@@ -3390,11 +3390,11 @@ void TMoverParameters::CompressorCheck(double dt)
// or if the switch is on and the pressure isn't maxed // or if the switch is on and the pressure isn't maxed
if( CompressorPower == 5 ) // jeśli zasilanie z następnego członu if( CompressorPower == 5 ) // jeśli zasilanie z następnego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if( Couplers[ side::rear ].Connected != NULL ) { if( Couplers[ end::rear ].Connected != NULL ) {
CompressorFlag = ( CompressorFlag = (
( ( Couplers[ side::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) ( ( Couplers[ end::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal ) && ( CompressorAllowLocal )
&& ( Couplers[ side::rear ].Connected->ConverterFlag ) ); && ( Couplers[ end::rear ].Connected->ConverterFlag ) );
} }
else { else {
// bez tamtego członu nie zadziała // bez tamtego członu nie zadziała
@@ -3403,11 +3403,11 @@ void TMoverParameters::CompressorCheck(double dt)
} }
else if( CompressorPower == 4 ) // jeśli zasilanie z poprzedniego członu else if( CompressorPower == 4 ) // jeśli zasilanie z poprzedniego członu
{ // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1) { // zasilanie sprężarki w członie ra z członu silnikowego (sprzęg 1)
if( Couplers[ side::front ].Connected != NULL ) { if( Couplers[ end::front ].Connected != NULL ) {
CompressorFlag = ( CompressorFlag = (
( ( Couplers[ side::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) ) ( ( Couplers[ end::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal ) && ( CompressorAllowLocal )
&& ( Couplers[ side::front ].Connected->ConverterFlag ) ); && ( Couplers[ end::front ].Connected->ConverterFlag ) );
} }
else { else {
CompressorFlag = false; // bez tamtego członu nie zadziała CompressorFlag = false; // bez tamtego członu nie zadziała
@@ -3961,15 +3961,15 @@ void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer)
Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo; Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo;
} // bo nie dzialalo } // bo nie dzialalo
else if( ( EngineType == TEngineType::ElectricInductionMotor ) else if( ( EngineType == TEngineType::ElectricInductionMotor )
|| ( ( ( Couplers[ side::front ].CouplingFlag & ctrain_power ) == ctrain_power ) || ( ( ( Couplers[ end::front ].CouplingFlag & ctrain_power ) == ctrain_power )
|| ( ( Couplers[ side::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) { || ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) {
// potem ulepszyc! pantogtrafy! // potem ulepszyc! pantogtrafy!
Voltage = Voltage =
std::max( std::max(
RunningTraction.TractionVoltage, RunningTraction.TractionVoltage,
std::max( std::max(
Couplers[ side::front ].power_high.voltage, Couplers[ end::front ].power_high.voltage,
Couplers[ side::rear ].power_high.voltage ) ); Couplers[ end::rear ].power_high.voltage ) );
} }
else { else {
Voltage = 0; Voltage = 0;
@@ -5058,8 +5058,10 @@ double TMoverParameters::TractionForce( double dt ) {
} }
dtrans = Hamulec->GetEDBCP(); dtrans = Hamulec->GetEDBCP();
if (((DoorLeftOpened) || (DoorRightOpened))) if( ( ( false == Doors.instances[ side::left ].is_closed )
|| ( false == Doors.instances[ side::right ].is_closed ) ) ) {
DynamicBrakeFlag = true; DynamicBrakeFlag = true;
}
else if (((dtrans < 0.25) && (LocHandle->GetCP() < 0.25) && (AnPos < 0.01)) || else if (((dtrans < 0.25) && (LocHandle->GetCP() < 0.25) && (AnPos < 0.01)) ||
((dtrans < 0.25) && (ShuntModeAllow) && (LocalBrakePosA < 0.01))) ((dtrans < 0.25) && (ShuntModeAllow) && (LocalBrakePosA < 0.01)))
DynamicBrakeFlag = false; DynamicBrakeFlag = false;
@@ -6719,49 +6721,64 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn
return ( LoadStatus >= 4 ); return ( LoadStatus >= 4 );
} }
// ************************************************************************************************* bool TMoverParameters::PermitDoors( side const Door, range_t const Notify ) {
// Q: 20160713
// Zwraca informacje o działającej blokadzie drzwi bool const initialstate { Doors.instances[Door].open_permit };
// *************************************************************************************************
bool TMoverParameters::DoorBlockedFlag( void ) { if( ( true == Battery )
// TBD: configurable lock activation threshold? && ( false == Doors.is_locked ) ) {
return (
( true == DoorBlocked ) Doors.instances[ Door ].open_permit = true;
&& ( true == DoorLockEnabled ) }
&& ( Vel >= 10.0 ) );
if( Notify != range_t::local ) {
SendCtrlToNext(
"DoorPermit",
( Door == ( CabNo > 0 ? side::left : side::right ) ? // 1=lewe, 2=prawe (swap if reversed)
1 :
2 ),
CabNo,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
return ( Doors.instances[ Door ].open_permit != initialstate );
} }
// ************************************************************************************************* bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) {
// Q: 20160713
// Otwiera / zamyka lewe drzwi
// *************************************************************************************************
// 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, range_t const Notify ) {
if( DoorLeftOpened == State ) { auto &door { Doors.instances[ Door ] };
/*
if( ( State == true ? door.is_open : door.is_closed ) ) {
// TBD: should the command be passed to other vehicles regardless of whether it affected the primary target? // 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) // (for the time being no, methods are often invoked blindly which would lead to commands spam)
return false; return false;
} }
*/
bool result { false }; bool result { false };
if( ( Battery == true ) if( Battery == true ) {
&& ( ( State == false ) // closing door works always, but if the lock is engaged they can't be opened
|| ( DoorBlockedFlag() == false ) ) ) {
DoorLeftOpened = State; if( Notify != range_t::local ) {
result = true; door.remote_open = State;
door.remote_close = ( false == State );
if( DoorCloseCtrl == control_t::autonomous ) {
// activate or disable the door timer depending on whether door were open or closed
// NOTE: this it a local-only operation but shouldn't be an issue as automatic door are operated locally anyway
DoorLeftOpenTimer = (
State == true ?
DoorStayOpen :
-1.0 );
} }
else {
door.local_open = State;
door.local_close = ( false == State );
}
result = true;
/*
// activate or disable the door timer depending on whether door were open or closed
// NOTE: this is a local-only operation but shouldn't be an issue as automatic door are operated locally anyway
door.auto_timer = (
( ( State == true ) && ( Notify == range_t::local ) ) ?
Doors.auto_duration :
-1.0 );
*/
} }
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
@@ -6769,7 +6786,7 @@ bool TMoverParameters::DoorLeft(bool State, range_t const Notify ) {
( State == true ? ( State == true ?
"DoorOpen" : "DoorOpen" :
"DoorClose" ), "DoorClose" ),
( CabNo > 0 ? // 1=lewe, 2=prawe (swap if reversed) ( Door == ( CabNo > 0 ? side::left : side::right ) ? // 1=lewe, 2=prawe (swap if reversed)
1 : 1 :
2 ), 2 ),
CabNo, CabNo,
@@ -6781,54 +6798,24 @@ bool TMoverParameters::DoorLeft(bool State, range_t const Notify ) {
return result; return result;
} }
// ************************************************************************************************* // toggle door lock
// Q: 20160713 bool TMoverParameters::LockDoors( bool const State, range_t const Notify ) {
// Otwiera / zamyka prawe drzwi
// *************************************************************************************************
// 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, range_t const Notify ) {
if( DoorRightOpened == State ) { Doors.lock_enabled = 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 )
&& ( ( State == false )
|| ( DoorBlockedFlag() == false ) ) ) {
DoorRightOpened = State;
result = true;
if( DoorCloseCtrl == control_t::autonomous ) {
// activate or disable the door timer depending on whether door were open or closed
// NOTE: this it a local-only operation but shouldn't be an issue as automatic door are operated locally anyway
DoorRightOpenTimer = (
State == true ?
DoorStayOpen :
-1.0 );
}
}
if( Notify != range_t::local ) { if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych?
SendCtrlToNext( SendCtrlToNext(
"DoorLock",
( State == true ? ( State == true ?
"DoorOpen" : 1 :
"DoorClose" ), 0 ),
( CabNo > 0 ? // 1=lewe, 2=prawe (swap if reversed)
2 :
1 ),
CabNo, CabNo,
( Notify == range_t::unit ? ( Notify == range_t::unit ?
coupling::control | coupling::permanent : coupling::control | coupling::permanent :
coupling::control ) ); coupling::control ) );
} }
return result; return true;
} }
// toggles departure warning // toggles departure warning
@@ -6859,38 +6846,166 @@ TMoverParameters::signal_departure( bool const State, range_t const Notify ) {
// automatic door controller update // automatic door controller update
void void
TMoverParameters::update_autonomous_doors( double const Deltatime ) { TMoverParameters::update_doors( double const Deltatime ) {
if( DoorCloseCtrl != control_t::autonomous ) { return; } if( Doors.range == 0.f ) { return; } // HACK: crude way to distinguish vehicles with actual doors
if( ( false == DoorLeftOpened )
&& ( false == DoorRightOpened ) ) { return; }
if( DoorStayOpen > 0.0 ) { // NBMX Obsluga drzwi, MC: zuniwersalnione
auto const localopencontrol {
( Doors.open_control == control_t::passenger )
|| ( Doors.open_control == control_t::mixed ) };
auto const remoteopencontrol {
( Doors.open_control == control_t::driver )
|| ( Doors.open_control == control_t::conductor )
|| ( Doors.open_control == control_t::mixed ) };
auto const localclosecontrol {
( Doors.close_control == control_t::passenger )
|| ( Doors.close_control == control_t::mixed ) };
auto const remoteclosecontrol {
( Doors.close_control == control_t::driver )
|| ( Doors.close_control == control_t::conductor )
|| ( Doors.close_control == control_t::mixed ) };
Doors.is_locked =
( true == Doors.has_lock )
&& ( true == Doors.lock_enabled )
&& ( Vel >= 10.0 );
for( auto &door : Doors.instances ) {
door.open_permit = door.open_permit && ( false == door.remote_close ) && ( false == Doors.is_locked );
door.is_open =
( door.position >= Doors.range )
&& ( door.step_position >= ( Doors.step_range != 0.f ? 1.f : 0.f ) );
door.is_closed =
( door.position <= 0.f )
&& ( door.step_position <= 0.f );
door.local_open = door.local_open && ( false == door.is_open ) && ( Doors.open_permit || door.open_permit );
door.remote_open = door.remote_open && ( false == door.is_open ) && ( Doors.open_permit || door.open_permit );
door.local_close = door.local_close && ( false == door.is_closed );
door.remote_close = door.remote_close && ( false == door.is_closed );
auto const openrequest {
( localopencontrol && door.local_open )
|| ( remoteopencontrol && door.remote_open ) };
auto const autocloserequest {
( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) )
|| ( ( Doors.auto_duration != -1.f ) && ( door.auto_timer <= 0.f ) ) };
auto const closerequest {
( remoteclosecontrol && door.remote_close )
|| ( localclosecontrol && door.local_close )
|| ( autocloserequest && door.local_close ) };
door.is_opening =
( false == door.is_open )
&& ( false == closerequest )
&& ( door.is_opening || openrequest );
door.is_closing =
( false == door.is_closed )
&& ( false == openrequest )
&& ( door.is_closing || closerequest );
if( true == door.is_opening ) {
door.auto_timer = (
( remoteopencontrol && door.remote_open ) ?
-1.f :
Doors.auto_duration );
}
// doors
if( ( true == door.is_opening )
&& ( door.position < Doors.range ) ) {
// open door
if( ( TrainType == dt_EZT )
|| ( TrainType == dt_DMU ) ) {
// multi-unit vehicles typically open door only after unfolding the doorstep
if( ( Doors.step_range == 0.f ) // no wait if no doorstep
|| ( Doors.step_type == 2 ) // no wait for rotating doorstep
|| ( door.step_position == 1.f ) ) {
door.position = std::min<float>(
Doors.range,
door.position + Doors.open_rate * Deltatime );
}
}
else {
door.position = std::min<float>(
Doors.range,
door.position + Doors.open_rate * Deltatime );
}
door.close_delay = 0.f;
}
if( ( true == door.is_closing )
&& ( door.position > 0.f ) ) {
// close door
door.close_delay += Deltatime;
if( door.close_delay > Doors.close_delay ) {
door.position = std::max<float>(
0.f,
door.position - Doors.close_rate * Deltatime );
}
}
// doorsteps
if( ( true == door.is_opening )
&& ( Doors.step_range != 0.f )
&& ( door.step_position < 1.f ) ) {
// unfold left doorstep
door.step_position = std::min<float>(
1.f,
door.step_position + Doors.step_rate * Deltatime );
}
if( ( true == door.is_closing )
&& ( door.step_position > 0.f )
&& ( door.close_delay > Doors.close_delay ) ) {
// fold left doorstep
if( ( TrainType == dt_EZT )
|| ( TrainType == dt_DMU ) ) {
// multi-unit vehicles typically fold the doorstep only after closing the door
if( door.position == 0.f ) {
door.step_position = std::max<float>(
0.f,
door.step_position - Doors.step_rate * Deltatime );
}
}
else {
door.step_position = std::max<float>(
0.f,
door.step_position - Doors.step_rate * Deltatime );
}
}
}
if( ( false == Doors.instances[side::right].is_open )
&& ( false == Doors.instances[side::left].is_open ) ) { return; }
if( Doors.auto_duration > 0.f ) {
// update door timers if the door close after defined time // update door timers if the door close after defined time
if( DoorLeftOpenTimer >= 0.0 ) { DoorLeftOpenTimer -= Deltatime; } for( auto &door : Doors.instances ) {
if( DoorRightOpenTimer >= 0.0 ) { DoorRightOpenTimer -= Deltatime; }
if( false == door.is_open ) { continue; }
if( door.auto_timer > 0.f ) {
door.auto_timer -= Deltatime;
} }
if( ( LoadStatus & ( 2 | 1 ) ) != 0 ) {
// if there's load exchange in progress, reset the timer(s) for already open doors // if there's load exchange in progress, reset the timer(s) for already open doors
if( true == DoorLeftOpened ) { DoorLeftOpenTimer = DoorStayOpen; } if( ( door.auto_timer != -1.f )
if( true == DoorRightOpened ) { DoorRightOpenTimer = DoorStayOpen; } && ( ( LoadStatus & ( 2 | 1 ) ) != 0 ) ) {
door.auto_timer = Doors.auto_duration;
} }
// the door are closed if their timer goes below 0, or if the vehicle is moving at > 10 km/h }
auto const closingspeed { 10.0 }; }
// NOTE: timer value of 0 is 'special' as it means the door will stay open until vehicle is moving
if( true == DoorLeftOpened ) { // the door are closed if their timer goes below 0, or if the vehicle is moving faster than defined threshold
if( ( ( DoorStayOpen > 0.0 ) && ( DoorLeftOpenTimer < 0.0 ) ) std::array<side, 2> const doorids { side::right, side::left };
|| ( Vel > closingspeed ) ) { for( auto const doorid : doorids ) {
auto const &door { Doors.instances[ doorid ] };
if( true == door.is_open ) {
if( ( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) )
|| ( ( door.auto_timer != -1.f ) && ( door.auto_timer <= 0.f ) ) ) {
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving) // close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving)
DoorLeft( false, range_t::local ); OperateDoors( doorid, false, range_t::local );
} }
} }
if( true == DoorRightOpened ) {
if( ( ( DoorStayOpen > 0.0 ) && ( DoorRightOpenTimer < 0.0 ) )
|| ( Vel > closingspeed ) ) {
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving)
DoorRight( false, range_t::local );
}
} }
} }
@@ -6982,17 +7097,17 @@ std::string TMoverParameters::EngineDescription(int what) const
double TMoverParameters::GetTrainsetVoltage(void) double TMoverParameters::GetTrainsetVoltage(void)
{//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT {//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT
return std::max( return std::max(
( ( ( Couplers[side::front].Connected ) ( ( ( Couplers[end::front].Connected )
&& ( ( Couplers[ side::front ].CouplingFlag & ctrain_power ) && ( ( Couplers[ end::front ].CouplingFlag & ctrain_power )
|| ( ( Heating ) || ( ( Heating )
&& ( Couplers[ side::front ].CouplingFlag & ctrain_heating ) ) ) ) ? && ( Couplers[ end::front ].CouplingFlag & ctrain_heating ) ) ) ) ?
Couplers[side::front].Connected->Couplers[ Couplers[side::front].ConnectedNr ].power_high.voltage : Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage :
0.0 ), 0.0 ),
( ( ( Couplers[side::rear].Connected ) ( ( ( Couplers[end::rear].Connected )
&& ( ( Couplers[ side::rear ].CouplingFlag & ctrain_power ) && ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power )
|| ( ( Heating ) || ( ( Heating )
&& ( Couplers[ side::rear ].CouplingFlag & ctrain_heating ) ) ) ) ? && ( Couplers[ end::rear ].CouplingFlag & ctrain_heating ) ) ) ) ?
Couplers[ side::rear ].Connected->Couplers[ Couplers[ side::rear ].ConnectedNr ].power_high.voltage : Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage :
0.0 ) ); 0.0 ) );
} }
@@ -7976,7 +8091,7 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) {
void TMoverParameters::LoadFIZ_Doors( std::string const &line ) { void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
std::map<std::string, int> doorcontrols { std::map<std::string, control_t> doorcontrols {
{ "Passenger", control_t::passenger }, { "Passenger", control_t::passenger },
{ "AutomaticCtrl", control_t::autonomous }, { "AutomaticCtrl", control_t::autonomous },
{ "DriverCtrl", control_t::driver }, { "DriverCtrl", control_t::driver },
@@ -7986,7 +8101,7 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
// opening method // opening method
{ {
auto lookup = doorcontrols.find( extract_value( "OpenCtrl", line ) ); auto lookup = doorcontrols.find( extract_value( "OpenCtrl", line ) );
DoorOpenCtrl = Doors.open_control =
lookup != doorcontrols.end() ? lookup != doorcontrols.end() ?
lookup->second : lookup->second :
control_t::passenger; control_t::passenger;
@@ -7994,37 +8109,60 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
// closing method // closing method
{ {
auto lookup = doorcontrols.find( extract_value( "CloseCtrl", line ) ); auto lookup = doorcontrols.find( extract_value( "CloseCtrl", line ) );
DoorCloseCtrl = Doors.close_control =
lookup != doorcontrols.end() ? lookup != doorcontrols.end() ?
lookup->second : lookup->second :
control_t::passenger; control_t::passenger;
if( Doors.close_control == control_t::autonomous ) {
// convert legacy method
Doors.close_control = control_t::passenger;
Doors.auto_velocity = 10.0;
}
}
// automatic closing conditions
extract_value( Doors.auto_duration, "DoorStayOpen", line, "" );
extract_value( Doors.auto_velocity, "DoorAutoCloseVel", line, "" );
// operation permit override
{
bool doorneedpermit { false };
extract_value( doorneedpermit, "DoorNeedPermit", line, "" );
Doors.open_permit = ( false == doorneedpermit );
} }
// automatic closing timer
if( DoorCloseCtrl == control_t::autonomous ) { extract_value( DoorStayOpen, "DoorStayOpen", line, "" ); }
extract_value( DoorOpenSpeed, "OpenSpeed", line, "" ); extract_value( Doors.open_rate, "OpenSpeed", line, "" );
extract_value( DoorCloseSpeed, "CloseSpeed", line, "" ); extract_value( Doors.close_rate, "CloseSpeed", line, "" );
extract_value( DoorCloseDelay, "DoorCloseDelay", line, "" ); extract_value( Doors.close_delay, "DoorCloseDelay", line, "" );
extract_value( DoorMaxShiftL, "DoorMaxShiftL", line, "" ); extract_value( Doors.range, "DoorMaxShiftL", line, "" );
extract_value( DoorMaxShiftR, "DoorMaxShiftR", line, "" ); extract_value( Doors.range, "DoorMaxShiftR", line, "" );
extract_value( DoorMaxPlugShift, "DoorMaxShiftPlug", line, "" ); extract_value( Doors.range_out, "DoorMaxShiftPlug", line, "" );
std::string openmethod; extract_value( openmethod, "DoorOpenMethod", line, "" ); std::map<std::string, int> doortypes {
if( openmethod == "Shift" ) { DoorOpenMethod = 1; } //przesuw { "Shift", 1 },
else if( openmethod == "Fold" ) { DoorOpenMethod = 3; } //3 submodele się obracają { "Rotate", 2 },
else if( openmethod == "Plug" ) { DoorOpenMethod = 4; } //odskokowo-przesuwne { "Fold", 3 },
{ "Plug", 4 },
};
// opening method
{
auto lookup = doortypes.find( extract_value( "DoorOpenMethod", line ) );
Doors.type =
lookup != doortypes.end() ?
lookup->second :
2; // default type is plain, rotating door
}
extract_value( DoorClosureWarning, "DoorClosureWarning", line, "" ); extract_value( Doors.has_warning, "DoorClosureWarning", line, "" );
extract_value( DoorClosureWarningAuto, "DoorClosureWarningAuto", line, "" ); extract_value( Doors.has_autowarning, "DoorClosureWarningAuto", line, "" );
extract_value( DoorBlocked, "DoorBlocked", line, "" ); extract_value( Doors.has_lock, "DoorBlocked", line, "" );
extract_value( PlatformSpeed, "PlatformSpeed", line, "" ); extract_value( Doors.step_rate, "PlatformSpeed", line, "" );
extract_value( PlatformMaxShift, "PlatformMaxShift", line, "" ); extract_value( Doors.step_range, "PlatformMaxShift", line, "" );
extract_value( MirrorMaxShift, "MirrorMaxShift", line, "" );
std::string platformopenmethod; extract_value( platformopenmethod, "PlatformOpenMethod", line, "" ); std::string platformopenmethod; extract_value( platformopenmethod, "PlatformOpenMethod", line, "" );
if( platformopenmethod == "Shift" ) { PlatformOpenMethod = 1; } // przesuw if( platformopenmethod == "Shift" ) { Doors.step_type = 1; } // przesuw
extract_value( MirrorMaxShift, "MirrorMaxShift", line, "" );
} }
void TMoverParameters::LoadFIZ_BuffCoupl( std::string const &line, int const Index ) { void TMoverParameters::LoadFIZ_BuffCoupl( std::string const &line, int const Index ) {
@@ -8336,8 +8474,8 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
// traction motor fans // traction motor fans
{ {
auto lookup = starts.find( extract_value( "MotorBlowersStart", line ) ); auto lookup = starts.find( extract_value( "MotorBlowersStart", line ) );
MotorBlowers[side::front].start_type = MotorBlowers[end::front].start_type =
MotorBlowers[side::rear].start_type = MotorBlowers[end::rear].start_type =
lookup != starts.end() ? lookup != starts.end() ?
lookup->second : lookup->second :
start_t::manual; start_t::manual;
@@ -8596,8 +8734,8 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
} }
// traction motors // traction motors
extract_value( MotorBlowers[ side::front ].speed, "MotorBlowersSpeed", Input, "" ); extract_value( MotorBlowers[ end::front ].speed, "MotorBlowersSpeed", Input, "" );
MotorBlowers[ side::rear ] = MotorBlowers[ side::front ]; MotorBlowers[ end::rear ] = MotorBlowers[ end::front ];
} }
void TMoverParameters::LoadFIZ_Switches( std::string const &Input ) { void TMoverParameters::LoadFIZ_Switches( std::string const &Input ) {
@@ -9032,8 +9170,8 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
CompressedVolume = VeselVolume * MinCompressor * ( 9.8 ) / 10.0; CompressedVolume = VeselVolume * MinCompressor * ( 9.8 ) / 10.0;
ScndPipePress = ( ScndPipePress = (
VeselVolume > 0.0 ? CompressedVolume / VeselVolume : VeselVolume > 0.0 ? CompressedVolume / VeselVolume :
( Couplers[ side::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 : ( Couplers[ end::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 :
( Couplers[ side::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 : ( Couplers[ end::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 :
0.0 ); 0.0 );
PipePress = CntrlPipePress; PipePress = CntrlPipePress;
BrakePress = 0.0; BrakePress = 0.0;
@@ -9062,8 +9200,8 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
*/ */
ScndPipePress = ( ScndPipePress = (
VeselVolume > 0.0 ? CompressedVolume / VeselVolume : VeselVolume > 0.0 ? CompressedVolume / VeselVolume :
( Couplers[ side::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 : ( Couplers[ end::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 :
( Couplers[ side::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 : ( Couplers[ end::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 :
0.0 ); 0.0 );
PipePress = LowPipePress; PipePress = LowPipePress;
PipeBrakePress = MaxBrakePress[ 3 ] * 0.5; PipeBrakePress = MaxBrakePress[ 3 ] * 0.5;
@@ -9376,34 +9514,34 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
else if( Command == "MotorBlowersFrontSwitch" ) { else if( Command == "MotorBlowersFrontSwitch" ) {
if( ( MotorBlowers[ side::front ].start_type != start_t::manual ) if( ( MotorBlowers[ end::front ].start_type != start_t::manual )
&& ( MotorBlowers[ side::front ].start_type != start_t::manualwithautofallback ) ) { && ( MotorBlowers[ end::front ].start_type != start_t::manualwithautofallback ) ) {
// automatic device ignores 'manual' state commands // automatic device ignores 'manual' state commands
MotorBlowers[side::front].is_enabled = ( CValue1 == 1 ); MotorBlowers[end::front].is_enabled = ( CValue1 == 1 );
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
else if( Command == "MotorBlowersFrontSwitchOff" ) { else if( Command == "MotorBlowersFrontSwitchOff" ) {
if( ( MotorBlowers[ side::front ].start_type != start_t::manual ) if( ( MotorBlowers[ end::front ].start_type != start_t::manual )
&& ( MotorBlowers[ side::front ].start_type != start_t::manualwithautofallback ) ) { && ( MotorBlowers[ end::front ].start_type != start_t::manualwithautofallback ) ) {
// automatic device ignores 'manual' state commands // automatic device ignores 'manual' state commands
MotorBlowers[side::front].is_disabled = ( CValue1 == 1 ); MotorBlowers[end::front].is_disabled = ( CValue1 == 1 );
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
else if( Command == "MotorBlowersRearSwitch" ) { else if( Command == "MotorBlowersRearSwitch" ) {
if( ( MotorBlowers[ side::rear ].start_type != start_t::manual ) if( ( MotorBlowers[ end::rear ].start_type != start_t::manual )
&& ( MotorBlowers[ side::rear ].start_type != start_t::manualwithautofallback ) ) { && ( MotorBlowers[ end::rear ].start_type != start_t::manualwithautofallback ) ) {
// automatic device ignores 'manual' state commands // automatic device ignores 'manual' state commands
MotorBlowers[side::rear].is_enabled = ( CValue1 == 1 ); MotorBlowers[end::rear].is_enabled = ( CValue1 == 1 );
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
else if( Command == "MotorBlowersRearSwitchOff" ) { else if( Command == "MotorBlowersRearSwitchOff" ) {
if( ( MotorBlowers[ side::rear ].start_type != start_t::manual ) if( ( MotorBlowers[ end::rear ].start_type != start_t::manual )
&& ( MotorBlowers[ side::rear ].start_type != start_t::manualwithautofallback ) ) { && ( MotorBlowers[ end::rear ].start_type != start_t::manualwithautofallback ) ) {
// automatic device ignores 'manual' state commands // automatic device ignores 'manual' state commands
MotorBlowers[side::rear].is_disabled = ( CValue1 == 1 ); MotorBlowers[end::rear].is_disabled = ( CValue1 == 1 );
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
@@ -9492,40 +9630,41 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
else if (Command == "DoorPermit") {
if( ( true == Battery )
&& ( false == Doors.is_locked ) ) {
auto const left { CValue2 > 0 ? 1 : 2 };
auto const right { 3 - left };
if( static_cast<int>( CValue1 ) & right ) {
Doors.instances[ side::right ].open_permit = true;
}
if( static_cast<int>( CValue1 ) & left ) {
Doors.instances[ side::left ].open_permit = true;
}
}
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
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( ( DoorOpenCtrl == control_t::conductor ) if( ( Doors.open_control == control_t::conductor )
|| ( DoorOpenCtrl == control_t::driver ) || ( Doors.open_control == control_t::driver )
|| ( DoorOpenCtrl == control_t::mixed ) ) { || ( Doors.open_control == control_t::mixed ) ) {
// ignore remote command if the door is only operated locally // ignore remote command if the door is only operated locally
if( CValue2 > 0 ) { if( true == Battery ) {
// normalne ustawienie pojazdu
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) { auto const left{ CValue2 > 0 ? 1 : 2 };
DoorLeftOpened = ( auto const right { 3 - left };
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ?
true : if( static_cast<int>( CValue1 ) & right ) {
DoorLeftOpened ); Doors.instances[ side::right ].remote_open = true;
Doors.instances[ side::right ].remote_close = false;
} }
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) { if( static_cast<int>( CValue1 ) & left ) {
DoorRightOpened = ( Doors.instances[ side::left ].remote_open = true;
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ? Doors.instances[ side::left ].remote_close = false;
true :
DoorRightOpened );
}
}
else {
// odwrotne ustawienie pojazdu
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) {
DoorLeftOpened = (
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ?
true :
DoorLeftOpened );
}
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) {
DoorRightOpened = (
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ?
true :
DoorRightOpened );
} }
} }
} }
@@ -9533,43 +9672,34 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
} }
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( ( DoorCloseCtrl == control_t::conductor ) if( ( Doors.open_control == control_t::conductor )
|| ( DoorCloseCtrl == control_t::driver ) || ( Doors.open_control == control_t::driver )
|| ( DoorCloseCtrl == control_t::mixed ) ) { || ( Doors.open_control == control_t::mixed ) ) {
// ignore remote command if the door is only operated locally // ignore remote command if the door is only operated locally
if( CValue2 > 0 ) { if( true == Battery ) {
// normalne ustawienie pojazdu
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) { auto const left{ CValue2 > 0 ? 1 : 2 };
DoorLeftOpened = ( auto const right { 3 - left };
true == Battery ?
false : if( static_cast<int>( CValue1 ) & right ) {
DoorLeftOpened ); Doors.instances[ side::right ].remote_close = true;
Doors.instances[ side::right ].remote_open = false;
} }
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) { if( static_cast<int>( CValue1 ) & left ) {
DoorRightOpened = ( Doors.instances[ side::left ].remote_close = true;
true == Battery ? Doors.instances[ side::left ].remote_open = false;
false :
DoorRightOpened );
}
}
else {
// odwrotne ustawienie pojazdu
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) {
DoorLeftOpened = (
true == Battery ?
false :
DoorLeftOpened );
}
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) {
DoorRightOpened = (
true == Battery ?
false :
DoorRightOpened );
} }
} }
} }
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
} }
else if( Command == "DoorLock" ) {
Doors.lock_enabled = (
CValue1 == 1 ?
true :
false );
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
else if( Command == "DepartureSignal" ) { else if( Command == "DepartureSignal" ) {
DepartureSignal = ( DepartureSignal = (
CValue1 == 1 ? CValue1 == 1 ?

View File

@@ -932,7 +932,7 @@ bool TTrack::AssignEvents() {
m_events = true; m_events = true;
} }
else { else {
ErrorLog( "Bad track: \"" + m_name + "\" can't find assigned event \"" + event.first + "\"" ); ErrorLog( "Bad track: " + ( m_name.empty() ? "unnamed track" : "\"" + m_name + "\"" ) + " can't find assigned event \"" + event.first + "\"" );
lookupfail = true; lookupfail = true;
} }
} }

553
Train.cpp

File diff suppressed because it is too large Load Diff

View File

@@ -139,6 +139,8 @@ class TTrain
void set_master_controller( double const Position ); void set_master_controller( double const Position );
// moves train brake lever to specified position, potentially emits switch sound if conditions are met // moves train brake lever to specified position, potentially emits switch sound if conditions are met
void set_train_brake( double const Position ); void set_train_brake( double const Position );
// potentially moves train brake lever to neutral position
void zero_charging_train_brake();
// sets specified brake acting speed for specified vehicle, potentially updating state of cab controls to match // sets specified brake acting speed for specified vehicle, potentially updating state of cab controls to match
void set_train_brake_speed( TDynamicObject *Vehicle, int const Speed ); void set_train_brake_speed( TDynamicObject *Vehicle, int const Speed );
// sets the motor connector button in paired unit to specified state // sets the motor connector button in paired unit to specified state
@@ -311,10 +313,13 @@ class TTrain
static void OnCommand_doorlocktoggle( TTrain *Train, command_data const &Command ); static void OnCommand_doorlocktoggle( TTrain *Train, command_data const &Command );
static void OnCommand_doortoggleleft( TTrain *Train, command_data const &Command ); static void OnCommand_doortoggleleft( TTrain *Train, command_data const &Command );
static void OnCommand_doortoggleright( TTrain *Train, command_data const &Command ); static void OnCommand_doortoggleright( TTrain *Train, command_data const &Command );
static void OnCommand_doorpermitleft( TTrain *Train, command_data const &Command );
static void OnCommand_doorpermitright( TTrain *Train, command_data const &Command );
static void OnCommand_dooropenleft( TTrain *Train, command_data const &Command ); static void OnCommand_dooropenleft( TTrain *Train, command_data const &Command );
static void OnCommand_dooropenright( TTrain *Train, command_data const &Command ); static void OnCommand_dooropenright( TTrain *Train, command_data const &Command );
static void OnCommand_doorcloseleft( TTrain *Train, command_data const &Command ); static void OnCommand_doorcloseleft( TTrain *Train, command_data const &Command );
static void OnCommand_doorcloseright( TTrain *Train, command_data const &Command ); static void OnCommand_doorcloseright( TTrain *Train, command_data const &Command );
static void OnCommand_dooropenall( TTrain *Train, command_data const &Command );
static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command ); static void OnCommand_doorcloseall( TTrain *Train, command_data const &Command );
static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingincrease( TTrain *Train, command_data const &Command );
static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command ); static void OnCommand_carcouplingdisconnect( TTrain *Train, command_data const &Command );
@@ -438,12 +443,15 @@ public: // reszta może by?publiczna
// oswietlenia kabiny // oswietlenia kabiny
// NBMX wrzesien 2003 - obsluga drzwi // NBMX wrzesien 2003 - obsluga drzwi
TGauge ggDoorLeftPermitButton;
TGauge ggDoorRightPermitButton;
TGauge ggDoorLeftButton; TGauge ggDoorLeftButton;
TGauge ggDoorRightButton; TGauge ggDoorRightButton;
TGauge ggDoorLeftOnButton; TGauge ggDoorLeftOnButton;
TGauge ggDoorRightOnButton; TGauge ggDoorRightOnButton;
TGauge ggDoorLeftOffButton; TGauge ggDoorLeftOffButton;
TGauge ggDoorRightOffButton; TGauge ggDoorRightOffButton;
TGauge ggDoorAllOnButton;
TGauge ggDoorAllOffButton; TGauge ggDoorAllOffButton;
TGauge ggDepartureSignalButton; TGauge ggDepartureSignalButton;
@@ -542,6 +550,7 @@ public: // reszta może by?publiczna
TButton btLampkaPrzekrMaxSila; TButton btLampkaPrzekrMaxSila;
TButton btLampkaDoorLeft; TButton btLampkaDoorLeft;
TButton btLampkaDoorRight; TButton btLampkaDoorRight;
TButton btLampkaDoors;
TButton btLampkaDepartureSignal; TButton btLampkaDepartureSignal;
TButton btLampkaBlokadaDrzwi; TButton btLampkaBlokadaDrzwi;
TButton btLampkaDoorLockOff; TButton btLampkaDoorLockOff;

View File

@@ -142,8 +142,11 @@ commanddescription_sequence Commands_descriptions = {
{ "carcouplingdisconnect", command_target::vehicle }, { "carcouplingdisconnect", command_target::vehicle },
{ "doortoggleleft", command_target::vehicle }, { "doortoggleleft", command_target::vehicle },
{ "doortoggleright", command_target::vehicle }, { "doortoggleright", command_target::vehicle },
{ "doorpermitleft", command_target::vehicle },
{ "doorpermitright", command_target::vehicle },
{ "dooropenleft", command_target::vehicle }, { "dooropenleft", command_target::vehicle },
{ "dooropenright", command_target::vehicle }, { "dooropenright", command_target::vehicle },
{ "dooropenall", command_target::vehicle },
{ "doorcloseleft", command_target::vehicle }, { "doorcloseleft", command_target::vehicle },
{ "doorcloseright", command_target::vehicle }, { "doorcloseright", command_target::vehicle },
{ "doorcloseall", command_target::vehicle }, { "doorcloseall", command_target::vehicle },

View File

@@ -135,8 +135,11 @@ enum class user_command {
carcouplingdisconnect, carcouplingdisconnect,
doortoggleleft, doortoggleleft,
doortoggleright, doortoggleright,
doorpermitleft,
doorpermitright,
dooropenleft, dooropenleft,
dooropenright, dooropenright,
dooropenall,
doorcloseleft, doorcloseleft,
doorcloseright, doorcloseright,
doorcloseall, doorcloseall,

View File

@@ -924,7 +924,7 @@ driver_mode::ExternalView() {
switch( m_externalviewmode ) { switch( m_externalviewmode ) {
case view::consistfront: { case view::consistfront: {
// bind camera with the vehicle // bind camera with the vehicle
auto *owner { vehicle->Mechanik->Vehicle( side::front ) }; auto *owner { vehicle->Mechanik->Vehicle( end::front ) };
Camera.m_owner = owner; Camera.m_owner = owner;
@@ -955,7 +955,7 @@ driver_mode::ExternalView() {
} }
case view::consistrear: { case view::consistrear: {
// bind camera with the vehicle // bind camera with the vehicle
auto *owner { vehicle->Mechanik->Vehicle( side::rear ) }; auto *owner { vehicle->Mechanik->Vehicle( end::rear ) };
Camera.m_owner = owner; Camera.m_owner = owner;
@@ -985,7 +985,7 @@ driver_mode::ExternalView() {
break; break;
} }
case view::bogie: { case view::bogie: {
auto *owner { vehicle->Mechanik->Vehicle( side::front ) }; auto *owner { vehicle->Mechanik->Vehicle( end::front ) };
Camera.m_owner = owner; Camera.m_owner = owner;

View File

@@ -551,6 +551,12 @@ drivermouse_input::default_bindings() {
{ "stlinoff_bt:", { { "stlinoff_bt:", {
user_command::motorconnectorsopen, user_command::motorconnectorsopen,
user_command::none } }, user_command::none } },
{ "doorleftpermit_sw:", {
user_command::doorpermitleft,
user_command::none } },
{ "doorrightpermit_sw:", {
user_command::doorpermitright,
user_command::none } },
{ "door_left_sw:", { { "door_left_sw:", {
user_command::doortoggleleft, user_command::doortoggleleft,
user_command::none } }, user_command::none } },
@@ -569,6 +575,9 @@ drivermouse_input::default_bindings() {
{ "doorrightoff_sw:", { { "doorrightoff_sw:", {
user_command::doorcloseright, user_command::doorcloseright,
user_command::none } }, user_command::none } },
{ "doorallon_sw:", {
user_command::dooropenall,
user_command::none } },
{ "dooralloff_sw:", { { "dooralloff_sw:", {
user_command::doorcloseall, user_command::doorcloseall,
user_command::none } }, user_command::none } },

View File

@@ -393,8 +393,8 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
mover.EngineDescription( 0 ).c_str(), mover.EngineDescription( 0 ).c_str(),
// TODO: put wheel flat reporting in the enginedescription() // TODO: put wheel flat reporting in the enginedescription()
std::string( mover.WheelFlat > 0.01 ? " Flat: " + to_string( mover.WheelFlat, 1 ) + " mm" : "" ).c_str(), std::string( mover.WheelFlat > 0.01 ? " Flat: " + to_string( mover.WheelFlat, 1 ) + " mm" : "" ).c_str(),
update_vehicle_coupler( side::front ).c_str(), update_vehicle_coupler( end::front ).c_str(),
update_vehicle_coupler( side::rear ).c_str() ); update_vehicle_coupler( end::rear ).c_str() );
Output.emplace_back( std::string{ m_buffer.data() }, Global.UITextColor ); Output.emplace_back( std::string{ m_buffer.data() }, Global.UITextColor );
@@ -419,13 +419,13 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
std::string( isplayervehicle ? locale::strings[ locale::string::debug_vehicle_radio ] + ( mover.Radio ? std::to_string( m_input.train->RadioChannel() ) : "-" ) : "" ).c_str(), std::string( isplayervehicle ? locale::strings[ locale::string::debug_vehicle_radio ] + ( mover.Radio ? std::to_string( m_input.train->RadioChannel() ) : "-" ) : "" ).c_str(),
std::string( isdieselenginepowered ? locale::strings[ locale::string::debug_vehicle_oilpressure ] + to_string( mover.OilPump.pressure, 2 ) : "" ).c_str(), std::string( isdieselenginepowered ? locale::strings[ locale::string::debug_vehicle_oilpressure ] + to_string( mover.OilPump.pressure, 2 ) : "" ).c_str(),
// power transfers // power transfers
mover.Couplers[ side::front ].power_high.voltage, mover.Couplers[ end::front ].power_high.voltage,
mover.Couplers[ side::front ].power_high.current, mover.Couplers[ end::front ].power_high.current,
std::string( mover.Couplers[ side::front ].power_high.local ? "" : "-" ).c_str(), std::string( mover.Couplers[ end::front ].power_high.local ? "" : "-" ).c_str(),
std::string( vehicle.DirectionGet() ? ":<<:" : ":>>:" ).c_str(), std::string( vehicle.DirectionGet() ? ":<<:" : ":>>:" ).c_str(),
std::string( mover.Couplers[ side::rear ].power_high.local ? "" : "-" ).c_str(), std::string( mover.Couplers[ end::rear ].power_high.local ? "" : "-" ).c_str(),
mover.Couplers[ side::rear ].power_high.voltage, mover.Couplers[ end::rear ].power_high.voltage,
mover.Couplers[ side::rear ].power_high.current ); mover.Couplers[ end::rear ].power_high.current );
Output.emplace_back( m_buffer.data(), Global.UITextColor ); Output.emplace_back( m_buffer.data(), Global.UITextColor );
@@ -443,8 +443,8 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
std::abs( mover.enrot ) * 60, std::abs( mover.enrot ) * 60,
std::abs( mover.nrot ) * mover.Transmision.Ratio * 60, std::abs( mover.nrot ) * mover.Transmision.Ratio * 60,
mover.RventRot * 60, mover.RventRot * 60,
std::abs( mover.MotorBlowers[side::front].revolutions ), std::abs( mover.MotorBlowers[end::front].revolutions ),
std::abs( mover.MotorBlowers[side::rear].revolutions ), std::abs( mover.MotorBlowers[end::rear].revolutions ),
mover.dizel_heat.rpmw, mover.dizel_heat.rpmw,
mover.dizel_heat.rpmw2 ); mover.dizel_heat.rpmw2 );
@@ -536,7 +536,7 @@ debug_panel::update_vehicle_coupler( int const Side ) {
std::string couplerstatus { locale::strings[ locale::string::debug_vehicle_none ] }; std::string couplerstatus { locale::strings[ locale::string::debug_vehicle_none ] };
auto const *connected { ( auto const *connected { (
Side == side::front ? Side == end::front ?
m_input.vehicle->PrevConnected : m_input.vehicle->PrevConnected :
m_input.vehicle->NextConnected ) }; m_input.vehicle->NextConnected ) };

View File

@@ -23,8 +23,8 @@ light_array::insert( TDynamicObject const *Owner ) {
// we're only storing lights for locos, which have two sets of lights, front and rear // we're only storing lights for locos, which have two sets of lights, front and rear
// for a more generic role this function would have to be tweaked to add vehicle type-specific light combinations // for a more generic role this function would have to be tweaked to add vehicle type-specific light combinations
data.emplace_back( Owner, side::front ); data.emplace_back( Owner, end::front );
data.emplace_back( Owner, side::rear ); data.emplace_back( Owner, end::rear );
} }
void void
@@ -44,7 +44,7 @@ light_array::update() {
for( auto &light : data ) { for( auto &light : data ) {
// update light parameters to match current data of the owner // update light parameters to match current data of the owner
if( light.index == side::front ) { if( light.index == end::front ) {
// front light set // front light set
light.position = light.owner->GetPosition() + ( light.owner->VectorFront() * light.owner->GetLength() * 0.4 ); light.position = light.owner->GetPosition() + ( light.owner->VectorFront() * light.owner->GetLength() * 0.4 );
light.direction = glm::make_vec3( light.owner->VectorFront().getArray() ); light.direction = glm::make_vec3( light.owner->VectorFront().getArray() );
@@ -61,7 +61,7 @@ light_array::update() {
|| ( true == light.owner->MoverParameters->ConverterFlag ) ) { || ( true == light.owner->MoverParameters->ConverterFlag ) ) {
// with power on, the intensity depends on the state of activated switches // with power on, the intensity depends on the state of activated switches
// first we cross-check the list of enabled lights with the lights installed in the vehicle... // first we cross-check the list of enabled lights with the lights installed in the vehicle...
auto const lights { light.owner->iLights[ light.index ] & light.owner->LightList( static_cast<side>( light.index ) ) }; auto const lights { light.owner->iLights[ light.index ] & light.owner->LightList( static_cast<end>( light.index ) ) };
// ...then check their individual state // ...then check their individual state
light.count = 0 light.count = 0
+ ( ( lights & light::headlight_left ) ? 1 : 0 ) + ( ( lights & light::headlight_left ) ? 1 : 0 )

View File

@@ -300,14 +300,19 @@ WyslijNamiary(TDynamicObject const *Vehicle)
r.iPar[19] = Vehicle->MoverParameters->MainCtrlActualPos; // Pozycja jezdna r.iPar[19] = Vehicle->MoverParameters->MainCtrlActualPos; // Pozycja jezdna
r.iPar[20] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania r.iPar[20] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[21] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania r.iPar[21] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[22] = Vehicle->MoverParameters->ResistorsFlag * 1 + r.iPar[22] = Vehicle->MoverParameters->ResistorsFlag * 1
Vehicle->MoverParameters->ConverterFlag * 2 + + Vehicle->MoverParameters->ConverterFlag * 2
+Vehicle->MoverParameters->CompressorFlag * 4 + + Vehicle->MoverParameters->CompressorFlag * 4
Vehicle->MoverParameters->Mains * 8 + + Vehicle->MoverParameters->Mains * 8
+Vehicle->MoverParameters->DoorLeftOpened * 16 + #ifdef EU07_USEOLDDOORCODE
Vehicle->MoverParameters->DoorRightOpened * 32 + + Vehicle->MoverParameters->DoorLeftOpened * 16
+Vehicle->MoverParameters->FuseFlag * 64 + + Vehicle->MoverParameters->DoorRightOpened * 32
Vehicle->MoverParameters->DepartureSignal * 128; #else
+ ( false == Vehicle->MoverParameters->Doors.instances[side::left].is_closed ) * 16
+ ( false == Vehicle->MoverParameters->Doors.instances[side::right].is_closed ) * 32
#endif
+ Vehicle->MoverParameters->FuseFlag * 64
+ Vehicle->MoverParameters->DepartureSignal * 128;
// WriteLog("Zapisalem stare"); // WriteLog("Zapisalem stare");
// WriteLog("Mam patykow "+IntToStr(t->DynamicObject->iAnimType[ANIM_PANTS])); // WriteLog("Mam patykow "+IntToStr(t->DynamicObject->iAnimType[ANIM_PANTS]));
for (int p = 0; p < 4; p++) for (int p = 0; p < 4; p++)

View File

@@ -337,8 +337,8 @@ state_serializer::deserialize_node( cParser &Input, scene::scratch_data &Scratch
} }
if( ( vehicle->MoverParameters->CategoryFlag == 1 ) // trains only if( ( vehicle->MoverParameters->CategoryFlag == 1 ) // trains only
&& ( ( ( vehicle->LightList( side::front ) & ( light::headlight_left | light::headlight_right | light::headlight_upper ) ) != 0 ) && ( ( ( vehicle->LightList( end::front ) & ( light::headlight_left | light::headlight_right | light::headlight_upper ) ) != 0 )
|| ( ( vehicle->LightList( side::rear ) & ( light::headlight_left | light::headlight_right | light::headlight_upper ) ) != 0 ) ) ) { || ( ( vehicle->LightList( end::rear ) & ( light::headlight_left | light::headlight_right | light::headlight_upper ) ) != 0 ) ) ) {
simulation::Lights.insert( vehicle ); simulation::Lights.insert( vehicle );
} }
} }
@@ -859,7 +859,7 @@ state_serializer::deserialize_dynamic( cParser &Input, scene::scratch_data &Scra
Scratchpad.trainset.offset -= length; Scratchpad.trainset.offset -= length;
// automatically establish permanent connections for couplers which specify them in their definitions // automatically establish permanent connections for couplers which specify them in their definitions
if( ( coupling != 0 ) if( ( coupling != 0 )
&& ( vehicle->MoverParameters->Couplers[ ( offset == -1.0 ? side::front : side::rear ) ].AllowedFlag & coupling::permanent ) ) { && ( vehicle->MoverParameters->Couplers[ ( offset == -1.0 ? end::front : end::rear ) ].AllowedFlag & coupling::permanent ) ) {
coupling |= coupling::permanent; coupling |= coupling::permanent;
} }
if( true == Scratchpad.trainset.is_open ) { if( true == Scratchpad.trainset.is_open ) {

View File

@@ -103,6 +103,9 @@ init() {
"right door", "right door",
"left door", "left door",
"right door", "right door",
"left door",
"right door",
"all doors",
"all doors", "all doors",
"departure signal", "departure signal",
"upper headlight", "upper headlight",
@@ -241,6 +244,9 @@ init() {
"drzwi prawe", "drzwi prawe",
"drzwi lewe", "drzwi lewe",
"drzwi prawe", "drzwi prawe",
"drzwi lewe",
"drzwi prawe",
"drzwi",
"drzwi", "drzwi",
"sygnal odjazdu", "sygnal odjazdu",
"reflektor gorny", "reflektor gorny",
@@ -345,12 +351,15 @@ init() {
"fuse_bt:", "fuse_bt:",
"converterfuse_bt:", "converterfuse_bt:",
"stlinoff_bt:", "stlinoff_bt:",
"doorleftpermit_sw:",
"doorrightpermit_sw:",
"door_left_sw:", "door_left_sw:",
"door_right_sw:", "door_right_sw:",
"doorlefton_sw:", "doorlefton_sw:",
"doorrighton_sw:", "doorrighton_sw:",
"doorleftoff_sw:", "doorleftoff_sw:",
"doorrightoff_sw:", "doorrightoff_sw:",
"doorallon_sw:",
"dooralloff_sw:", "dooralloff_sw:",
"departure_signal_bt:", "departure_signal_bt:",
"upperlight_sw:", "upperlight_sw:",

View File

@@ -86,12 +86,15 @@ enum string {
cab_fuse_bt, cab_fuse_bt,
cab_converterfuse_bt, cab_converterfuse_bt,
cab_stlinoff_bt, cab_stlinoff_bt,
cab_doorleftpermit_sw,
cab_doorrightpermit_sw,
cab_door_left_sw, cab_door_left_sw,
cab_door_right_sw, cab_door_right_sw,
cab_doorlefton_sw, cab_doorlefton_sw,
cab_doorrighton_sw, cab_doorrighton_sw,
cab_doorleftoff_sw, cab_doorleftoff_sw,
cab_doorrightoff_sw, cab_doorrightoff_sw,
cab_doorallon_sw,
cab_dooralloff_sw, cab_dooralloff_sw,
cab_departure_signal_bt, cab_departure_signal_bt,
cab_upperlight_sw, cab_upperlight_sw,

View File

@@ -1,5 +1,5 @@
#pragma once #pragma once
#define VERSION_MAJOR 19 #define VERSION_MAJOR 19
#define VERSION_MINOR 119 #define VERSION_MINOR 129
#define VERSION_REVISION 0 #define VERSION_REVISION 0