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

Merge branch 'tmj-dev' into milek-dev

This commit is contained in:
milek7
2019-02-21 18:18:32 +01:00
29 changed files with 1460 additions and 1069 deletions

View File

@@ -1007,21 +1007,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ą
@@ -1043,9 +1028,9 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
+ ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute) + ": at " + std::to_string(simulation::Time.data().wHour) + ":" + std::to_string(simulation::Time.data().wMinute)
+ " next " + asNextStop); // informacja + " next " + asNextStop); // informacja
#endif #endif
// update brake settings and ai braking tables // update consist weight, brake settings and ai braking tables
// NOTE: this calculation is expected to run after completing loading/unloading // NOTE: this calculation is expected to run after completing loading/unloading
AutoRewident(); // nastawianie hamulca do jazdy pociągowej CheckVehicles(); // nastawianie hamulca do jazdy pociągowej
if( static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 1 ) ) ) ) % 2 ) { if( static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 1 ) ) ) ) % 2 ) {
// nie podjeżdżać do semafora, jeśli droga nie jest wolna // nie podjeżdżać do semafora, jeśli droga nie jest wolna
@@ -2087,8 +2072,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 );
} }
@@ -2112,12 +2097,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,
@@ -2154,9 +2139,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
@@ -2471,10 +2459,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
@@ -2556,15 +2544,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 mvOccupied->OperateDoors( side::right, false );
if( mvOccupied->DoorLeftOpened ) { mvOccupied->OperateDoors( side::left, false );
mvOccupied->DoorLeft( false );
}
if( mvOccupied->DoorRightOpened ) {
mvOccupied->DoorRight( false );
}
}
if( true == mvControlling->Mains ) { if( true == mvControlling->Mains ) {
mvControlling->CompressorSwitch( false ); mvControlling->CompressorSwitch( false );
@@ -3188,7 +3170,7 @@ void TController::SpeedSet()
// Ra 2014-06: "automatyczna" skrzynia biegów... // Ra 2014-06: "automatyczna" skrzynia biegów...
if (!mvControlling->MotorParam[mvControlling->ScndCtrlPos].AutoSwitch) // gdy biegi ręczne if (!mvControlling->MotorParam[mvControlling->ScndCtrlPos].AutoSwitch) // gdy biegi ręczne
if ((mvControlling->ShuntMode ? mvControlling->AnPos : 1.0) * mvControlling->Vel > if ((mvControlling->ShuntMode ? mvControlling->AnPos : 1.0) * mvControlling->Vel >
0.6 * mvControlling->MotorParam[mvControlling->ScndCtrlPos].mfi) 0.75 * mvControlling->MotorParam[mvControlling->ScndCtrlPos].mfi)
// if (mvControlling->enrot>0.95*mvControlling->dizel_nMmax) //youBy: jeśli obroty > // if (mvControlling->enrot>0.95*mvControlling->dizel_nMmax) //youBy: jeśli obroty >
// 0,95 nmax, wrzuć wyższy bieg - Ra: to nie działa // 0,95 nmax, wrzuć wyższy bieg - Ra: to nie działa
{ // jak prędkość większa niż 0.6 maksymalnej na danym biegu, wrzucić wyższy { // jak prędkość większa niż 0.6 maksymalnej na danym biegu, wrzucić wyższy
@@ -3236,36 +3218,41 @@ 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 ) { auto const prawe = 3 - lewe;
// otwieranie drzwi w pojazdach - flaga zezwolenia była by lepsza
if( vehicle->MoverParameters->DoorOpenCtrl != control_t::passenger ) { if( ( true == pVehicle->MoverParameters->Doors.permit_needed )
// if the door are controlled by the driver, we let the user operate them... && ( true == AIControllFlag ) ) {
if( true == AIControllFlag ) { // grant door control permission if it's not automatic
// ...unless this user is an ai // TBD: stricter requirements?
// Side=platform side (1:left, 2:right, 3:both) if( Side & prawe )
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie pVehicle->MoverParameters->PermitDoors( side::right );
auto const lewe = ( vehicle->DirectionGet() > 0 ) ? 1 : 2; if( Side & lewe )
auto const prawe = 3 - lewe; pVehicle->MoverParameters->PermitDoors( side::left );
if( Side & lewe ) }
vehicle->MoverParameters->DoorLeft( true, range_t::local );
if( Side & prawe ) if( ( pVehicle->MoverParameters->Doors.open_control == control_t::conductor )
vehicle->MoverParameters->DoorRight( true, range_t::local ); || ( ( true == AIControllFlag )
} && ( ( pVehicle->MoverParameters->Doors.open_control == control_t::driver )
} || ( pVehicle->MoverParameters->Doors.open_control == control_t::mixed ) ) ) ) {
// pojazd podłączony z tyłu (patrząc od czoła) // if the door can be operated by the driver we let the user operate them unless this user is an ai
vehicle = vehicle->Next(); // 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( ( false == pVehicle->MoverParameters->Doors.permit_needed )
// the doors are already closed, we can skip all hard work && ( false == doors_open() ) ) {
// 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
@@ -3277,12 +3264,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)
} }
@@ -3305,8 +3302,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;
} }
@@ -3723,8 +3720,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();
@@ -3844,6 +3841,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
@@ -3877,6 +3875,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)
} }
@@ -3936,7 +3943,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 );
} }
@@ -4468,8 +4475,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 );
@@ -4923,6 +4930,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 ) {
@@ -5684,7 +5701,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
@@ -6325,7 +6342,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;

File diff suppressed because it is too large Load Diff

View File

@@ -272,12 +272,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)
@@ -317,6 +311,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 {
@@ -622,7 +617,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

@@ -886,9 +886,14 @@ whois_event::run_() {
auto *targetcell { static_cast<TMemCell *>( std::get<scene::basic_node *>( target ) ) }; auto *targetcell { static_cast<TMemCell *>( std::get<scene::basic_node *>( target ) ) };
if( targetcell == nullptr ) { continue; } if( targetcell == nullptr ) { continue; }
// event effect code // event effect code
// +24: vehicle type, consist brake level, obstacle distance
// +16: load type, load amount, max load amount
// +8: destination, direction, engine power
// +0: train name, station count, stop on next station
if( m_input.flags & flags::load ) { if( m_input.flags & flags::load ) {
// +16 or +24
// jeśli pytanie o ładunek // jeśli pytanie o ładunek
if( m_input.flags & flags::mode_add ) { if( m_input.flags & flags::mode_alt ) {
// jeśli typ pojazdu // jeśli typ pojazdu
// TODO: define and recognize individual request types // TODO: define and recognize individual request types
auto const owner { ( auto const owner { (
@@ -912,7 +917,7 @@ whois_event::run_() {
WriteLog( WriteLog(
"Type: WhoIs (" + to_string( m_input.flags ) + ") - " "Type: WhoIs (" + to_string( m_input.flags ) + ") - "
+ "[name: " + m_activator->MoverParameters->TypeName + "], " + "[type: " + m_activator->MoverParameters->TypeName + "], "
+ "[consist brake level: " + to_string( consistbrakelevel, 2 ) + "], " + "[consist brake level: " + to_string( consistbrakelevel, 2 ) + "], "
+ "[obstacle distance: " + to_string( collisiondistance, 2 ) + " m]" ); + "[obstacle distance: " + to_string( collisiondistance, 2 ) + " m]" );
} }
@@ -931,7 +936,8 @@ whois_event::run_() {
+ "[max load: " + to_string( m_activator->MoverParameters->MaxLoad, 2 ) + "]" ); + "[max load: " + to_string( m_activator->MoverParameters->MaxLoad, 2 ) + "]" );
} }
} }
else if( m_input.flags & flags::mode_add ) { // jeśli miejsce docelowe pojazdu // +8
else if( m_input.flags & flags::mode_alt ) { // jeśli miejsce docelowe pojazdu
targetcell->UpdateValues( targetcell->UpdateValues(
m_activator->asDestination, // adres docelowy m_activator->asDestination, // adres docelowy
m_activator->DirectionGet(), // kierunek pojazdu względem czoła składu (1=zgodny,-1=przeciwny) m_activator->DirectionGet(), // kierunek pojazdu względem czoła składu (1=zgodny,-1=przeciwny)
@@ -944,6 +950,7 @@ whois_event::run_() {
+ "[direction: " + to_string( m_activator->DirectionGet() ) + "], " + "[direction: " + to_string( m_activator->DirectionGet() ) + "], "
+ "[engine power: " + to_string( m_activator->MoverParameters->Power, 2 ) + "]" ); + "[engine power: " + to_string( m_activator->MoverParameters->Power, 2 ) + "]" );
} }
// +0
else if( m_activator->Mechanik ) { else if( m_activator->Mechanik ) {
if( m_activator->Mechanik->Primary() ) { // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera! if( m_activator->Mechanik->Primary() ) { // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera!
targetcell->UpdateValues( targetcell->UpdateValues(

View File

@@ -27,8 +27,10 @@ public:
value_1 = 1 << 1, value_1 = 1 << 1,
value_2 = 1 << 2, value_2 = 1 << 2,
// update values // update values
load = 1 << 3, mode_add = 1 << 3,
mode_add = 1 << 4, // whois
mode_alt = 1 << 3,
load = 1 << 4,
// condition values // condition values
track_busy = 1 << 3, track_busy = 1 << 3,
track_free = 1 << 4, track_free = 1 << 4,

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,
@@ -632,6 +638,20 @@ class TMoverParameters
private: private:
// types // types
// communication cable, exchanging control signals with adjacent vehicle
struct jumper_cable {
// types
using flag_pair = std::pair<bool, bool>;
// members
// booleans
// std::array<bool, 1> flags {};
// boolean pairs, exchanged data is swapped when connected to a matching end (front to front or back to back)
// TBD, TODO: convert to regular bool array for efficiency once it's working?
std::array<flag_pair, 1> flag_pairs {};
// integers
// std::array<int, 1> values {};
};
// basic approximation of a generic device // basic approximation of a generic device
// TBD: inheritance or composition? // TBD: inheritance or composition?
struct basic_device { struct basic_device {
@@ -677,6 +697,58 @@ 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
bool auto_include_remote { false }; // automatic door closure applies also to remote control
bool permit_needed { false };
std::vector<int> permit_presets; // permit presets selectable with preset switch
// ld inputs
bool lock_enabled { true };
// internal data
int permit_preset { -1 }; // curent position of preset selection switch
// 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 +1055,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 +1067,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 +1131,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 +1275,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 +1436,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 +1490,12 @@ 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, bool const State = true, range_t const Notify = range_t::consist );
bool DoorRight(bool State, range_t const Notify = range_t::consist ); //obsluga drzwi prawych bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist );
bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist );
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)
@@ -2653,7 +2653,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 ] };
@@ -2669,7 +2669,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 ?
@@ -2680,7 +2680,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 ] };
@@ -2696,7 +2696,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 ?
@@ -3324,11 +3324,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
@@ -3337,11 +3337,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
@@ -3400,11 +3400,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
@@ -3413,11 +3413,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
@@ -3971,15 +3971,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;
@@ -4605,8 +4605,13 @@ double TMoverParameters::TractionForce( double dt ) {
case TEngineType::ElectricSeriesMotor: { case TEngineType::ElectricSeriesMotor: {
// update the state of voltage relays // update the state of voltage relays
auto const voltage { std::max( GetTrainsetVoltage(), std::abs( RunningTraction.TractionVoltage ) ) }; auto const voltage { std::max( GetTrainsetVoltage(), std::abs( RunningTraction.TractionVoltage ) ) };
NoVoltRelay = ( voltage >= EnginePowerSource.CollectorParameters.MinV ); NoVoltRelay =
OvervoltageRelay = ( voltage <= EnginePowerSource.CollectorParameters.MaxV ) || ( false == EnginePowerSource.CollectorParameters.OVP ); ( EnginePowerSource.SourceType != TPowerSource::CurrentCollector )
|| ( voltage >= EnginePowerSource.CollectorParameters.MinV );
OvervoltageRelay =
( EnginePowerSource.SourceType != TPowerSource::CurrentCollector )
|| ( voltage <= EnginePowerSource.CollectorParameters.MaxV )
|| ( false == EnginePowerSource.CollectorParameters.OVP );
// wywalanie szybkiego z powodu niewłaściwego napięcia // wywalanie szybkiego z powodu niewłaściwego napięcia
EventFlag |= ( ( true == Mains ) EventFlag |= ( ( true == Mains )
&& ( ( false == NoVoltRelay ) || ( false == OvervoltageRelay ) ) && ( ( false == NoVoltRelay ) || ( false == OvervoltageRelay ) )
@@ -5068,8 +5073,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;
@@ -5590,10 +5597,10 @@ bool TMoverParameters::AutoRelayCheck(void)
// sprawdzenie wszystkich warunkow (AutoRelayFlag, AutoSwitch, Im<Imin) // sprawdzenie wszystkich warunkow (AutoRelayFlag, AutoSwitch, Im<Imin)
auto const ARFASI2 { ( auto const ARFASI2 { (
( !AutoRelayFlag ) ( false == AutoRelayFlag )
|| ( ( MotorParam[ ScndCtrlActualPos ].AutoSwitch ) && ( abs( Im ) < Imin ) ) ) }; || ( ( MotorParam[ ScndCtrlActualPos ].AutoSwitch ) && ( abs( Im ) < Imin ) ) ) };
auto const ARFASI { ( auto const ARFASI { (
( !AutoRelayFlag ) ( false == AutoRelayFlag )
|| ( ( RList[ MainCtrlActualPos ].AutoSwitch ) && ( abs( Im ) < Imin ) ) || ( ( RList[ MainCtrlActualPos ].AutoSwitch ) && ( abs( Im ) < Imin ) )
|| ( ( !RList[ MainCtrlActualPos ].AutoSwitch ) && ( RList[ MainCtrlActualPos ].Relay < MainCtrlPos ) ) ) }; || ( ( !RList[ MainCtrlActualPos ].AutoSwitch ) && ( RList[ MainCtrlActualPos ].Relay < MainCtrlPos ) ) ) };
// brak PSR na tej pozycji działa PSR i prąd poniżej progu // brak PSR na tej pozycji działa PSR i prąd poniżej progu
@@ -6729,49 +6736,84 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn
return ( LoadStatus >= 4 ); return ( LoadStatus >= 4 );
} }
// ************************************************************************************************* bool TMoverParameters::ChangeDoorPermitPreset( int const Change, range_t const Notify ) {
// Q: 20160713
// Zwraca informacje o działającej blokadzie drzwi auto const initialstate { Doors.permit_preset };
// *************************************************************************************************
bool TMoverParameters::DoorBlockedFlag( void ) { if( false == Doors.permit_presets.empty() ) {
// TBD: configurable lock activation threshold?
return ( Doors.permit_preset = clamp<int>( Doors.permit_preset + Change, 0, Doors.permit_presets.size() - 1 );
( true == DoorBlocked ) auto const doors { Doors.permit_presets[ Doors.permit_preset ] };
&& ( true == DoorLockEnabled ) auto const permitleft = doors & 1;
&& ( Vel >= 10.0 ) ); auto const permitright = doors & 2;
PermitDoors( ( CabNo > 0 ? side::left : side::right ), permitleft, Notify );
PermitDoors( ( CabNo > 0 ? side::right : side::left ), permitright, Notify );
}
return ( Doors.permit_preset != initialstate );
} }
// ************************************************************************************************* bool TMoverParameters::PermitDoors( 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 ) { bool const initialstate { Doors.instances[Door].open_permit };
if( ( false == Doors.permit_presets.empty() ) // HACK: for cases where preset switch is used before battery
|| ( ( true == Battery )
&& ( false == Doors.is_locked ) ) ) {
Doors.instances[ Door ].open_permit = State;
}
if( Notify != range_t::local ) {
SendCtrlToNext(
"DoorPermit",
( State ? 1 : -1 ) // positive: grant, negative: revoke
* ( 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 ) {
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 ) {
@@ -6779,7 +6821,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,
@@ -6791,54 +6833,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
@@ -6869,39 +6881,178 @@ 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 ) {
// revoke permit if...
door.open_permit =
( true == door.open_permit ) // ...we already have one...
&& ( ( false == Doors.permit_presets.empty() ) // ...there's no permit preset switch...
|| ( ( false == Doors.is_locked ) // ...and the door lock is engaged...
&& ( false == door.remote_close ) ) );// ...or about to be closed
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 ) && ( ( false == Doors.permit_needed ) || door.open_permit );
door.remote_open = door.remote_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || 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 ) )
|| ( ( door.auto_timer != -1.f ) && ( door.auto_timer <= 0.f ) )
|| ( ( Doors.permit_needed ) && ( false == door.open_permit ) ) };
auto const closerequest {
( door.remote_close && remoteclosecontrol )
|| ( door.local_close && localclosecontrol )
|| ( autocloserequest && door.is_open ) };
door.is_opening =
( false == door.is_open )
&& ( true == Battery )
&& ( false == closerequest )
&& ( ( true == door.is_opening )
|| ( ( true == openrequest )
&& ( false == Doors.is_locked ) ) );
door.is_closing =
( false == door.is_closed )
&& ( true == Battery )
&& ( false == openrequest )
&& ( door.is_closing || closerequest );
if( true == door.is_opening ) {
door.auto_timer = (
( localopencontrol && door.local_open ) ? Doors.auto_duration :
( remoteopencontrol && door.remote_open && Doors.auto_include_remote ) ? Doors.auto_duration :
-1.f );
}
// 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( ( LoadStatus & ( 2 | 1 ) ) != 0 ) {
// if there's load exchange in progress, reset the timer(s) for already open doors if( door.auto_timer > 0.f ) {
if( true == DoorLeftOpened ) { DoorLeftOpenTimer = DoorStayOpen; } door.auto_timer -= Deltatime;
if( true == DoorRightOpened ) { DoorRightOpenTimer = DoorStayOpen; } }
} // if there's load exchange in progress, reset the timer(s) for already open doors
// the door are closed if their timer goes below 0, or if the vehicle is moving at > 10 km/h if( ( door.auto_timer != -1.f )
auto const closingspeed { 10.0 }; && ( ( LoadStatus & ( 2 | 1 ) ) != 0 ) ) {
// NOTE: timer value of 0 is 'special' as it means the door will stay open until vehicle is moving door.auto_timer = Doors.auto_duration;
if( true == DoorLeftOpened ) { }
if( ( ( DoorStayOpen > 0.0 ) && ( DoorLeftOpenTimer < 0.0 ) )
|| ( Vel > closingspeed ) ) {
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving)
DoorLeft( false, range_t::local );
} }
} }
if( true == DoorRightOpened ) { /*
if( ( ( DoorStayOpen > 0.0 ) && ( DoorRightOpenTimer < 0.0 ) ) // the door are closed if their timer goes below 0, or if the vehicle is moving faster than defined threshold
|| ( Vel > closingspeed ) ) { std::array<side, 2> const doorids { side::right, side::left };
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving) for( auto const doorid : doorids ) {
DoorRight( false, range_t::local ); 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)
OperateDoors( doorid, false, range_t::local );
}
} }
} }
*/
} }
// ************************************************************************************************* // *************************************************************************************************
@@ -6992,17 +7143,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 ) );
} }
@@ -7991,7 +8142,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 },
@@ -8001,7 +8152,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;
@@ -8009,37 +8160,72 @@ 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, "" );
extract_value( Doors.auto_include_remote, "DoorAutoCloseRemote", line, "" );
// operation permit
extract_value( Doors.permit_needed, "DoorNeedPermit", line, "" );
{
auto permitpresets = Split( extract_value( "DoorPermitList", line ), '|' );
for( auto const &permit : permitpresets ) {
Doors.permit_presets.emplace_back( std::stoi( permit ) );
}
if( false == Doors.permit_presets.empty() ) {
// HACK: legacy position indices start from 1, so we deduct 1 to arrive at proper index into the array
extract_value( Doors.permit_preset, "DoorPermitListDefault", line, "1" );
Doors.permit_preset =
std::min<int>(
Doors.permit_presets.size(),
Doors.permit_preset )
- 1;
}
} }
// 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 ) {
@@ -8351,8 +8537,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;
@@ -8611,8 +8797,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 ) {
@@ -8812,7 +8998,8 @@ TPowerSource TMoverParameters::LoadFIZ_SourceDecode( std::string const &Source )
std::map<std::string, TPowerSource> powersources{ std::map<std::string, TPowerSource> powersources{
{ "Transducer", TPowerSource::Transducer }, { "Transducer", TPowerSource::Transducer },
{ "Generator", TPowerSource::Generator }, { "Generator", TPowerSource::Generator },
{ "Accu", TPowerSource::Accumulator }, { "Accu", TPowerSource::Accumulator }, // legacy compatibility leftover. TODO: check if we can get rid of it
{ "Accumulator", TPowerSource::Accumulator },
{ "CurrentCollector", TPowerSource::CurrentCollector }, { "CurrentCollector", TPowerSource::CurrentCollector },
{ "PowerCable", TPowerSource::PowerCable }, { "PowerCable", TPowerSource::PowerCable },
{ "Heater", TPowerSource::Heater }, { "Heater", TPowerSource::Heater },
@@ -9047,8 +9234,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;
@@ -9077,8 +9264,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;
@@ -9127,10 +9314,12 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
BrakeDelayFlag = bdelay_G; BrakeDelayFlag = bdelay_G;
if ((TestFlag(BrakeDelays, bdelay_R)) && !(TestFlag(BrakeDelays, bdelay_G))) if ((TestFlag(BrakeDelays, bdelay_R)) && !(TestFlag(BrakeDelays, bdelay_G)))
BrakeDelayFlag = bdelay_R; BrakeDelayFlag = bdelay_R;
/*
// disabled, as test mode is used in specific situations and not really a default
if (BrakeOpModes & bom_PS) if (BrakeOpModes & bom_PS)
BrakeOpModeFlag = bom_PS; BrakeOpModeFlag = bom_PS;
else else
*/
BrakeOpModeFlag = bom_PN; BrakeOpModeFlag = bom_PN;
// yB: jesli pojazdy nie maja zadeklarowanych czasow, to wsadz z przepisow +-16,(6)% // yB: jesli pojazdy nie maja zadeklarowanych czasow, to wsadz z przepisow +-16,(6)%
@@ -9391,34 +9580,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 );
} }
@@ -9507,40 +9696,38 @@ 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") {
auto const left { CValue2 > 0 ? 1 : 2 };
auto const right { 3 - left };
if( std::abs( static_cast<int>( CValue1 ) ) & right ) {
Doors.instances[ side::right ].open_permit = (CValue1 > 0);
}
if( std::abs( static_cast<int>( CValue1 ) ) & left ) {
Doors.instances[ side::left ].open_permit = (CValue1 > 0);
}
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 );
} }
} }
} }
@@ -9548,43 +9735,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.close_control == control_t::conductor )
|| ( DoorCloseCtrl == control_t::driver ) || ( Doors.close_control == control_t::driver )
|| ( DoorCloseCtrl == control_t::mixed ) ) { || ( Doors.close_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

@@ -23,7 +23,10 @@ void render_task::run() {
// convert provided input to a python dictionary // convert provided input to a python dictionary
auto *input = PyDict_New(); auto *input = PyDict_New();
if( input == nullptr ) { goto exit; } if( input == nullptr ) {
cancel();
return;
}
for( auto const &datapair : m_input->floats ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetFloat( datapair.second ) ); } for( auto const &datapair : m_input->floats ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetFloat( datapair.second ) ); }
for( auto const &datapair : m_input->integers ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetInt( datapair.second ) ); } for( auto const &datapair : m_input->integers ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetInt( datapair.second ) ); }
for( auto const &datapair : m_input->bools ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetBool( datapair.second ) ); } for( auto const &datapair : m_input->bools ) { PyDict_SetItemString( input, datapair.first.c_str(), PyGetBool( datapair.second ) ); }
@@ -62,10 +65,8 @@ void render_task::run() {
Py_DECREF( output ); Py_DECREF( output );
} }
exit:
// clean up after yourself // clean up after yourself
delete m_input; cancel();
delete this;
} }
void render_task::cancel() { void render_task::cancel() {

View File

@@ -938,7 +938,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;
} }
} }

