build 200824. emergency_brake getvalues event support, utf bom parsing fix, brake state vehicle debug panel enhancement, ai cab change logic fixes, ai door operation logic fixes, minor ai logic fixes, gfx renderer framerate calculation tweak, minor bug fixes

This commit is contained in:
tmj-fstate
2020-08-26 13:43:24 +02:00
parent 55687e975e
commit c4ef056102
17 changed files with 180 additions and 106 deletions

View File

@@ -189,11 +189,22 @@ void TCamera::Update()
// attached movement position update
auto movement { Velocity * -2.0 };
movement.y = -movement.y;
auto const *owner { (
m_owner->Mechanik ?
m_owner->Mechanik :
m_owner->ctOwner ) };
if( ( owner )
&& ( owner->Occupied()->CabOccupied < 0 ) ) {
movement *= -1.f;
movement.y = -movement.y;
}
/*
if( ( m_owner->ctOwner )
&& ( m_owner->ctOwner->Vehicle()->DirectionGet() != m_owner->DirectionGet() ) ) {
movement *= -1.f;
movement.y = -movement.y;
}
*/
movement.RotateY( Angle.y );
m_owneroffset += movement * deltatime;

View File

@@ -76,7 +76,8 @@ enum class TCommandType
cm_ChangeDirection,
cm_PassengerStopPoint,
cm_OutsideStation,
cm_Shunt,
// cm_Shunt, // unused?
cm_EmergencyBrake,
cm_Command // komenda pobierana z komórki
};

View File

