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

Merge branch 'milek-dev' into udpnetwork

This commit is contained in:
milek7
2019-02-21 19:57:08 +01:00
30 changed files with 1467 additions and 1072 deletions

View File

@@ -1007,21 +1007,6 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
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) {
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)
+ " next " + asNextStop); // informacja
#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
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 ) {
// nie podjeżdżać do semafora, jeśli droga nie jest wolna
@@ -2086,8 +2071,8 @@ bool TController::CheckVehicles(TOrders user)
{
// HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi...
if( ( p != pVehicle )
&& ( ( p->MoverParameters->Couplers[ side::front ].CouplingFlag & ( coupling::control | coupling::permanent ) ) == 0 )
&& ( ( p->MoverParameters->Couplers[ side::rear ].CouplingFlag & ( coupling::control | coupling::permanent ) ) == 0 ) ) {
&& ( ( p->MoverParameters->Couplers[ end::front ].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
p->MoverParameters->BatterySwitch( true );
}
@@ -2111,12 +2096,12 @@ bool TController::CheckVehicles(TOrders user)
// jeśli jazda pociągowa
// światła pociągowe (Pc1) i końcówki (Pc5)
auto const frontlights { (
( m_lighthints[ side::front ] != -1 ) ?
m_lighthints[ side::front ] :
( m_lighthints[ end::front ] != -1 ) ?
m_lighthints[ end::front ] :
light::headlight_left | light::headlight_right | light::headlight_upper ) };
auto const rearlights { (
( m_lighthints[ side::rear ] != -1 ) ?
m_lighthints[ side::rear ] :
( m_lighthints[ end::rear ] != -1 ) ?
m_lighthints[ end::rear ] :
light::redmarker_left | light::redmarker_right | light::rearendsignals ) };
Lights(
frontlights,
@@ -2153,9 +2138,12 @@ bool TController::CheckVehicles(TOrders user)
Lights( 0, light::headlight_right );
}
}
// nastawianie hamulca do jazdy pociągowej
if( OrderCurrentGet() & ( Obey_train | Shunt ) ) {
// nastawianie hamulca do jazdy pociągowej
AutoRewident();
// enable door locks
mvOccupied->LockDoors( true );
}
}
else { // gdy człowiek i gdy nastąpiło połącznie albo rozłączenie
@@ -2470,10 +2458,10 @@ bool TController::PrepareEngine()
// w EN57 sprężarka w ra jest zasilana z silnikowego
mvOccupied->CompressorSwitch( true );
// enable motor blowers
mvOccupied->MotorBlowersSwitchOff( false, side::front );
mvOccupied->MotorBlowersSwitch( true, side::front );
mvOccupied->MotorBlowersSwitchOff( false, side::rear );
mvOccupied->MotorBlowersSwitch( true, side::rear );
mvOccupied->MotorBlowersSwitchOff( false, end::front );
mvOccupied->MotorBlowersSwitch( true, end::front );
mvOccupied->MotorBlowersSwitchOff( false, end::rear );
mvOccupied->MotorBlowersSwitch( true, end::rear );
}
}
else
@@ -2555,15 +2543,9 @@ bool TController::ReleaseEngine() {
while( ( mvOccupied->ActiveDir > 0 ) && ( mvOccupied->DirectionBackward() ) ) { ; }
while( ( mvOccupied->ActiveDir < 0 ) && ( mvOccupied->DirectionForward() ) ) { ; }
if( mvOccupied->DoorCloseCtrl == control_t::driver ) {
// zamykanie drzwi
if( mvOccupied->DoorLeftOpened ) {
mvOccupied->DoorLeft( false );
}
if( mvOccupied->DoorRightOpened ) {
mvOccupied->DoorRight( false );
}
}
mvOccupied->OperateDoors( side::right, false );
mvOccupied->OperateDoors( side::left, false );
if( true == mvControlling->Mains ) {
mvControlling->CompressorSwitch( false );
@@ -3183,7 +3165,7 @@ void TController::SpeedSet()
// Ra 2014-06: "automatyczna" skrzynia biegów...
if (!mvControlling->MotorParam[mvControlling->ScndCtrlPos].AutoSwitch) // gdy biegi ręczne
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 >
// 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
@@ -3231,36 +3213,41 @@ void TController::Doors( bool const Open, int const Side ) {
// otwieranie drzwi
// otwieranie drzwi w składach wagonowych - docelowo wysyłać komendę zezwolenia na otwarcie drzwi
// tu będzie jeszcze długość peronu zaokrąglona do 10m (20m bezpieczniej, bo nie modyfikuje bitu 1)
auto *vehicle = pVehicles[0]; // pojazd na czole składu
while( vehicle != nullptr ) {
// otwieranie drzwi w pojazdach - flaga zezwolenia była by lepsza
if( vehicle->MoverParameters->DoorOpenCtrl != control_t::passenger ) {
// if the door are controlled by the driver, we let the user operate them...
if( true == AIControllFlag ) {
// ...unless this user is an ai
// Side=platform side (1:left, 2:right, 3:both)
// jeśli jedzie do tyłu, to drzwi otwiera odwrotnie
auto const lewe = ( vehicle->DirectionGet() > 0 ) ? 1 : 2;
auto const lewe = ( pVehicle->DirectionGet() > 0 ) ? 1 : 2;
auto const prawe = 3 - lewe;
if( Side & lewe )
vehicle->MoverParameters->DoorLeft( true, range_t::local );
if( ( true == pVehicle->MoverParameters->Doors.permit_needed )
&& ( true == AIControllFlag ) ) {
// grant door control permission if it's not automatic
// TBD: stricter requirements?
if( Side & prawe )
vehicle->MoverParameters->DoorRight( true, range_t::local );
pVehicle->MoverParameters->PermitDoors( side::right );
if( Side & lewe )
pVehicle->MoverParameters->PermitDoors( side::left );
}
}
// pojazd podłączony z tyłu (patrząc od czoła)
vehicle = vehicle->Next();
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 can be operated by the driver we let the user operate them unless this user is an ai
// the train conductor, if present, handles door operation also for human-driven trains
if( Side & prawe )
pVehicle->MoverParameters->OperateDoors( side::right, true );
if( Side & lewe )
pVehicle->MoverParameters->OperateDoors( side::left, true );
}
}
else {
// zamykanie
if( false == doors_open() ) {
// the doors are already closed, we can skip all hard work
if( ( false == pVehicle->MoverParameters->Doors.permit_needed )
&& ( 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;
}
if( AIControllFlag ) {
if( ( true == mvOccupied->DoorClosureWarning )
if( ( true == mvOccupied->Doors.has_autowarning )
&& ( false == mvOccupied->DepartureSignal )
&& ( true == TestFlag( iDrivigFlags, moveDoorOpened ) ) ) {
mvOccupied->signal_departure( true ); // załącenie bzyczka
@@ -3272,12 +3259,22 @@ void TController::Doors( bool const Open, int const Side ) {
&& ( ( fActionTime > -0.5 )
|| ( false == AIControllFlag ) ) ) {
// ai doesn't close the door until it's free to depart, but human driver has free reign to do stupid things
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
while( vehicle != nullptr ) {
// zamykanie drzwi w pojazdach - flaga zezwolenia była by lepsza
if( vehicle->MoverParameters->DoorCloseCtrl != control_t::autonomous ) {
vehicle->MoverParameters->DoorLeft( false, range_t::local ); // w lokomotywie można by nie zamykać...
vehicle->MoverParameters->DoorRight( false, range_t::local );
if( vehicle->MoverParameters->Doors.auto_velocity < 0.f ) {
vehicle->MoverParameters->OperateDoors( side::right, false, range_t::local ); // w lokomotywie można by nie zamykać...
vehicle->MoverParameters->OperateDoors( side::left, false, range_t::local );
}
vehicle = vehicle->Next(); // pojazd podłączony z tyłu (patrząc od czoła)
}
@@ -3300,8 +3297,8 @@ TController::doors_open() const {
auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu
while( vehicle != nullptr ) {
if( ( vehicle->MoverParameters->DoorRightOpened == true )
|| ( vehicle->MoverParameters->DoorLeftOpened == true ) ) {
if( ( false == vehicle->MoverParameters->Doors.instances[side::right].is_closed )
|| ( false == vehicle->MoverParameters->Doors.instances[side::left].is_closed ) ) {
// any open door is enough
return true;
}
@@ -3718,8 +3715,8 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
if( NewCommand == "SetLights" ) {
// set consist lights pattern hints
m_lighthints[ side::front ] = static_cast<int>( NewValue1 );
m_lighthints[ side::rear ] = static_cast<int>( NewValue2 );
m_lighthints[ end::front ] = static_cast<int>( NewValue1 );
m_lighthints[ end::rear ] = static_cast<int>( NewValue2 );
if( true == TestFlag( OrderCurrentGet(), Obey_train ) ) {
// light hints only apply in the obey_train mode
CheckVehicles();
@@ -3839,6 +3836,7 @@ TController::UpdateSituation(double dt) {
fAccGravity = 0.0; // przyspieszenie wynikające z pochylenia
double dy; // składowa styczna grawitacji, w przedziale <0,1>
double AbsAccS = 0;
IsAnyDoorOpen[ side::right ] = IsAnyDoorOpen[ side::left ] = false;
TDynamicObject *p = pVehicles[0]; // pojazd na czole składu
while (p)
{ // sprawdzenie odhamowania wszystkich połączonych pojazdów
@@ -3872,6 +3870,15 @@ TController::UpdateSituation(double dt) {
&& ( vehicle->FuseFlag ) ) { // wywalony nadmiarowy
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)
}
@@ -3931,7 +3938,7 @@ TController::UpdateSituation(double dt) {
// TODO: check if this situation still happens and the hack is still needed
if( ( false == AIControllFlag )
&& ( 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
Doors( false );
}
@@ -4463,8 +4470,8 @@ TController::UpdateSituation(double dt) {
&& ( false == TestFlag( iDrivigFlags, movePress ) )
&& ( iCoupler == 0 )
// && ( mvOccupied->Vel > 0.0 )
&& ( pVehicle->MoverParameters->Couplers[ side::front ].CouplingFlag == coupling::faux )
&& ( pVehicle->MoverParameters->Couplers[ side::rear ].CouplingFlag == coupling::faux ) ) {
&& ( pVehicle->MoverParameters->Couplers[ end::front ].CouplingFlag == coupling::faux )
&& ( pVehicle->MoverParameters->Couplers[ end::rear ].CouplingFlag == coupling::faux ) ) {
SetVelocity(0, 0, stopJoin); // 1. faza odczepiania: zatrzymanie
// WriteLog("Zatrzymanie w celu odczepienia");
AccPreferred = std::min( 0.0, AccPreferred );
@@ -4918,6 +4925,16 @@ TController::UpdateSituation(double dt) {
if( fStopTime < 0 ) {
// czas postoju przed dalszą jazdą (np. na przystanku)
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 ) {
@@ -5679,7 +5696,7 @@ void TController::OrderCheck()
if( OrderList[ OrderPos ] != Obey_train ) {
// 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 ) ) {
CheckVehicles(); // sprawdzić światła
@@ -6320,7 +6337,7 @@ bool TController::IsStop() const
double
TController::TrackBlock() const {
return pVehicles[ side::front ]->fTrackBlock;
return pVehicles[ end::front ]->fTrackBlock;
}
void TController::MoveTo(TDynamicObject *to)

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -274,12 +274,6 @@ private:
public:
TAnim *pants; // indeks obiektu animującego dla pantografu 0
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 dMirrorMoveR{ 0.0 };
TSubModel *smBrakeSet; // nastawa hamulca (wajcha)
@@ -319,6 +313,7 @@ private:
sound_source unlock { sound_placement::general };
sound_source step_open { sound_placement::general };
sound_source step_close { sound_placement::general };
side placement {};
};
struct exchange_sounds {
@@ -622,7 +617,7 @@ private:
void RadioStop();
void Damage(char flag);
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 );
TDynamicObject * FirstFind(int &coupler_nr, int cf = 1);
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 ) ) };
if( targetcell == nullptr ) { continue; }
// 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 ) {
// +16 or +24
// jeśli pytanie o ładunek
if( m_input.flags & flags::mode_add ) {
if( m_input.flags & flags::mode_alt ) {
// jeśli typ pojazdu
// TODO: define and recognize individual request types
auto const owner { (
@@ -912,7 +917,7 @@ whois_event::run_() {
WriteLog(
"Type: WhoIs (" + to_string( m_input.flags ) + ") - "
+ "[name: " + m_activator->MoverParameters->TypeName + "], "
+ "[type: " + m_activator->MoverParameters->TypeName + "], "
+ "[consist brake level: " + to_string( consistbrakelevel, 2 ) + "], "
+ "[obstacle distance: " + to_string( collisiondistance, 2 ) + " m]" );
}
@@ -931,7 +936,8 @@ whois_event::run_() {
+ "[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(
m_activator->asDestination, // adres docelowy
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() ) + "], "
+ "[engine power: " + to_string( m_activator->MoverParameters->Power, 2 ) + "]" );
}
// +0
else if( m_activator->Mechanik ) {
if( m_activator->Mechanik->Primary() ) { // tylko jeśli ktoś tam siedzi - nie powinno dotyczyć pasażera!
targetcell->UpdateValues(
@@ -1835,8 +1842,12 @@ lua_event::deserialize_( cParser &Input, scene::scratch_data &Scratchpad ) {
// run() subclass details
void
lua_event::run_() {
try {
if (lua_func)
lua_func(this, m_activator);
} catch (...) {
ErrorLog(simulation::Lua.get_error());
}
}
// export_as_text() subclass details

View File

@@ -28,8 +28,10 @@ public:
value_1 = 1 << 1,
value_2 = 1 << 2,
// update values
load = 1 << 3,
mode_add = 1 << 4,
mode_add = 1 << 3,
// whois
mode_alt = 1 << 3,
load = 1 << 4,
// condition values
track_busy = 1 << 3,
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_depot = 128; //nie rozłączalny podczas zwykłych manewrów (międzyczłonowy), we wpisie wartość ujemna
// vehicle sides; exclusive
enum side {
enum end {
front = 0,
rear
};
enum side {
right = 0,
left = 1
};
// possible coupling types; can be combined
enum coupling {
faux = 0x0,
@@ -632,6 +638,20 @@ class TMoverParameters
private:
// 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
// TBD: inheritance or composition?
struct basic_device {
@@ -677,6 +697,58 @@ private:
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 {
// config
struct heater_config_t {
@@ -983,6 +1055,7 @@ public:
float MaxLoad = 0.f; /*masa w T lub ilosc w sztukach - 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*/
#ifdef EU07_USEOLDDOORCODE
int DoorOpenCtrl = 0; int DoorCloseCtrl = 0; /*0: przez pasazera, 1: przez maszyniste, 2: samoczynne (zamykanie)*/
double DoorStayOpen = 0.0; /*jak dlugo otwarte w przypadku DoorCloseCtrl=2*/
bool DoorClosureWarning = false; /*czy jest ostrzeganie przed zamknieciem*/
@@ -994,6 +1067,7 @@ public:
double PlatformSpeed = 0.5; /*szybkosc stopnia*/
double PlatformMaxShift { 0.0 }; /*wysuniecie stopnia*/
int PlatformOpenMethod { 2 }; /*sposob animacji stopnia*/
#endif
double MirrorMaxShift { 90.0 };
bool ScndS = false; /*Czy jest bocznikowanie na szeregowej*/
double SpeedCtrlDelay = 2; /*opoznienie dzialania tempomatu z wybieralna predkoscia*/
@@ -1057,6 +1131,7 @@ public:
bool WaterCircuitsLink { false }; // optional connection between water circuits
heat_data dizel_heat;
std::array<cooling_fan, 2> MotorBlowers;
door_data Doors;
int BrakeCtrlPos = -2; /*nastawa hamulca zespolonego*/
double BrakeCtrlPosR = 0.0; /*nastawa hamulca zespolonego - plynna dla FV4a*/
@@ -1200,13 +1275,14 @@ public:
std::string LoadQuantity; // jednostki miary
int LoadStatus = 0; //+1=trwa rozladunek,+2=trwa zaladunek,+4=zakończono,0=zaktualizowany model
double LastLoadChangeTime = 0.0; //raz (roz)ładowania
#ifdef EU07_USEOLDDOORCODE
bool DoorBlocked = false; //Czy jest blokada drzwi
bool DoorLockEnabled { true };
bool DoorLeftOpened = false; //stan drzwi
double DoorLeftOpenTimer { -1.0 }; // left door closing timer for automatic door type
bool DoorRightOpened = false;
double DoorRightOpenTimer{ -1.0 }; // right door closing timer for automatic door type
#endif
bool PantFrontUp = false; //stan patykow 'Winger 160204
bool PantRearUp = false;
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 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 MotorBlowersSwitch( bool State, side 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 MotorBlowersSwitch( bool State, end 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*/
void MainSwitch_( bool const State );
bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/
@@ -1414,11 +1490,12 @@ public:
/* funckje dla wagonow*/
bool AssignLoad( std::string const &Name, float const Amount = 0.f );
bool LoadingDone(double LSpeed, std::string const &Loadname);
bool DoorLeft(bool State, range_t const Notify = range_t::consist ); //obsluga drzwi lewych
bool DoorRight(bool State, range_t const Notify = range_t::consist ); //obsluga drzwi prawych
bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi
bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist );
bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist );
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
void update_autonomous_doors( double const Deltatime ); // automatic door controller update
void update_doors( double const Deltatime ); // door controller update
/* funkcje dla samochodow*/
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
auto const converteractive{ (
( ConverterFlag )
|| ( ( ( Couplers[ side::front ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ side::front ].Connected->ConverterFlag )
|| ( ( ( Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ side::rear ].Connected->ConverterFlag ) )
|| ( ( ( Couplers[ end::front ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ end::front ].Connected->ConverterFlag )
|| ( ( ( Couplers[ end::rear ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ end::rear ].Connected->ConverterFlag ) )
|| ( ( EngineType == TEngineType::DieselElectric ) && ( 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 ) {
// 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 )
|| ( ( 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 ) {
// bez napiecia...
@@ -1151,9 +1151,9 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
&& ( Couplers[ side ].CouplingFlag & ctrain_heating ) ) ) {
auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == side::front ?
side::rear :
side::front ) ];
( Couplers[ side ].ConnectedNr == end::front ?
end::rear :
end::front ) ];
Couplers[ side ].power_high.current =
connectedcoupler.power_high.current
+ 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 ) ) ) {
auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == side::front ?
side::rear :
side::front ) ];
( Couplers[ side ].ConnectedNr == end::front ?
end::rear :
end::front ) ];
TotalCurrent += connectedcoupler.power_high.current;
Couplers[ side ].power_high.current = 0.0;
}
@@ -1465,7 +1465,7 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
}
BrakeSlippingTimer += Deltatime;
// automatic doors
update_autonomous_doors( Deltatime );
update_doors( Deltatime );
}
double TMoverParameters::ShowEngineRotation(int VehN)
@@ -2653,7 +2653,7 @@ bool TMoverParameters::OilPumpSwitchOff( bool State, range_t const Notify ) {
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 ] };
@@ -2669,7 +2669,7 @@ bool TMoverParameters::MotorBlowersSwitch( bool State, side const Side, range_t
if( Notify != range_t::local ) {
SendCtrlToNext(
( Side == side::front ? "MotorBlowersFrontSwitch" : "MotorBlowersRearSwitch" ),
( Side == end::front ? "MotorBlowersFrontSwitch" : "MotorBlowersRearSwitch" ),
( fan.is_enabled ? 1 : 0 ),
CabNo,
( Notify == range_t::unit ?
@@ -2680,7 +2680,7 @@ bool TMoverParameters::MotorBlowersSwitch( bool State, side const Side, range_t
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 ] };
@@ -2696,7 +2696,7 @@ bool TMoverParameters::MotorBlowersSwitchOff( bool State, side const Side, range
if( Notify != range_t::local ) {
SendCtrlToNext(
( Side == side::front ? "MotorBlowersFrontSwitchOff" : "MotorBlowersRearSwitchOff" ),
( Side == end::front ? "MotorBlowersFrontSwitchOff" : "MotorBlowersRearSwitchOff" ),
( fan.is_disabled ? 1 : 0 ),
CabNo,
( Notify == range_t::unit ?
@@ -3324,11 +3324,11 @@ void TMoverParameters::CompressorCheck(double dt)
{ // sprawdzić możliwe warunki wyłączenia sprężarki
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)
if( Couplers[ side::rear ].Connected != NULL ) {
if( Couplers[ end::rear ].Connected != NULL ) {
CompressorFlag = (
( ( Couplers[ side::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
( ( Couplers[ end::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal )
&& ( Couplers[ side::rear ].Connected->ConverterFlag ) );
&& ( Couplers[ end::rear ].Connected->ConverterFlag ) );
}
else {
// 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
{ // 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 = (
( ( Couplers[ side::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
( ( Couplers[ end::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal )
&& ( Couplers[ side::front ].Connected->ConverterFlag ) );
&& ( Couplers[ end::front ].Connected->ConverterFlag ) );
}
else {
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
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)
if( Couplers[ side::rear ].Connected != NULL ) {
if( Couplers[ end::rear ].Connected != NULL ) {
CompressorFlag = (
( ( Couplers[ side::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
( ( Couplers[ end::rear ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal )
&& ( Couplers[ side::rear ].Connected->ConverterFlag ) );
&& ( Couplers[ end::rear ].Connected->ConverterFlag ) );
}
else {
// 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
{ // 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 = (
( ( Couplers[ side::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
( ( Couplers[ end::front ].Connected->CompressorAllow ) || ( CompressorStart == start_t::automatic ) )
&& ( CompressorAllowLocal )
&& ( Couplers[ side::front ].Connected->ConverterFlag ) );
&& ( Couplers[ end::front ].Connected->ConverterFlag ) );
}
else {
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;
} // bo nie dzialalo
else if( ( EngineType == TEngineType::ElectricInductionMotor )
|| ( ( ( Couplers[ side::front ].CouplingFlag & ctrain_power ) == ctrain_power )
|| ( ( Couplers[ side::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) {
|| ( ( ( Couplers[ end::front ].CouplingFlag & ctrain_power ) == ctrain_power )
|| ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) {
// potem ulepszyc! pantogtrafy!
Voltage =
std::max(
RunningTraction.TractionVoltage,
std::max(
Couplers[ side::front ].power_high.voltage,
Couplers[ side::rear ].power_high.voltage ) );
Couplers[ end::front ].power_high.voltage,
Couplers[ end::rear ].power_high.voltage ) );
}
else {
Voltage = 0;
@@ -4605,8 +4605,13 @@ double TMoverParameters::TractionForce( double dt ) {
case TEngineType::ElectricSeriesMotor: {
// update the state of voltage relays
auto const voltage { std::max( GetTrainsetVoltage(), std::abs( RunningTraction.TractionVoltage ) ) };
NoVoltRelay = ( voltage >= EnginePowerSource.CollectorParameters.MinV );
OvervoltageRelay = ( voltage <= EnginePowerSource.CollectorParameters.MaxV ) || ( false == EnginePowerSource.CollectorParameters.OVP );
NoVoltRelay =
( 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
EventFlag |= ( ( true == Mains )
&& ( ( false == NoVoltRelay ) || ( false == OvervoltageRelay ) )
@@ -5068,8 +5073,10 @@ double TMoverParameters::TractionForce( double dt ) {
}
dtrans = Hamulec->GetEDBCP();
if (((DoorLeftOpened) || (DoorRightOpened)))
if( ( ( false == Doors.instances[ side::left ].is_closed )
|| ( false == Doors.instances[ side::right ].is_closed ) ) ) {
DynamicBrakeFlag = true;
}
else if (((dtrans < 0.25) && (LocHandle->GetCP() < 0.25) && (AnPos < 0.01)) ||
((dtrans < 0.25) && (ShuntModeAllow) && (LocalBrakePosA < 0.01)))
DynamicBrakeFlag = false;
@@ -5590,10 +5597,10 @@ bool TMoverParameters::AutoRelayCheck(void)
// sprawdzenie wszystkich warunkow (AutoRelayFlag, AutoSwitch, Im<Imin)
auto const ARFASI2 { (
( !AutoRelayFlag )
( false == AutoRelayFlag )
|| ( ( MotorParam[ ScndCtrlActualPos ].AutoSwitch ) && ( abs( Im ) < Imin ) ) ) };
auto const ARFASI { (
( !AutoRelayFlag )
( false == AutoRelayFlag )
|| ( ( RList[ MainCtrlActualPos ].AutoSwitch ) && ( abs( Im ) < Imin ) )
|| ( ( !RList[ MainCtrlActualPos ].AutoSwitch ) && ( RList[ MainCtrlActualPos ].Relay < MainCtrlPos ) ) ) };
// 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 );
}
// *************************************************************************************************
// Q: 20160713
// Zwraca informacje o działającej blokadzie drzwi
// *************************************************************************************************
bool TMoverParameters::DoorBlockedFlag( void ) {
// TBD: configurable lock activation threshold?
return (
( true == DoorBlocked )
&& ( true == DoorLockEnabled )
&& ( Vel >= 10.0 ) );
bool TMoverParameters::ChangeDoorPermitPreset( int const Change, range_t const Notify ) {
auto const initialstate { Doors.permit_preset };
if( false == Doors.permit_presets.empty() ) {
Doors.permit_preset = clamp<int>( Doors.permit_preset + Change, 0, Doors.permit_presets.size() - 1 );
auto const doors { Doors.permit_presets[ Doors.permit_preset ] };
auto const permitleft = doors & 1;
auto const permitright = doors & 2;
PermitDoors( ( CabNo > 0 ? side::left : side::right ), permitleft, Notify );
PermitDoors( ( CabNo > 0 ? side::right : side::left ), permitright, 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 ) {
return ( Doors.permit_preset != initialstate );
}
if( DoorLeftOpened == State ) {
bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t const Notify ) {
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?
// (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 ) // closing door works always, but if the lock is engaged they can't be opened
|| ( DoorBlockedFlag() == false ) ) ) {
if( Battery == true ) {
DoorLeftOpened = 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
DoorLeftOpenTimer = (
State == true ?
DoorStayOpen :
-1.0 );
if( Notify != range_t::local ) {
door.remote_open = State;
door.remote_close = ( false == State );
}
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 ) {
@@ -6779,7 +6821,7 @@ bool TMoverParameters::DoorLeft(bool State, range_t const Notify ) {
( State == true ?
"DoorOpen" :
"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 :
2 ),
CabNo,
@@ -6791,54 +6833,24 @@ bool TMoverParameters::DoorLeft(bool State, range_t const Notify ) {
return result;
}
// *************************************************************************************************
// Q: 20160713
// 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 ) {
// toggle door lock
bool TMoverParameters::LockDoors( bool const State, range_t const Notify ) {
if( DoorRightOpened == State ) {
// TBD: should the command be passed to other vehicles regardless of whether it affected the primary target?
// (for the time being no, methods are often invoked blindly which would lead to commands spam)
return false;
}
bool result { false };
if( ( Battery == true )
&& ( ( 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 );
}
}
Doors.lock_enabled = State;
if( Notify != range_t::local ) {
// wysłanie wyłączenia do pozostałych?
SendCtrlToNext(
"DoorLock",
( State == true ?
"DoorOpen" :
"DoorClose" ),
( CabNo > 0 ? // 1=lewe, 2=prawe (swap if reversed)
2 :
1 ),
1 :
0 ),
CabNo,
( Notify == range_t::unit ?
coupling::control | coupling::permanent :
coupling::control ) );
}
return result;
return true;
}
// toggles departure warning
@@ -6869,39 +6881,178 @@ TMoverParameters::signal_departure( bool const State, range_t const Notify ) {
// automatic door controller update
void
TMoverParameters::update_autonomous_doors( double const Deltatime ) {
TMoverParameters::update_doors( double const Deltatime ) {
if( DoorCloseCtrl != control_t::autonomous ) { return; }
if( ( false == DoorLeftOpened )
&& ( false == DoorRightOpened ) ) { return; }
if( Doors.range == 0.f ) { return; } // HACK: crude way to distinguish vehicles with actual doors
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
if( DoorLeftOpenTimer >= 0.0 ) { DoorLeftOpenTimer -= Deltatime; }
if( DoorRightOpenTimer >= 0.0 ) { DoorRightOpenTimer -= Deltatime; }
for( auto &door : Doors.instances ) {
if( false == door.is_open ) { continue; }
if( door.auto_timer > 0.f ) {
door.auto_timer -= Deltatime;
}
if( ( LoadStatus & ( 2 | 1 ) ) != 0 ) {
// if there's load exchange in progress, reset the timer(s) for already open doors
if( true == DoorLeftOpened ) { DoorLeftOpenTimer = DoorStayOpen; }
if( true == DoorRightOpened ) { DoorRightOpenTimer = DoorStayOpen; }
if( ( door.auto_timer != -1.f )
&& ( ( LoadStatus & ( 2 | 1 ) ) != 0 ) ) {
door.auto_timer = Doors.auto_duration;
}
// the door are closed if their timer goes below 0, or if the vehicle is moving at > 10 km/h
auto const closingspeed { 10.0 };
// NOTE: timer value of 0 is 'special' as it means the door will stay open until vehicle is moving
if( true == DoorLeftOpened ) {
if( ( ( DoorStayOpen > 0.0 ) && ( DoorLeftOpenTimer < 0.0 ) )
|| ( Vel > closingspeed ) ) {
}
}
/*
// the door are closed if their timer goes below 0, or if the vehicle is moving faster than defined threshold
std::array<side, 2> const doorids { side::right, side::left };
for( auto const doorid : doorids ) {
auto const &door { Doors.instances[ doorid ] };
if( true == door.is_open ) {
if( ( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) )
|| ( ( door.auto_timer != -1.f ) && ( door.auto_timer <= 0.f ) ) ) {
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving)
DoorLeft( false, range_t::local );
OperateDoors( doorid, false, range_t::local );
}
}
if( true == DoorRightOpened ) {
if( ( ( DoorStayOpen > 0.0 ) && ( DoorRightOpenTimer < 0.0 ) )
|| ( Vel > closingspeed ) ) {
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving)
DoorRight( false, range_t::local );
}
}
*/
}
// *************************************************************************************************
@@ -6992,17 +7143,17 @@ std::string TMoverParameters::EngineDescription(int what) const
double TMoverParameters::GetTrainsetVoltage(void)
{//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT
return std::max(
( ( ( Couplers[side::front].Connected )
&& ( ( Couplers[ side::front ].CouplingFlag & ctrain_power )
( ( ( Couplers[end::front].Connected )
&& ( ( Couplers[ end::front ].CouplingFlag & ctrain_power )
|| ( ( Heating )
&& ( Couplers[ side::front ].CouplingFlag & ctrain_heating ) ) ) ) ?
Couplers[side::front].Connected->Couplers[ Couplers[side::front].ConnectedNr ].power_high.voltage :
&& ( Couplers[ end::front ].CouplingFlag & ctrain_heating ) ) ) ) ?
Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage :
0.0 ),
( ( ( Couplers[side::rear].Connected )
&& ( ( Couplers[ side::rear ].CouplingFlag & ctrain_power )
( ( ( Couplers[end::rear].Connected )
&& ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power )
|| ( ( Heating )
&& ( Couplers[ side::rear ].CouplingFlag & ctrain_heating ) ) ) ) ?
Couplers[ side::rear ].Connected->Couplers[ Couplers[ side::rear ].ConnectedNr ].power_high.voltage :
&& ( Couplers[ end::rear ].CouplingFlag & ctrain_heating ) ) ) ) ?
Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage :
0.0 ) );
}
@@ -7991,7 +8142,7 @@ void TMoverParameters::LoadFIZ_Brake( 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 },
{ "AutomaticCtrl", control_t::autonomous },
{ "DriverCtrl", control_t::driver },
@@ -8001,7 +8152,7 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
// opening method
{
auto lookup = doorcontrols.find( extract_value( "OpenCtrl", line ) );
DoorOpenCtrl =
Doors.open_control =
lookup != doorcontrols.end() ?
lookup->second :
control_t::passenger;
@@ -8009,37 +8160,72 @@ void TMoverParameters::LoadFIZ_Doors( std::string const &line ) {
// closing method
{
auto lookup = doorcontrols.find( extract_value( "CloseCtrl", line ) );
DoorCloseCtrl =
Doors.close_control =
lookup != doorcontrols.end() ?
lookup->second :
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( DoorCloseSpeed, "CloseSpeed", line, "" );
extract_value( DoorCloseDelay, "DoorCloseDelay", line, "" );
extract_value( DoorMaxShiftL, "DoorMaxShiftL", line, "" );
extract_value( DoorMaxShiftR, "DoorMaxShiftR", line, "" );
extract_value( DoorMaxPlugShift, "DoorMaxShiftPlug", line, "" );
extract_value( Doors.open_rate, "OpenSpeed", line, "" );
extract_value( Doors.close_rate, "CloseSpeed", line, "" );
extract_value( Doors.close_delay, "DoorCloseDelay", line, "" );
extract_value( Doors.range, "DoorMaxShiftL", line, "" );
extract_value( Doors.range, "DoorMaxShiftR", line, "" );
extract_value( Doors.range_out, "DoorMaxShiftPlug", line, "" );
std::string openmethod; extract_value( openmethod, "DoorOpenMethod", line, "" );
if( openmethod == "Shift" ) { DoorOpenMethod = 1; } //przesuw
else if( openmethod == "Fold" ) { DoorOpenMethod = 3; } //3 submodele się obracają
else if( openmethod == "Plug" ) { DoorOpenMethod = 4; } //odskokowo-przesuwne
std::map<std::string, int> doortypes {
{ "Shift", 1 },
{ "Rotate", 2 },
{ "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( DoorClosureWarningAuto, "DoorClosureWarningAuto", line, "" );
extract_value( DoorBlocked, "DoorBlocked", line, "" );
extract_value( Doors.has_warning, "DoorClosureWarning", line, "" );
extract_value( Doors.has_autowarning, "DoorClosureWarningAuto", line, "" );
extract_value( Doors.has_lock, "DoorBlocked", line, "" );
extract_value( PlatformSpeed, "PlatformSpeed", line, "" );
extract_value( PlatformMaxShift, "PlatformMaxShift", line, "" );
extract_value( MirrorMaxShift, "MirrorMaxShift", line, "" );
extract_value( Doors.step_rate, "PlatformSpeed", line, "" );
extract_value( Doors.step_range, "PlatformMaxShift", 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 ) {
@@ -8351,8 +8537,8 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
// traction motor fans
{
auto lookup = starts.find( extract_value( "MotorBlowersStart", line ) );
MotorBlowers[side::front].start_type =
MotorBlowers[side::rear].start_type =
MotorBlowers[end::front].start_type =
MotorBlowers[end::rear].start_type =
lookup != starts.end() ?
lookup->second :
start_t::manual;
@@ -8611,8 +8797,8 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
}
// traction motors
extract_value( MotorBlowers[ side::front ].speed, "MotorBlowersSpeed", Input, "" );
MotorBlowers[ side::rear ] = MotorBlowers[ side::front ];
extract_value( MotorBlowers[ end::front ].speed, "MotorBlowersSpeed", Input, "" );
MotorBlowers[ end::rear ] = MotorBlowers[ end::front ];
}
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{
{ "Transducer", TPowerSource::Transducer },
{ "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 },
{ "PowerCable", TPowerSource::PowerCable },
{ "Heater", TPowerSource::Heater },
@@ -9047,8 +9234,8 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
CompressedVolume = VeselVolume * MinCompressor * ( 9.8 ) / 10.0;
ScndPipePress = (
VeselVolume > 0.0 ? CompressedVolume / VeselVolume :
( Couplers[ side::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 :
( Couplers[ side::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 :
( Couplers[ end::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 :
( Couplers[ end::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 :
0.0 );
PipePress = CntrlPipePress;
BrakePress = 0.0;
@@ -9077,8 +9264,8 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
*/
ScndPipePress = (
VeselVolume > 0.0 ? CompressedVolume / VeselVolume :
( Couplers[ side::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 :
( Couplers[ side::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 :
( Couplers[ end::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 :
( Couplers[ end::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 :
0.0 );
PipePress = LowPipePress;
PipeBrakePress = MaxBrakePress[ 3 ] * 0.5;
@@ -9127,10 +9314,12 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
BrakeDelayFlag = bdelay_G;
if ((TestFlag(BrakeDelays, bdelay_R)) && !(TestFlag(BrakeDelays, bdelay_G)))
BrakeDelayFlag = bdelay_R;
/*
// disabled, as test mode is used in specific situations and not really a default
if (BrakeOpModes & bom_PS)
BrakeOpModeFlag = bom_PS;
else
*/
BrakeOpModeFlag = bom_PN;
// 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 );
}
else if( Command == "MotorBlowersFrontSwitch" ) {
if( ( MotorBlowers[ side::front ].start_type != start_t::manual )
&& ( MotorBlowers[ side::front ].start_type != start_t::manualwithautofallback ) ) {
if( ( MotorBlowers[ end::front ].start_type != start_t::manual )
&& ( MotorBlowers[ end::front ].start_type != start_t::manualwithautofallback ) ) {
// 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 );
}
else if( Command == "MotorBlowersFrontSwitchOff" ) {
if( ( MotorBlowers[ side::front ].start_type != start_t::manual )
&& ( MotorBlowers[ side::front ].start_type != start_t::manualwithautofallback ) ) {
if( ( MotorBlowers[ end::front ].start_type != start_t::manual )
&& ( MotorBlowers[ end::front ].start_type != start_t::manualwithautofallback ) ) {
// 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 );
}
else if( Command == "MotorBlowersRearSwitch" ) {
if( ( MotorBlowers[ side::rear ].start_type != start_t::manual )
&& ( MotorBlowers[ side::rear ].start_type != start_t::manualwithautofallback ) ) {
if( ( MotorBlowers[ end::rear ].start_type != start_t::manual )
&& ( MotorBlowers[ end::rear ].start_type != start_t::manualwithautofallback ) ) {
// 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 );
}
else if( Command == "MotorBlowersRearSwitchOff" ) {
if( ( MotorBlowers[ side::rear ].start_type != start_t::manual )
&& ( MotorBlowers[ side::rear ].start_type != start_t::manualwithautofallback ) ) {
if( ( MotorBlowers[ end::rear ].start_type != start_t::manual )
&& ( MotorBlowers[ end::rear ].start_type != start_t::manualwithautofallback ) ) {
// 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 );
}
@@ -9507,40 +9696,38 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
}
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*/
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
if( ( DoorOpenCtrl == control_t::conductor )
|| ( DoorOpenCtrl == control_t::driver )
|| ( DoorOpenCtrl == control_t::mixed ) ) {
if( ( Doors.open_control == control_t::conductor )
|| ( Doors.open_control == control_t::driver )
|| ( Doors.open_control == control_t::mixed ) ) {
// ignore remote command if the door is only operated locally
if( CValue2 > 0 ) {
// normalne ustawienie pojazdu
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) {
DoorLeftOpened = (
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ?
true :
DoorLeftOpened );
if( true == Battery ) {
auto const left{ CValue2 > 0 ? 1 : 2 };
auto const right { 3 - left };
if( static_cast<int>( CValue1 ) & right ) {
Doors.instances[ side::right ].remote_open = true;
Doors.instances[ side::right ].remote_close = false;
}
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) {
DoorRightOpened = (
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ?
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 );
if( static_cast<int>( CValue1 ) & left ) {
Doors.instances[ side::left ].remote_open = true;
Doors.instances[ side::left ].remote_close = false;
}
}
}
@@ -9548,43 +9735,34 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
}
else if (Command == "DoorClose") /*NBMX*/
{ // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów
if( ( DoorCloseCtrl == control_t::conductor )
|| ( DoorCloseCtrl == control_t::driver )
|| ( DoorCloseCtrl == control_t::mixed ) ) {
if( ( Doors.close_control == control_t::conductor )
|| ( Doors.close_control == control_t::driver )
|| ( Doors.close_control == control_t::mixed ) ) {
// ignore remote command if the door is only operated locally
if( CValue2 > 0 ) {
// normalne ustawienie pojazdu
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) {
DoorLeftOpened = (
true == Battery ?
false :
DoorLeftOpened );
if( true == Battery ) {
auto const left{ CValue2 > 0 ? 1 : 2 };
auto const right { 3 - left };
if( static_cast<int>( CValue1 ) & right ) {
Doors.instances[ side::right ].remote_close = true;
Doors.instances[ side::right ].remote_open = false;
}
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) {
DoorRightOpened = (
true == Battery ?
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 );
if( static_cast<int>( CValue1 ) & left ) {
Doors.instances[ side::left ].remote_close = true;
Doors.instances[ side::left ].remote_open = false;
}
}
}
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" ) {
DepartureSignal = (
CValue1 == 1 ?

View File

@@ -29,7 +29,6 @@ List of requirements for compiling executable. For usage/runtime requirements [s
- [sndfile](https://github.com/erikd/libsndfile) (1.0.28)
- [LuajIT](http://luajit.org/) (2.0.5)
- [GLEW](http://glew.sourceforge.net/) (2.1.0)
- [freeglut/GLUT](http://freeglut.sourceforge.net/) (freeglut 3.0.0)
- [PNG](http://www.libpng.org/pub/png/libpng.html) (1.6.34)
- [OpenAL](https://www.openal.org/) (1.18.2)
- pthread

View File

@@ -944,7 +944,7 @@ bool TTrack::AssignEvents() {
m_events = true;
}
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;
}
}

601
Train.cpp

File diff suppressed because it is too large Load Diff

14
Train.h
View File

@@ -141,6 +141,8 @@ class TTrain
void set_master_controller( double const Position );
// moves train brake lever to specified position, potentially emits switch sound if conditions are met
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
void set_train_brake_speed( TDynamicObject *Vehicle, int const Speed );
// sets the motor connector button in paired unit to specified state
@@ -313,10 +315,15 @@ class TTrain
static void OnCommand_doorlocktoggle( 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_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_dooropenright( 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_dooropenall( 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_carcouplingdisconnect( TTrain *Train, command_data const &Command );
@@ -444,12 +451,16 @@ public: // reszta może by?publiczna
// oswietlenia kabiny
// NBMX wrzesien 2003 - obsluga drzwi
TGauge ggDoorLeftPermitButton;
TGauge ggDoorRightPermitButton;
TGauge ggDoorPermitPresetButton;
TGauge ggDoorLeftButton;
TGauge ggDoorRightButton;
TGauge ggDoorLeftOnButton;
TGauge ggDoorRightOnButton;
TGauge ggDoorLeftOffButton;
TGauge ggDoorRightOffButton;
TGauge ggDoorAllOnButton;
TGauge ggDoorAllOffButton;
TGauge ggDepartureSignalButton;
@@ -515,7 +526,7 @@ public: // reszta może by?publiczna
TButton btInstrumentLight;
TButton btDashboardLight;
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 DashboardLightActive{ false };
bool TimetableLightActive{ false };
@@ -548,6 +559,7 @@ public: // reszta może by?publiczna
TButton btLampkaPrzekrMaxSila;
TButton btLampkaDoorLeft;
TButton btLampkaDoorRight;
TButton btLampkaDoors;
TButton btLampkaDepartureSignal;
TButton btLampkaBlokadaDrzwi;
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
// Ra: zwraca false, jeśli pojazd ma być usunięty
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
double s; // roboczy dystans
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
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)
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 ) {
//McZapkie-140602: wyzwalanie zdarzenia gdy pojazd stoi
if( ( Owner->Mechanik != nullptr )
@@ -127,18 +130,14 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
&& ( Owner->Mechanik->Primary() ) ) {
// tylko dla jednego członu
// McZapkie-280503: wyzwalanie event tylko dla pojazdow z obsada
if( true == bPrimary ) {
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner );
}
}
}
if( SetFlag( iEventallFlag, -1 ) ) {
// McZapkie-280503: wyzwalanie eventall dla wszystkich pojazdow
if( true == bPrimary ) {
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1all, Owner );
}
}
}
else if( ( fDistance > 0 ) && ( eventfilter > 0 ) ) {
// event2, eventall2
if( SetFlag( iEventFlag, -2 ) ) {
@@ -146,19 +145,15 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
if( ( Owner->Mechanik != nullptr )
&& ( Owner->Mechanik->Primary() ) ) {
// tylko dla jednego członu
if( true == bPrimary ) {
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner );
}
}
}
if( SetFlag( iEventallFlag, -2 ) ) {
// sprawdza i zeruje na przyszłość, true jeśli zmieni z 2 na 0
if( true == bPrimary ) {
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2all, Owner );
}
}
}
}
if (!pCurrentSegment) // jeżeli nie ma powiązanego segmentu toru?
return false;
// if (fDistance==0.0) return true; //Ra: jak stoi, to chyba dalej nie ma co kombinować?

View File

@@ -143,8 +143,13 @@ commanddescription_sequence Commands_descriptions = {
{ "carcouplingdisconnect", command_target::vehicle, command_mode::oneoff },
{ "doortoggleleft", 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 },
{ "dooropenright", command_target::vehicle, command_mode::oneoff },
{ "dooropenall", command_target::vehicle, command_mode::oneoff },
{ "doorcloseleft", command_target::vehicle, command_mode::oneoff },
{ "doorcloseright", command_target::vehicle, command_mode::oneoff },
{ "doorcloseall", command_target::vehicle, command_mode::oneoff },

View File

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

View File

@@ -144,8 +144,13 @@ driverkeyboard_input::default_bindings() {
{ user_command::carcouplingdisconnect, GLFW_KEY_DELETE },
{ user_command::doortoggleleft, GLFW_KEY_COMMA },
{ 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,
// dooropenright,
{ user_command::dooropenall, GLFW_KEY_SLASH | keymodifier::shift },
// doorcloseleft,
// doorcloseright,
{ user_command::doorcloseall, GLFW_KEY_SLASH | keymodifier::control },
@@ -202,8 +207,8 @@ driverkeyboard_input::default_bindings() {
{ user_command::instrumentlighttoggle, GLFW_KEY_SEMICOLON },
// instrumentlightenable,
// instrumentlightdisable,
// dashboardlighttoggle,
// timetablelighttoggle,
{ user_command::dashboardlighttoggle, GLFW_KEY_SEMICOLON | keymodifier::shift },
{ user_command::timetablelighttoggle, GLFW_KEY_APOSTROPHE | keymodifier::shift },
{ user_command::generictoggle0, GLFW_KEY_0 },
{ user_command::generictoggle1, GLFW_KEY_1 },
{ user_command::generictoggle2, GLFW_KEY_2 },

View File

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

View File

@@ -558,6 +558,15 @@ drivermouse_input::default_bindings() {
{ "stlinoff_bt:", {
user_command::motorconnectorsopen,
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:", {
user_command::doortoggleleft,
user_command::none } },
@@ -576,6 +585,9 @@ drivermouse_input::default_bindings() {
{ "doorrightoff_sw:", {
user_command::doorcloseright,
user_command::none } },
{ "doorallon_sw:", {
user_command::dooropenall,
user_command::none } },
{ "dooralloff_sw:", {
user_command::doorcloseall,
user_command::none } },

View File

@@ -204,19 +204,47 @@ timetable_panel::update() {
auto textline = " -> " + nextstation;
text_lines.emplace_back( textline, Global.UITextColor );
text_lines.emplace_back( "", Global.UITextColor );
}
}
if( is_expanded ) {
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->Prev( coupling::permanent ) };
if( previous != nullptr ) { consistmass -= previous->MoverParameters->TotalMass; }
auto const *next { owner->pVehicle->Next( 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 ) {
// only bother if there's stations to list
text_lines.emplace_back( locale::strings[ locale::string::driver_timetable_notimetable ], Global.UITextColor );
}
else {
auto const readycolor { glm::vec4( 84.0f / 255.0f, 164.0f / 255.0f, 132.0f / 255.0f, 1.f ) };
// header
text_lines.emplace_back( "+-----+------------------------------------+-------+-----+", Global.UITextColor );
@@ -398,8 +426,8 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
mover.EngineDescription( 0 ).c_str(),
// TODO: put wheel flat reporting in the enginedescription()
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( side::rear ).c_str() );
update_vehicle_coupler( end::front ).c_str(),
update_vehicle_coupler( end::rear ).c_str() );
Output.emplace_back( std::string{ m_buffer.data() }, Global.UITextColor );
@@ -424,13 +452,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( isdieselenginepowered ? locale::strings[ locale::string::debug_vehicle_oilpressure ] + to_string( mover.OilPump.pressure, 2 ) : "" ).c_str(),
// power transfers
mover.Couplers[ side::front ].power_high.voltage,
mover.Couplers[ side::front ].power_high.current,
std::string( mover.Couplers[ side::front ].power_high.local ? "" : "-" ).c_str(),
mover.Couplers[ end::front ].power_high.voltage,
mover.Couplers[ end::front ].power_high.current,
std::string( mover.Couplers[ end::front ].power_high.local ? "" : "-" ).c_str(),
std::string( vehicle.DirectionGet() ? ":<<:" : ":>>:" ).c_str(),
std::string( mover.Couplers[ side::rear ].power_high.local ? "" : "-" ).c_str(),
mover.Couplers[ side::rear ].power_high.voltage,
mover.Couplers[ side::rear ].power_high.current );
std::string( mover.Couplers[ end::rear ].power_high.local ? "" : "-" ).c_str(),
mover.Couplers[ end::rear ].power_high.voltage,
mover.Couplers[ end::rear ].power_high.current );
Output.emplace_back( m_buffer.data(), Global.UITextColor );
@@ -448,8 +476,8 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
std::abs( mover.enrot ) * 60,
std::abs( mover.nrot ) * mover.Transmision.Ratio * 60,
mover.RventRot * 60,
std::abs( mover.MotorBlowers[side::front].revolutions ),
std::abs( mover.MotorBlowers[side::rear].revolutions ),
std::abs( mover.MotorBlowers[end::front].revolutions ),
std::abs( mover.MotorBlowers[end::rear].revolutions ),
mover.dizel_heat.rpmw,
mover.dizel_heat.rpmw2 );
@@ -541,7 +569,7 @@ debug_panel::update_vehicle_coupler( int const Side ) {
std::string couplerstatus { locale::strings[ locale::string::debug_vehicle_none ] };
auto const *connected { (
Side == side::front ?
Side == end::front ?
m_input.vehicle->PrevConnected :
m_input.vehicle->NextConnected ) };
@@ -660,6 +688,10 @@ debug_panel::update_section_ai( std::vector<text_line> &Output ) {
// biezaca komenda dla AI
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 );
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
// 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, side::rear );
data.emplace_back( Owner, end::front );
data.emplace_back( Owner, end::rear );
}
void
@@ -43,7 +43,7 @@ light_array::update() {
for( auto &light : data ) {
// update light parameters to match current data of the owner
if( light.index == side::front ) {
if( light.index == end::front ) {
// front light set
light.position = light.owner->GetPosition() + ( light.owner->VectorFront() * light.owner->GetLength() * 0.4 );
light.direction = glm::make_vec3( light.owner->VectorFront().getArray() );
@@ -60,7 +60,7 @@ light_array::update() {
|| ( true == light.owner->MoverParameters->ConverterFlag ) ) {
// 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...
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
light.count = 0
+ ( ( lights & light::headlight_left ) ? 1 : 0 )

10
lua.cpp
View File

@@ -29,6 +29,11 @@ lua::~lua()
state = nullptr;
}
std::string lua::get_error()
{
return std::string(lua_tostring(state, -1));
}
void lua::interpret(std::string file)
{
if (luaL_dofile(state, file.c_str())) {
@@ -43,10 +48,7 @@ void lua::interpret(std::string file)
int lua::atpanic(lua_State *s)
{
std::string err(lua_tostring(s, -1));
ErrorLog(std::string(err), logtype::lua);
#ifdef _WIN32
MessageBox(NULL, err.c_str(), "MaSzyna", MB_OK);
#endif
ErrorLog(err, logtype::lua);
return 0;
}

1
lua.h
View File

@@ -15,6 +15,7 @@ public:
lua();
~lua();
std::string get_error();
void interpret(std::string file);
typedef void (*eventhandler_t)(basic_event*, const TDynamicObject*);

View File

@@ -300,14 +300,19 @@ WyslijNamiary(TDynamicObject const *Vehicle)
r.iPar[19] = Vehicle->MoverParameters->MainCtrlActualPos; // Pozycja jezdna
r.iPar[20] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[21] = Vehicle->MoverParameters->ScndCtrlActualPos; // Pozycja bocznikowania
r.iPar[22] = Vehicle->MoverParameters->ResistorsFlag * 1 +
Vehicle->MoverParameters->ConverterFlag * 2 +
+Vehicle->MoverParameters->CompressorFlag * 4 +
Vehicle->MoverParameters->Mains * 8 +
+Vehicle->MoverParameters->DoorLeftOpened * 16 +
Vehicle->MoverParameters->DoorRightOpened * 32 +
+Vehicle->MoverParameters->FuseFlag * 64 +
Vehicle->MoverParameters->DepartureSignal * 128;
r.iPar[22] = Vehicle->MoverParameters->ResistorsFlag * 1
+ Vehicle->MoverParameters->ConverterFlag * 2
+ Vehicle->MoverParameters->CompressorFlag * 4
+ Vehicle->MoverParameters->Mains * 8
#ifdef EU07_USEOLDDOORCODE
+ Vehicle->MoverParameters->DoorLeftOpened * 16
+ Vehicle->MoverParameters->DoorRightOpened * 32
#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("Mam patykow "+IntToStr(t->DynamicObject->iAnimType[ANIM_PANTS]));
for (int p = 0; p < 4; p++)

View File

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

View File

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

View File

@@ -345,8 +345,8 @@ state_serializer::deserialize_node( cParser &Input, scene::scratch_data &Scratch
}
if( ( vehicle->MoverParameters->CategoryFlag == 1 ) // trains only
&& ( ( ( vehicle->LightList( side::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::front ) & ( 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 );
}
}
@@ -872,7 +872,7 @@ state_serializer::deserialize_dynamic( cParser &Input, scene::scratch_data &Scra
Scratchpad.trainset.offset -= length;
// automatically establish permanent connections for couplers which specify them in their definitions
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;
}
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 };
if( parameters.Doors.range == 0.f ) { goto next; }
if( parameters.LoadType.name.empty() ) {
// (try to) set the cargo type for empty cars
parameters.LoadAmount = 0.f; // safety measure against edge cases
@@ -57,7 +59,7 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
firststop ? 0 :
std::min<float>(
parameters.LoadAmount,
Random( parameters.MaxLoad * 0.10 * stationsizemodifier ) ) );
Random( parameters.MaxLoad * 0.15f * stationsizemodifier ) ) );
auto loadcount = static_cast<int>(
laststop ?
0 :
@@ -73,6 +75,7 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
exchangetime = std::max( exchangetime, vehicle->LoadExchangeTime() );
}
}
next:
vehicle = vehicle->Next();
}

View File

@@ -41,6 +41,7 @@ init() {
"Timetable",
"Time: %d:%02d:%02d",
"(no timetable)",
"Consist weight: %d t (specified) %d t (actual)\nConsist length: %d m",
"Transcripts",
@@ -114,13 +115,17 @@ init() {
"motor overload relay reset",
"converter overload relay reset",
"motor connectors",
"left door (permit)",
"right door (permit)",
"door (permit)",
"left door",
"right door",
"left door",
"right door",
"left door",
"right door",
"all doors",
"left door (open)",
"right door (open)",
"left door (close)",
"right door (close)",
"all doors (open)",
"all doors (close)",
"departure signal",
"upper headlight",
"left headlight",
@@ -196,6 +201,7 @@ init() {
u8"Rozkład jazdy",
u8"Godzina: %d:%02d:%02d",
u8"(brak rozkładu)",
u8"Brutto: %d t (rozkładowe) %d t (rzeczywiste)\nDługość pociągu: %d m",
u8"Transkrypcje",
@@ -269,13 +275,17 @@ init() {
u8"przekaźnik nadmiarowy silników trakcyjnych",
u8"przekaźnik nadmiarowy przetwornicy",
u8"styczniki liniowe",
u8"drzwi lewe (zezwól)",
u8"drzwi prawe (zezwól)",
u8"drzwi (zezwól)",
u8"drzwi lewe",
u8"drzwi prawe",
u8"drzwi lewe",
u8"drzwi prawe",
u8"drzwi lewe",
u8"drzwi prawe",
u8"drzwi",
u8"drzwi lewe (otwórz)",
u8"drzwi prawe (otwórz)",
u8"drzwi lewe (zamknij)",
u8"drzwi prawe (zamknij)",
u8"drzwi (otwórz)",
u8"drzwi (zamknij)",
u8"sygnal odjazdu",
u8"reflektor gorny",
u8"reflektor lewy",
@@ -379,12 +389,16 @@ init() {
"fuse_bt:",
"converterfuse_bt:",
"stlinoff_bt:",
"doorleftpermit_sw:",
"doorrightpermit_sw:",
"doorpermitpreset_sw:",
"door_left_sw:",
"door_right_sw:",
"doorlefton_sw:",
"doorrighton_sw:",
"doorleftoff_sw:",
"doorrightoff_sw:",
"doorallon_sw:",
"dooralloff_sw:",
"departure_signal_bt:",
"upperlight_sw:",

View File

@@ -30,6 +30,7 @@ enum string {
driver_timetable_header,
driver_timetable_time,
driver_timetable_notimetable,
driver_timetable_consistdata,
driver_transcripts_header,
@@ -103,12 +104,16 @@ enum string {
cab_fuse_bt,
cab_converterfuse_bt,
cab_stlinoff_bt,
cab_doorleftpermit_sw,
cab_doorrightpermit_sw,
cab_doorpermitpreset_sw,
cab_door_left_sw,
cab_door_right_sw,
cab_doorlefton_sw,
cab_doorrighton_sw,
cab_doorleftoff_sw,
cab_doorrightoff_sw,
cab_doorallon_sw,
cab_dooralloff_sw,
cab_departure_signal_bt,
cab_upperlight_sw,

View File

@@ -1 +1 @@
#define VERSION_INFO "M7 (GL3 NET) 27.01.2018, based on milek-4dc7b3d3d, tmj-753cf7ee5"
#define VERSION_INFO "M7 (GL3 NET) 21.02.2018, based on milek-267c4472a, tmj-bc60b5ac6"