621
Train.cpp

File diff suppressed because it is too large Load Diff

14
Train.h
View File

@@ -140,6 +140,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
@@ -312,10 +314,15 @@ 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_doorpermitpresetactivatenext( TTrain *Train, command_data const &Command );
static void OnCommand_doorpermitpresetactivateprevious( 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 );
@@ -439,12 +446,16 @@ 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 ggDoorPermitPresetButton;
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;
@@ -510,7 +521,7 @@ public: // reszta może by?publiczna
TButton btInstrumentLight; TButton btInstrumentLight;
TButton btDashboardLight; TButton btDashboardLight;
TButton btTimetableLight; TButton btTimetableLight;
int InstrumentLightType{ 0 }; // ABu 030405 - swiecenie uzaleznione od: 0-nic, 1-obw.gl, 2-przetw., 3-rozrzad int InstrumentLightType{ 0 }; // ABu 030405 - swiecenie uzaleznione od: 0-nic, 1-obw.gl, 2-przetw., 3-rozrzad, 4-external lights
bool InstrumentLightActive{ false }; bool InstrumentLightActive{ false };
bool DashboardLightActive{ false }; bool DashboardLightActive{ false };
bool TimetableLightActive{ false }; bool TimetableLightActive{ false };
@@ -543,6 +554,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

