build 180313. automatic door, door controls ai tweaks, truck hunting camera shake

This commit is contained in:
tmj-fstate
2018-03-13 21:22:09 +01:00
parent d96b259191
commit c100fcb7d8
9 changed files with 232 additions and 64 deletions

View File

@@ -1954,19 +1954,26 @@ bool TController::CheckVehicles(TOrders user)
}
else if (OrderCurrentGet() & (Shunt | Connect))
{
Lights(16, (pVehicles[1]->MoverParameters->CabNo) ?
1 :
0); //światła manewrowe (Tb1) na pojeździe z napędem
Lights(
light::headlight_right,
( pVehicles[ 1 ]->MoverParameters->CabNo ) ?
1 :
0 ); //światła manewrowe (Tb1) na pojeździe z napędem
if (OrderCurrentGet() & Connect) // jeśli łączenie, skanować dalej
pVehicles[0]->fScanDist = 5000.0; // odległość skanowania w poszukiwaniu innych pojazdów
}
else if (OrderCurrentGet() == Disconnect)
if (mvOccupied->ActiveDir > 0) // jak ma kierunek do przodu
Lights(16, 0); //światła manewrowe (Tb1) tylko z przodu, aby nie pozostawić
// odczepionego ze światłem
else // jak dociska
Lights(0, 16); //światła manewrowe (Tb1) tylko z przodu, aby nie pozostawić
// odczepionego ze światłem
else if( OrderCurrentGet() == Disconnect ) {
if( mvOccupied->ActiveDir > 0 ) {
// jak ma kierunek do przodu
// światła manewrowe (Tb1) tylko z przodu, aby nie pozostawić odczepionego ze światłem
Lights( light::headlight_right, 0 );
}
else {
// jak dociska
// światła manewrowe (Tb1) tylko z przodu, aby nie pozostawić odczepionego ze światłem
Lights( 0, light::headlight_right );
}
}
}
else // Ra 2014-02: lepiej tu niż w pętli obsługującej komendy, bo tam się zmieni informacja
// o składzie
@@ -3036,6 +3043,11 @@ void TController::Doors( bool const Open, int const Side ) {
}
else {
// zamykanie
if( false == doors_open() ) {
// the doors are already closed, we can skip all hard work
iDrivigFlags &= ~moveDoorOpened;
}
if( AIControllFlag ) {
if( ( true == mvOccupied->DoorClosureWarning )
&& ( false == mvOccupied->DepartureSignal )
@@ -3064,6 +3076,23 @@ void TController::Doors( bool const Open, int const Side ) {
}
}
// returns true if any vehicle in the consist has open doors
bool
TController::doors_open() const {
auto *vehicle = pVehicles[ 0 ]; // pojazd na czole składu
while( vehicle != nullptr ) {
if( ( vehicle->MoverParameters->DoorRightOpened == true )
|| ( vehicle->MoverParameters->DoorLeftOpened == true ) ) {
// any open door is enough
return true;
}
vehicle = vehicle->Next();
}
// if we're still here there's nothing open
return false;
}
void TController::RecognizeCommand()
{ // odczytuje i wykonuje komendę przekazaną lokomotywie
TCommand *c = &mvOccupied->CommandIn;
@@ -3128,6 +3157,9 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
}
else
{ // inicjacja pierwszego przystanku i pobranie jego nazwy
// HACK: clear the potentially set door state flag to ensure door get opened if applicable
iDrivigFlags &= ~( moveDoorOpened );
TrainParams->UpdateMTable( simulation::Time, TrainParams->NextStationName );
TrainParams->StationIndexInc(); // przejście do następnej
iStationStart = TrainParams->StationIndex;
@@ -3903,8 +3935,7 @@ TController::UpdateSituation(double dt) {
// jeśli stanął już blisko, unikając zderzenia i można próbować podłączyć
fMinProximityDist = -0.5;
fMaxProximityDist = 0.0; //[m] dojechać maksymalnie
fVelPlus = 0.5; // dopuszczalne przekroczenie prędkości na ograniczeniu bez
// hamowania
fVelPlus = 0.5; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
fVelMinus = 0.5; // margines prędkości powodujący załączenie napędu
if (AIControllFlag)
{ // to robi tylko AI, wersję dla człowieka trzeba dopiero zrobić
@@ -3952,11 +3983,7 @@ TController::UpdateSituation(double dt) {
CheckVehicles(); // sprawdzić światła nowego składu
JumpToNextOrder(); // wykonanie następnej komendy
}
/*
// NOTE: disabled as speed limit is decided in another place based on distance to potential target
else
SetVelocity(2.0, 0.0); // jazda w ustawionym kierunku z prędkością 2 (18s)
*/
} // if (AIControllFlag) //koniec zblokowania, bo była zmienna lokalna
}
else {
@@ -5167,8 +5194,13 @@ void TController::JumpToFirstOrder()
void TController::OrderCheck()
{ // reakcja na zmianę rozkazu
if (OrderList[OrderPos] & (Shunt | Connect | Obey_train))
if( OrderList[ OrderPos ] & ( Shunt | Connect | Obey_train ) ) {
CheckVehicles(); // sprawdzić światła
}
if( OrderList[ OrderPos ] & ( Shunt | Connect ) ) {
// HACK: ensure consist doors will be closed on departure
iDrivigFlags |= moveDoorOpened;
}
if (OrderList[OrderPos] & Change_direction) // może być nałożona na inną i wtedy ma priorytet
iDirectionOrder = -iDirection; // trzeba zmienić jawnie, bo się nie domyśli
else if (OrderList[OrderPos] == Obey_train)

View File

@@ -305,6 +305,8 @@ private:
bool DecSpeed(bool force = false);
void SpeedSet();
void Doors(bool const Open, int const Side = 0);
// returns true if any vehicle in the consist has an open door
bool doors_open() const;
void RecognizeCommand(); // odczytuje komende przekazana lokomotywie
void Activation(); // umieszczenie obsady w odpowiednim członie
void ControllingSet(); // znajduje człon do sterowania

View File

@@ -1959,6 +1959,15 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
ActPar.erase( 0, indexend );
break;
}
case 'H': {
// truck hunting
auto const indexstart { 1 };
auto const indexend { ActPar.find_first_not_of( "1234567890", indexstart ) };
auto const huntingchance { std::atoi( ActPar.substr( indexstart, indexend ).c_str() ) };
MoverParameters->TruckHunting = ( Random( 0, 100 ) <= huntingchance );
ActPar.erase( 0, indexend );
break;
}
default: {
// unrecognized key
ActPar.erase( 0, 1 );
@@ -2563,8 +2572,16 @@ void TDynamicObject::update_exchange( double const Deltatime ) {
if( ( MoverParameters->DoorCloseCtrl == control::passenger )
|| ( MoverParameters->DoorCloseCtrl == control::mixed ) ) {
MoverParameters->DoorLeft( false, range::local );
MoverParameters->DoorRight( false, range::local );
if( ( MoverParameters->Vel > 2.0 )
|| ( Random() < (
// remotely controlled door are more likely to be left open
MoverParameters->DoorCloseCtrl == control::passenger ?
0.75 :
0.50 ) ) ) {
MoverParameters->DoorLeft( false, range::local );
MoverParameters->DoorRight( false, range::local );
}
}
}
}

View File

@@ -869,6 +869,7 @@ public:
double AccVert = 0.0; // vertical acceleration
double nrot = 0.0;
double WheelFlat = 0.0;
bool TruckHunting { true }; // enable/disable truck hunting calculation
/*! rotacja kol [obr/s]*/
double EnginePower = 0.0; /*! chwilowa moc silnikow*/
double dL = 0.0; double Fb = 0.0; double Ff = 0.0; /*przesuniecie, sila hamowania i tarcia*/
@@ -1041,8 +1042,10 @@ public:
bool DoorBlocked = false; //Czy jest blokada drzwi
bool DoorLeftOpened = false; //stan drzwi
double DoorLeftOpenTimer { -1.0 }; // left door closing timer for automatic door type
bool DoorRightOpened = false;
bool PantFrontUp = false; //stan patykow 'Winger 160204
double DoorRightOpenTimer{ -1.0 }; // right door closing timer for automatic door type
bool PantFrontUp = false; //stan patykow 'Winger 160204
bool PantRearUp = false;
bool PantFrontSP = true; //dzwiek patykow 'Winger 010304
bool PantRearSP = true;
@@ -1232,8 +1235,9 @@ public:
bool DoorRight(bool State, int const Notify = range::consist ); //obsluga drzwi prawych
bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi
bool signal_departure( bool const State, int const Notify = range::consist ); // toggles departure warning
void update_autonomous_doors( double const Deltatime ); // automatic door controller update
/* funkcje dla samochodow*/
/* funkcje dla samochodow*/
bool ChangeOffsetH(double DeltaOffset);
/*funkcje ladujace pliki opisujace pojazd*/

View File

@@ -1409,23 +1409,10 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
// hamulec antypoślizgowy - wyłączanie
if ((BrakeSlippingTimer > 0.8) && (ASBType != 128)) // ASBSpeed=0.8
Hamulec->ASB(0);
// SetFlag(BrakeStatus,-b_antislip);
BrakeSlippingTimer += dt;
// sypanie piasku - wyłączone i piasek się nie kończy - błędy AI
// if AIControllFlag then
// if SandDose then
// if Sand>0 then
// begin
// Sand:=Sand-NPoweredAxles*SandSpeed*dt;
// if Random<dt then SandDose:=false;
// end
// else
// begin
// SandDose:=false;
// Sand:=0;
// end;
// czuwak/SHP
// if (Vel>10) and (not DebugmodeFlag) then
// automatic doors
update_autonomous_doors( dt );
// security system
if (!DebugModeFlag)
SecuritySystemCheck(dt1);
@@ -1533,6 +1520,8 @@ double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape
if ((BrakeSlippingTimer > 0.8) && (ASBType != 128)) // ASBSpeed=0.8
Hamulec->ASB(0);
BrakeSlippingTimer += dt;
// automatic doors
update_autonomous_doors( dt );
return d;
};
@@ -6016,10 +6005,20 @@ bool TMoverParameters::DoorLeft(bool State, int const Notify ) {
bool result { false };
if( ( Battery == true )
&& ( DoorBlockedFlag() == false ) ) {
&& ( ( State == false ) // closing door works always, but if the lock is engaged they can't be opened
|| ( DoorBlockedFlag() == false ) ) ) {
DoorLeftOpened = State;
result = true;
if( DoorCloseCtrl == control::autonomous ) {
// activate or disable the door timer depending on whether door were open or closed
// NOTE: this it a local-only operation but shouldn't be an issue as automatic door are operated locally anyway
DoorLeftOpenTimer = (
State == true ?
DoorStayOpen :
-1.0 );
}
}
if( Notify != range::local ) {
@@ -6056,10 +6055,20 @@ bool TMoverParameters::DoorRight(bool State, int const Notify ) {
bool result { false };
if( ( Battery == true )
&& ( DoorBlockedFlag() == false ) ) {
&& ( ( State == false )
|| ( DoorBlockedFlag() == false ) ) ) {
DoorRightOpened = State;
result = true;
if( DoorCloseCtrl == control::autonomous ) {
// activate or disable the door timer depending on whether door were open or closed
// NOTE: this it a local-only operation but shouldn't be an issue as automatic door are operated locally anyway
DoorRightOpenTimer = (
State == true ?
DoorStayOpen :
-1.0 );
}
}
if( Notify != range::local ) {
@@ -6105,6 +6114,45 @@ TMoverParameters::signal_departure( bool const State, int const Notify ) {
return true;
}
// automatic door controller update
void
TMoverParameters::update_autonomous_doors( double const Deltatime ) {
if( ( DoorCloseCtrl != control::autonomous )
|| ( ( false == DoorLeftOpened )
&& ( false == DoorRightOpened ) ) ) {
// nothing to do
return;
}
if( DoorStayOpen > 0.0 ) {
// update door timers if the door close after defined time
if( DoorLeftOpenTimer >= 0.0 ) { DoorLeftOpenTimer -= Deltatime; }
if( DoorRightOpenTimer >= 0.0 ) { DoorRightOpenTimer -= Deltatime; }
}
if( ( LoadStatus & ( 2 | 1 ) ) != 0 ) {
// if there's load exchange in progress, reset the timer(s) for already open doors
if( true == DoorLeftOpened ) { DoorLeftOpenTimer = DoorStayOpen; }
if( true == DoorRightOpened ) { DoorRightOpenTimer = DoorStayOpen; }
}
// the door are closed if their timer goes below 0, or if the vehicle is moving at > 5 km/h
// NOTE: timer value of 0 is 'special' as it means the door will stay open until vehicle is moving
if( true == DoorLeftOpened ) {
if( ( DoorLeftOpenTimer < 0.0 )
|| ( Vel > 5.0 ) ) {
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving)
DoorLeft( false, range::local );
}
}
if( true == DoorRightOpened ) {
if( ( DoorRightOpenTimer < 0.0 )
|| ( Vel > 5.0 ) ) {
// close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving)
DoorRight( false, range::local );
}
}
}
// *************************************************************************************************
// Q: 20160713
// Przesuwa pojazd o podaną wartość w bok względem toru (dla samochodów)
@@ -8503,17 +8551,33 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
// ignore remote command if the door is only operated locally
if( CValue2 > 0 ) {
// normalne ustawienie pojazdu
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
DoorLeftOpened = true;
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
DoorRightOpened = true;
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) {
DoorLeftOpened = (
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ?
true :
DoorLeftOpened );
}
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) {
DoorRightOpened = (
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ?
true :
DoorRightOpened );
}
}
else {
// odwrotne ustawienie pojazdu
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
DoorLeftOpened = true;
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
DoorRightOpened = true;
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) {
DoorLeftOpened = (
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ?
true :
DoorLeftOpened );
}
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) {
DoorRightOpened = (
( ( true == Battery ) && ( false == DoorBlockedFlag() ) ) ?
true :
DoorRightOpened );
}
}
}
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
@@ -8526,17 +8590,33 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
// ignore remote command if the door is only operated locally
if( CValue2 > 0 ) {
// normalne ustawienie pojazdu
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
DoorLeftOpened = false;
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
DoorRightOpened = false;
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) {
DoorLeftOpened = (
true == Battery ?
false :
DoorLeftOpened );
}
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) {
DoorRightOpened = (
true == Battery ?
false :
DoorRightOpened );
}
}
else {
// odwrotne ustawienie pojazdu
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) )
DoorLeftOpened = false;
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) )
DoorRightOpened = false;
if( ( CValue1 == 2 ) || ( CValue1 == 3 ) ) {
DoorLeftOpened = (
true == Battery ?
false :
DoorLeftOpened );
}
if( ( CValue1 == 1 ) || ( CValue1 == 3 ) ) {
DoorRightOpened = (
true == Battery ?
false :
DoorRightOpened );
}
}
}
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );

