diff --git a/Driver.cpp b/Driver.cpp index 6a80d78c..d99c45ba 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -479,9 +479,17 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle) // jeśli w kierunku Point2 toru fTrackLength = pTrack->Length() - fTrackLength; // przeskanowana zostanie odległość do Point2 } - fTrackLength -= pVehicle->tracing_offset(); - fCurrentDistance = -fLength - fTrackLength; // aktualna odległość ma być ujemna gdyż jesteśmy na końcu składu - fLastVel = -1.0; // pTrack->VelocityGet(); // aktualna prędkość // changed to -1 to recognize speed limit, if any + // account for the fact tracing begins from active axle, not the actual front of the vehicle + // NOTE: position of the couplers is modified by track offset, but the axles ain't, so we need to account for this as well + fTrackLength -= ( + pVehicle->AxlePositionGet() + - pVehicle->RearPosition() + + pVehicle->VectorLeft() * pVehicle->MoverParameters->OffsetTrackH ) + .Length(); + // aktualna odległość ma być ujemna gdyż jesteśmy na końcu składu + fCurrentDistance = -fLength - fTrackLength; + // aktualna prędkość // changed to -1 to recognize speed limit, if any + fLastVel = -1.0; sSpeedTable.clear(); iLast = -1; tLast = nullptr; //żaden nie sprawdzony @@ -1429,13 +1437,13 @@ TController::braking_distance_multiplier( float const Targetvelocity ) const { return interpolate( 2.f, 1.f, static_cast( mvOccupied->Vel / 40.0 ) ); } // HACK: cargo trains or trains going downhill with high braking threshold need more distance to come to a full stop - if( ( fBrake_a0[ 0 ] > 0.2 ) - && ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ) - || ( fAccGravity > 0.025 ) ) { + if( ( fBrake_a0[ 1 ] > 0.2 ) + && ( ( true == IsCargoTrain ) + || ( fAccGravity > 0.025 ) ) ) { return interpolate( 1.f, 2.f, clamp( - ( fBrake_a0[ 0 ] - 0.2 ) / 0.2, + ( fBrake_a0[ 1 ] - 0.2 ) / 0.2, 0.0, 1.0 ) ); } @@ -1868,59 +1876,71 @@ void TController::AutoRewident() } d = d->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła) } - //teraz zerujemy tabelkę opóźnienia hamowania - double velstep = (mvOccupied->Vmax*0.5) / BrakeAccTableSize; - for (int i = 0; i < BrakeAccTableSize; i++) + //ustawianie trybu pracy zadajnika hamulca, wystarczy raz po inicjalizacji AI + for( int i = 1; i <= 8; i *= 2 ) { + if( ( mvOccupied->BrakeOpModes & i ) > 0 ) { + mvOccupied->BrakeOpModeFlag = i; + } + } + // teraz zerujemy tabelkę opóźnienia hamowania + for (int i = 0; i < BrakeAccTableSize; ++i) { fBrake_a0[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 - // HACK: calculated brake thresholds for cars are so high they prevent the AI from effectively braking - // thus we artificially reduce them until a better solution for the problem is found - auto const braketablescale { ( - d->MoverParameters->CategoryFlag == 2 ? - 0.6 : - 1.0 ) }; while (d) { for( int i = 0; i < BrakeAccTableSize; ++i ) { - fBrake_a0[ i + 1 ] += braketablescale * d->MoverParameters->BrakeForceR( 0.25, velstep*( 1 + 2 * i ) ); - fBrake_a1[ i + 1 ] += braketablescale * d->MoverParameters->BrakeForceR( 1.00, velstep*( 1 + 2 * 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++) + 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 ) { - fAccThreshold = std::max(-fBrake_a0[BrakeAccTableSize] - 8 * fBrake_a1[BrakeAccTableSize], -0.55); + fAccThreshold = std::max( -0.55, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] ); fBrakeReaction = 0.25; } else if( mvOccupied->TrainType == dt_DMU ) { - fAccThreshold = std::max( -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ], -0.45 ); + fAccThreshold = std::max( -0.45, -fBrake_a0[ BrakeAccTableSize ] - 8 * fBrake_a1[ BrakeAccTableSize ] ); fBrakeReaction = 0.25; } - else if (ustaw > 16) - { - fAccThreshold = -fBrake_a0[BrakeAccTableSize] - 4 * fBrake_a1[BrakeAccTableSize]; + else if (ustaw > 16) { + fAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 4 * fBrake_a1[ BrakeAccTableSize ]; fBrakeReaction = 1.00 + fLength*0.004; } - else - { - fAccThreshold = -fBrake_a0[BrakeAccTableSize] - 1 * fBrake_a1[BrakeAccTableSize]; + else { + fAccThreshold = -fBrake_a0[ BrakeAccTableSize ] - 1 * fBrake_a1[ BrakeAccTableSize ]; fBrakeReaction = 1.00 + fLength*0.005; } - for (int i = 1; i <= 8; i *= 2) //ustawianie trybu pracy zadajnika hamulca, wystarczy raz po inicjalizacji AI - { - if ((mvOccupied->BrakeOpModes & i) > 0) { - mvOccupied->BrakeOpModeFlag = i; - } - } +/* + if( IsHeavyCargoTrain ) { + // HACK: heavy cargo trains don't activate brakes early enough + fAccThreshold = std::max( -0.2, fAccThreshold ); + } +*/ } double TController::ESMVelocity(bool Main) @@ -2418,7 +2438,10 @@ bool TController::PrepareEngine() mvControlling->IncMainCtrl( 1 ); } } - mvControlling->MainSwitch(true); + if( ( mvControlling->EnginePowerSource.SourceType != TPowerSource::CurrentCollector ) + || ( std::max( mvControlling->GetTrainsetVoltage(), std::abs( mvControlling->RunningTraction.TractionVoltage ) ) > mvControlling->EnginePowerSource.CollectorParameters.MinV ) ) { + mvControlling->MainSwitch( true ); + } /* if (mvControlling->EngineType == DieselEngine) { // Ra 2014-06: dla SN61 trzeba wrzucić pierwszą pozycję - nie wiem, czy tutaj... @@ -2621,7 +2644,9 @@ bool TController::IncBrake() d = pVehicles[0]; // pojazd na czele składu while (d) { // przeliczanie dodatkowego potrzebnego spadku ciśnienia - pos_corr+=(d->MoverParameters->Hamulec->GetCRP() - 5.0)*d->MoverParameters->TotalMass; + if( ( d->MoverParameters->Hamulec->GetBrakeStatus() & b_dmg ) == 0 ) { + pos_corr += ( d->MoverParameters->Hamulec->GetCRP() - 5.0 ) * d->MoverParameters->TotalMass; + } d = d->Next(); // kolejny pojazd, podłączony od tyłu (licząc od czoła) } pos_corr = pos_corr / fMass * 2.5; @@ -2636,10 +2661,7 @@ bool TController::IncBrake() if( deltaAcc > fBrake_a1[0]) { if( mvOccupied->BrakeCtrlPosR < 0.1 ) { - OK = mvOccupied->BrakeLevelAdd( ( - mvOccupied->BrakeDelayFlag > bdelay_G ? - 1.0 : - 1.25 ) ); + OK = mvOccupied->BrakeLevelAdd( BrakingInitialLevel ); /* // HACK: stronger braking to overcome SA134 engine behaviour if( ( mvOccupied->TrainType == dt_DMU ) @@ -2654,10 +2676,11 @@ bool TController::IncBrake() } else { - OK = mvOccupied->BrakeLevelAdd( 0.25 ); - if( ( deltaAcc > 5 * fBrake_a1[ 0 ] ) - && ( mvOccupied->BrakeCtrlPosR <= 3.0 ) ) { - mvOccupied->BrakeLevelAdd( 0.75 ); + OK = mvOccupied->BrakeLevelAdd( BrakingLevelIncrease ); + // brake harder if the acceleration is much higher than desired + if( ( deltaAcc > 2 * fBrake_a1[ 0 ] ) + && ( mvOccupied->BrakeCtrlPosR + BrakingLevelIncrease <= 5.0 ) ) { + mvOccupied->BrakeLevelAdd( BrakingLevelIncrease ); } } } @@ -2793,36 +2816,42 @@ bool TController::IncSpeed() // na pozycji 0 przejdzie, a na pozostałych będzie czekać, aż się załączą liniowe (zgaśnie DelayCtrlFlag) if (Ready || (iDrivigFlags & movePress)) { // use series mode: - // to build up speed to 30/40 km/h for passenger/cargo train (10 km/h less if going uphill) // if high threshold is set for motor overload relay, - // if the power station is heavily burdened + // if the power station is heavily burdened, + // if it generates enough traction force + // to build up speed to 30/40 km/h for passenger/cargo train (10 km/h less if going uphill) + auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 125 : 100 ) * 1000.0 }; auto const useseriesmodevoltage { 0.80 * mvControlling->EnginePowerSource.CollectorParameters.MaxV }; + 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 useseriesmode = ( - ( mvOccupied->Vel <= ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ? 35 : 25 ) + ( mvControlling->ScndCtrlPos == 0 ? 0 : 5 ) - ( ( fAccGravity < -0.025 ) ? 10 : 0 ) ) - || ( mvControlling->Imax > mvControlling->ImaxLo ) - || ( fVoltage < useseriesmodevoltage ) ); + ( mvControlling->Imax > mvControlling->ImaxLo ) + || ( fVoltage < useseriesmodevoltage ) + || ( ( true == sufficienttractionforce ) + && ( mvOccupied->Vel <= ( IsCargoTrain ? 35 : 25 ) + ( seriesmodefieldshunting ? 5 : 0 ) - ( ( fAccGravity < -0.025 ) ? 10 : 0 ) ) ) ); // when not in series mode use the first available parallel mode configuration until 50/60 km/h for passenger/cargo train // (if there's only one parallel mode configuration it'll be used regardless of current speed) - auto const scndctrl = ( + auto const usefieldshunting = ( ( mvControlling->StLinFlag ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].R < 0.01 ) && ( useseriesmode ? mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 : - ( ( mvOccupied->Vel <= ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ? 55 : 45 ) + ( mvControlling->ScndCtrlPos == 0 ? 0 : 5 ) ) ? + ( ( true == sufficienttractionforce ) + && ( mvOccupied->Vel <= ( IsCargoTrain ? 55 : 45 ) + ( parallelmodefieldshunting ? 5 : 0 ) ) ? mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 : mvControlling->MainCtrlPos == mvControlling->MainCtrlPosNo ) ) ); double Vs = 99999; - if( scndctrl ? + if( usefieldshunting ? ( mvControlling->ScndCtrlPos < mvControlling->ScndCtrlPosNo ) : ( mvControlling->MainCtrlPos < mvControlling->MainCtrlPosNo ) ) { - Vs = ESMVelocity( !scndctrl ); + Vs = ESMVelocity( !usefieldshunting ); } if( ( std::abs( mvControlling->Im ) < ( fReady < 0.4 ? mvControlling->Imin : mvControlling->IminLo ) ) || ( mvControlling->Vel > Vs ) ) { // Ra: wywalał nadmiarowy, bo Im może być ujemne; jak nie odhamowany, to nie przesadzać z prądem - if( scndctrl ) { + if( usefieldshunting ) { // to dać bocznik // engage the shuntfield only if there's sufficient power margin to draw from OK = ( @@ -3787,12 +3816,13 @@ TController::UpdateSituation(double dt) { // Ra: odluźnianie przeładowanych lokomotyw, ciągniętych na zimno - prowizorka... if (AIControllFlag) // skład jak dotąd był wyluzowany { - if (mvOccupied->BrakeCtrlPos == 0) // jest pozycja jazdy - if ((p->MoverParameters->PipePress - 5.0) > - -0.1) // jeśli ciśnienie jak dla jazdy - if (p->MoverParameters->Hamulec->GetCRP() > - p->MoverParameters->PipePress + 0.12) // za dużo w zbiorniku - p->MoverParameters->BrakeReleaser(1); // indywidualne luzowanko + if( ( mvOccupied->BrakeCtrlPos == 0 ) // jest pozycja jazdy + && ( ( p->MoverParameters->Hamulec->GetBrakeStatus() & b_dmg ) == 0 ) // brake isn't broken + && ( p->MoverParameters->PipePress - 5.0 > -0.1 ) // jeśli ciśnienie jak dla jazdy + && ( p->MoverParameters->Hamulec->GetCRP() > p->MoverParameters->PipePress + 0.12 ) ) { // za dużo w zbiorniku + // indywidualne luzowanko + p->MoverParameters->BrakeReleaser( 1 ); + } if (p->MoverParameters->Power > 0.01) // jeśli ma silnik if (p->MoverParameters->FuseFlag) // wywalony nadmiarowy Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego @@ -4355,34 +4385,14 @@ TController::UpdateSituation(double dt) { } case Shunt: { // na jaką odleglość i z jaką predkością ma podjechać -/* - fMinProximityDist = 5.0; - fMaxProximityDist = 10.0; //[m] - - if( pVehicles[ 0 ] != pVehicles[ 1 ] ) { - // for larger consists increase margins to account for slower braking etc - // NOTE: this will affect also multi-unit vehicles TBD: is this what we want? - fMinProximityDist *= 2.0; - fMaxProximityDist *= 2.0; - if( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ) { - // additional safety margin for cargo consists - fMinProximityDist *= 2.0; - fMaxProximityDist *= 2.0; - if( fBrake_a0[ 0 ] >= 0.35 ) { - // cargo trains with high braking threshold may require even larger safety margin - fMaxProximityDist += 20.0; - } - } - } -*/ + // TODO: test if we can use the distances calculation from obey_train fMinProximityDist = std::min( 5 + iVehicles, 25 ); fMaxProximityDist = std::min( 10 + iVehicles, 50 ); - if( ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ) - && ( fBrake_a0[ 0 ] >= 0.35 ) ) { - // cargo trains with high braking threshold may require even larger safety margin +/* + if( IsHeavyCargoTrain ) { fMaxProximityDist *= 1.5; } - +*/ fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania // margines prędkości powodujący załączenie napędu // były problemy z jazdą np. 3km/h podczas ładowania wagonów @@ -4393,11 +4403,25 @@ TController::UpdateSituation(double dt) { // na jaka odleglosc i z jaka predkoscia ma podjechac do przeszkody if( mvOccupied->CategoryFlag & 1 ) { // jeśli pociąg - fMinProximityDist = 15.0; - fMaxProximityDist = - ( mvOccupied->Vel > 0.0 ) ? - 25.0 : - 50.0; //[m] jak stanie za daleko, to niech nie dociąga paru metrów + fMinProximityDist = clamp( 5 + iVehicles, 10, 15 ); + fMaxProximityDist = clamp( 10 + iVehicles, 15, 40 ); + + if( IsCargoTrain ) { + // increase distances for cargo trains to take into account slower reaction to brakes + fMinProximityDist += 10.0; + fMaxProximityDist += 10.0; +/* + if( IsHeavyCargoTrain ) { + // cargo trains with high braking threshold may require even larger safety margin + fMaxProximityDist += 20.0; + } +*/ + } + if( mvOccupied->Vel < 0.1 ) { + // jak stanie za daleko, to niech nie dociąga paru metrów + fMaxProximityDist = 50.0; + } + if( iDrivigFlags & moveLate ) { // jeśli spóźniony, to gna fVelMinus = 1.0; @@ -4412,20 +4436,11 @@ TController::UpdateSituation(double dt) { // bottom margin raised to 2 km/h to give the AI more leeway at low speed limits fVelPlus = clamp( std::ceil( 0.05 * VelDesired ), 2.0, 5.0 ); } - if( mvOccupied->BrakeDelayFlag == bdelay_G ) { - // increase distances for cargo trains to take into account slower reaction to brakes - fMinProximityDist += 10.0; - fMaxProximityDist += 15.0; - if( fBrake_a0[ 0 ] >= 0.35 ) { - // cargo trains with high braking threshold may require even larger safety margin - fMaxProximityDist += 20.0; - } - } } else { // samochod (sokista też) - fMinProximityDist = std::max( 3.0, mvOccupied->Vel * 0.2 ); - fMaxProximityDist = std::max( 9.0, mvOccupied->Vel * 0.375 ); //[m] + fMinProximityDist = std::max( 3.5, mvOccupied->Vel * 0.2 ); + fMaxProximityDist = std::max( 9.5, mvOccupied->Vel * 0.375 ); //[m] // margines prędkości powodujący załączenie napędu fVelMinus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania @@ -4701,14 +4716,15 @@ TController::UpdateSituation(double dt) { fMinProximityDist : // cars can bunch up tighter fMaxProximityDist ) ); // other vehicle types less so */ - ActualProximityDist = std::min( - ActualProximityDist, - vehicle->fTrackBlock ); double k = coupler->Connected->Vel; // prędkość pojazdu z przodu (zakładając, // że jedzie w tę samą stronę!!!) - if( k - vel < 10 ) { + if( k - vel < 5 ) { // porównanie modułów prędkości [km/h] // zatroszczyć się trzeba, jeśli tamten nie jedzie znacząco szybciej + ActualProximityDist = std::min( + ActualProximityDist, + vehicle->fTrackBlock ); + double const distance = vehicle->fTrackBlock - fMaxProximityDist - ( fBrakeDist * 1.15 ); // odległość bezpieczna zależy od prędkości if( distance < 0.0 ) { // jeśli odległość jest zbyt mała @@ -4939,13 +4955,17 @@ TController::UpdateSituation(double dt) { } else { // outside of max safe range + AccDesired = AccPreferred; if( vel > min_speed( 10.0, VelDesired ) ) { // allow to coast at reasonably low speed + auto const brakingdistance { fBrakeDist * braking_distance_multiplier( VelNext ) }; auto const slowdowndistance { ( - ( OrderCurrentGet() & Connect ) == 0 ? - 100.0 : - 25.0 ) }; - if( ( std::max( slowdowndistance, fMaxProximityDist ) + fBrakeDist * braking_distance_multiplier( VelNext ) ) >= ( ActualProximityDist - fMaxProximityDist ) ) { + mvOccupied->CategoryFlag == 2 ? // cars can stop on a dime, for bigger vehicles we enforce some minimal braking distance + brakingdistance : + std::max( + ( ( OrderCurrentGet() & Connect ) == 0 ? 100.0 : 25.0 ), + brakingdistance ) ) }; + if( ( brakingdistance + std::max( slowdowndistance, fMaxProximityDist ) ) >= ( ActualProximityDist - fMaxProximityDist ) ) { // don't slow down prematurely; as long as we have room to come to a full stop at a safe distance, we're good // ensure some minimal coasting speed, otherwise a vehicle entering this zone at very low speed will be crawling forever auto const brakingpointoffset = VelNext * braking_distance_multiplier( VelNext ); @@ -5060,8 +5080,8 @@ TController::UpdateSituation(double dt) { // if it looks like we'll exceed maximum speed start thinking about slight slowing down AccDesired = std::min( AccDesired, -0.25 ); // HACK: for cargo trains with high braking threshold ensure we cross that threshold - if( ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 ) - && ( fBrake_a0[ 0 ] > 0.2 ) ) { + if( ( true == IsCargoTrain ) + && ( fBrake_a0[ 0 ] > 0.2 ) ) { AccDesired -= clamp( fBrake_a0[ 0 ] - 0.2, 0.0, 0.15 ); } } @@ -5119,7 +5139,10 @@ TController::UpdateSituation(double dt) { // last step sanity check, until the whole calculation is straightened out AccDesired = std::min( AccDesired, AccPreferred ); - AccDesired = clamp( AccDesired, -0.9, 0.9 ); + AccDesired = clamp( + AccDesired, + ( mvControlling->CategoryFlag == 2 ? -2.0 : -0.9 ), + ( mvControlling->CategoryFlag == 2 ? 2.0 : 0.9 ) ); if (AIControllFlag) { // część wykonawcza tylko dla AI, dla człowieka jedynie napisy @@ -5211,7 +5234,7 @@ TController::UpdateSituation(double dt) { && ( BrakeChargingCooldown >= 0.0 ) ) { if( ( iDrivigFlags & moveOerlikons ) - || ( mvOccupied->BrakeDelayFlag & bdelay_G ) ) { + || ( true == IsCargoTrain ) ) { // napełnianie w Oerlikonie mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_FS ) ); // don't charge the brakes too often, or we risk overcharging diff --git a/Driver.h b/Driver.h index 581ba9b4..e7a05617 100644 --- a/Driver.h +++ b/Driver.h @@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/. #include "Classes.h" #include "mczapkie/mover.h" #include "sound.h" +#include "dynobj.h" enum TOrders { // rozkazy dla AI @@ -208,8 +209,15 @@ public: double fBrakeReaction = 1.0; //opóźnienie zadziałania hamulca - czas w s / (km/h) double fAccThreshold = 0.0; // próg opóźnienia dla zadziałania hamulca double AbsAccS_pub = 0.0; // próg opóźnienia dla zadziałania hamulca - double fBrake_a0[BrakeAccTableSize+1] = { 0.0 }; // próg opóźnienia dla zadziałania hamulca - double fBrake_a1[BrakeAccTableSize+1] = { 0.0 }; // próg opóźnienia dla zadziałania hamulca + // dla fBrake_aX: + // indeks [0] - wartości odpowiednie dla aktualnej prędkości + // a potem jest 20 wartości dla różnych prędkości zmieniających się co 5 % Vmax pojazdu obsadzonego + double fBrake_a0[BrakeAccTableSize+1] = { 0.0 }; // opóźnienia hamowania przy ustawieniu zaworu maszynisty w pozycji 1.0 + double fBrake_a1[BrakeAccTableSize+1] = { 0.0 }; // przyrost opóźnienia hamowania po przestawieniu zaworu maszynisty o 0,25 pozycji + double BrakingInitialLevel{ 1.0 }; + double BrakingLevelIncrease{ 0.25 }; + bool IsCargoTrain{ false }; + bool IsHeavyCargoTrain{ false }; double fLastStopExpDist = -1.0; // odległość wygasania ostateniego przystanku double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca @@ -354,7 +362,7 @@ private: std::vector CheckTrackEvent(TTrack *Track, double const fDirection ) const; bool TableAddNew(); bool TableNotFound(TEvent const *Event) const; - void TableTraceRoute(double fDistance, TDynamicObject *pVehicle = nullptr); + void TableTraceRoute(double fDistance, TDynamicObject *pVehicle); void TableCheck(double fDistance); TCommandType TableUpdate(double &fVelDes, double &fDist, double &fNext, double &fAcc); // modifies brake distance for low target speeds, to ease braking rate in such situations @@ -412,4 +420,8 @@ private: std::string OwnerName() const; TMoverParameters const *Controlling() const { return mvControlling; } + int Direction() const { + return iDirection; } + TDynamicObject const *Vehicle() const { + return pVehicle; } }; diff --git a/DynObj.cpp b/DynObj.cpp index c019cd46..2cd111c3 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2772,66 +2772,6 @@ bool TDynamicObject::Update(double dt, double dt1) if (!bEnabled) return false; // a normalnie powinny mieć bEnabled==false - // McZapkie-260202 - if ((MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector) && - (MoverParameters->Power > 1.0)) // aby rozrządczy nie opuszczał silnikowemu -/* - if ((MechInside) || (MoverParameters->TrainType == dt_EZT)) - { -*/ - // if - // ((!MoverParameters->PantCompFlag)&&(MoverParameters->CompressedVolume>=2.8)) - // MoverParameters->PantVolume=MoverParameters->CompressedVolume; - - if( MoverParameters->PantPress < MoverParameters->EnginePowerSource.CollectorParameters.MinPress ) { - // 3.5 wg http://www.transportszynowy.pl/eu06-07pneumat.php - if( true == MoverParameters->PantPressSwitchActive ) { - // opuszczenie pantografów przy niskim ciśnieniu -/* - // NOTE: disabled, the pantographs drop by themseleves when the pantograph tank pressure gets low enough - MoverParameters->PantFront( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) ); - MoverParameters->PantRear( false, ( MoverParameters->TrainType == dt_EZT ? range::unit : range::local ) ); -*/ - if( MoverParameters->TrainType != dt_EZT ) { - // pressure switch safety measure -- open the line breaker, unless there's alternate source of traction voltage - if( MoverParameters->GetTrainsetVoltage() < 0.5 * MoverParameters->EnginePowerSource.MaxVoltage ) { - // TODO: check whether line breaker should be open EMU-wide - MoverParameters->MainSwitch( false, ( MoverParameters->TrainType == dt_EZT ? range_t::unit : range_t::local ) ); - } - } - else { - // specialized variant for EMU -- pwr system disables converter and heating, - // and prevents their activation until pressure switch is set again - MoverParameters->PantPressLockActive = true; - // TODO: separate 'heating allowed' from actual heating flag, so we can disable it here without messing up heating toggle - MoverParameters->ConverterSwitch( false, range_t::unit ); - } - // mark the pressure switch as spent - MoverParameters->PantPressSwitchActive = false; - } - } - else { - if( MoverParameters->PantPress >= 4.6 ) { - // NOTE: we require active low power source to prime the pressure switch - // this is a work-around for potential isssues caused by the switch activating on otherwise idle vehicles, but should check whether it's accurate - if( ( true == MoverParameters->Battery ) - || ( true == MoverParameters->ConverterFlag ) ) { - // prime the pressure switch - MoverParameters->PantPressSwitchActive = true; - // turn off the subsystems lock - MoverParameters->PantPressLockActive = false; - } - - if( MoverParameters->PantPress >= 4.8 ) { - // Winger - automatyczne wylaczanie malej sprezarki - // TODO: governor lock, disables usage until pressure drop below 3.8 (should really make compressor object we could reuse) - MoverParameters->PantCompFlag = false; - } - } - } -/* - } // Ra: do Mover to trzeba przenieść, żeby AI też mogło sobie podpompować -*/ double dDOMoveLen; TLocation l; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 25133abb..1fb943dd 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -733,8 +733,9 @@ void TMoverParameters::UpdatePantVolume(double dt) // Ra 2014-07: kurek trójdrogowy łączy spr.pom. z pantografami i wyłącznikiem ciśnieniowym WS // Ra 2014-07: zbiornika rozrządu nie pompuje się tu, tylko pantografy; potem można zamknąć // WS i odpalić resztę - if ((TrainType == dt_EZT) ? (PantPress < ScndPipePress) : - bPantKurek3) // kurek zamyka połączenie z ZG + if ((TrainType == dt_EZT) ? + (PantPress < ScndPipePress) : + bPantKurek3) // kurek zamyka połączenie z ZG { // zbiornik pantografu połączony ze zbiornikiem głównym - małą sprężarką się tego nie napompuje // Ra 2013-12: Niebugocław mówi, że w EZT nie ma potrzeby odcinać kurkiem PantPress = ScndPipePress; @@ -758,33 +759,48 @@ void TMoverParameters::UpdatePantVolume(double dt) } if( !PantCompFlag && ( PantVolume > 0.1 ) ) PantVolume -= dt * 0.0003 * std::max( 1.0, PantPress * 0.5 ); // nieszczelności: 0.0003=0.3l/s -/* - // NOTE: disabled as this is redundant with check done in dynobj.update() - // TODO: determine if this isn't a mistake -- - // though unlikely it's possible this is emulation of a different circuit than the pantograph pressure switch, with similar function? - // TBD, TODO: alternatively, move the dynobj.update() subroutine here, as it doesn't touch elements outside of the mover object - if( Mains ) { - // nie wchodzić w funkcję bez potrzeby - if( EngineType == ElectricSeriesMotor ) { - // nie dotyczy... czego właściwie? - if( ( true == PantPressSwitchActive ) - && ( PantPress < EnginePowerSource.CollectorParameters.MinPress ) ) { - // wywalenie szybkiego z powodu niskiego ciśnienia - if( GetTrainsetVoltage() < 0.5 * EnginePowerSource.MaxVoltage ) { - // to jest trochę proteza; zasilanie członu może być przez sprzęg WN - if( MainSwitch( false, ( TrainType == dt_EZT ? range::unit : range::local ) ) ) { - EventFlag = true; - } + + if( PantPress < EnginePowerSource.CollectorParameters.MinPress ) { + // 3.5 wg http://www.transportszynowy.pl/eu06-07pneumat.php + if( true == PantPressSwitchActive ) { + // opuszczenie pantografów przy niskim ciśnieniu + if( TrainType != dt_EZT ) { + // pressure switch safety measure -- open the line breaker, unless there's alternate source of traction voltage + if( GetTrainsetVoltage() < EnginePowerSource.CollectorParameters.MinV ) { + // TODO: check whether line breaker should be open EMU-wide + MainSwitch( false, ( TrainType == dt_EZT ? range_t::unit : range_t::local ) ); } + } + else { + // specialized variant for EMU -- pwr system disables converter and heating, + // and prevents their activation until pressure switch is set again + PantPressLockActive = true; + // TODO: separate 'heating allowed' from actual heating flag, so we can disable it here without messing up heating toggle + ConverterSwitch( false, range_t::unit ); + } + // mark the pressure switch as spent + PantPressSwitchActive = false; + } + } + else { + if( PantPress >= 4.6 ) { + // NOTE: we require active low power source to prime the pressure switch + // this is a work-around for potential isssues caused by the switch activating on otherwise idle vehicles, but should check whether it's accurate + if( ( true == Battery ) + || ( true == ConverterFlag ) ) { + // prime the pressure switch + PantPressSwitchActive = true; + // turn off the subsystems lock + PantPressLockActive = false; + } - // NOTE: disabled, the flag gets set in dynobj.update() when the pantograph actually drops - // mark the pressure switch as spent, regardless whether line breaker actually opened - PantPressSwitchActive = false; - + if( PantPress >= 4.8 ) { + // Winger - automatyczne wylaczanie malej sprezarki + // TODO: governor lock, disables usage until pressure drop below 3.8 (should really make compressor object we could reuse) + PantCompFlag = false; } } } -*/ /* // NOTE: pantograph tank pressure sharing experimentally disabled for more accurate simulation if (TrainType != dt_EZT) // w EN57 pompuje się tylko w silnikowym @@ -1351,9 +1367,6 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap } // liczone dL, predkosc i przyspieszenie - if (Power > 1.0) // w rozrządczym nie (jest błąd w FIZ!) - Ra 2014-07: teraz we wszystkich - UpdatePantVolume(dt); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów - auto const d { ( EngineType == TEngineType::WheelsDriven ? dL * CabNo : // na chwile dla testu @@ -1364,6 +1377,7 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap // koniec procedury, tu nastepuja dodatkowe procedury pomocnicze compute_movement_( dt ); + // security system if (!DebugModeFlag) SecuritySystemCheck(dt1); @@ -1430,9 +1444,6 @@ double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape if (Couplers[b].CheckCollision) CollisionDetect(b, dt); // zmienia niejawnie AccS, V !!! } // liczone dL, predkosc i przyspieszenie - // QQQ - if (Power > 1.0) // w rozrządczym nie (jest błąd w FIZ!) - UpdatePantVolume(dt); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów auto const d { ( EngineType == TEngineType::WheelsDriven ? @@ -1482,6 +1493,11 @@ void TMoverParameters::compute_movement_( double const Deltatime ) { // sprężarka musi mieć jakąś niezerową wydajność żeby rozważać jej załączenie i pracę CompressorCheck( Deltatime ); } + if( Power > 1.0 ) { + // w rozrządczym nie (jest błąd w FIZ!) - Ra 2014-07: teraz we wszystkich + UpdatePantVolume( Deltatime ); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów + } + UpdateBrakePressure(Deltatime); UpdatePipePressure(Deltatime); UpdateBatteryVoltage(Deltatime); @@ -2695,61 +2711,21 @@ bool TMoverParameters::IncBrakeLevelOld(void) { bool IBLO = false; - if ((BrakeCtrlPosNo > 0) /*and (LocalBrakePos=0)*/) + if (BrakeCtrlPosNo > 0) { if (BrakeCtrlPos < BrakeCtrlPosNo) { - BrakeCtrlPos++; - // BrakeCtrlPosR = BrakeCtrlPos; - - // youBy: wywalilem to, jak jest EP, to sa przenoszone sygnaly nt. co ma robic, a nie - // poszczegolne pozycje; - // wystarczy spojrzec na Knorra i Oerlikona EP w EN57; mogly ze soba - // wspolapracowac - //{ - // if (BrakeSystem==ElectroPneumatic) - // if (BrakePressureActual.BrakeType==ElectroPneumatic) - // { - // BrakeStatus = ord(BrakeCtrlPos > 0); - // SendCtrlToNext("BrakeCtrl", BrakeCtrlPos, CabNo); - // } - // else SendCtrlToNext("BrakeCtrl", -2, CabNo); - // else - // if (!TestFlag(BrakeStatus,b_dmg)) - // BrakeStatus = b_on;} - + ++BrakeCtrlPos; // youBy: EP po nowemu - IBLO = true; if ((BrakePressureActual.PipePressureVal < 0) && (BrakePressureTable[BrakeCtrlPos - 1].PipePressureVal > 0)) LimPipePress = PipePress; - - //ten kawałek jest bez sensu gdyż nic nie robił. Zakomntowałem. GF 20161124 - //if (BrakeSystem == ElectroPneumatic) - // if (BrakeSubsystem != ss_K) - // { - // if ((BrakeCtrlPos * BrakeCtrlPos) == 1) - // { - // // SendCtrlToNext('Brake',BrakeCtrlPos,CabNo); - // // SetFlag(BrakeStatus,b_epused); - // } - // else - // { - // // SendCtrlToNext('Brake',0,CabNo); - // // SetFlag(BrakeStatus,-b_epused); - // } - // } } - else - { + else { IBLO = false; - // if (BrakeSystem == Pneumatic) - // EmergencyBrakeSwitch(true); } } - else - IBLO = false; return IBLO; } @@ -2762,69 +2738,20 @@ bool TMoverParameters::DecBrakeLevelOld(void) { bool DBLO = false; - if ((BrakeCtrlPosNo > 0) /*&& (LocalBrakePos == 0)*/) + if (BrakeCtrlPosNo > 0) { - if (BrakeCtrlPos > -1 - int(BrakeHandle == TBrakeHandle::FV4a)) + if (BrakeCtrlPos > ( ( BrakeHandle == TBrakeHandle::FV4a ) ? -2 : -1 ) ) { - BrakeCtrlPos--; - // BrakeCtrlPosR:=BrakeCtrlPos; - //if (EmergencyBrakeFlag) - //{ - // EmergencyBrakeFlag = false; //!!! - // SendCtrlToNext("Emergency_brake", 0, CabNo); - //} - - // youBy: wywalilem to, jak jest EP, to sa przenoszone sygnaly nt. co ma robic, a nie - // poszczegolne pozycje; - // wystarczy spojrzec na Knorra i Oerlikona EP w EN57; mogly ze soba - // wspolapracowac - /* - if (BrakeSystem == ElectroPneumatic) - if (BrakePressureActual.BrakeType == ElectroPneumatic) - { - // BrakeStatus =ord(BrakeCtrlPos > 0); - SendCtrlToNext("BrakeCtrl",BrakeCtrlPos,CabNo); - } - else SendCtrlToNext('BrakeCtrl',-2,CabNo); - // else} - // if (not TestFlag(BrakeStatus,b_dmg) and (not - TestFlag(BrakeStatus,b_release))) then - // BrakeStatus:=b_off; {luzowanie jesli dziala oraz nie byl wlaczony - odluzniacz - */ - + --BrakeCtrlPos; // youBy: EP po nowemu DBLO = true; - // if ((BrakePressureTable[BrakeCtrlPos].PipePressureVal<0.0) && - // (BrakePressureTable[BrakeCtrlPos+1].PipePressureVal > 0)) - // LimPipePress:=PipePress; - - // to nic nie robi. Zakomentowałem. GF 20161124 - //if (BrakeSystem == ElectroPneumatic) - // if (BrakeSubsystem != ss_K) - // { - // if ((BrakeCtrlPos * BrakeCtrlPos) == 1) - // { - // // SendCtrlToNext("Brake", BrakeCtrlPos, CabNo); - // // SetFlag(BrakeStatus, b_epused); - // } - // else - // { - // // SendCtrlToNext("Brake", 0, CabNo); - // // SetFlag(BrakeStatus, -b_epused); - // } - // } - // for b:=0 to 1 do {poprawic to!} - // with Couplers[b] do - // if CouplingFlag and ctrain_controll=ctrain_controll then - // Connected^.BrakeCtrlPos:=BrakeCtrlPos; - // +// if ((BrakePressureTable[BrakeCtrlPos].PipePressureVal<0.0) && +// (BrakePressureTable[BrakeCtrlPos+1].PipePressureVal > 0)) +// LimPipePress=PipePress; } else DBLO = false; } - else - DBLO = false; return DBLO; } diff --git a/Track.cpp b/Track.cpp index 497ddfb2..09663ef7 100644 --- a/Track.cpp +++ b/Track.cpp @@ -1409,7 +1409,10 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) { case tt_Switch: // dla zwrotnicy dwa razy szyny if( m_material1 || m_material2 ) { // iglice liczone tylko dla zwrotnic - gfx::basic_vertex rpts3[24], rpts4[24]; + gfx::basic_vertex + rpts3[24], + rpts4[24]; + glm::vec3 const flipxvalue { -1, 1, 1 }; for( int i = 0; i < 12; ++i ) { rpts3[ i ] = { @@ -1428,17 +1431,17 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) { { ( -fHTW - iglica[ i ].position.x ) * cos1 + iglica[ i ].position.y * sin1, -( -fHTW - iglica[ i ].position.x ) * sin1 + iglica[ i ].position.y * cos1, 0.f}, - {iglica[ i ].normal}, + {iglica[ i ].normal * flipxvalue}, {iglica[ i ].texture.x, 0.f} }; rpts4[ 23 - i ] = { { ( -fHTW2 - szyna[ i ].position.x ) * cos2 + szyna[ i ].position.y * sin2, -( -fHTW2 - szyna[ i ].position.x ) * sin2 + iglica[ i ].position.y * cos2, 0.f}, - {szyna[ i ].normal}, + {szyna[ i ].normal * flipxvalue}, {szyna[ i ].texture.x, 0.f} }; } // TODO, TBD: change all track geometry to triangles, to allow packing data in less, larger buffers - auto const bladelength { 2 * Global.SplineFidelity }; + auto const bladelength { static_cast( std::ceil( SwitchExtension->Segments[ 0 ]->RaSegCount() * 0.65 ) ) }; if (SwitchExtension->RightSwitch) { // nowa wersja z SPKS, ale odwrotnie lewa/prawa gfx::vertex_array vertices; @@ -2464,6 +2467,7 @@ TTrack * TTrack::RaAnimate() gfx::basic_vertex rpts3[ 24 ], rpts4[ 24 ]; + glm::vec3 const flipxvalue { -1, 1, 1 }; for (int i = 0; i < 12; ++i) { rpts3[ i ] = { @@ -2482,19 +2486,18 @@ TTrack * TTrack::RaAnimate() {+( -fHTW - iglica[ i ].position.x ) * cos1 + iglica[ i ].position.y * sin1, -( -fHTW - iglica[ i ].position.x ) * sin1 + iglica[ i ].position.y * cos1, 0.f}, - {iglica[ i ].normal}, + {iglica[ i ].normal * flipxvalue}, {iglica[ i ].texture.x, 0.f} }; rpts4[ 23 - i ] = { { ( -fHTW2 - szyna[ i ].position.x ) * cos2 + szyna[ i ].position.y * sin2, -( -fHTW2 - szyna[ i ].position.x ) * sin2 + iglica[ i ].position.y * cos2, 0.f}, - {szyna[ i ].normal}, + {szyna[ i ].normal * flipxvalue}, {szyna[ i ].texture.x, 0.f} }; } gfx::vertex_array vertices; - - auto const bladelength { 2 * Global.SplineFidelity }; + auto const bladelength { static_cast( std::ceil( SwitchExtension->Segments[ 0 ]->RaSegCount() * 0.65 ) ) }; if (SwitchExtension->RightSwitch) { // nowa wersja z SPKS, ale odwrotnie lewa/prawa if( m_material1 ) { diff --git a/Train.cpp b/Train.cpp index 310ca4f3..0009c254 100644 --- a/Train.cpp +++ b/Train.cpp @@ -4832,8 +4832,8 @@ bool TTrain::Update( double const Deltatime ) // hunter-080812: wyrzucanie szybkiego na elektrykach gdy nie ma napiecia przy dowolnym ustawieniu kierunkowego // Ra: to już jest w T_MoverParameters::TractionForce(), ale zależy od kierunku if( ( mvControlled->Mains ) - && ( mvControlled->EngineType == TEngineType::ElectricSeriesMotor ) ) { - if( std::max( mvControlled->GetTrainsetVoltage(), std::fabs( mvControlled->RunningTraction.TractionVoltage ) ) < 0.5 * mvControlled->EnginePowerSource.MaxVoltage ) { + && ( mvControlled->EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) ) { + if( std::max( mvControlled->GetTrainsetVoltage(), std::abs( mvControlled->RunningTraction.TractionVoltage ) ) < 0.5 * mvControlled->EnginePowerSource.MaxVoltage ) { // TODO: check whether it should affect entire consist for EMU // TODO: check whether it should happen if there's power supplied alternatively through hvcouplers // TODO: potentially move this to the mover module, as there isn't much reason to have this dependent on the operator presence @@ -5627,24 +5627,28 @@ bool TTrain::Update( double const Deltatime ) } case 1: { //światło wewnętrzne przygaszone (255 216 176) - if( mvOccupied->ConverterFlag == true ) { - // jasnosc dla zalaczonej przetwornicy - DynamicObject->InteriorLightLevel = 0.4f; - } - else { - DynamicObject->InteriorLightLevel = 0.2f; - } + auto const converteractive { ( + ( mvOccupied->ConverterFlag ) + || ( ( ( mvOccupied->Couplers[ side::front ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::front ].Connected->ConverterFlag ) + || ( ( ( mvOccupied->Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::rear ].Connected->ConverterFlag ) ) }; + + DynamicObject->InteriorLightLevel = ( + converteractive ? + 0.4f : + 0.2f ); break; } case 2: { //światło wewnętrzne zapalone (255 216 176) - if( mvOccupied->ConverterFlag == true ) { - // jasnosc dla zalaczonej przetwornicy - DynamicObject->InteriorLightLevel = 1.0f; - } - else { - DynamicObject->InteriorLightLevel = 0.5f; - } + auto const converteractive { ( + ( mvOccupied->ConverterFlag ) + || ( ( ( mvOccupied->Couplers[ side::front ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::front ].Connected->ConverterFlag ) + || ( ( ( mvOccupied->Couplers[ side::rear ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ side::rear ].Connected->ConverterFlag ) ) }; + + DynamicObject->InteriorLightLevel = ( + converteractive ? + 1.0f : + 0.5f ); break; } } diff --git a/TrkFoll.cpp b/TrkFoll.cpp index b1bfab6c..0d828768 100644 --- a/TrkFoll.cpp +++ b/TrkFoll.cpp @@ -95,6 +95,11 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) { // przesuwanie wózka po torach o odległość (fDistance), z wyzwoleniem eventów // 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ł @@ -105,8 +110,7 @@ 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) - if( ( std::abs( fDistance ) < 0.01 ) - && ( Owner->GetVelocity() < 0.01 ) ) { + if( false == ismoving ) { //McZapkie-140602: wyzwalanie zdarzenia gdy pojazd stoi if( ( Owner->Mechanik != nullptr ) && ( Owner->Mechanik->Primary() ) ) { @@ -115,7 +119,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) } pCurrentTrack->QueueEvents( pCurrentTrack->m_events0all, Owner ); } - else if (fDistance < 0) { + else if( (fDistance < 0) && ( eventfilter < 0 ) ) { // event1, eventall1 if( SetFlag( iEventFlag, -1 ) ) { // zawsze zeruje flagę sprawdzenia, jak mechanik dosiądzie, to się nie wykona @@ -135,7 +139,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary) } } } - else if (fDistance > 0) { + else if( ( fDistance > 0 ) && ( eventfilter > 0 ) ) { // event2, eventall2 if( SetFlag( iEventFlag, -2 ) ) { // zawsze ustawia flagę sprawdzenia, jak mechanik dosiądzie, to się nie wykona diff --git a/material.cpp b/material.cpp index 0cfad9d4..f11b97a1 100644 --- a/material.cpp +++ b/material.cpp @@ -55,14 +55,16 @@ opengl_material::deserialize_mapping( cParser &Input, int const Priority, bool c ; // all work is done in the header } } - else if( key == "texture1:" ) { + else if( ( key == "texture1:" ) + || ( key == "texture_diffuse:" ) ) { if( ( texture1 == null_handle ) || ( Priority > priority1 ) ) { texture1 = GfxRenderer.Fetch_Texture( value, Loadnow ); priority1 = Priority; } } - else if( key == "texture2:" ) { + else if( ( key == "texture2:" ) + || ( key == "texture_normalmap:" ) ) { if( ( texture2 == null_handle ) || ( Priority > priority2 ) ) { texture2 = GfxRenderer.Fetch_Texture( value, Loadnow );