@@ -96,10 +96,6 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
// bPrimary=true - jest pierwszą osią w pojeździe, czyli generuje eventy i przepisuje pojazd // bPrimary=true - jest pierwszą osią w pojeździe, czyli generuje eventy i przepisuje pojazd
// Ra: zwraca false, jeśli pojazd ma być usunięty // Ra: zwraca false, jeśli pojazd ma być usunięty
auto const ismoving { ( std::abs( fDistance ) > 0.01 ) && ( Owner->GetVelocity() > 0.01 ) }; auto const ismoving { ( std::abs( fDistance ) > 0.01 ) && ( Owner->GetVelocity() > 0.01 ) };
int const eventfilter { (
( ( true == ismoving ) && ( Owner->ctOwner != nullptr ) ) ?
Owner->ctOwner->Direction() * ( Owner->ctOwner->Vehicle()->DirectionGet() == Owner->DirectionGet() ? 1 : -1 ) * ( fDirection > 0 ? 1 : -1 ) :
0 ) };
fDistance *= fDirection; // dystans mnożnony przez kierunek fDistance *= fDirection; // dystans mnożnony przez kierunek
double s; // roboczy dystans double s; // roboczy dystans
double dir; // zapamiętany kierunek do sprawdzenia, czy się zmienił double dir; // zapamiętany kierunek do sprawdzenia, czy się zmienił
@@ -110,6 +106,13 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
// TODO: refactor following block as track method // TODO: refactor following block as track method
if( pCurrentTrack->m_events ) { // sumaryczna informacja o eventach if( pCurrentTrack->m_events ) { // sumaryczna informacja o eventach
// omijamy cały ten blok, gdy tor nie ma on żadnych eventów (większość nie ma) // omijamy cały ten blok, gdy tor nie ma on żadnych eventów (większość nie ma)
int const eventfilter { (
false == ismoving ? 0 : // only moving vehicles activate events type 1/2
false == bPrimary ? 0 : // only primary axle activates events type 1/2
Owner->ctOwner == nullptr ?
( fDistance > 0 ? 1 : -1 ) : // loose vehicle has no means to determine 'intended' direction so the filter does effectively nothing in such case
( fDirection > 0 ? 1 : -1 ) * Owner->ctOwner->Direction() * ( Owner->ctOwner->Vehicle()->DirectionGet() == Owner->DirectionGet() ? 1 : -1 ) ) };
if( false == ismoving ) { if( false == ismoving ) {
//McZapkie-140602: wyzwalanie zdarzenia gdy pojazd stoi //McZapkie-140602: wyzwalanie zdarzenia gdy pojazd stoi
if( ( Owner->Mechanik != nullptr ) if( ( Owner->Mechanik != nullptr )
@@ -127,16 +130,12 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
&& ( Owner->Mechanik->Primary() ) ) { && ( Owner->Mechanik->Primary() ) ) {
// tylko dla jednego członu // tylko dla jednego członu
// McZapkie-280503: wyzwalanie event tylko dla pojazdow z obsada // McZapkie-280503: wyzwalanie event tylko dla pojazdow z obsada
if( true == bPrimary ) { pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner );
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner );
}
} }
} }
if( SetFlag( iEventallFlag, -1 ) ) { if( SetFlag( iEventallFlag, -1 ) ) {
// McZapkie-280503: wyzwalanie eventall dla wszystkich pojazdow // McZapkie-280503: wyzwalanie eventall dla wszystkich pojazdow
if( true == bPrimary ) { pCurrentTrack->QueueEvents( pCurrentTrack->m_events1all, Owner );
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1all, Owner );
}
} }
} }
else if( ( fDistance > 0 ) && ( eventfilter > 0 ) ) { else if( ( fDistance > 0 ) && ( eventfilter > 0 ) ) {
@@ -146,16 +145,12 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
if( ( Owner->Mechanik != nullptr ) if( ( Owner->Mechanik != nullptr )
&& ( Owner->Mechanik->Primary() ) ) { && ( Owner->Mechanik->Primary() ) ) {
// tylko dla jednego członu // tylko dla jednego członu
if( true == bPrimary ) { pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner );
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner );
}
} }
} }
if( SetFlag( iEventallFlag, -2 ) ) { if( SetFlag( iEventallFlag, -2 ) ) {
// sprawdza i zeruje na przyszłość, true jeśli zmieni z 2 na 0 // sprawdza i zeruje na przyszłość, true jeśli zmieni z 2 na 0
if( true == bPrimary ) { pCurrentTrack->QueueEvents( pCurrentTrack->m_events2all, Owner );
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2all, Owner );
}
} }
} }
} }