View File

@@ -3721,7 +3721,7 @@ void TTrain::UpdateMechPosition(double dt)
if( std::abs( mvOccupied->enrot ) > 0.0 ) {
// engine vibration
shakevector.x +=
( std::cos( mvOccupied->eAngle * 4.0 ) * dt * EngineShake.scale )
( std::sin( mvOccupied->eAngle * 4.0 ) * dt * EngineShake.scale )
// fade in with rpm above threshold
* clamp(
( mvOccupied->enrot - EngineShake.fadein_offset ) * EngineShake.fadein_factor,
@@ -3734,6 +3734,20 @@ void TTrain::UpdateMechPosition(double dt)
0.0, 1.0 ) );
}
}
if( ( HuntingShake.fadein_begin > 0.f )
&& ( true == mvOccupied->TruckHunting ) ) {
// hunting oscillation
HuntingAngle = clamp_circular( HuntingAngle + 4.0 * HuntingShake.frequency * dt * mvOccupied->Vel, 360.0 );
shakevector.x +=
( std::sin( glm::radians( HuntingAngle ) ) * dt * HuntingShake.scale )
* interpolate(
0.0, 1.0,
clamp(
( mvOccupied->Vel - HuntingShake.fadein_begin ) / ( HuntingShake.fadein_end - HuntingShake.fadein_begin ),
0.0, 1.0 ) );
}
if( iVel > 0.5 ) {
// acceleration-driven base shake
shakevector += Math3D::vector3(
@@ -5406,6 +5420,17 @@ bool TTrain::LoadMMediaFile(std::string const &asFileName)
>> EngineShake.fadein_factor
>> EngineShake.fadeout_offset
>> EngineShake.fadeout_factor;
// offsets values are provided as rpm for convenience
EngineShake.fadein_offset /= 60.f;
EngineShake.fadeout_offset /= 60.f;
}
else if( token == "huntingspring:" ) {
parser.getTokens( 4, false );
parser
>> HuntingShake.scale
>> HuntingShake.frequency
>> HuntingShake.fadein_begin
>> HuntingShake.fadein_end;
}
} while (token != "");