@@ -268,12 +268,18 @@ void TSpeedPos::CommandCheck()
fVelNext = -1;
iFlags |= spOutsideStation; // W5
break;
case TCommandType::cm_EmergencyBrake:
fVelNext = -1;
break;
default:
// inna komenda w evencie skanowanym powoduje zatrzymanie i wysłanie tej komendy
// nie manewrowa, nie przystanek, nie zatrzymać na SBL
iFlags &= ~(spShuntSemaphor | spPassengerStopPoint | spStopOnSBL);
// jak nieznana komenda w komórce sygnałowej, to zatrzymujemy
fVelNext = 0.0;
fVelNext = (
evEvent->is_command() ?
0.0 : // ask for a stop if we have a command for the vehicle
-1.0 ); // if we don't or it was already passed then don't be a bother
}
};
@@ -336,10 +342,14 @@ bool TSpeedPos::Update()
std::string TSpeedPos::GetName() const
{
if (iFlags & spTrack) // jeśli tor
if( iFlags & spTrack ) // jeśli tor
return trTrack->name();
else if( iFlags & spEvent ) // jeśli event
return evEvent->m_name;
return
evEvent->m_name
+ " [" + to_string( static_cast<int>( evEvent->input_value( 1 ) ) )
+ ", " + to_string( static_cast<int>( evEvent->input_value( 2 ) ) )
+ "]";
else
return "";
}
@@ -877,7 +887,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// stop points are irrelevant when not in one of the basic modes
if( ( OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank ) ) == 0 ) { continue; }
// first 19 chars of the command is expected to be "PassengerStopPoint:" so we skip them
if ( ToLower(sSpeedTable[i].evEvent->input_text()).compare( 19, sizeof(asNextStop), ToLower(asNextStop)) != 0 )
if( ToLower( sSpeedTable[ i ].evEvent->input_text() ).compare( 19, sizeof( asNextStop ), ToLower( asNextStop ) ) != 0 )
{ // jeśli nazwa nie jest zgodna
if( ( false == IsScheduledPassengerStopVisible ) // check if our next scheduled stop didn't show up earlier in the scan
&& ( sSpeedTable[i].fDist < ( 1.15 * fBrakeDist + 300 ) )
@@ -998,7 +1008,6 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// w razie przełączenia na AI ma nie podciągać do W4, gdy użytkownik zatrzymał za daleko
iDrivigFlags &= ~moveStopCloser;
}
if (TrainParams.UpdateMTable( simulation::Time, asNextStop) ) {
// to się wykona tylko raz po zatrzymaniu na W4
if( TrainParams.StationIndex < TrainParams.StationCount ) {
@@ -1012,12 +1021,13 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// HACK: manual check if we didn't already do load exchange at this stop
// TODO: remove the check once the station system is in place
if( m_lastexchangestop != asNextStop ) {
auto const platformside = static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10;
auto const exchangetime = simulation::Station.update_load( pVehicles[ end::front ], TrainParams, platformside );
m_lastexchangestop = asNextStop;
m_lastexchangedirection = pVehicle->DirectionGet();
m_lastexchangeplatforms = static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10;
auto const exchangetime { simulation::Station.update_load( pVehicles[ end::front ], TrainParams, m_lastexchangeplatforms ) };
WaitingSet( exchangetime );
// announce the stop name while at it
announce( announcement_t::current );
m_lastexchangestop = asNextStop;
m_makenextstopannouncement = true;
}
@@ -1053,11 +1063,21 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
}
}
if( pVehicle->DirectionGet() != m_lastexchangedirection ) {
// generally means the ai driver moved to the opposite end of the consist
// TODO: investigate whether user playing with the reverser can mess this up
auto const left { ( m_lastexchangedirection > 0 ) ? 1 : 2 };
auto const right { 3 - left };
m_lastexchangeplatforms =
( ( m_lastexchangeplatforms & left ) != 0 ? right : 0 )
+ ( ( m_lastexchangeplatforms & right ) != 0 ? left : 0 );
m_lastexchangedirection = pVehicle->DirectionGet();
}
if( ( false == TrainParams.IsMaintenance() )
&& ( ( false == TestFlag( iDrivigFlags, moveDoorOpened ) )
|| ( true == DoesAnyDoorNeedOpening ) ) ) {
iDrivigFlags |= moveDoorOpened; // nie wykonywać drugi raz
Doors( true, static_cast<int>( std::floor( std::abs( sSpeedTable[ i ].evEvent->input_value( 2 ) ) ) ) % 10 );
Doors( true, m_lastexchangeplatforms );
}
if (OrderCurrentGet() & ( Shunt | Loose_shunt )) {
@@ -1181,6 +1201,15 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
}
SemNextStopIndex = -1; // jeśli minęliśmy semafor od ograniczenia to go kasujemy ze zmiennej sprawdzającej dla skanowania w przód
}
switch( sSpeedTable[ i ].evEvent->input_command() ) {
case TCommandType::cm_EmergencyBrake: {
pVehicle->RadioStop();
sSpeedTable[ i ].iFlags = 0; // signal reveived, deactivate
}
default: {
break;
}
}
}
if( sSpeedTable[ i ].fDist > 0.0 ) {
// check signals ahead
@@ -1333,8 +1362,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
//sprawdzenie eventów pasywnych przed nami
if( ( mvOccupied->CategoryFlag & 1 )
&& ( sSpeedTable[ i ].fDist > Obstacle.distance - 20 ) ) {
// jak sygnał jest dalej niż zawalidroga
&& ( sSpeedTable[ i ].fDist > Obstacle.distance - 20 ) ) {
// jak sygnał jest dalej niż zawalidroga
v = 0.0; // to może być podany dla tamtego: jechać tak, jakby tam stop był
}
else
@@ -1378,8 +1407,8 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if( go == TCommandType::cm_Unknown ) {
// jeśli nie było komendy wcześniej - pierwsza się liczy - ustawianie VelSignal
if( ( v < 0.0 )
|| ( v >= 1.0 ) ) {
// bo wartość 0.1 służy do hamowania tylko
|| ( v >= 1.0 ) ) {
// bo wartość 0.1 służy do hamowania tylko
go = TCommandType::cm_SetVelocity; // może odjechać
// Ra 2014-06: (VelSignal) nie może być tu ustawiane, bo semafor może być daleko
// VelSignal=v; //nie do końca tak, to jest druga prędkość; -1 nie wpisywać...
@@ -1888,52 +1917,68 @@ void TController::Activation()
iDirection = iDirectionOrder; // kierunek (względem sprzęgów pojazdu z AI) właśnie został ustalony (zmieniony)
if (iDirection)
{ // jeśli jest ustalony kierunek
TDynamicObject *old = pVehicle, *d = pVehicle; // w tym siedzi AI
TController *drugi; // jakby były dwa, to zamienić miejscami, a nie robić wycieku pamięci poprzez nadpisanie
auto const localbrakelevel { mvOccupied->LocalBrakePosA };
auto *initialvehicle { pVehicle };
/*
auto const initiallocalbrakelevel { mvOccupied->LocalBrakePosA };
*/
auto const initialspringbrakestate { mvOccupied->SpringBrake.Activate };
// switch off tempomat
SpeedCntrl( 0.0 );
mvControlling->DecScndCtrl( 2 );
// reset controls
ZeroSpeed();
ZeroDirection();
mvOccupied->SpringBrakeActivate( true );
if (TestFlag(d->MoverParameters->Couplers[iDirectionOrder < 0 ? end::rear : end::front].CouplingFlag, coupling::control)) {
mvControlling->MainSwitch( false ); // dezaktywacja czuwaka, jeśli przejście do innego członu
mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca w opuszczanym pojeździe
// mvOccupied->BrakeLevelSet((mvOccupied->BrakeHandle==FVel6)?4:-2); //odcięcie na
// zaworze maszynisty, FVel6 po drugiej stronie nie luzuje
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos(bh_NP) ); // odcięcie na zaworze maszynisty
BrakeLevelSet( gbh_NP ); //ustawienie zmiennej GBH
}
mvOccupied->CabOccupied = mvOccupied->CabActive; // użytkownik moze zmienić CabOccupied wychodząc
mvOccupied->CabDeactivisation(); // tak jest w Train.cpp
if (TestFlag(pVehicle->MoverParameters->Couplers[iDirectionOrder < 0 ? end::rear : end::front].CouplingFlag, coupling::control)) {
ZeroLocalBrake();
if( initialspringbrakestate ) {
mvOccupied->SpringBrakeActivate( false );
}
// odcięcie na zaworze maszynisty, FVel6 po drugiej stronie nie luzuje
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos(bh_NP) ); // odcięcie na zaworze maszynisty
BrakeLevelSet( mvOccupied->BrakeCtrlPos ); //ustawienie zmiennej GBH
}
// przejście AI na drugą stronę EN57, ET41 itp.
// TODO: clean this up, there's lot of redundancy with TMoverParameters::ChangeCab() and TTrain::MoveToVehicle()
{
int movedirection { ( iDirection < 0 ? end::rear : end::front ) };
d = pVehicle->FirstFind( movedirection, coupling::control );
if( pVehicle != d ) {
drugi = d->Mechanik; // zapamiętanie tego, co ewentualnie tam siedzi, żeby w razie dwóch zamienić miejscami
d->Mechanik = this; // na razie bilokacja
d->MoverParameters->SetInternalCommand("", 0, 0); // usunięcie ewentualnie zalegającej komendy (Change_direction?)
if( d->DirectionGet() != pVehicle->DirectionGet() ) {
auto *targetvehicle { pVehicle->FirstFind( movedirection, coupling::control ) };
if( pVehicle != targetvehicle ) {
auto *targetvehicledriver { targetvehicle->Mechanik }; // zapamiętanie tego, co ewentualnie tam siedzi, żeby w razie dwóch zamienić miejscami
// move to the new vehicle
targetvehicle->Mechanik = this; // na razie bilokacja
targetvehicle->MoverParameters->SetInternalCommand("", 0, 0); // usunięcie ewentualnie zalegającej komendy (Change_direction?)
if( targetvehicle->DirectionGet() != pVehicle->DirectionGet() ) {
// jeśli są przeciwne do siebie to będziemy jechać w drugą stronę względem zasiedzianego pojazdu
iDirection = -iDirection;
}
pVehicle->Mechanik = drugi; // wsadzamy tego, co ewentualnie był (podwójna trakcja)
/*
pVehicle->MoverParameters->CabActive = 0; // wyłączanie kabin po drodze
pVehicle->MoverParameters->CabOccupied = 0; // i zaznaczenie, że nie ma tam nikogo
*/
pVehicle = d; // a mechu ma nowy pojazd (no, człon)
// move the other driver to our old vehicle
pVehicle->Mechanik = targetvehicledriver; // wsadzamy tego, co ewentualnie był (podwójna trakcja)
// NOTE: having caboccupied != 0 (by swapping in the driver from the target vehicle) may lead to dysfunctional brake
// TODO: investigate and resolve if necessary
pVehicle->MoverParameters->CabOccupied = targetvehicle->MoverParameters->CabOccupied;
if( pVehicle->Mechanik ) { // not guaranteed, as target vehicle can be empty
pVehicle->Mechanik->BrakeLevelSet( pVehicle->MoverParameters->BrakeCtrlPos );
}
// finish driver swap
pVehicle = targetvehicle;
}
}
if (pVehicle != old)
if (pVehicle != initialvehicle)
{ // jeśli zmieniony został pojazd prowadzony
TTrain *train = simulation::Trains.find(old->name());
if (train)
train->MoveToVehicle(pVehicle);
auto *train { simulation::Trains.find( initialvehicle->name() ) };
if( train ) {
train->MoveToVehicle( pVehicle );
}
ControllingSet(); // utworzenie połączenia do sterowanego pojazdu (może się zmienić) - silnikowy dla EZT
if( ( mvOccupied->BrakeCtrlPosNo > 0 )
&& ( ( mvOccupied->BrakeSystem == TBrakeSystem::Pneumatic )
|| ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) ) {
mvOccupied->LimPipePress = mvOccupied->PipePress;
mvOccupied->ActFlowSpeed = 0;
}
BrakeLevelSet( mvOccupied->BrakeCtrlPos );
}
if( mvControlling->EngineType == TEngineType::DieselEngine ) {
// dla 2Ls150 - przed ustawieniem kierunku - można zmienić tryb pracy
@@ -1945,12 +1990,17 @@ void TController::Activation()
}
// Ra: to przełączanie poniżej jest tu bez sensu
mvOccupied->CabOccupied = iDirection; // aktywacja kabiny w prowadzonym pojeżdzie (silnikowy może być odwrotnie?)
// mvOccupied->CabActive=iDirection;
// mvOccupied->DirActive=0; //żeby sam ustawił kierunek
mvOccupied->CabActivisation(); // uruchomienie kabin w członach
DirectionForward(true); // nawrotnik do przodu
if (localbrakelevel > 0.0) // hamowanie tylko jeśli był wcześniej zahamowany (bo możliwe, że jedzie!)
mvOccupied->LocalBrakePosA = localbrakelevel; // zahamuj jak wcześniej
/*
// NOTE: this won't restore local brake if the vehicle has integrated local brake control
// TBD, TODO: fix or let the ai activate the brake again as part of its standard logic?
if (initiallocalbrakelevel > 0.0) // hamowanie tylko jeśli był wcześniej zahamowany (bo możliwe, że jedzie!)
mvOccupied->LocalBrakePosA = initiallocalbrakelevel; // zahamuj jak wcześniej
*/
if( initialspringbrakestate ) {
mvOccupied->SpringBrakeActivate( initialspringbrakestate );
}
CheckVehicles(); // sprawdzenie składu, AI zapali światła
TableClear(); // resetowanie tabelki skanowania torów
}
@@ -3180,13 +3230,15 @@ bool TController::DecBrake()
return OK;
};
bool TController::ZeroLocalBrake() {
void TController::ZeroLocalBrake() {
if( mvOccupied->UniCtrlIntegratedLocalBrakeCtrl ) {
return DecBrakeEIM();
while( DecBrakeEIM() ) {
;
}
}
else {
return mvOccupied->DecLocalBrakeLevel( 2 );
mvOccupied->DecLocalBrakeLevel( LocalBrakePosNo );
}
}
@@ -3197,7 +3249,8 @@ bool TController::DecBrakeEIM()
{
case 0: {
if( mvOccupied->MED_amax != 9.81 ) {
auto const brakeposition { clamp( -1.0 * mvOccupied->AIHintLocalBrakeAccFactor * std::max( 0.0, AccDesired ) / mvOccupied->MED_amax, 0.0, 1.0 ) };
auto const desiredacceleration { ( mvOccupied->Vel > 0.01 ? AccDesired : std::max( 0.0, AccDesired ) ) };
auto const brakeposition { clamp( -1.0 * mvOccupied->AIHintLocalBrakeAccFactor * desiredacceleration / mvOccupied->MED_amax, 0.0, 1.0 ) };
OK = ( brakeposition != mvOccupied->LocalBrakePosA );
mvOccupied->LocalBrakePosA = brakeposition;
}
@@ -3244,7 +3297,7 @@ bool TController::IncSpeed()
// zamykanie drzwi - tutaj wykonuje tylko AI (zmienia fActionTime)
Doors( false );
}
if (mvOccupied->SpringBrake.IsActive && mvOccupied->SpringBrake.Activate) {
if (mvOccupied->SpringBrake.Activate) {
mvOccupied->SpringBrakeActivate(false);
}
// Doors() call can potentially adjust fActionTime
@@ -6482,6 +6535,7 @@ TController::UpdateSituation(double dt) {
if( ( mvOccupied->EqvtPipePress < 4.5 )
&& ( fReady > 0.35 )
&& ( mvOccupied->Compressor >= 7.5 ) // don't charge without sufficient pressure in the tank
&& ( BrakeChargingCooldown >= 0.0 )
&& ( ( ActualProximityDist > 100.0 ) // don't charge if we're about to be braking soon
|| ( min_speed( mvOccupied->Vel, VelNext ) == mvOccupied->Vel ) ) ) {
@@ -6504,8 +6558,9 @@ TController::UpdateSituation(double dt) {
*/
}
if( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition < 0 )
&& ( mvOccupied->EqvtPipePress > ( fReady < 0.25 ? 5.1 : 5.2 ) ) ) {
if( ( mvOccupied->Compressor < 5.0 )
|| ( ( /*GBH mvOccupied->BrakeCtrlPos*/BrakeCtrlPosition < 0 )
&& ( mvOccupied->EqvtPipePress > ( fReady < 0.25 ? 5.1 : 5.2 ) ) ) ) {
/* GBH mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); */
BrakeLevelSet( gbh_RP );
}

View File

@@ -233,7 +233,7 @@ private:
void SetDriverPsyche();
bool IncBrake();
bool DecBrake();
bool ZeroLocalBrake();
void ZeroLocalBrake();
bool IncSpeed();
bool DecSpeed( bool force = false );
void ZeroSpeed( bool const Enforce = false );
@@ -450,6 +450,8 @@ private:
std::string asNextStop; // nazwa następnego punktu zatrzymania wg rozkładu
int iStationStart = 0; // numer pierwszej stacji pokazywanej na podglądzie rozkładu
std::string m_lastexchangestop; // HACK: safeguard to prevent multiple load exchanges per station
int m_lastexchangeplatforms { 0 }; // cached station platforms for last exchange
int m_lastexchangedirection { 0 }; //
double fLastStopExpDist = -1.0; // odległość wygasania ostateniego przystanku
int iRadioChannel = 1; // numer aktualnego kanału radiowego
int iGuardRadio = 0; // numer kanału radiowego kierownika (0, gdy nie używa radia)

View File

@@ -2632,7 +2632,7 @@ bool TDynamicObject::UpdateForce(double dt)
}
// initiates load change by specified amounts, with a platform on specified side
void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int const Platform ) {
void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int const Platforms ) {
/*
if( ( MoverParameters->Doors.open_control == control_t::passenger )
|| ( MoverParameters->Doors.open_control == control_t::mixed ) ) {
@@ -2647,15 +2647,21 @@ void TDynamicObject::LoadExchange( int const Disembark, int const Embark, int co
}
}
*/
if( Platform == 0 ) { return; } // edge case, if there's no accessible platforms discard the request
if( Platforms == 0 ) { return; } // edge case, if there's no accessible platforms discard the request
m_exchange.unload_count += Disembark;
m_exchange.load_count += Embark;
m_exchange.platforms = Platform;
m_exchange.platforms = Platforms;
m_exchange.time = 0.0;
}
// calculates time needed to complete current load change
float TDynamicObject::LoadExchangeTime( int const Platforms ) {
m_exchange.platforms = Platforms;
return LoadExchangeTime();
}
float TDynamicObject::LoadExchangeTime() const {
if( ( m_exchange.unload_count < 0.01 ) && ( m_exchange.load_count < 0.01 ) ) { return 0.f; }
@@ -4754,8 +4760,7 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
token = "";
parser.getTokens(); parser >> token;
if( ( token == "models:" )
|| ( token == "\xef\xbb\xbfmodels:" ) ) { // crude way to handle utf8 bom potentially appearing before the first token
if( token == "models:" ) {
// modele i podmodele
m_materialdata.multi_textures = 0; // czy jest wiele tekstur wymiennych?
parser.getTokens();

View File

@@ -598,8 +598,10 @@ private:
void AttachNext(TDynamicObject *Object, int iType = 1);
bool UpdateForce(double dt);
// initiates load change by specified amounts, with a platform on specified side
void LoadExchange( int const Disembark, int const Embark, int const Platform );
// calculates time needed to complete current load change
void LoadExchange( int const Disembark, int const Embark, int const Platforms );
// calculates time needed to complete current load change, using specified platforms
float LoadExchangeTime( int const Platforms );
// calculates time needed to complete current load change, using previously specified platforms
float LoadExchangeTime() const;
// calculates current load exchange factor, where 1 = nominal rate, higher = faster
float LoadExchangeSpeed() const; // TODO: make private when cleaning up

View File

@@ -609,42 +609,20 @@ bool TMoverParameters::DecBrakeLevel()
bool TMoverParameters::ChangeCab(int direction)
{ // zmiana kabiny i resetowanie ustawien
if (abs(CabOccupied + direction) < 2)
if (std::abs(CabOccupied + direction) < 2)
{
// if (CabOccupied+direction=0) then LastCab:=CabOccupied;
CabOccupied = CabOccupied + direction;
if( ( BrakeCtrlPosNo > 0 )
&& ( ( BrakeSystem == TBrakeSystem::Pneumatic )
|| ( BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) ) {
// if (BrakeHandle==FV4a) //!!!POBIERAĆ WARTOŚĆ Z KLASY ZAWORU!!!
// BrakeLevelSet(-2); //BrakeCtrlPos=-2;
// else if ((BrakeHandle==FVel6)||(BrakeHandle==St113))
// BrakeLevelSet(2);
// else
// BrakeLevelSet(1);
BrakeLevelSet(Handle->GetPos(bh_NP));
LimPipePress = PipePress;
ActFlowSpeed = 0;
}
else
// if (TrainType=dt_EZT) and (BrakeCtrlPosNo>0) then
// BrakeCtrlPos:=5; //z Megapacka
// else
// BrakeLevelSet(0); //BrakeCtrlPos=0;
BrakeLevelSet(Handle->GetPos(bh_NP));
// if not TestFlag(BrakeStatus,b_dmg) then
// BrakeStatus:=b_off; //z Megapacka
MainCtrlPos = MainCtrlNoPowerPos();
ScndCtrlPos = 0;
// Ra: to poniżej jest bez sensu - można przejść nie wyłączając
// if ((EngineType!=DieselEngine)&&(EngineType!=DieselElectric))
//{
// Mains=false;
// CompressorAllow=false;
// ConverterAllow=false;
//}
// DirActive=0;
// DirAbsolute=0;
return true;
}
return false;
@@ -6170,7 +6148,7 @@ double TMoverParameters::TractionForce( double dt ) {
if( ( RlistSize > 0 )
&& ( ( std::abs( eimv[ eimv_If ] ) > 1.0 )
&& ( tmpV > 0.1 ) ) ) {
&& ( tmpV > 0.0001 ) ) ) {
int i = 0;
while( ( i < RlistSize - 1 )

View File

@@ -81,6 +81,11 @@ TCommandType TMemCell::CommandCheck()
eCommand = TCommandType::cm_SetProximityVelocity;
bCommand = false; // ta komenda nie jest wysyłana
}
else if( szText == "Emergency_brake" )
{
eCommand = TCommandType::cm_EmergencyBrake;
bCommand = false;
}
else
{
eCommand = TCommandType::cm_Unknown; // ciąg nierozpoznany (nie jest komendą)

View File

@@ -136,8 +136,8 @@ driverkeyboard_input::default_bindings() {
{ user_command::hornhighactivate, GLFW_KEY_S },
{ user_command::whistleactivate, GLFW_KEY_Z },
{ user_command::radiotoggle, GLFW_KEY_R | keymodifier::control },
{ user_command::radiochannelincrease, GLFW_KEY_R | keymodifier::shift },
{ user_command::radiochanneldecrease, GLFW_KEY_R },
{ user_command::radiochannelincrease, GLFW_KEY_EQUAL },
{ user_command::radiochanneldecrease, GLFW_KEY_MINUS },
{ user_command::radiostopsend, GLFW_KEY_PAUSE | keymodifier::shift | keymodifier::control },
{ user_command::radiostoptest, GLFW_KEY_R | keymodifier::shift | keymodifier::control },
{ user_command::radiocall3send, GLFW_KEY_BACKSPACE },

View File

@@ -763,10 +763,12 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
locale::strings[ locale::string::debug_vehicle_brakespressures ].c_str(),
// brakes
mover.fBrakeCtrlPos,
mover.LocalBrakePosA,
mover.BrakeOpModeFlag,
update_vehicle_brake().c_str(),
mover.LoadFlag,
mover.LocalBrakePosA,
( mover.ManualBrakePos / ManualBrakePosNo ),
( mover.SpringBrake.Activate ? 1.f : 0.f ),
// cylinders
mover.BrakePress,
mover.LocBrakePress,

View File

@@ -467,23 +467,24 @@ bool TTrainParameters::LoadTTfile(std::string scnpath, int iPlus, double vmax)
{
auto const stationware { Split( record->StationWare, ',' ) };
for( auto const &entry : stationware ) {
if( entry.front() == 'R' ) {
auto const entrysplit { split_string_and_number( entry ) };
if( ( entrysplit.first == "R" )
&& ( entrysplit.second <= 10 ) ) {
auto const radiochannel { entrysplit.second };
if( ( record->radio_channel == -1 )
|| ( radiochannel != activeradiochannel ) ) {
// if the station has more than one radiochannel listed,
// it generally means we should switch to the one we weren't using so far
// TODO: reverse this behaviour (keep the channel used so far) once W28 signs are included in the system
record->radio_channel = radiochannel;
}
if( entry.front() != 'R' ) {
continue;
}
auto const entrysplit { split_string_and_number( entry ) };
if( ( entrysplit.first == "R" )
&& ( entrysplit.second <= 10 ) ) {
auto const radiochannel { entrysplit.second };
if( ( record->radio_channel == -1 )
|| ( radiochannel != activeradiochannel ) ) {
// if the station has more than one radiochannel listed,
// it generally means we should switch to the one we weren't using so far
// TODO: reverse this behaviour (keep the channel used so far) once W28 signs are included in the system
record->radio_channel = radiochannel;
}
}
}
if( record->radio_channel != -1 ) {
activeradiochannel == record->radio_channel;
activeradiochannel = record->radio_channel;
}
}
record->TrackNo = atoi(s.c_str());

View File

@@ -4112,7 +4112,7 @@ void opengl33_renderer::Update(double const Deltatime)
// TODO: it doesn't make much sense with vsync
if( Global.targetfps == 0.0f ) {
// automatic adjustment
auto const framerate = interpolate( 1000.f / Timer::subsystem.gfx_color.average(), m_framerate, 0.25f );
auto const framerate = interpolate( 1000.f / Timer::subsystem.gfx_color.average(), m_framerate, 0.75f );
float targetfactor;
if( framerate > 120.0 ) { targetfactor = 3.00f; }
else if( framerate > 90.0 ) { targetfactor = 1.50f; }

View File

@@ -4170,7 +4170,7 @@ opengl_renderer::Update( double const Deltatime ) {
// adjust draw ranges etc, based on recent performance
if( Global.targetfps == 0.0f ) {
// automatic adjustment
auto const framerate = 0.5f * ( m_framerate + 1000.f / Timer::subsystem.gfx_color.average() );
auto const framerate = interpolate( 1000.f / Timer::subsystem.gfx_color.average(), m_framerate, 0.75f );
float targetfactor;
if( framerate > 120.0 ) { targetfactor = 3.00f; }
else if( framerate > 90.0 ) { targetfactor = 1.50f; }

View File

@@ -211,6 +211,17 @@ std::string cParser::readToken( bool ToLower, const char *Break ) {
}
} while( token == "" && mStream->peek() != EOF ); // double check in case of consecutive separators
}
// check the first token for potential presence of utf bom
if( mFirstToken ) {
mFirstToken = false;
if( token.rfind( "\xef\xbb\xbf", 0 ) == 0 ) {
token.erase( 0, 3 );
}
if( true == token.empty() ) {
// potentially possible if our first token was standalone utf bom
token = readToken( ToLower, Break );
}
}
if( false == parameters.empty() ) {
// if there's parameter list, check the token for potential parameters to replace

View File

@@ -104,6 +104,7 @@ class cParser //: public std::stringstream
std::streamoff mSize { 0 }; // size of open stream, for progress report.
std::size_t mLine { 0 }; // currently processed line
bool mIncFile { false }; // the parser is processing an *.inc file
bool mFirstToken { true }; // processing first token in the current file; helper used when checking for utf bom
typedef std::map<std::string, std::string> commentmap;
commentmap mComments {
commentmap::value_type( "/*", "*/" ),

View File

@@ -76,7 +76,7 @@ init() {
"Controllers:\n master: %d(%d), secondary: %s\nEngine output: %.1f, current: %.0f\nRevolutions:\n engine: %.0f, motors: %.0f\n engine fans: %.0f, motor fans: %.0f+%.0f, cooling fans: %.0f+%.0f",
" (shunt mode)",
"\nTemperatures:\n engine: %.2f, oil: %.2f, water: %.2f%c%.2f",
"Brakes:\n train: %.2f, independent: %.2f, mode: %d, delay: %s, load flag: %d\nBrake cylinder pressures:\n train: %.2f, independent: %.2f, status: 0x%.2x\nPipe pressures:\n brake: %.2f (hat: %.2f), main: %.2f, control: %.2f\nTank pressures:\n auxiliary: %.2f, main: %.2f, control: %.2f",
"Brakes:\n train: %.2f (mode: %d, delay: %s, load flag: %d)\n independent: %.2f, manual: %.2f, spring: %.2f\nBrake cylinder pressures:\n train: %.2f, independent: %.2f, status: 0x%.2x\nPipe pressures:\n brake: %.2f (hat: %.2f), main: %.2f, control: %.2f\nTank pressures:\n auxiliary: %.2f, main: %.2f, control: %.2f",
" pantograph: %.2f%cMT",
"Forces:\n tractive: %.1f, brake: %.1f, friction: %.2f%s\nAcceleration:\n tangential: %.2f, normal: %.2f (path radius: %s)\nVelocity: %.2f, distance traveled: %.2f\nPosition: [%.2f, %.2f, %.2f]",
@@ -281,7 +281,7 @@ init() {
"Nastawniki:\n glowny: %d(%d), dodatkowy: %s\nMoc silnika: %.1f, prad silnika: %.0f\nObroty:\n silnik: %.0f, motory: %.0f\n went.silnika: %.0f, went.motorow: %.0f+%.0f, went.chlodnicy: %.0f+%.0f",
" (tryb manewrowy)",
"\nTemperatury:\n silnik: %.2f, olej: %.2f, woda: %.2f%c%.2f",
"Hamulce:\n zespolony: %.2f, pomocniczy: %.2f, tryb: %d, nastawa: %s, ladunek: %d\nCisnienie w cylindrach:\n zespolony: %.2f, pomocniczy: %.2f, status: 0x%.2x\nCisnienia w przewodach:\n glowny: %.2f (kapturek: %.2f), zasilajacy: %.2f, kontrolny: %.2f\nCisnienia w zbiornikach:\n pomocniczy: %.2f, glowny: %.2f, sterujacy: %.2f",
"Hamulce:\n zespolony: %.2f (tryb: %d, nastawa: %s, ladunek: %d)\n pomocniczy: %.2f, postojowy: %.2f, sprezynowy: %.2f\nCisnienie w cylindrach:\n zespolony: %.2f, pomocniczy: %.2f, status: 0x%.2x\nCisnienia w przewodach:\n glowny: %.2f (kapturek: %.2f), zasilajacy: %.2f, kontrolny: %.2f\nCisnienia w zbiornikach:\n pomocniczy: %.2f, glowny: %.2f, sterujacy: %.2f",
" pantograf: %.2f%cZG",
"Sily:\n napedna: %.1f, hamowania: %.1f, tarcie: %.2f%s\nPrzyspieszenia:\n styczne: %.2f, normalne: %.2f (promien: %s)\nPredkosc: %.2f, pokonana odleglosc: %.2f\nPozycja: [%.2f, %.2f, %.2f]",

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 20
#define VERSION_MINOR 806
#define VERSION_MINOR 824
#define VERSION_REVISION 0