View File

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

View File

@@ -136,8 +136,13 @@ enum class user_command {
carcouplingdisconnect, carcouplingdisconnect,
doortoggleleft, doortoggleleft,
doortoggleright, doortoggleright,
doorpermitleft,
doorpermitright,
doorpermitpresetactivatenext,
doorpermitpresetactivateprevious,
dooropenleft, dooropenleft,
dooropenright, dooropenright,
dooropenall,
doorcloseleft, doorcloseleft,
doorcloseright, doorcloseright,
doorcloseall, doorcloseall,

View File

@@ -144,8 +144,13 @@ driverkeyboard_input::default_bindings() {
{ user_command::carcouplingdisconnect, GLFW_KEY_DELETE }, { user_command::carcouplingdisconnect, GLFW_KEY_DELETE },
{ user_command::doortoggleleft, GLFW_KEY_COMMA }, { user_command::doortoggleleft, GLFW_KEY_COMMA },
{ user_command::doortoggleright, GLFW_KEY_PERIOD }, { user_command::doortoggleright, GLFW_KEY_PERIOD },
{ user_command::doorpermitleft, GLFW_KEY_COMMA | keymodifier::shift },
{ user_command::doorpermitright, GLFW_KEY_PERIOD | keymodifier::shift },
{ user_command::doorpermitpresetactivatenext, GLFW_KEY_PERIOD | keymodifier::shift | keymodifier::control },
{ user_command::doorpermitpresetactivateprevious, GLFW_KEY_COMMA | keymodifier::shift | keymodifier::control },
// dooropenleft, // dooropenleft,
// dooropenright, // dooropenright,
{ user_command::dooropenall, GLFW_KEY_SLASH | keymodifier::shift },
// doorcloseleft, // doorcloseleft,
// doorcloseright, // doorcloseright,
{ user_command::doorcloseall, GLFW_KEY_SLASH | keymodifier::control }, { user_command::doorcloseall, GLFW_KEY_SLASH | keymodifier::control },
@@ -202,8 +207,8 @@ driverkeyboard_input::default_bindings() {
{ user_command::instrumentlighttoggle, GLFW_KEY_SEMICOLON }, { user_command::instrumentlighttoggle, GLFW_KEY_SEMICOLON },
// instrumentlightenable, // instrumentlightenable,
// instrumentlightdisable, // instrumentlightdisable,
// dashboardlighttoggle, { user_command::dashboardlighttoggle, GLFW_KEY_SEMICOLON | keymodifier::shift },
// timetablelighttoggle, { user_command::timetablelighttoggle, GLFW_KEY_APOSTROPHE | keymodifier::shift },
{ user_command::generictoggle0, GLFW_KEY_0 }, { user_command::generictoggle0, GLFW_KEY_0 },
{ user_command::generictoggle1, GLFW_KEY_1 }, { user_command::generictoggle1, GLFW_KEY_1 },
{ user_command::generictoggle2, GLFW_KEY_2 }, { user_command::generictoggle2, GLFW_KEY_2 },

View File

@@ -918,7 +918,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;
@@ -949,7 +949,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;
@@ -979,7 +979,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

@@ -552,6 +552,15 @@ 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 } },
{ "doorpermitpreset_sw:", {
user_command::doorpermitpresetactivatenext,
user_command::doorpermitpresetactivateprevious } },
{ "door_left_sw:", { { "door_left_sw:", {
user_command::doortoggleleft, user_command::doortoggleleft,
user_command::none } }, user_command::none } },
@@ -570,6 +579,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

@@ -207,20 +207,48 @@ timetable_panel::update() {
auto textline = " -> " + nextstation; auto textline = " -> " + nextstation;
text_lines.emplace_back( textline, Global.UITextColor ); text_lines.emplace_back( textline, Global.UITextColor );
text_lines.emplace_back( "", Global.UITextColor );
} }
} }
if( is_expanded ) { if( is_expanded ) {
text_lines.emplace_back( "", Global.UITextColor ); if( vehicle->MoverParameters->CategoryFlag == 1 ) {
// consist data
auto consistmass { owner->fMass };
auto consistlength { owner->fLength };
if( ( owner->mvControlling->TrainType != dt_DMU )
&& ( owner->mvControlling->TrainType != dt_EZT )
&& ( owner->pVehicles[end::front] != owner->pVehicles[end::rear] ) ) {
//odejmij lokomotywy czynne, a przynajmniej aktualną
consistmass -= owner->pVehicle->MoverParameters->TotalMass;
// subtract potential other half of a two-part vehicle
auto const *previous { owner->pVehicle->PrevC( coupling::permanent ) };
if( previous != nullptr ) { consistmass -= previous->MoverParameters->TotalMass; }
auto const *next { owner->pVehicle->NextC( coupling::permanent ) };
if( next != nullptr ) { consistmass -= next->MoverParameters->TotalMass; }
// consistlength -= owner->pVehicle->MoverParameters->Dim.L;
}
std::snprintf(
m_buffer.data(), m_buffer.size(),
locale::strings[ locale::string::driver_timetable_consistdata ].c_str(),
static_cast<int>( table->LocLoad ),
static_cast<int>( consistmass / 1000 ),
static_cast<int>( consistlength ) );
text_lines.emplace_back( m_buffer.data(), Global.UITextColor );
text_lines.emplace_back( "", Global.UITextColor );
}
if( 0 == table->StationCount ) { if( 0 == table->StationCount ) {
// only bother if there's stations to list // only bother if there's stations to list
text_lines.emplace_back( locale::strings[ locale::string::driver_timetable_notimetable ], Global.UITextColor ); text_lines.emplace_back( locale::strings[ locale::string::driver_timetable_notimetable ], Global.UITextColor );
} }
else { else {
auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) }; auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) };
// header
// header
text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor ); text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor );
TMTableLine const *tableline; TMTableLine const *tableline;
@@ -401,8 +429,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 );
@@ -427,13 +455,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 );
@@ -451,8 +479,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 );
@@ -544,7 +572,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 ) };
@@ -663,6 +691,10 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
// biezaca komenda dla AI // biezaca komenda dla AI
auto textline = "Current order: " + mechanik.OrderCurrent(); auto textline = "Current order: " + mechanik.OrderCurrent();
if( mechanik.fStopTime < 0.0 ) {
textline += "\n stop time: " + to_string( std::abs( mechanik.fStopTime ), 1 );
}
Output.emplace_back( textline, Global.UITextColor ); Output.emplace_back( textline, Global.UITextColor );
if( ( mechanik.VelNext == 0.0 ) if( ( mechanik.VelNext == 0.0 )

View File

@@ -22,8 +22,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
@@ -43,7 +43,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() );
@@ -60,7 +60,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

@@ -299,14 +299,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

@@ -174,6 +174,7 @@ opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream
// try to set up the buffer we need // try to set up the buffer we need
::glGenBuffers( 1, &m_buffer ); ::glGenBuffers( 1, &m_buffer );
bind_buffer(); bind_buffer();
if( m_buffer == 0 ) { return; } // if we didn't get a buffer we'll try again during the next draw call
// NOTE: we're using static_draw since it's generally true for all we have implemented at the moment // NOTE: we're using static_draw since it's generally true for all we have implemented at the moment
// TODO: allow to specify usage hint at the object creation, and pass it here // TODO: allow to specify usage hint at the object creation, and pass it here
::glBufferData( ::glBufferData(

View File

@@ -188,7 +188,7 @@ std::string cParser::readToken( bool ToLower, const char *Break ) {
c = tolower( c ); c = tolower( c );
token += c; token += c;
if( findQuotes( token ) ) // do glue together words enclosed in quotes if( findQuotes( token ) ) // do glue together words enclosed in quotes
break; continue;
if( trimComments( token ) ) // don't glue together words separated with comment if( trimComments( token ) ) // don't glue together words separated with comment
break; break;
} }

View File

@@ -124,7 +124,8 @@ basic_cell::update_events() {
// event launchers // event launchers
for( auto *launcher : m_eventlaunchers ) { for( auto *launcher : m_eventlaunchers ) {
if( ( true == ( launcher->check_activation() && launcher->check_conditions() ) ) if( ( true == ( launcher->check_activation() && launcher->check_conditions() ) )
&& ( SquareMagnitude( launcher->location() - Global.pCamera.Pos ) < launcher->dRadius ) ) { && ( ( launcher->dRadius < 0.0 )
|| ( SquareMagnitude( launcher->location() - Global.pCamera.Pos ) < launcher->dRadius ) ) ) {
launch_event( launcher ); launch_event( launcher );
} }

View File

@@ -344,8 +344,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 );
} }
} }
@@ -871,7 +871,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