11
Train.h
View File

@@ -507,11 +507,18 @@ public: // reszta może by?publiczna
double fMechPitch;
struct engineshake_config {
float scale { 2.f };
float fadein_offset { 1.5f };
float fadein_offset { 1.5f }; // 90 rpm
float fadein_factor { 0.3f };
float fadeout_offset { 10.f };
float fadeout_offset { 10.f }; // 600 rpm
float fadeout_factor { 0.5f };
} EngineShake;
struct huntingshake_config {
float scale { 1.f };
float frequency { 1.f };
float fadein_begin { 0.f }; // effect start speed in km/h
float fadein_end { 0.f }; // full effect speed in km/h
} HuntingShake;
float HuntingAngle { 0.f }; // crude approximation of hunting oscillation; current angle of sine wave
sound_source dsbReverserKey { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // hunter-121211
sound_source dsbNastawnikJazdy { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };

View File

@@ -233,12 +233,13 @@ mouse_input::default_bindings() {
{ "brakeprofile_sw:", {
user_command::brakeactingspeedincrease,
user_command::brakeactingspeeddecrease } },
// TODO: dedicated methods for braking speed switches
{ "brakeprofileg_sw:", {
user_command::brakeactingspeeddecrease,
user_command::none } },
user_command::brakeactingspeedsetcargo,
user_command::brakeactingspeedsetpassenger } },
{ "brakeprofiler_sw:", {
user_command::brakeactingspeedincrease,
user_command::none } },
user_command::brakeactingspeedsetrapid,
user_command::brakeactingspeedsetpassenger } },
{ "maxcurrent_sw:", {
user_command::motoroverloadrelaythresholdtoggle,
user_command::none } },

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 18
#define VERSION_MINOR 311
#define VERSION_MINOR 313
#define VERSION_REVISION 0