mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 17:29:18 +02:00
generic cab control state indicators, ai master controller logic enhancements, battery charging for diesel powered vehicles workaround, water heater damage fix, ai route scanning fixes, material loading fix
This commit is contained in:
180
Driver.cpp
180
Driver.cpp
@@ -182,9 +182,9 @@ TSpeedPos::TSpeedPos(TTrack *track, double dist, int flag)
|
|||||||
Set(track, dist, flag);
|
Set(track, dist, flag);
|
||||||
};
|
};
|
||||||
|
|
||||||
TSpeedPos::TSpeedPos(basic_event *event, double dist, TOrders order)
|
TSpeedPos::TSpeedPos(basic_event *event, double dist, double length, TOrders order)
|
||||||
{
|
{
|
||||||
Set(event, dist, order);
|
Set(event, dist, length, order);
|
||||||
};
|
};
|
||||||
|
|
||||||
void TSpeedPos::Clear()
|
void TSpeedPos::Clear()
|
||||||
@@ -366,13 +366,20 @@ bool TSpeedPos::IsProperSemaphor(TOrders order)
|
|||||||
return false; // true gdy zatrzymanie, wtedy nie ma po co skanować dalej
|
return false; // true gdy zatrzymanie, wtedy nie ma po co skanować dalej
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TSpeedPos::Set(basic_event *event, double dist, TOrders order)
|
bool TSpeedPos::Set(basic_event *event, double dist, double length, TOrders order)
|
||||||
{ // zapamiętanie zdarzenia
|
{ // zapamiętanie zdarzenia
|
||||||
fDist = dist;
|
fDist = dist;
|
||||||
iFlags = spEnabled | spEvent; // event+istotny
|
iFlags = spEvent;
|
||||||
evEvent = event;
|
evEvent = event;
|
||||||
vPos = event->input_location(); // współrzędne eventu albo komórki pamięci (zrzutować na tor?)
|
vPos = event->input_location(); // współrzędne eventu albo komórki pamięci (zrzutować na tor?)
|
||||||
CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości
|
if( dist + length >= 0 ) {
|
||||||
|
iFlags |= spEnabled;
|
||||||
|
CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// located behind the tracking consist, don't bother with it
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// zależnie od trybu sprawdzenie czy jest tutaj gdzieś semafor lub tarcza manewrowa
|
// zależnie od trybu sprawdzenie czy jest tutaj gdzieś semafor lub tarcza manewrowa
|
||||||
// jeśli wskazuje stop wtedy wystawiamy true jako koniec sprawdzania
|
// jeśli wskazuje stop wtedy wystawiamy true jako koniec sprawdzania
|
||||||
// WriteLog("EventSet: Vel=" + AnsiString(fVelNext) + " iFlags=" + AnsiString(iFlags) + " order="+AnsiString(order));
|
// WriteLog("EventSet: Vel=" + AnsiString(fVelNext) + " iFlags=" + AnsiString(iFlags) + " order="+AnsiString(order));
|
||||||
@@ -582,6 +589,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
|
|||||||
if( newspeedpoint.Set(
|
if( newspeedpoint.Set(
|
||||||
pEvent,
|
pEvent,
|
||||||
GetDistanceToEvent( pTrack, pEvent, fLastDir, fCurrentDistance ),
|
GetDistanceToEvent( pTrack, pEvent, fLastDir, fCurrentDistance ),
|
||||||
|
fLength,
|
||||||
OrderCurrentGet() ) ) {
|
OrderCurrentGet() ) ) {
|
||||||
|
|
||||||
fDistance = newspeedpoint.fDist; // jeśli sygnał stop, to nie ma potrzeby dalej skanować
|
fDistance = newspeedpoint.fDist; // jeśli sygnał stop, to nie ma potrzeby dalej skanować
|
||||||
@@ -1911,72 +1919,83 @@ void TController::AutoRewident()
|
|||||||
mvOccupied->BrakeOpModeFlag = i;
|
mvOccupied->BrakeOpModeFlag = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// teraz zerujemy tabelkę opóźnienia hamowania
|
// teraz zerujemy tabelkę opóźnienia hamowania
|
||||||
for (int i = 0; i < BrakeAccTableSize; ++i)
|
for (int i = 0; i < BrakeAccTableSize; ++i)
|
||||||
{
|
{
|
||||||
fBrake_a0[i+1] = 0;
|
fBrake_a0[i+1] = 0;
|
||||||
fBrake_a1[i+1] = 0;
|
fBrake_a1[i+1] = 0;
|
||||||
}
|
}
|
||||||
// 4. Przeliczanie siły hamowania
|
|
||||||
double const velstep = ( mvOccupied->Vmax*0.5 ) / BrakeAccTableSize;
|
|
||||||
d = pVehicles[0]; // pojazd na czele składu
|
|
||||||
while (d) {
|
|
||||||
for( int i = 0; i < BrakeAccTableSize; ++i ) {
|
|
||||||
fBrake_a0[ i + 1 ] += d->MoverParameters->BrakeForceR( 0.25, velstep*( 1 + 2 * i ) );
|
|
||||||
fBrake_a1[ i + 1 ] += d->MoverParameters->BrakeForceR( 1.00, velstep*( 1 + 2 * i ) );
|
|
||||||
}
|
|
||||||
d = d->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
|
|
||||||
}
|
|
||||||
for (int i = 0; i < BrakeAccTableSize; ++i)
|
|
||||||
{
|
|
||||||
fBrake_a1[i+1] -= fBrake_a0[i+1];
|
|
||||||
fBrake_a0[i+1] /= fMass;
|
|
||||||
fBrake_a0[i + 1] += 0.001*velstep*(1 + 2 * i);
|
|
||||||
fBrake_a1[i+1] /= (12*fMass);
|
|
||||||
}
|
|
||||||
|
|
||||||
IsCargoTrain = ( mvOccupied->CategoryFlag == 1 ) && ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 );
|
if( OrderCurrentGet() & Shunt ) {
|
||||||
IsHeavyCargoTrain = ( true == IsCargoTrain ) && ( fBrake_a0[ 1 ] > 0.4 );
|
// for uniform behaviour and compatibility with older scenarios set default acceleration table values for shunting
|
||||||
|
fAccThreshold = (
|
||||||
BrakingInitialLevel = (
|
mvOccupied->TrainType == dt_EZT ? -0.55 :
|
||||||
IsHeavyCargoTrain ? 1.25 :
|
mvOccupied->TrainType == dt_DMU ? -0.45 :
|
||||||
IsCargoTrain ? 1.25 :
|
-0.2 );
|
||||||
1.00 );
|
// HACK: emu with induction motors need to start their braking a bit sooner than the ones with series motors
|
||||||
|
if( ( mvOccupied->TrainType == dt_EZT )
|
||||||
BrakingLevelIncrease = (
|
&& ( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) ) {
|
||||||
IsHeavyCargoTrain ? 0.25 :
|
fAccThreshold += 0.10;
|
||||||
IsCargoTrain ? 0.25 :
|
|
||||||
0.25 );
|
|
||||||
|
|
||||||
if( mvOccupied->TrainType == dt_EZT ) {
|
|
||||||
if( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) {
|
|
||||||
// HACK: emu with induction motors need to start their braking a bit sooner than the ones with series motors
|
|
||||||
fNominalAccThreshold = std::max( -0.60, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
fNominalAccThreshold = std::max( -0.75, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
|
|
||||||
}
|
|
||||||
fBrakeReaction = 0.25;
|
|
||||||
}
|
|
||||||
else if( mvOccupied->TrainType == dt_DMU ) {
|
|
||||||
fNominalAccThreshold = std::max( -0.45, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
|
|
||||||
fBrakeReaction = 0.25;
|
|
||||||
}
|
}
|
||||||
else if (ustaw > 16) {
|
|
||||||
fNominalAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 4 * fBrake_a1[ BrakeAccTableSize ];
|
if( OrderCurrentGet() & Obey_train ) {
|
||||||
fBrakeReaction = 1.00 + fLength*0.004;
|
// 4. Przeliczanie siły hamowania
|
||||||
}
|
double const velstep = ( mvOccupied->Vmax*0.5 ) / BrakeAccTableSize;
|
||||||
else {
|
d = pVehicles[0]; // pojazd na czele składu
|
||||||
fNominalAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 1 * fBrake_a1[ BrakeAccTableSize ];
|
while (d) {
|
||||||
fBrakeReaction = 1.00 + fLength*0.005;
|
for( int i = 0; i < BrakeAccTableSize; ++i ) {
|
||||||
}
|
fBrake_a0[ i + 1 ] += d->MoverParameters->BrakeForceR( 0.25, velstep*( 1 + 2 * i ) );
|
||||||
fAccThreshold = fNominalAccThreshold;
|
fBrake_a1[ i + 1 ] += d->MoverParameters->BrakeForceR( 1.00, velstep*( 1 + 2 * i ) );
|
||||||
/*
|
}
|
||||||
if( IsHeavyCargoTrain ) {
|
d = d->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła)
|
||||||
// HACK: heavy cargo trains don't activate brakes early enough
|
}
|
||||||
fAccThreshold = std::max( -0.2, fAccThreshold );
|
for (int i = 0; i < BrakeAccTableSize; ++i)
|
||||||
|
{
|
||||||
|
fBrake_a1[i+1] -= fBrake_a0[i+1];
|
||||||
|
fBrake_a0[i+1] /= fMass;
|
||||||
|
fBrake_a0[i + 1] += 0.001*velstep*(1 + 2 * i);
|
||||||
|
fBrake_a1[i+1] /= (12*fMass);
|
||||||
|
}
|
||||||
|
|
||||||
|
IsCargoTrain = ( mvOccupied->CategoryFlag == 1 ) && ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 );
|
||||||
|
IsHeavyCargoTrain = ( true == IsCargoTrain ) && ( fBrake_a0[ 1 ] > 0.4 );
|
||||||
|
|
||||||
|
BrakingInitialLevel = (
|
||||||
|
IsHeavyCargoTrain ? 1.25 :
|
||||||
|
IsCargoTrain ? 1.25 :
|
||||||
|
1.00 );
|
||||||
|
|
||||||
|
BrakingLevelIncrease = (
|
||||||
|
IsHeavyCargoTrain ? 0.25 :
|
||||||
|
IsCargoTrain ? 0.25 :
|
||||||
|
0.25 );
|
||||||
|
|
||||||
|
if( mvOccupied->TrainType == dt_EZT ) {
|
||||||
|
if( mvControlling->EngineType == TEngineType::ElectricInductionMotor ) {
|
||||||
|
// HACK: emu with induction motors need to start their braking a bit sooner than the ones with series motors
|
||||||
|
fNominalAccThreshold = std::max( -0.60, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fNominalAccThreshold = std::max( -0.75, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
|
||||||
|
}
|
||||||
|
fBrakeReaction = 0.25;
|
||||||
|
}
|
||||||
|
else if( mvOccupied->TrainType == dt_DMU ) {
|
||||||
|
fNominalAccThreshold = std::max( -0.45, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] );
|
||||||
|
fBrakeReaction = 0.25;
|
||||||
|
}
|
||||||
|
else if (ustaw > 16) {
|
||||||
|
fNominalAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 4 * fBrake_a1[ BrakeAccTableSize ];
|
||||||
|
fBrakeReaction = 1.00 + fLength*0.004;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fNominalAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 1 * fBrake_a1[ BrakeAccTableSize ];
|
||||||
|
fBrakeReaction = 1.00 + fLength*0.005;
|
||||||
|
}
|
||||||
|
fAccThreshold = fNominalAccThreshold;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double TController::ESMVelocity(bool Main)
|
double TController::ESMVelocity(bool Main)
|
||||||
@@ -2854,7 +2873,11 @@ bool TController::IncSpeed()
|
|||||||
auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 125 : 100 ) * 1000.0 };
|
auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 125 : 100 ) * 1000.0 };
|
||||||
auto const seriesmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 ) };
|
auto const seriesmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 ) };
|
||||||
auto const parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) };
|
auto const parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) };
|
||||||
auto const useseriesmodevoltage { mvControlling->EnginePowerSource.CollectorParameters.MaxV * ( IsHeavyCargoTrain ? 0.70 : 0.80 ) };
|
auto const useseriesmodevoltage {
|
||||||
|
interpolate(
|
||||||
|
mvControlling->EnginePowerSource.CollectorParameters.MinV,
|
||||||
|
mvControlling->EnginePowerSource.CollectorParameters.MaxV,
|
||||||
|
( IsHeavyCargoTrain ? 0.35 : 0.40 ) ) };
|
||||||
auto const useseriesmode = (
|
auto const useseriesmode = (
|
||||||
( mvControlling->Imax > mvControlling->ImaxLo )
|
( mvControlling->Imax > mvControlling->ImaxLo )
|
||||||
|| ( fVoltage < useseriesmodevoltage )
|
|| ( fVoltage < useseriesmodevoltage )
|
||||||
@@ -2885,7 +2908,7 @@ bool TController::IncSpeed()
|
|||||||
if( usefieldshunting ) {
|
if( usefieldshunting ) {
|
||||||
// to dać bocznik
|
// to dać bocznik
|
||||||
// engage the shuntfield only if there's sufficient power margin to draw from
|
// engage the shuntfield only if there's sufficient power margin to draw from
|
||||||
auto const sufficientpowermargin { fVoltage - useseriesmodevoltage > ( IsHeavyCargoTrain ? 100.0 : 50.0 ) };
|
auto const sufficientpowermargin { fVoltage - useseriesmodevoltage > ( IsHeavyCargoTrain ? 100.0 : 75.0 ) };
|
||||||
|
|
||||||
OK = (
|
OK = (
|
||||||
sufficientpowermargin ?
|
sufficientpowermargin ?
|
||||||
@@ -2898,7 +2921,14 @@ bool TController::IncSpeed()
|
|||||||
mvControlling->DecScndCtrl( 2 );
|
mvControlling->DecScndCtrl( 2 );
|
||||||
}
|
}
|
||||||
// kręcimy nastawnik jazdy
|
// kręcimy nastawnik jazdy
|
||||||
auto const sufficientpowermargin { fVoltage - useseriesmodevoltage > ( IsHeavyCargoTrain ? 80.0 : 40.0 ) };
|
// don't draw too much power;
|
||||||
|
// keep from dropping into series mode when entering/using parallel mode, and from shutting down in the series mode
|
||||||
|
auto const sufficientpowermargin {
|
||||||
|
fVoltage - (
|
||||||
|
mvControlling->RList[ std::min( mvControlling->MainCtrlPos + 1, mvControlling->MainCtrlPosNo ) ].Bn == 1 ?
|
||||||
|
mvControlling->EnginePowerSource.CollectorParameters.MinV :
|
||||||
|
useseriesmodevoltage )
|
||||||
|
> ( IsHeavyCargoTrain ? 80.0 : 60.0 ) };
|
||||||
|
|
||||||
OK = (
|
OK = (
|
||||||
( sufficientpowermargin && ( false == mvControlling->DelayCtrlFlag ) ) ?
|
( sufficientpowermargin && ( false == mvControlling->DelayCtrlFlag ) ) ?
|
||||||
@@ -3909,12 +3939,13 @@ TController::UpdateSituation(double dt) {
|
|||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
// crude way to deal with automatic door opening on W4 preventing further ride
|
// HACK: crude way to deal with automatic door opening on W4 preventing further ride
|
||||||
// for human-controlled vehicles with no door control and dynamic brake auto-activating with door open
|
// for human-controlled vehicles with no door control and dynamic brake auto-activating with door open
|
||||||
|
// 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->DoorCloseCtrl != control_t::driver )
|
||||||
&& ( mvControlling->MainCtrlPos > 0 ) ) {
|
&& ( mvControlling->MainCtrlPos > ( mvControlling->EngineType != TEngineType::DieselEngine ? 0 : 1 ) ) ) { // for diesel 1st position is effectively 0
|
||||||
Doors( false );
|
Doors( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4013,7 +4044,12 @@ TController::UpdateSituation(double dt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const useseriesmodevoltage { mvControlling->EnginePowerSource.CollectorParameters.MaxV * ( IsHeavyCargoTrain ? 0.70 : 0.80 ) };
|
// TODO: refactor this calculation into a subroutine
|
||||||
|
auto const useseriesmodevoltage {
|
||||||
|
interpolate(
|
||||||
|
mvControlling->EnginePowerSource.CollectorParameters.MinV,
|
||||||
|
mvControlling->EnginePowerSource.CollectorParameters.MaxV,
|
||||||
|
( IsHeavyCargoTrain ? 0.35 : 0.40 ) ) };
|
||||||
|
|
||||||
if( fVoltage <= useseriesmodevoltage ) {
|
if( fVoltage <= useseriesmodevoltage ) {
|
||||||
// if the power station is heavily burdened try to reduce the load
|
// if the power station is heavily burdened try to reduce the load
|
||||||
@@ -5865,12 +5901,20 @@ basic_event * TController::CheckTrackEventBackward(double fDirection, TTrack *Tr
|
|||||||
{ // sprawdzanie eventu w torze, czy jest sygnałowym - skanowanie do tyłu
|
{ // sprawdzanie eventu w torze, czy jest sygnałowym - skanowanie do tyłu
|
||||||
// NOTE: this method returns only one event which meets the conditions, due to limitations in the caller
|
// NOTE: this method returns only one event which meets the conditions, due to limitations in the caller
|
||||||
// TBD, TODO: clean up the caller and return all suitable events, as in theory things will go awry if the track has more than one signal
|
// TBD, TODO: clean up the caller and return all suitable events, as in theory things will go awry if the track has more than one signal
|
||||||
|
auto const dir{ pVehicles[ 0 ]->VectorFront() * pVehicles[ 0 ]->DirectionGet() };
|
||||||
|
auto const pos{ pVehicles[ 0 ]->HeadPosition() };
|
||||||
auto const &eventsequence { ( fDirection > 0 ? Track->m_events2 : Track->m_events1 ) };
|
auto const &eventsequence { ( fDirection > 0 ? Track->m_events2 : Track->m_events1 ) };
|
||||||
for( auto const &event : eventsequence ) {
|
for( auto const &event : eventsequence ) {
|
||||||
if( ( event.second != nullptr )
|
if( ( event.second != nullptr )
|
||||||
&& ( event.second->m_passive )
|
&& ( event.second->m_passive )
|
||||||
&& ( typeid(*(event.second)) == typeid( getvalues_event ) ) ) {
|
&& ( typeid(*(event.second)) == typeid( getvalues_event ) ) ) {
|
||||||
return event.second;
|
// since we're checking for events behind us discard the sources in front of the scanning vehicle
|
||||||
|
auto const sl{ event.second->input_location() }; // położenie komórki pamięci
|
||||||
|
auto const sem{ sl - pos }; // wektor do komórki pamięci od końca składu
|
||||||
|
if( dir.x * sem.x + dir.z * sem.z < 0 ) {
|
||||||
|
// iloczyn skalarny jest ujemny, gdy sygnał stoi z tyłu
|
||||||
|
return event.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
4
Driver.h
4
Driver.h
@@ -141,7 +141,7 @@ class TSpeedPos
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
TSpeedPos(TTrack *track, double dist, int flag);
|
TSpeedPos(TTrack *track, double dist, int flag);
|
||||||
TSpeedPos(basic_event *event, double dist, TOrders order);
|
TSpeedPos(basic_event *event, double dist, double length, TOrders order);
|
||||||
TSpeedPos() = default;
|
TSpeedPos() = default;
|
||||||
void Clear();
|
void Clear();
|
||||||
bool Update();
|
bool Update();
|
||||||
@@ -150,7 +150,7 @@ class TSpeedPos
|
|||||||
void
|
void
|
||||||
UpdateDistance( double dist ) {
|
UpdateDistance( double dist ) {
|
||||||
fDist -= dist; }
|
fDist -= dist; }
|
||||||
bool Set(basic_event *e, double d, TOrders order = Wait_for_orders);
|
bool Set(basic_event *e, double d, double length, TOrders order = Wait_for_orders);
|
||||||
void Set(TTrack *t, double d, int f);
|
void Set(TTrack *t, double d, int f);
|
||||||
std::string TableText() const;
|
std::string TableText() const;
|
||||||
std::string GetName() const;
|
std::string GetName() const;
|
||||||
|
|||||||
@@ -2782,7 +2782,7 @@ TDynamicObject::update_load_visibility() {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
auto loadpercentage { (
|
auto loadpercentage { (
|
||||||
MoverParameters->MaxLoad == 0.0 ?
|
MoverParameters->MaxLoad == 0.f ?
|
||||||
0.0 :
|
0.0 :
|
||||||
100.0 * MoverParameters->LoadAmount / MoverParameters->MaxLoad ) };
|
100.0 * MoverParameters->LoadAmount / MoverParameters->MaxLoad ) };
|
||||||
auto const sectionloadpercentage { (
|
auto const sectionloadpercentage { (
|
||||||
@@ -2816,7 +2816,7 @@ TDynamicObject::update_load_offset() {
|
|||||||
if( MoverParameters->LoadType.offset_min == 0.f ) { return; }
|
if( MoverParameters->LoadType.offset_min == 0.f ) { return; }
|
||||||
|
|
||||||
auto const loadpercentage { (
|
auto const loadpercentage { (
|
||||||
MoverParameters->MaxLoad == 0.0 ?
|
MoverParameters->MaxLoad == 0.f ?
|
||||||
0.0 :
|
0.0 :
|
||||||
100.0 * MoverParameters->LoadAmount / MoverParameters->MaxLoad ) };
|
100.0 * MoverParameters->LoadAmount / MoverParameters->MaxLoad ) };
|
||||||
|
|
||||||
|
|||||||
@@ -812,10 +812,13 @@ void TMoverParameters::UpdateBatteryVoltage(double dt)
|
|||||||
|
|
||||||
// HACK: allow to draw power also from adjacent converter, applicable for EMUs
|
// HACK: allow to draw power also from adjacent converter, applicable for EMUs
|
||||||
// TODO: expand power cables system to include low voltage power transfers
|
// TODO: expand power cables system to include low voltage power transfers
|
||||||
|
// 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[ side::front ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ side::front ].Connected->ConverterFlag )
|
||||||
|| ( ( ( Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ side::rear ].Connected->ConverterFlag ) ) };
|
|| ( ( ( Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && Couplers[ side::rear ].Connected->ConverterFlag ) )
|
||||||
|
|| ( ( EngineType == TEngineType::DieselElectric ) && ( true == Mains ) )
|
||||||
|
|| ( ( EngineType == TEngineType::DieselEngine ) && ( true == Mains ) ) };
|
||||||
|
|
||||||
if ((NominalBatteryVoltage / BatteryVoltage < 1.22) && Battery)
|
if ((NominalBatteryVoltage / BatteryVoltage < 1.22) && Battery)
|
||||||
{ // 110V
|
{ // 110V
|
||||||
@@ -1529,18 +1532,18 @@ void TMoverParameters::WaterPumpCheck( double const Timestep ) {
|
|||||||
// water heater status check
|
// water heater status check
|
||||||
void TMoverParameters::WaterHeaterCheck( double const Timestep ) {
|
void TMoverParameters::WaterHeaterCheck( double const Timestep ) {
|
||||||
|
|
||||||
WaterHeater.is_damaged = (
|
|
||||||
( true == WaterHeater.is_damaged )
|
|
||||||
|| ( ( true == WaterHeater.is_active )
|
|
||||||
&& ( false == WaterPump.is_active ) ) );
|
|
||||||
|
|
||||||
WaterHeater.is_active = (
|
WaterHeater.is_active = (
|
||||||
( false == WaterHeater.is_damaged )
|
( false == WaterHeater.is_damaged )
|
||||||
&& ( true == Battery )
|
&& ( true == Battery )
|
||||||
&& ( true == WaterHeater.is_enabled )
|
&& ( true == WaterHeater.is_enabled )
|
||||||
&& ( true == WaterHeater.breaker )
|
&& ( true == WaterHeater.breaker )
|
||||||
&& ( ( WaterHeater.is_active ) || ( WaterHeater.config.temp_min < 0 ) || ( dizel_heat.temperatura1 < WaterHeater.config.temp_min ) ) );
|
&& ( ( WaterHeater.is_active ) || ( WaterHeater.config.temp_min < 0 ) || ( dizel_heat.temperatura1 < WaterHeater.config.temp_min ) ) );
|
||||||
|
|
||||||
|
WaterHeater.is_damaged = (
|
||||||
|
( true == WaterHeater.is_damaged )
|
||||||
|
|| ( ( true == WaterHeater.is_active )
|
||||||
|
&& ( false == WaterPump.is_active ) ) );
|
||||||
|
|
||||||
if( ( WaterHeater.config.temp_max > 0 )
|
if( ( WaterHeater.config.temp_max > 0 )
|
||||||
&& ( dizel_heat.temperatura1 > WaterHeater.config.temp_max ) ) {
|
&& ( dizel_heat.temperatura1 > WaterHeater.config.temp_max ) ) {
|
||||||
WaterHeater.is_active = false;
|
WaterHeater.is_active = false;
|
||||||
@@ -6664,7 +6667,7 @@ TMoverParameters::AssignLoad( std::string const &Name, float const Amount ) {
|
|||||||
for( auto const &loadattributes : LoadAttributes ) {
|
for( auto const &loadattributes : LoadAttributes ) {
|
||||||
if( Name == loadattributes.name ) {
|
if( Name == loadattributes.name ) {
|
||||||
LoadType = loadattributes;
|
LoadType = loadattributes;
|
||||||
LoadAmount = Amount;
|
LoadAmount = clamp( Amount, 0.f, MaxLoad ) ;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6702,7 +6705,7 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn
|
|||||||
if( ( LoadAmount <= 0 ) || ( CommandIn.Value1 <= 0 ) ) {
|
if( ( LoadAmount <= 0 ) || ( CommandIn.Value1 <= 0 ) ) {
|
||||||
// pusto lub rozładowano żądaną ilość
|
// pusto lub rozładowano żądaną ilość
|
||||||
LoadStatus = 4; // skończony rozładunek
|
LoadStatus = 4; // skończony rozładunek
|
||||||
LoadAmount = std::max( 0.f, LoadAmount ); //ładunek nie może być ujemny
|
LoadAmount = clamp( LoadAmount, 0.f, MaxLoad); //ładunek nie może być ujemny
|
||||||
}
|
}
|
||||||
if( LoadAmount == 0.f ) {
|
if( LoadAmount == 0.f ) {
|
||||||
AssignLoad(""); // jak nic nie ma, to nie ma też nazwy
|
AssignLoad(""); // jak nic nie ma, to nie ma też nazwy
|
||||||
|
|||||||
65
Train.cpp
65
Train.cpp
@@ -448,9 +448,9 @@ PyObject *TTrain::GetTrainState() {
|
|||||||
// basic systems state data
|
// basic systems state data
|
||||||
PyDict_SetItemString( dict, "battery", PyGetBool( mvControlled->Battery ) );
|
PyDict_SetItemString( dict, "battery", PyGetBool( mvControlled->Battery ) );
|
||||||
PyDict_SetItemString( dict, "linebreaker", PyGetBool( mvControlled->Mains ) );
|
PyDict_SetItemString( dict, "linebreaker", PyGetBool( mvControlled->Mains ) );
|
||||||
PyDict_SetItemString( dict, "converter", PyGetBool( mover->ConverterFlag ) );
|
PyDict_SetItemString( dict, "converter", PyGetBool( mvControlled->ConverterFlag ) );
|
||||||
PyDict_SetItemString( dict, "converter_overload", PyGetBool( mover->ConvOvldFlag ) );
|
PyDict_SetItemString( dict, "converter_overload", PyGetBool( mvControlled->ConvOvldFlag ) );
|
||||||
PyDict_SetItemString( dict, "compress", PyGetBool( mover->CompressorFlag ) );
|
PyDict_SetItemString( dict, "compress", PyGetBool( mvControlled->CompressorFlag ) );
|
||||||
// reverser
|
// reverser
|
||||||
PyDict_SetItemString( dict, "direction", PyGetInt( mover->ActiveDir ) );
|
PyDict_SetItemString( dict, "direction", PyGetInt( mover->ActiveDir ) );
|
||||||
// throttle
|
// throttle
|
||||||
@@ -463,34 +463,35 @@ PyObject *TTrain::GetTrainState() {
|
|||||||
bool const bEP = ( mvControlled->LocHandle->GetCP() > 0.2 ) || ( fEIMParams[ 0 ][ 2 ] > 0.01 );
|
bool const bEP = ( mvControlled->LocHandle->GetCP() > 0.2 ) || ( fEIMParams[ 0 ][ 2 ] > 0.01 );
|
||||||
PyDict_SetItemString( dict, "dir_brake", PyGetBool( bEP ) );
|
PyDict_SetItemString( dict, "dir_brake", PyGetBool( bEP ) );
|
||||||
bool bPN;
|
bool bPN;
|
||||||
if( ( typeid( *mvControlled->Hamulec ) == typeid( TLSt ) )
|
if( ( typeid( *mvOccupied->Hamulec ) == typeid( TLSt ) )
|
||||||
|| ( typeid( *mvControlled->Hamulec ) == typeid( TEStED ) ) ) {
|
|| ( typeid( *mvOccupied->Hamulec ) == typeid( TEStED ) ) ) {
|
||||||
|
|
||||||
TBrake* temp_ham = mvControlled->Hamulec.get();
|
TBrake* temp_ham = mvOccupied->Hamulec.get();
|
||||||
bPN = ( static_cast<TLSt*>( temp_ham )->GetEDBCP() > 0.2 );
|
bPN = ( static_cast<TLSt*>( temp_ham )->GetEDBCP() > 0.2 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
bPN = false;
|
bPN = false;
|
||||||
PyDict_SetItemString( dict, "indir_brake", PyGetBool( bPN ) );
|
PyDict_SetItemString( dict, "indir_brake", PyGetBool( bPN ) );
|
||||||
PyDict_SetItemString( dict, "brake_delay_flag", PyGetInt( mvControlled->BrakeDelayFlag ));
|
PyDict_SetItemString( dict, "brake_delay_flag", PyGetInt( mvOccupied->BrakeDelayFlag ));
|
||||||
PyDict_SetItemString( dict, "brake_op_mode_flag", PyGetInt( mvControlled->BrakeOpModeFlag ));
|
PyDict_SetItemString( dict, "brake_op_mode_flag", PyGetInt( mvOccupied->BrakeOpModeFlag ));
|
||||||
// other controls
|
// other controls
|
||||||
PyDict_SetItemString( dict, "ca", PyGetBool( TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) ) );
|
PyDict_SetItemString( dict, "ca", PyGetBool( TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) ) );
|
||||||
PyDict_SetItemString( dict, "shp", PyGetBool( TestFlag( mvOccupied->SecuritySystem.Status, s_active ) ) );
|
PyDict_SetItemString( dict, "shp", PyGetBool( TestFlag( mvOccupied->SecuritySystem.Status, s_active ) ) );
|
||||||
PyDict_SetItemString( dict, "pantpress", PyGetFloat( mvControlled->PantPress ) );
|
PyDict_SetItemString( dict, "pantpress", PyGetFloat( mvControlled->PantPress ) );
|
||||||
PyDict_SetItemString( dict, "universal3", PyGetBool( InstrumentLightActive ) );
|
PyDict_SetItemString( dict, "universal3", PyGetBool( InstrumentLightActive ) );
|
||||||
PyDict_SetItemString( dict, "radio_channel", PyGetInt( iRadioChannel ) );
|
PyDict_SetItemString( dict, "radio_channel", PyGetInt( iRadioChannel ) );
|
||||||
|
PyDict_SetItemString( dict, "door_lock", PyGetInt( mvOccupied->DoorLockEnabled ) );
|
||||||
// movement data
|
// movement data
|
||||||
PyDict_SetItemString( dict, "velocity", PyGetFloat( mover->Vel ) );
|
PyDict_SetItemString( dict, "velocity", PyGetFloat( mover->Vel ) );
|
||||||
PyDict_SetItemString( dict, "tractionforce", PyGetFloat( mover->Ft ) );
|
PyDict_SetItemString( dict, "tractionforce", PyGetFloat( mover->Ft ) );
|
||||||
PyDict_SetItemString( dict, "slipping_wheels", PyGetBool( mover->SlippingWheels ) );
|
PyDict_SetItemString( dict, "slipping_wheels", PyGetBool( mover->SlippingWheels ) );
|
||||||
PyDict_SetItemString( dict, "sanding", PyGetBool( mover->SandDose ) );
|
PyDict_SetItemString( dict, "sanding", PyGetBool( mover->SandDose ) );
|
||||||
// electric current data
|
// electric current data
|
||||||
PyDict_SetItemString( dict, "traction_voltage", PyGetFloat( mover->RunningTraction.TractionVoltage ) );
|
PyDict_SetItemString( dict, "traction_voltage", PyGetFloat( mvControlled->RunningTraction.TractionVoltage ) );
|
||||||
PyDict_SetItemString( dict, "voltage", PyGetFloat( mover->Voltage ) );
|
PyDict_SetItemString( dict, "voltage", PyGetFloat( mvControlled->Voltage ) );
|
||||||
PyDict_SetItemString( dict, "im", PyGetFloat( mover->Im ) );
|
PyDict_SetItemString( dict, "im", PyGetFloat( mvControlled->Im ) );
|
||||||
PyDict_SetItemString( dict, "fuse", PyGetBool( mover->FuseFlag ) );
|
PyDict_SetItemString( dict, "fuse", PyGetBool( mvControlled->FuseFlag ) );
|
||||||
PyDict_SetItemString( dict, "epfuse", PyGetBool( mover->EpFuse ) );
|
PyDict_SetItemString( dict, "epfuse", PyGetBool( mvOccupied->EpFuse ) );
|
||||||
// induction motor state data
|
// induction motor state data
|
||||||
char const *TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
|
char const *TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
|
||||||
char const *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
|
char const *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
|
||||||
@@ -575,6 +576,7 @@ PyObject *TTrain::GetTrainState() {
|
|||||||
PyDict_SetItemString( dict, "minutes", PyGetInt( simulation::Time.data().wMinute ) );
|
PyDict_SetItemString( dict, "minutes", PyGetInt( simulation::Time.data().wMinute ) );
|
||||||
PyDict_SetItemString( dict, "seconds", PyGetInt( simulation::Time.second() ) );
|
PyDict_SetItemString( dict, "seconds", PyGetInt( simulation::Time.second() ) );
|
||||||
PyDict_SetItemString( dict, "air_temperature", PyGetInt( Global.AirTemperature ) );
|
PyDict_SetItemString( dict, "air_temperature", PyGetInt( Global.AirTemperature ) );
|
||||||
|
PyDict_SetItemString( dict, "light_level", PyGetFloat( Global.fLuminance - std::max( 0.f, Global.Overcast - 1.f ) ) );
|
||||||
|
|
||||||
Application.release_python_lock();
|
Application.release_python_lock();
|
||||||
return dict;
|
return dict;
|
||||||
@@ -1041,7 +1043,7 @@ void TTrain::OnCommand_trainbrakeincrease( TTrain *Train, command_data const &Co
|
|||||||
if( Command.action != GLFW_RELEASE ) {
|
if( Command.action != GLFW_RELEASE ) {
|
||||||
|
|
||||||
if( Train->mvOccupied->BrakeHandle == TBrakeHandle::FV4a ) {
|
if( Train->mvOccupied->BrakeHandle == TBrakeHandle::FV4a ) {
|
||||||
Train->mvOccupied->BrakeLevelAdd( 0.1 /*15.0 * Command.time_delta*/ );
|
Train->mvOccupied->BrakeLevelAdd( 0.1 * Global.fBrakeStep );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Train->set_train_brake( Train->mvOccupied->BrakeCtrlPos + Global.fBrakeStep );
|
Train->set_train_brake( Train->mvOccupied->BrakeCtrlPos + Global.fBrakeStep );
|
||||||
@@ -1054,7 +1056,7 @@ void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Co
|
|||||||
if( Command.action != GLFW_RELEASE ) {
|
if( Command.action != GLFW_RELEASE ) {
|
||||||
// press or hold
|
// press or hold
|
||||||
if( Train->mvOccupied->BrakeHandle == TBrakeHandle::FV4a ) {
|
if( Train->mvOccupied->BrakeHandle == TBrakeHandle::FV4a ) {
|
||||||
Train->mvOccupied->BrakeLevelAdd( -0.1 /*-15.0 * Command.time_delta*/ );
|
Train->mvOccupied->BrakeLevelAdd( -0.1 * Global.fBrakeStep );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Train->set_train_brake( Train->mvOccupied->BrakeCtrlPos - Global.fBrakeStep );
|
Train->set_train_brake( Train->mvOccupied->BrakeCtrlPos - Global.fBrakeStep );
|
||||||
@@ -4085,14 +4087,14 @@ void TTrain::OnCommand_generictoggle( TTrain *Train, command_data const &Command
|
|||||||
|
|
||||||
auto const itemindex = static_cast<int>( Command.command ) - static_cast<int>( user_command::generictoggle0 );
|
auto const itemindex = static_cast<int>( Command.command ) - static_cast<int>( user_command::generictoggle0 );
|
||||||
auto &item = Train->ggUniversals[ itemindex ];
|
auto &item = Train->ggUniversals[ itemindex ];
|
||||||
|
/*
|
||||||
if( item.SubModel == nullptr ) {
|
if( item.SubModel == nullptr ) {
|
||||||
if( Command.action == GLFW_PRESS ) {
|
if( Command.action == GLFW_PRESS ) {
|
||||||
WriteLog( "Train generic item " + std::to_string( itemindex ) + " is missing, or wasn't defined" );
|
WriteLog( "Train generic item " + std::to_string( itemindex ) + " is missing, or wasn't defined" );
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if( Command.action == GLFW_PRESS ) {
|
if( Command.action == GLFW_PRESS ) {
|
||||||
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
||||||
if( item.GetDesiredValue() < 0.5 ) {
|
if( item.GetDesiredValue() < 0.5 ) {
|
||||||
@@ -5475,6 +5477,10 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
// others
|
// others
|
||||||
btLampkaMalfunction.Turn( mvControlled->dizel_heat.PA );
|
btLampkaMalfunction.Turn( mvControlled->dizel_heat.PA );
|
||||||
btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ side::front ].is_active ) && ( mvControlled->MotorBlowers[ side::rear ].is_active ) );
|
btLampkaMotorBlowers.Turn( ( mvControlled->MotorBlowers[ side::front ].is_active ) && ( mvControlled->MotorBlowers[ side::rear ].is_active ) );
|
||||||
|
// universal devices state indicators
|
||||||
|
for( auto idx = 0; idx < btUniversals.size(); ++idx ) {
|
||||||
|
btUniversals[ idx ].Turn( ggUniversals[ idx ].GetValue() > 0.5 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// wylaczone
|
// wylaczone
|
||||||
@@ -5530,6 +5536,10 @@ bool TTrain::Update( double const Deltatime )
|
|||||||
// others
|
// others
|
||||||
btLampkaMalfunction.Turn( false );
|
btLampkaMalfunction.Turn( false );
|
||||||
btLampkaMotorBlowers.Turn( false );
|
btLampkaMotorBlowers.Turn( false );
|
||||||
|
// universal devices state indicators
|
||||||
|
for( auto &universal : btUniversals ) {
|
||||||
|
universal.Turn( false );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // yB - wskazniki drugiego czlonu
|
{ // yB - wskazniki drugiego czlonu
|
||||||
@@ -6184,7 +6194,9 @@ void TTrain::update_sounds_runningnoise( sound_source &Sound ) {
|
|||||||
// volume calculation
|
// volume calculation
|
||||||
auto volume =
|
auto volume =
|
||||||
Sound.m_amplitudeoffset
|
Sound.m_amplitudeoffset
|
||||||
+ Sound.m_amplitudefactor * mvOccupied->Vel;
|
+ Sound.m_amplitudefactor * interpolate(
|
||||||
|
mvOccupied->Vel / ( 1 + mvOccupied->Vmax ), 1.0,
|
||||||
|
0.5 ); // scale base volume between 0.5-1.0
|
||||||
if( std::abs( mvOccupied->nrot ) > 0.01 ) {
|
if( std::abs( mvOccupied->nrot ) > 0.01 ) {
|
||||||
// hamulce wzmagaja halas
|
// hamulce wzmagaja halas
|
||||||
auto const brakeforceratio { (
|
auto const brakeforceratio { (
|
||||||
@@ -6208,7 +6220,7 @@ void TTrain::update_sounds_runningnoise( sound_source &Sound ) {
|
|||||||
interpolate(
|
interpolate(
|
||||||
0.0, 1.0,
|
0.0, 1.0,
|
||||||
clamp(
|
clamp(
|
||||||
mvOccupied->Vel / 40.0,
|
mvOccupied->Vel / 25.0,
|
||||||
0.0, 1.0 ) );
|
0.0, 1.0 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7075,6 +7087,9 @@ void TTrain::clear_cab_controls()
|
|||||||
btLampkaHamulecReczny.Clear();
|
btLampkaHamulecReczny.Clear();
|
||||||
btLampkaBlokadaDrzwi.Clear();
|
btLampkaBlokadaDrzwi.Clear();
|
||||||
btLampkaDoorLockOff.Clear();
|
btLampkaDoorLockOff.Clear();
|
||||||
|
for( auto &universal : btUniversals ) {
|
||||||
|
universal.Clear();
|
||||||
|
}
|
||||||
btInstrumentLight.Clear();
|
btInstrumentLight.Clear();
|
||||||
btDashboardLight.Clear();
|
btDashboardLight.Clear();
|
||||||
btTimetableLight.Clear();
|
btTimetableLight.Clear();
|
||||||
@@ -7507,7 +7522,17 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
|
|||||||
{ "i-rearrightend:", btLampkaRearRightEndLight },
|
{ "i-rearrightend:", btLampkaRearRightEndLight },
|
||||||
{ "i-dashboardlight:", btDashboardLight },
|
{ "i-dashboardlight:", btDashboardLight },
|
||||||
{ "i-timetablelight:", btTimetableLight },
|
{ "i-timetablelight:", btTimetableLight },
|
||||||
{ "i-cablight:", btCabLight }
|
{ "i-cablight:", btCabLight },
|
||||||
|
{ "i-universal0:", btUniversals[ 0 ] },
|
||||||
|
{ "i-universal1:", btUniversals[ 1 ] },
|
||||||
|
{ "i-universal2:", btUniversals[ 2 ] },
|
||||||
|
{ "i-universal3:", btUniversals[ 3 ] },
|
||||||
|
{ "i-universal4:", btUniversals[ 4 ] },
|
||||||
|
{ "i-universal5:", btUniversals[ 5 ] },
|
||||||
|
{ "i-universal6:", btUniversals[ 6 ] },
|
||||||
|
{ "i-universal7:", btUniversals[ 7 ] },
|
||||||
|
{ "i-universal8:", btUniversals[ 8 ] },
|
||||||
|
{ "i-universal9:", btUniversals[ 9 ] }
|
||||||
};
|
};
|
||||||
auto lookup = lights.find( Label );
|
auto lookup = lights.find( Label );
|
||||||
if( lookup != lights.end() ) {
|
if( lookup != lights.end() ) {
|
||||||
|
|||||||
1
Train.h
1
Train.h
@@ -505,6 +505,7 @@ public: // reszta może by?publiczna
|
|||||||
TButton btLampkaHamowanie2zes;
|
TButton btLampkaHamowanie2zes;
|
||||||
TButton btLampkaOpory;
|
TButton btLampkaOpory;
|
||||||
TButton btLampkaWysRozr;
|
TButton btLampkaWysRozr;
|
||||||
|
std::array<TButton, 10> btUniversals; // NOTE: temporary arrangement until we have dynamically built control table
|
||||||
TButton btInstrumentLight;
|
TButton btInstrumentLight;
|
||||||
TButton btDashboardLight;
|
TButton btDashboardLight;
|
||||||
TButton btTimetableLight;
|
TButton btTimetableLight;
|
||||||
|
|||||||
@@ -1133,6 +1133,7 @@ driver_mode::InOutKey()
|
|||||||
|
|
||||||
if( train == nullptr ) {
|
if( train == nullptr ) {
|
||||||
FreeFlyModeFlag = true; // nadal poza kabiną
|
FreeFlyModeFlag = true; // nadal poza kabiną
|
||||||
|
Camera.m_owner = nullptr; // detach camera from the vehicle
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,17 +60,19 @@ opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool c
|
|||||||
}
|
}
|
||||||
else if( ( key == "texture1:" )
|
else if( ( key == "texture1:" )
|
||||||
|| ( key == "texture_diffuse:" ) ) {
|
|| ( key == "texture_diffuse:" ) ) {
|
||||||
|
auto const value { deserialize_random_set( Input ) };
|
||||||
if( ( texture1 == null_handle )
|
if( ( texture1 == null_handle )
|
||||||
|| ( Priority > priority1 ) ) {
|
|| ( Priority > priority1 ) ) {
|
||||||
texture1 = GfxRenderer.Fetch_Texture( deserialize_random_set( Input ), Loadnow );
|
texture1 = GfxRenderer.Fetch_Texture( value, Loadnow );
|
||||||
priority1 = Priority;
|
priority1 = Priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( ( key == "texture2:" )
|
else if( ( key == "texture2:" )
|
||||||
|| ( key == "texture_normalmap:" ) ) {
|
|| ( key == "texture_normalmap:" ) ) {
|
||||||
|
auto const value { deserialize_random_set( Input ) };
|
||||||
if( ( texture2 == null_handle )
|
if( ( texture2 == null_handle )
|
||||||
|| ( Priority > priority2 ) ) {
|
|| ( Priority > priority2 ) ) {
|
||||||
texture2 = GfxRenderer.Fetch_Texture( deserialize_random_set( Input ), Loadnow );
|
texture2 = GfxRenderer.Fetch_Texture( value, Loadnow );
|
||||||
priority2 = Priority;
|
priority2 = Priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user