@@ -43,6 +43,8 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
auto &parameters { *vehicle->MoverParameters }; auto &parameters { *vehicle->MoverParameters };
if( parameters.Doors.range == 0.f ) { goto next; }
if( parameters.LoadType.name.empty() ) { if( parameters.LoadType.name.empty() ) {
// (try to) set the cargo type for empty cars // (try to) set the cargo type for empty cars
parameters.LoadAmount = 0.f; // safety measure against edge cases parameters.LoadAmount = 0.f; // safety measure against edge cases
@@ -57,7 +59,7 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
firststop ? 0 : firststop ? 0 :
std::min<float>( std::min<float>(
parameters.LoadAmount, parameters.LoadAmount,
Random( parameters.MaxLoad * 0.10 * stationsizemodifier ) ) ); Random( parameters.MaxLoad * 0.15f * stationsizemodifier ) ) );
auto loadcount = static_cast<int>( auto loadcount = static_cast<int>(
laststop ? laststop ?
0 : 0 :
@@ -73,6 +75,7 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
exchangetime = std::max( exchangetime, vehicle->LoadExchangeTime() ); exchangetime = std::max( exchangetime, vehicle->LoadExchangeTime() );
} }
} }
next:
vehicle = vehicle->Next(); vehicle = vehicle->Next();
} }

View File

@@ -41,6 +41,7 @@ init() {
"Timetable", "Timetable",
"Time: %d:%02d:%02d", "Time: %d:%02d:%02d",
"(no timetable)", "(no timetable)",
"Consist weight: %d t (specified) %d t (actual)\nConsist length: %d m",
"Transcripts", "Transcripts",
@@ -97,13 +98,17 @@ init() {
"motor overload relay reset", "motor overload relay reset",
"converter overload relay reset", "converter overload relay reset",
"motor connectors", "motor connectors",
"left door (permit)",
"right door (permit)",
"door (permit)",
"left door", "left door",
"right door", "right door",
"left door", "left door (open)",
"right door", "right door (open)",
"left door", "left door (close)",
"right door", "right door (close)",
"all doors", "all doors (open)",
"all doors (close)",
"departure signal", "departure signal",
"upper headlight", "upper headlight",
"left headlight", "left headlight",
@@ -179,6 +184,7 @@ init() {
"Rozklad jazdy", "Rozklad jazdy",
"Godzina: %d:%02d:%02d", "Godzina: %d:%02d:%02d",
"(brak rozkladu)", "(brak rozkladu)",
"Brutto: %d t (rozkladowe) %d t (rzeczywiste)\nDlugosc pociagu: %d m",
"Transkrypcje", "Transkrypcje",
@@ -235,13 +241,17 @@ init() {
"przekaznik nadmiarowy silnikow trakcyjnych", "przekaznik nadmiarowy silnikow trakcyjnych",
"przekaznik nadmiarowy przetwornicy", "przekaznik nadmiarowy przetwornicy",
"styczniki liniowe", "styczniki liniowe",
"drzwi lewe (zezwol)",
"drzwi prawe (zezwol)",
"drzwi (zezwol)",
"drzwi lewe", "drzwi lewe",
"drzwi prawe", "drzwi prawe",
"drzwi lewe", "drzwi lewe (otworz)",
"drzwi prawe", "drzwi prawe (otworz)",
"drzwi lewe", "drzwi lewe (zamknij)",
"drzwi prawe", "drzwi prawe (zamknij)",
"drzwi", "drzwi (otworz)",
"drzwi (zamknij)",
"sygnal odjazdu", "sygnal odjazdu",
"reflektor gorny", "reflektor gorny",
"reflektor lewy", "reflektor lewy",
@@ -345,12 +355,16 @@ init() {
"fuse_bt:", "fuse_bt:",
"converterfuse_bt:", "converterfuse_bt:",
"stlinoff_bt:", "stlinoff_bt:",
"doorleftpermit_sw:",
"doorrightpermit_sw:",
"doorpermitpreset_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

@@ -30,6 +30,7 @@ enum string {
driver_timetable_header, driver_timetable_header,
driver_timetable_time, driver_timetable_time,
driver_timetable_notimetable, driver_timetable_notimetable,
driver_timetable_consistdata,
driver_transcripts_header, driver_transcripts_header,
@@ -86,12 +87,16 @@ 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_doorpermitpreset_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 +1 @@
#define VERSION_INFO "M7 27.01.2018, based on tmj-753cf7ee5" #define VERSION_INFO "M7 21.02.2018, based on tmj-bc60b5ac6"