mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
windows build fix log uart write error uart changes uart changes uart changes uart changes uart changes uart works uart changes verbose uart log uart changes uart changes uart logging uart logging uart changes changes uart changes
7549 lines
298 KiB
C++
7549 lines
298 KiB
C++
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
/*
|
|
MaSzyna EU07 locomotive simulator
|
|
Copyright (C) 2001-2004 Marcin Wozniak, Maciej Czapkiewicz and others
|
|
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "Train.h"
|
|
|
|
#include "Globals.h"
|
|
#include "Logs.h"
|
|
#include "MdlMngr.h"
|
|
#include "Timer.h"
|
|
#include "Driver.h"
|
|
#include "Console.h"
|
|
#include "sound.h"
|
|
|
|
void
|
|
control_mapper::insert( TGauge const &Gauge, std::string const &Label ) {
|
|
|
|
auto const submodel = Gauge.SubModel;
|
|
if( submodel != nullptr ) {
|
|
m_controlnames.emplace( submodel, Label );
|
|
}
|
|
}
|
|
|
|
std::string
|
|
control_mapper::find( TSubModel const *Control ) const {
|
|
|
|
auto const lookup = m_controlnames.find( Control );
|
|
if( lookup != m_controlnames.end() ) {
|
|
return lookup->second;
|
|
}
|
|
else {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
TCab::TCab()
|
|
{
|
|
CabPos1.x = -1.0;
|
|
CabPos1.y = 1.0;
|
|
CabPos1.z = 1.0;
|
|
CabPos2.x = 1.0;
|
|
CabPos2.y = 1.0;
|
|
CabPos2.z = -1.0;
|
|
bEnabled = false;
|
|
bOccupied = true;
|
|
dimm_r = dimm_g = dimm_b = 1;
|
|
intlit_r = intlit_g = intlit_b = 0;
|
|
intlitlow_r = intlitlow_g = intlitlow_b = 0;
|
|
/*
|
|
iGaugesMax = 100; // 95 - trzeba pobierać to z pliku konfiguracyjnego
|
|
ggList = new TGauge[iGaugesMax];
|
|
iGauges = 0; // na razie nie są dodane
|
|
iButtonsMax = 60; // 55 - trzeba pobierać to z pliku konfiguracyjnego
|
|
btList = new TButton[iButtonsMax];
|
|
iButtons = 0;
|
|
*/
|
|
}
|
|
/*
|
|
void TCab::Init(double Initx1, double Inity1, double Initz1, double Initx2, double Inity2,
|
|
double Initz2, bool InitEnabled, bool InitOccupied)
|
|
{
|
|
CabPos1.x = Initx1;
|
|
CabPos1.y = Inity1;
|
|
CabPos1.z = Initz1;
|
|
CabPos2.x = Initx2;
|
|
CabPos2.y = Inity2;
|
|
CabPos2.z = Initz2;
|
|
bEnabled = InitEnabled;
|
|
bOccupied = InitOccupied;
|
|
}
|
|
*/
|
|
void TCab::Load(cParser &Parser)
|
|
{
|
|
// NOTE: clearing control tables here is bit of a crutch, imposed by current scheme of loading compartments anew on each cab change
|
|
ggList.clear();
|
|
btList.clear();
|
|
|
|
std::string token;
|
|
Parser.getTokens();
|
|
Parser >> token;
|
|
if (token == "cablight")
|
|
{
|
|
Parser.getTokens( 9, false );
|
|
Parser
|
|
>> dimm_r
|
|
>> dimm_g
|
|
>> dimm_b
|
|
>> intlit_r
|
|
>> intlit_g
|
|
>> intlit_b
|
|
>> intlitlow_r
|
|
>> intlitlow_g
|
|
>> intlitlow_b;
|
|
Parser.getTokens(); Parser >> token;
|
|
}
|
|
CabPos1.x = std::stod( token );
|
|
Parser.getTokens( 5, false );
|
|
Parser
|
|
>> CabPos1.y
|
|
>> CabPos1.z
|
|
>> CabPos2.x
|
|
>> CabPos2.y
|
|
>> CabPos2.z;
|
|
|
|
bEnabled = true;
|
|
bOccupied = true;
|
|
}
|
|
|
|
TCab::~TCab()
|
|
{
|
|
/*
|
|
delete[] ggList;
|
|
delete[] btList;
|
|
*/
|
|
};
|
|
|
|
TGauge &TCab::Gauge(int n)
|
|
{ // pobranie adresu obiektu aniomowanego ruchem
|
|
/*
|
|
if (n < 0)
|
|
{ // rezerwacja wolnego
|
|
ggList[iGauges].Clear();
|
|
return ggList + iGauges++;
|
|
}
|
|
else if (n < iGauges)
|
|
return ggList + n;
|
|
return NULL;
|
|
*/
|
|
if( n < 0 ) {
|
|
ggList.emplace_back();
|
|
return ggList.back();
|
|
}
|
|
else {
|
|
return ggList[ n ];
|
|
}
|
|
};
|
|
|
|
TButton &TCab::Button(int n)
|
|
{ // pobranie adresu obiektu animowanego wyborem 1 z 2
|
|
/*
|
|
if (n < 0)
|
|
{ // rezerwacja wolnego
|
|
return btList + iButtons++;
|
|
}
|
|
else if (n < iButtons)
|
|
return btList + n;
|
|
return NULL;
|
|
*/
|
|
if( n < 0 ) {
|
|
btList.emplace_back();
|
|
return btList.back();
|
|
}
|
|
else {
|
|
return btList[ n ];
|
|
}
|
|
};
|
|
|
|
void TCab::Update()
|
|
{ // odczyt parametrów i ustawienie animacji submodelom
|
|
/*
|
|
int i;
|
|
for (i = 0; i < iGauges; ++i)
|
|
{ // animacje izometryczne
|
|
ggList[i].UpdateValue(); // odczyt parametru i przeliczenie na kąt
|
|
ggList[i].Update(); // ustawienie animacji
|
|
}
|
|
for (i = 0; i < iButtons; ++i)
|
|
{ // animacje dwustanowe
|
|
btList[i].Update(); // odczyt parametru i wybór submodelu
|
|
}
|
|
*/
|
|
for( auto &gauge : ggList ) {
|
|
// animacje izometryczne
|
|
gauge.UpdateValue(); // odczyt parametru i przeliczenie na kąt
|
|
gauge.Update(); // ustawienie animacji
|
|
}
|
|
for( auto &button : btList ) {
|
|
// animacje dwustanowe
|
|
button.Update(); // odczyt parametru i wybór submodelu
|
|
}
|
|
};
|
|
|
|
// NOTE: we're currently using universal handlers and static handler map but it may be beneficial to have these implemented on individual class instance basis
|
|
// TBD, TODO: consider this approach if we ever want to have customized consist behaviour to received commands, based on the consist/vehicle type or whatever
|
|
TTrain::commandhandler_map const TTrain::m_commandhandlers = {
|
|
|
|
{ user_command::mastercontrollerincrease, &TTrain::OnCommand_mastercontrollerincrease },
|
|
{ user_command::mastercontrollerincreasefast, &TTrain::OnCommand_mastercontrollerincreasefast },
|
|
{ user_command::mastercontrollerdecrease, &TTrain::OnCommand_mastercontrollerdecrease },
|
|
{ user_command::mastercontrollerdecreasefast, &TTrain::OnCommand_mastercontrollerdecreasefast },
|
|
{ user_command::secondcontrollerincrease, &TTrain::OnCommand_secondcontrollerincrease },
|
|
{ user_command::secondcontrollerincreasefast, &TTrain::OnCommand_secondcontrollerincreasefast },
|
|
{ user_command::secondcontrollerdecrease, &TTrain::OnCommand_secondcontrollerdecrease },
|
|
{ user_command::secondcontrollerdecreasefast, &TTrain::OnCommand_secondcontrollerdecreasefast },
|
|
{ user_command::notchingrelaytoggle, &TTrain::OnCommand_notchingrelaytoggle },
|
|
{ user_command::mucurrentindicatorothersourceactivate, &TTrain::OnCommand_mucurrentindicatorothersourceactivate },
|
|
{ user_command::independentbrakeincrease, &TTrain::OnCommand_independentbrakeincrease },
|
|
{ user_command::independentbrakeincreasefast, &TTrain::OnCommand_independentbrakeincreasefast },
|
|
{ user_command::independentbrakedecrease, &TTrain::OnCommand_independentbrakedecrease },
|
|
{ user_command::independentbrakedecreasefast, &TTrain::OnCommand_independentbrakedecreasefast },
|
|
{ user_command::independentbrakebailoff, &TTrain::OnCommand_independentbrakebailoff },
|
|
{ user_command::trainbrakeincrease, &TTrain::OnCommand_trainbrakeincrease },
|
|
{ user_command::trainbrakedecrease, &TTrain::OnCommand_trainbrakedecrease },
|
|
{ user_command::trainbrakecharging, &TTrain::OnCommand_trainbrakecharging },
|
|
{ user_command::trainbrakerelease, &TTrain::OnCommand_trainbrakerelease },
|
|
{ user_command::trainbrakefirstservice, &TTrain::OnCommand_trainbrakefirstservice },
|
|
{ user_command::trainbrakeservice, &TTrain::OnCommand_trainbrakeservice },
|
|
{ user_command::trainbrakefullservice, &TTrain::OnCommand_trainbrakefullservice },
|
|
{ user_command::trainbrakeemergency, &TTrain::OnCommand_trainbrakeemergency },
|
|
{ user_command::manualbrakeincrease, &TTrain::OnCommand_manualbrakeincrease },
|
|
{ user_command::manualbrakedecrease, &TTrain::OnCommand_manualbrakedecrease },
|
|
{ user_command::alarmchaintoggle, &TTrain::OnCommand_alarmchaintoggle },
|
|
{ user_command::wheelspinbrakeactivate, &TTrain::OnCommand_wheelspinbrakeactivate },
|
|
{ user_command::sandboxactivate, &TTrain::OnCommand_sandboxactivate },
|
|
{ user_command::epbrakecontroltoggle, &TTrain::OnCommand_epbrakecontroltoggle },
|
|
{ user_command::brakeactingspeedincrease, &TTrain::OnCommand_brakeactingspeedincrease },
|
|
{ user_command::brakeactingspeeddecrease, &TTrain::OnCommand_brakeactingspeeddecrease },
|
|
{ user_command::mubrakingindicatortoggle, &TTrain::OnCommand_mubrakingindicatortoggle },
|
|
{ user_command::reverserincrease, &TTrain::OnCommand_reverserincrease },
|
|
{ user_command::reverserdecrease, &TTrain::OnCommand_reverserdecrease },
|
|
{ user_command::alerteracknowledge, &TTrain::OnCommand_alerteracknowledge },
|
|
{ user_command::batterytoggle, &TTrain::OnCommand_batterytoggle },
|
|
{ user_command::pantographcompressorvalvetoggle, &TTrain::OnCommand_pantographcompressorvalvetoggle },
|
|
{ user_command::pantographcompressoractivate, &TTrain::OnCommand_pantographcompressoractivate },
|
|
{ user_command::pantographtogglefront, &TTrain::OnCommand_pantographtogglefront },
|
|
{ user_command::pantographtogglerear, &TTrain::OnCommand_pantographtogglerear },
|
|
{ user_command::pantographlowerall, &TTrain::OnCommand_pantographlowerall },
|
|
{ user_command::linebreakertoggle, &TTrain::OnCommand_linebreakertoggle },
|
|
{ user_command::convertertoggle, &TTrain::OnCommand_convertertoggle },
|
|
{ user_command::convertertogglelocal, &TTrain::OnCommand_convertertogglelocal },
|
|
{ user_command::converteroverloadrelayreset, &TTrain::OnCommand_converteroverloadrelayreset },
|
|
{ user_command::compressortoggle, &TTrain::OnCommand_compressortoggle },
|
|
{ user_command::compressortogglelocal, &TTrain::OnCommand_compressortogglelocal },
|
|
{ user_command::motorconnectorsopen, &TTrain::OnCommand_motorconnectorsopen },
|
|
{ user_command::motordisconnect, &TTrain::OnCommand_motordisconnect },
|
|
{ user_command::motoroverloadrelaythresholdtoggle, &TTrain::OnCommand_motoroverloadrelaythresholdtoggle },
|
|
{ user_command::motoroverloadrelayreset, &TTrain::OnCommand_motoroverloadrelayreset },
|
|
{ user_command::heatingtoggle, &TTrain::OnCommand_heatingtoggle },
|
|
{ user_command::headlighttoggleleft, &TTrain::OnCommand_headlighttoggleleft },
|
|
{ user_command::headlighttoggleright, &TTrain::OnCommand_headlighttoggleright },
|
|
{ user_command::headlighttoggleupper, &TTrain::OnCommand_headlighttoggleupper },
|
|
{ user_command::redmarkertoggleleft, &TTrain::OnCommand_redmarkertoggleleft },
|
|
{ user_command::redmarkertoggleright, &TTrain::OnCommand_redmarkertoggleright },
|
|
{ user_command::headlighttogglerearleft, &TTrain::OnCommand_headlighttogglerearleft },
|
|
{ user_command::headlighttogglerearright, &TTrain::OnCommand_headlighttogglerearright },
|
|
{ user_command::headlighttogglerearupper, &TTrain::OnCommand_headlighttogglerearupper },
|
|
{ user_command::redmarkertogglerearleft, &TTrain::OnCommand_redmarkertogglerearleft },
|
|
{ user_command::redmarkertogglerearright, &TTrain::OnCommand_redmarkertogglerearright },
|
|
{ user_command::headlightsdimtoggle, &TTrain::OnCommand_headlightsdimtoggle },
|
|
{ user_command::interiorlighttoggle, &TTrain::OnCommand_interiorlighttoggle },
|
|
{ user_command::interiorlightdimtoggle, &TTrain::OnCommand_interiorlightdimtoggle },
|
|
{ user_command::instrumentlighttoggle, &TTrain::OnCommand_instrumentlighttoggle },
|
|
{ user_command::doorlocktoggle, &TTrain::OnCommand_doorlocktoggle },
|
|
{ user_command::doortoggleleft, &TTrain::OnCommand_doortoggleleft },
|
|
{ user_command::doortoggleright, &TTrain::OnCommand_doortoggleright },
|
|
{ user_command::departureannounce, &TTrain::OnCommand_departureannounce },
|
|
{ user_command::hornlowactivate, &TTrain::OnCommand_hornlowactivate },
|
|
{ user_command::hornhighactivate, &TTrain::OnCommand_hornhighactivate },
|
|
{ user_command::radiotoggle, &TTrain::OnCommand_radiotoggle },
|
|
{ user_command::radiostoptest, &TTrain::OnCommand_radiostoptest },
|
|
{ user_command::generictoggle0, &TTrain::OnCommand_generictoggle },
|
|
{ user_command::generictoggle1, &TTrain::OnCommand_generictoggle },
|
|
{ user_command::generictoggle2, &TTrain::OnCommand_generictoggle },
|
|
{ user_command::generictoggle3, &TTrain::OnCommand_generictoggle },
|
|
{ user_command::generictoggle4, &TTrain::OnCommand_generictoggle },
|
|
{ user_command::generictoggle5, &TTrain::OnCommand_generictoggle },
|
|
{ user_command::generictoggle6, &TTrain::OnCommand_generictoggle },
|
|
{ user_command::generictoggle7, &TTrain::OnCommand_generictoggle },
|
|
{ user_command::generictoggle8, &TTrain::OnCommand_generictoggle },
|
|
{ user_command::generictoggle9, &TTrain::OnCommand_generictoggle }
|
|
};
|
|
|
|
std::vector<std::string> const TTrain::fPress_labels = {
|
|
|
|
"ch1: ", "ch2: ", "ch3: ", "ch4: ", "ch5: ", "ch6: ", "ch7: ", "ch8: ", "ch9: ", "ch0: "
|
|
};
|
|
|
|
TTrain::TTrain() {
|
|
/*
|
|
Universal4Active = false;
|
|
*/
|
|
ShowNextCurrent = false;
|
|
// McZapkie-240302 - przyda sie do tachometru
|
|
fTachoVelocity = 0;
|
|
fTachoCount = 0;
|
|
fPPress = fNPress = 0;
|
|
|
|
// asMessage="";
|
|
pMechShake = vector3(0, 0, 0);
|
|
vMechMovement = vector3(0, 0, 0);
|
|
pMechOffset = vector3(0, 0, 0);
|
|
fBlinkTimer = 0;
|
|
fHaslerTimer = 0;
|
|
keybrakecount = 0;
|
|
DynamicSet(NULL); // ustawia wszystkie mv*
|
|
iCabLightFlag = 0;
|
|
// hunter-091012
|
|
bCabLight = false;
|
|
bCabLightDim = false;
|
|
//-----
|
|
pMechSittingPosition = vector3(0, 0, 0); // ABu: 180404
|
|
InstrumentLightActive = false; // ABu: 030405
|
|
dsbNastawnikJazdy = NULL;
|
|
dsbNastawnikBocz = NULL;
|
|
dsbRelay = NULL;
|
|
dsbPneumaticRelay = NULL;
|
|
dsbSwitch = NULL;
|
|
dsbPneumaticSwitch = NULL;
|
|
dsbReverserKey = NULL; // hunter-121211
|
|
dsbCouplerAttach = NULL;
|
|
dsbCouplerDetach = NULL;
|
|
dsbDieselIgnition = NULL;
|
|
dsbDoorClose = NULL;
|
|
dsbDoorOpen = NULL;
|
|
dsbPantUp = NULL;
|
|
dsbPantDown = NULL;
|
|
dsbWejscie_na_bezoporow = NULL;
|
|
dsbWejscie_na_drugi_uklad = NULL; // hunter-081211: poprawka literowki
|
|
dsbHasler = NULL;
|
|
dsbBuzzer = NULL;
|
|
dsbSlipAlarm = NULL; // Bombardier 011010: alarm przy poslizgu dla 181/182
|
|
dsbCouplerStretch = NULL;
|
|
dsbEN57_CouplerStretch = NULL;
|
|
dsbBufferClamp = NULL;
|
|
iRadioChannel = 0;
|
|
fTachoTimer = 0.0; // włączenie skoków wskazań prędkościomierza
|
|
|
|
//
|
|
for( int i = 0; i < 8; i++ ) {
|
|
bMains[ i ] = false;
|
|
fCntVol[ i ] = 0.0f;
|
|
bPants[ i ][ 0 ] = false;
|
|
bPants[ i ][ 1 ] = false;
|
|
bFuse[ i ] = false;
|
|
bBatt[ i ] = false;
|
|
bConv[ i ] = false;
|
|
bComp[ i ][ 0 ] = false;
|
|
bComp[ i ][ 1 ] = false;
|
|
bHeat[ i ] = false;
|
|
}
|
|
for( int i = 0; i < 9; ++i )
|
|
for( int j = 0; j < 10; ++j )
|
|
fEIMParams[ i ][ j ] = 0.0;
|
|
|
|
for( int i = 0; i < 20; ++i )
|
|
for( int j = 0; j < 3; ++j )
|
|
fPress[ i ][ j ] = 0.0;
|
|
}
|
|
|
|
TTrain::~TTrain()
|
|
{
|
|
if (DynamicObject)
|
|
if (DynamicObject->Mechanik)
|
|
DynamicObject->Mechanik->TakeControl(
|
|
true); // likwidacja kabiny wymaga przejęcia przez AI
|
|
|
|
sound_man->destroy_sound(&dsbNastawnikJazdy);
|
|
sound_man->destroy_sound(&dsbNastawnikBocz);
|
|
sound_man->destroy_sound(&dsbRelay);
|
|
sound_man->destroy_sound(&dsbPneumaticRelay);
|
|
sound_man->destroy_sound(&dsbSwitch);
|
|
sound_man->destroy_sound(&dsbPneumaticSwitch);
|
|
sound_man->destroy_sound(&dsbReverserKey);
|
|
sound_man->destroy_sound(&dsbCouplerAttach);
|
|
sound_man->destroy_sound(&dsbCouplerDetach);
|
|
sound_man->destroy_sound(&dsbDieselIgnition);
|
|
sound_man->destroy_sound(&dsbDoorClose);
|
|
sound_man->destroy_sound(&dsbDoorOpen);
|
|
sound_man->destroy_sound(&dsbPantUp);
|
|
sound_man->destroy_sound(&dsbPantDown);
|
|
sound_man->destroy_sound(&dsbWejscie_na_bezoporow);
|
|
sound_man->destroy_sound(&dsbWejscie_na_drugi_uklad);
|
|
sound_man->destroy_sound(&rsBrake);
|
|
sound_man->destroy_sound(&rsSlippery);
|
|
sound_man->destroy_sound(&rsHiss);
|
|
sound_man->destroy_sound(&rsHissU);
|
|
sound_man->destroy_sound(&rsHissE);
|
|
sound_man->destroy_sound(&rsHissX);
|
|
sound_man->destroy_sound(&rsHissT);
|
|
sound_man->destroy_sound(&rsSBHiss);
|
|
sound_man->destroy_sound(&rsRunningNoise);
|
|
sound_man->destroy_sound(&rsEngageSlippery);
|
|
sound_man->destroy_sound(&rsFadeSound);
|
|
sound_man->destroy_sound(&dsbHasler);
|
|
sound_man->destroy_sound(&dsbBuzzer);
|
|
sound_man->destroy_sound(&dsbSlipAlarm);
|
|
sound_man->destroy_sound(&dsbCouplerStretch);
|
|
sound_man->destroy_sound(&dsbEN57_CouplerStretch);
|
|
sound_man->destroy_sound(&dsbBufferClamp);
|
|
}
|
|
|
|
bool TTrain::Init(TDynamicObject *NewDynamicObject, bool e3d)
|
|
{ // powiązanie ręcznego sterowania kabiną z pojazdem
|
|
// Global::pUserDynamic=NewDynamicObject; //pojazd renderowany bez trzęsienia
|
|
DynamicSet(NewDynamicObject);
|
|
if (!e3d)
|
|
if (DynamicObject->Mechanik == NULL)
|
|
return false;
|
|
// if (DynamicObject->Mechanik->AIControllFlag==AIdriver)
|
|
// return false;
|
|
DynamicObject->MechInside = true;
|
|
|
|
/* iPozSzereg=28;
|
|
for (int i=1; i<mvControlled->MainCtrlPosNo; i++)
|
|
{
|
|
if (mvControlled->RList[i].Bn>1)
|
|
{
|
|
iPozSzereg=i-1;
|
|
i=mvControlled->MainCtrlPosNo+1;
|
|
}
|
|
}
|
|
*/
|
|
MechSpring.Init(0.015, 250);
|
|
vMechVelocity = vector3(0, 0, 0);
|
|
pMechOffset = vector3( 0, 0, 0 );
|
|
fMechSpringX = 1;
|
|
fMechSpringY = 0.5;
|
|
fMechSpringZ = 0.5;
|
|
fMechMaxSpring = 0.15;
|
|
fMechRoll = 0.05;
|
|
fMechPitch = 0.1;
|
|
fMainRelayTimer = 0; // Hunter, do k...y nędzy, ustawiaj wartości początkowe zmiennych!
|
|
|
|
if( false == LoadMMediaFile( DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + ".mmd" ) ) {
|
|
return false;
|
|
}
|
|
|
|
// McZapkie: w razie wykolejenia
|
|
// dsbDerailment=TSoundsManager::GetFromName("derail.wav");
|
|
// McZapkie: jazda luzem:
|
|
// dsbRunningNoise=TSoundsManager::GetFromName("runningnoise.wav");
|
|
|
|
// McZapkie? - dzwieki slyszalne tylko wewnatrz kabiny - generowane przez
|
|
// obiekt sterowany:
|
|
|
|
// McZapkie-080302 sWentylatory.Init("wenton.wav","went.wav","wentoff.wav");
|
|
// McZapkie-010302
|
|
// sCompressor.Init("compressor-start.wav","compressor.wav","compressor-stop.wav");
|
|
|
|
// sHorn1.Init("horn1.wav",0.3);
|
|
// sHorn2.Init("horn2.wav",0.3);
|
|
|
|
// sHorn1.Init("horn1-start.wav","horn1.wav","horn1-stop.wav");
|
|
// sHorn2.Init("horn2-start.wav","horn2.wav","horn2-stop.wav");
|
|
|
|
// sConverter.Init("converter.wav",1.5); //NBMX obsluga przez AdvSound
|
|
iCabn = 0;
|
|
// Ra: taka proteza - przesłanie kierunku do członów connected
|
|
if (mvControlled->ActiveDir > 0)
|
|
{ // było do przodu
|
|
mvControlled->DirectionBackward();
|
|
mvControlled->DirectionForward();
|
|
}
|
|
else if (mvControlled->ActiveDir < 0)
|
|
{
|
|
mvControlled->DirectionForward();
|
|
mvControlled->DirectionBackward();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
PyObject *TTrain::GetTrainState() {
|
|
PyObject *dict = PyDict_New();
|
|
if( dict == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
auto const &mover = DynamicObject->MoverParameters;
|
|
|
|
PyDict_SetItemString( dict, "cab", PyGetInt( mover->ActiveCab ) );
|
|
// basic systems state data
|
|
PyDict_SetItemString( dict, "battery", PyGetBool( mvControlled->Battery ) );
|
|
PyDict_SetItemString( dict, "linebreaker", PyGetBool( mvControlled->Mains ) );
|
|
PyDict_SetItemString( dict, "converter", PyGetBool( mover->ConverterFlag ) );
|
|
PyDict_SetItemString( dict, "converter_overload", PyGetBool( mover->ConvOvldFlag ) );
|
|
PyDict_SetItemString( dict, "compress", PyGetBool( mover->CompressorFlag ) );
|
|
// reverser
|
|
PyDict_SetItemString( dict, "direction", PyGetInt( mover->ActiveDir ) );
|
|
// throttle
|
|
PyDict_SetItemString( dict, "mainctrl_pos", PyGetInt( mover->MainCtrlPos ) );
|
|
PyDict_SetItemString( dict, "main_ctrl_actual_pos", PyGetInt( mover->MainCtrlActualPos ) );
|
|
PyDict_SetItemString( dict, "scndctrl_pos", PyGetInt( mover->ScndCtrlPos ) );
|
|
PyDict_SetItemString( dict, "scnd_ctrl_actual_pos", PyGetInt( mover->ScndCtrlActualPos ) );
|
|
// brakes
|
|
PyDict_SetItemString( dict, "manual_brake", PyGetBool( mvOccupied->ManualBrakePos > 0 ) );
|
|
bool const bEP = ( mvControlled->LocHandle->GetCP()>0.2 ) || ( fEIMParams[ 0 ][ 2 ]>0.01 );
|
|
PyDict_SetItemString( dict, "dir_brake", PyGetBool( bEP ) );
|
|
bool bPN;
|
|
if( ( typeid( *mvControlled->Hamulec ) == typeid( TLSt ) )
|
|
|| ( typeid( *mvControlled->Hamulec ) == typeid( TEStED ) ) ) {
|
|
|
|
TBrake* temp_ham = mvControlled->Hamulec.get();
|
|
bPN = ( static_cast<TLSt*>( temp_ham )->GetEDBCP()>0.2 );
|
|
}
|
|
else
|
|
bPN = false;
|
|
PyDict_SetItemString( dict, "indir_brake", PyGetBool( bPN ) );
|
|
// other controls
|
|
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, "pantpress", PyGetFloat( mvControlled->PantPress ) );
|
|
PyDict_SetItemString( dict, "universal3", PyGetBool( InstrumentLightActive ) );
|
|
// movement data
|
|
PyDict_SetItemString( dict, "velocity", PyGetFloat( mover->Vel ) );
|
|
PyDict_SetItemString( dict, "tractionforce", PyGetFloat( mover->Ft ) );
|
|
PyDict_SetItemString( dict, "slipping_wheels", PyGetBool( mover->SlippingWheels ) );
|
|
// electric current data
|
|
PyDict_SetItemString( dict, "traction_voltage", PyGetFloat( mover->RunningTraction.TractionVoltage ) );
|
|
PyDict_SetItemString( dict, "voltage", PyGetFloat( mover->Voltage ) );
|
|
PyDict_SetItemString( dict, "im", PyGetFloat( mover->Im ) );
|
|
PyDict_SetItemString( dict, "fuse", PyGetBool( mover->FuseFlag ) );
|
|
// induction motor state data
|
|
const char* TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
|
|
const char* TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
|
|
const char* TXTP[ 3 ] = { "bc", "bp", "sp" };
|
|
for( int j = 0; j < 10; ++j )
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_t_" ) + std::string( TXTT[ j ] ) ).c_str(), PyGetFloatS( fEIMParams[ 0 ][ j ] ) );
|
|
for( int i = 0; i < 8; ++i ) {
|
|
for( int j = 0; j < 10; ++j )
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_c" ) + std::to_string( i + 1 ) + std::string( "_" ) + std::string( TXTC[ j ] ) ).c_str(), PyGetFloatS( fEIMParams[ i + 1 ][ j ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_c" ) + std::to_string( i + 1 ) + std::string( "_ms" ) ).c_str(), PyGetBool( bMains[ i ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_c" ) + std::to_string( i + 1 ) + std::string( "_cv" ) ).c_str(), PyGetFloatS( fCntVol[ i ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_u" ) + std::to_string( i + 1 ) + std::string( "_pf" ) ).c_str(), PyGetBool( bPants[ i ][ 0 ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_u" ) + std::to_string( i + 1 ) + std::string( "_pr" ) ).c_str(), PyGetBool( bPants[ i ][ 1 ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_c" ) + std::to_string( i + 1 ) + std::string( "_fuse" ) ).c_str(), PyGetBool( bFuse[ i ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_c" ) + std::to_string( i + 1 ) + std::string( "_batt" ) ).c_str(), PyGetBool( bBatt[ i ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_c" ) + std::to_string( i + 1 ) + std::string( "_conv" ) ).c_str(), PyGetBool( bConv[ i ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_u" ) + std::to_string( i + 1 ) + std::string( "_comp_a" ) ).c_str(), PyGetBool( bComp[ i ][ 0 ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_u" ) + std::to_string( i + 1 ) + std::string( "_comp_w" ) ).c_str(), PyGetBool( bComp[ i ][ 1 ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_c" ) + std::to_string( i + 1 ) + std::string( "_heat" ) ).c_str(), PyGetBool( bHeat[ i ] ) );
|
|
|
|
}
|
|
for( int i = 0; i < 20; ++i ) {
|
|
for( int j = 0; j < 3; ++j )
|
|
PyDict_SetItemString( dict, ( std::string( "eimp_pn" ) + std::to_string( i + 1 ) + std::string( "_" ) + std::string( TXTP[ j ] ) ).c_str(),
|
|
PyGetFloatS( fPress[ i ][ j ] ) );
|
|
}
|
|
// multi-unit state data
|
|
PyDict_SetItemString( dict, "car_no", PyGetInt( iCarNo ) );
|
|
PyDict_SetItemString( dict, "power_no", PyGetInt( iPowerNo ) );
|
|
PyDict_SetItemString( dict, "unit_no", PyGetInt( iUnitNo ) );
|
|
|
|
for( int i = 0; i < 20; i++ ) {
|
|
PyDict_SetItemString( dict, ( std::string( "doors_" ) + std::to_string( i + 1 ) ).c_str(), PyGetFloatS( bDoors[ i ][ 0 ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "doors_r_" ) + std::to_string( i + 1 ) ).c_str(), PyGetFloatS( bDoors[ i ][ 1 ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "doors_l_" ) + std::to_string( i + 1 ) ).c_str(), PyGetFloatS( bDoors[ i ][ 2 ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "doors_no_" ) + std::to_string( i + 1 ) ).c_str(), PyGetInt( iDoorNo[ i ] ) );
|
|
PyDict_SetItemString( dict, ( std::string( "code_" ) + std::to_string( i + 1 ) ).c_str(), PyGetString( std::string( std::to_string( iUnits[ i ] ) +
|
|
cCode[ i ] ).c_str() ) );
|
|
PyDict_SetItemString( dict, ( std::string( "car_name" ) + std::to_string( i + 1 ) ).c_str(), PyGetString( asCarName[ i ].c_str() ) );
|
|
}
|
|
// ai state data
|
|
auto const &driver = DynamicObject->Mechanik;
|
|
|
|
PyDict_SetItemString( dict, "velocity_desired", PyGetFloat( driver->VelDesired ) );
|
|
PyDict_SetItemString( dict, "velroad", PyGetFloat( driver->VelRoad ) );
|
|
PyDict_SetItemString( dict, "vellimitlast", PyGetFloat( driver->VelLimitLast ) );
|
|
PyDict_SetItemString( dict, "velsignallast", PyGetFloat( driver->VelSignalLast ) );
|
|
PyDict_SetItemString( dict, "velsignalnext", PyGetFloat( driver->VelSignalNext ) );
|
|
PyDict_SetItemString( dict, "velnext", PyGetFloat( driver->VelNext ) );
|
|
PyDict_SetItemString( dict, "actualproximitydist", PyGetFloat( driver->ActualProximityDist ) );
|
|
PyDict_SetItemString( dict, "trainnumber", PyGetString( driver->TrainName().c_str() ) );
|
|
// world state data
|
|
PyDict_SetItemString( dict, "hours", PyGetInt( simulation::Time.data().wHour ) );
|
|
PyDict_SetItemString( dict, "minutes", PyGetInt( simulation::Time.data().wMinute ) );
|
|
PyDict_SetItemString( dict, "seconds", PyGetInt( simulation::Time.second() ) );
|
|
|
|
return dict;
|
|
}
|
|
|
|
bool TTrain::is_eztoer() const {
|
|
|
|
return
|
|
( ( mvControlled->TrainType == dt_EZT )
|
|
&& ( mvOccupied->BrakeSubsystem == ss_ESt )
|
|
&& ( mvControlled->Battery == true )
|
|
&& ( mvControlled->EpFuse == true )
|
|
&& ( mvControlled->ActiveDir != 0 ) ); // od yB
|
|
}
|
|
|
|
// command handlers
|
|
void TTrain::OnCommand_mastercontrollerincrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// on press or hold
|
|
Train->mvControlled->IncMainCtrl( 1 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_mastercontrollerincreasefast( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// on press or hold
|
|
Train->mvControlled->IncMainCtrl( 2 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_mastercontrollerdecrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// on press or hold
|
|
Train->mvControlled->DecMainCtrl( 1 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_mastercontrollerdecreasefast( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// on press or hold
|
|
Train->mvControlled->DecMainCtrl( 2 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_secondcontrollerincrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// on press or hold
|
|
if( Train->mvControlled->ShuntMode ) {
|
|
Train->mvControlled->AnPos += ( Command.time_delta * 0.75f );
|
|
if( Train->mvControlled->AnPos > 1 )
|
|
Train->mvControlled->AnPos = 1;
|
|
}
|
|
else {
|
|
Train->mvControlled->IncScndCtrl( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_secondcontrollerincreasefast( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// on press or hold
|
|
Train->mvControlled->IncScndCtrl( 2 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_notchingrelaytoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->mvOccupied->AutoRelayFlag ) {
|
|
// turn on
|
|
Train->mvOccupied->AutoRelaySwitch( true );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->mvOccupied->AutoRelaySwitch( false );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_mucurrentindicatorothersourceactivate( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->ggNextCurrentButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Current Indicator Source switch is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// turn on
|
|
Train->ShowNextCurrent = true;
|
|
// visual feedback
|
|
Train->ggNextCurrentButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
//turn off
|
|
Train->ShowNextCurrent = false;
|
|
// visual feedback
|
|
Train->ggNextCurrentButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_secondcontrollerdecrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// on press or hold
|
|
if( Train->mvControlled->ShuntMode ) {
|
|
Train->mvControlled->AnPos -= ( Command.time_delta * 0.75f );
|
|
if( Train->mvControlled->AnPos > 1 )
|
|
Train->mvControlled->AnPos = 1;
|
|
}
|
|
Train->mvControlled->DecScndCtrl( 1 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_secondcontrollerdecreasefast( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// on press or hold
|
|
Train->mvControlled->DecScndCtrl( 2 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_independentbrakeincrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
|
|
if( Train->mvOccupied->LocalBrake != ManualBrake ) {
|
|
Train->mvOccupied->IncLocalBrakeLevel( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_independentbrakeincreasefast( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
|
|
if( Train->mvOccupied->LocalBrake != ManualBrake ) {
|
|
Train->mvOccupied->IncLocalBrakeLevel( 2 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_independentbrakedecrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
|
|
if( ( Train->mvOccupied->LocalBrake != ManualBrake )
|
|
// Ra 1014-06: AI potrafi zahamować pomocniczym mimo jego braku - odhamować jakoś trzeba
|
|
// TODO: sort AI out so it doesn't do things it doesn't have equipment for
|
|
|| ( Train->mvOccupied->LocalBrakePos != 0 ) ) {
|
|
Train->mvOccupied->DecLocalBrakeLevel( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_independentbrakedecreasefast( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
|
|
if( ( Train->mvOccupied->LocalBrake != ManualBrake )
|
|
// Ra 1014-06: AI potrafi zahamować pomocniczym mimo jego braku - odhamować jakoś trzeba
|
|
// TODO: sort AI out so it doesn't do things it doesn't have equipment for
|
|
|| ( Train->mvOccupied->LocalBrakePos != 0 ) ) {
|
|
Train->mvOccupied->DecLocalBrakeLevel( 2 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_independentbrakebailoff( TTrain *Train, command_data const &Command ) {
|
|
// TODO: check if this set of conditions can be simplified.
|
|
// it'd be more flexible to have an attribute indicating whether bail off position is supported
|
|
if( ( Train->mvControlled->TrainType != dt_EZT )
|
|
&& ( ( Train->mvControlled->EngineType == ElectricSeriesMotor )
|
|
|| ( Train->mvControlled->EngineType == DieselElectric )
|
|
|| ( Train->mvControlled->EngineType == ElectricInductionMotor ) )
|
|
&& ( Train->mvOccupied->BrakeCtrlPosNo > 0 ) ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// press or hold
|
|
Train->mvOccupied->BrakeReleaser( 1 );
|
|
// visual feedback
|
|
Train->ggReleaserButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// release
|
|
Train->mvOccupied->BrakeReleaser( 0 );
|
|
// visual feedback
|
|
Train->ggReleaserButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_trainbrakeincrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
|
|
if( Train->mvOccupied->BrakeHandle == FV4a ) {
|
|
Train->mvOccupied->BrakeLevelAdd( 0.1 /*15.0 * Command.time_delta*/ );
|
|
}
|
|
else {
|
|
if( Train->mvOccupied->BrakeLevelAdd( Global::fBrakeStep ) ) {
|
|
// nieodpowiedni warunek; true, jeśli można dalej kręcić
|
|
Train->keybrakecount = 0;
|
|
if( ( Train->is_eztoer() ) && ( Train->mvOccupied->BrakeCtrlPos < 3 ) ) {
|
|
// Ra: uzależnić dźwięk od zmiany stanu EP, nie od klawisza
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_trainbrakedecrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// press or hold
|
|
if( Train->mvOccupied->BrakeHandle == FV4a ) {
|
|
Train->mvOccupied->BrakeLevelAdd( -0.1 /*-15.0 * Command.time_delta*/ );
|
|
}
|
|
else {
|
|
// nową wersję dostarczył ZiomalCl ("fixed looped sound in ezt when using NUM_9 key")
|
|
if( ( Train->mvOccupied->BrakeCtrlPos > -1 )
|
|
|| ( Train->keybrakecount > 1 ) ) {
|
|
|
|
if( ( Train->is_eztoer() )
|
|
&& ( Train->mvControlled->Mains )
|
|
&& ( Train->mvOccupied->BrakeCtrlPos != -1 ) ) {
|
|
// Ra: uzależnić dźwięk od zmiany stanu EP, nie od klawisza
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
}
|
|
Train->mvOccupied->BrakeLevelAdd( -Global::fBrakeStep );
|
|
}
|
|
else
|
|
Train->keybrakecount += 1;
|
|
// koniec wersji dostarczonej przez ZiomalCl
|
|
}
|
|
}
|
|
else {
|
|
// release
|
|
if( ( Train->mvOccupied->BrakeCtrlPos == -1 )
|
|
&& ( Train->mvOccupied->BrakeHandle == FVel6 )
|
|
&& ( Train->DynamicObject->Controller != AIdriver )
|
|
&& ( Global::iFeedbackMode != 4 ) ) {
|
|
// Odskakiwanie hamulce EP
|
|
Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->BrakeCtrlPos + 1 );
|
|
Train->keybrakecount = 0;
|
|
if( ( Train->mvOccupied->TrainType == dt_EZT )
|
|
&& ( Train->mvControlled->Mains )
|
|
&& ( Train->mvControlled->ActiveDir != 0 ) ) {
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_trainbrakecharging( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// press or hold
|
|
// sound feedback
|
|
if( ( Train->is_eztoer() )
|
|
&& ( Train->mvControlled->Mains )
|
|
&& ( Train->mvOccupied->BrakeCtrlPos != -1 ) ) {
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
}
|
|
|
|
Train->mvOccupied->BrakeLevelSet( -1 );
|
|
}
|
|
else {
|
|
// release
|
|
if( ( Train->mvOccupied->BrakeCtrlPos == -1 )
|
|
&& ( Train->mvOccupied->BrakeHandle == FVel6 )
|
|
&& ( Train->DynamicObject->Controller != AIdriver )
|
|
&& ( Global::iFeedbackMode != 4 ) ) {
|
|
// Odskakiwanie hamulce EP
|
|
Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->BrakeCtrlPos + 1 );
|
|
Train->keybrakecount = 0;
|
|
if( ( Train->mvOccupied->TrainType == dt_EZT )
|
|
&& ( Train->mvControlled->Mains )
|
|
&& ( Train->mvControlled->ActiveDir != 0 ) ) {
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_trainbrakerelease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
|
|
// sound feedback
|
|
if( ( Train->is_eztoer() )
|
|
&& ( ( Train->mvOccupied->BrakeCtrlPos == 1 )
|
|
|| ( Train->mvOccupied->BrakeCtrlPos == -1 ) ) ) {
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
}
|
|
|
|
Train->mvOccupied->BrakeLevelSet( 0 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_trainbrakefirstservice( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
|
|
// sound feedback
|
|
if( ( Train->is_eztoer() )
|
|
&& ( Train->mvControlled->Mains )
|
|
&& ( Train->mvOccupied->BrakeCtrlPos != 1 ) ) {
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
}
|
|
|
|
Train->mvOccupied->BrakeLevelSet( 1 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_trainbrakeservice( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
|
|
// sound feedback
|
|
if( ( Train->is_eztoer() )
|
|
&& ( Train->mvControlled->Mains )
|
|
&& ( ( Train->mvOccupied->BrakeCtrlPos == 1 )
|
|
|| ( Train->mvOccupied->BrakeCtrlPos == -1 ) ) ) {
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
}
|
|
|
|
Train->mvOccupied->BrakeLevelSet(
|
|
Train->mvOccupied->BrakeCtrlPosNo / 2
|
|
+ ( Train->mvOccupied->BrakeHandle == FV4a ?
|
|
1 :
|
|
0 ) );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_trainbrakefullservice( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
|
|
// sound feedback
|
|
if( ( Train->is_eztoer() )
|
|
&& ( Train->mvControlled->Mains )
|
|
&& ( ( Train->mvOccupied->BrakeCtrlPos == 1 )
|
|
|| ( Train->mvOccupied->BrakeCtrlPos == -1 ) ) ) {
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
}
|
|
Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->BrakeCtrlPosNo - 1 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_trainbrakeemergency( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
|
|
Train->mvOccupied->BrakeLevelSet( Train->mvOccupied->Handle->GetPos( bh_EB ) );
|
|
/*
|
|
if( Train->mvOccupied->BrakeCtrlPosNo <= 0.1 ) {
|
|
// hamulec bezpieczeństwa dla wagonów
|
|
Train->mvOccupied->RadioStopFlag = true;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_manualbrakeincrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
|
|
if( ( Train->mvOccupied->LocalBrake == ManualBrake )
|
|
|| ( Train->mvOccupied->MBrake == true ) ) {
|
|
|
|
Train->mvOccupied->IncManualBrakeLevel( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_manualbrakedecrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
|
|
if( ( Train->mvOccupied->LocalBrake == ManualBrake )
|
|
|| ( Train->mvOccupied->MBrake == true ) ) {
|
|
|
|
Train->mvOccupied->DecManualBrakeLevel( 1 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_alarmchaintoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
|
|
if( false == Train->mvOccupied->AlarmChainFlag ) {
|
|
// pull
|
|
Train->mvOccupied->AlarmChainSwitch( true );
|
|
// visual feedback
|
|
Train->ggAlarmChain.UpdateValue( 1.0 );
|
|
}
|
|
else {
|
|
// release
|
|
Train->mvOccupied->AlarmChainSwitch( false );
|
|
// visual feedback
|
|
Train->ggAlarmChain.UpdateValue( 0.0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_wheelspinbrakeactivate( TTrain *Train, command_data const &Command ) {
|
|
|
|
// TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels
|
|
if( Train->ggAntiSlipButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Wheelspin Brake button is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
if( Train->mvOccupied->BrakeSystem == ElectroPneumatic ) {
|
|
return;
|
|
}
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// press or hold
|
|
Train->mvControlled->AntiSlippingBrake();
|
|
// visual feedback
|
|
Train->ggAntiSlipButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// release
|
|
/*
|
|
// audio feedback
|
|
if( Train->ggAntiSlipButton.GetValue() > 0.5 ) {
|
|
Train->play_sound( Train->dsbSwitch );
|
|
}
|
|
*/
|
|
// visual feedback
|
|
Train->ggAntiSlipButton.UpdateValue( 0.0 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_sandboxactivate( TTrain *Train, command_data const &Command ) {
|
|
|
|
// TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels
|
|
if( Train->ggSandButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Sandbox activation button is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// press
|
|
Train->mvControlled->Sandbox( true );
|
|
// visual feedback
|
|
Train->ggSandButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else if( Command.action == GLFW_RELEASE) {
|
|
// release
|
|
Train->mvControlled->Sandbox( false );
|
|
/*
|
|
// audio feedback
|
|
if( Train->ggAntiSlipButton.GetValue() > 0.5 ) {
|
|
Train->play_sound( Train->dsbSwitch );
|
|
}
|
|
*/
|
|
// visual feedback
|
|
Train->ggSandButton.UpdateValue( 0.0 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_epbrakecontroltoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->mvOccupied->EpFuse ) {
|
|
// turn on
|
|
if( Train->mvOccupied->EpFuseSwitch( true ) ) {
|
|
// audio feedback
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
// visual feedback
|
|
// NOTE: there's no button for ep brake control switch
|
|
// TBD, TODO: add ep brake control switch?
|
|
}
|
|
}
|
|
else {
|
|
//turn off
|
|
if( Train->mvOccupied->EpFuseSwitch( false ) ) {
|
|
// audio feedback
|
|
Train->play_sound( Train->dsbPneumaticSwitch );
|
|
// visual feedback
|
|
// NOTE: there's no button for ep brake control switch
|
|
// TBD, TODO: add ep brake control switch?
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_brakeactingspeedincrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
if( ( Train->mvOccupied->BrakeDelayFlag & bdelay_M ) != 0 ) {
|
|
// can't speed it up any more than this
|
|
return;
|
|
}
|
|
auto const fasterbrakesetting = (
|
|
Train->mvOccupied->BrakeDelayFlag < bdelay_R ?
|
|
Train->mvOccupied->BrakeDelayFlag << 1 :
|
|
Train->mvOccupied->BrakeDelayFlag | bdelay_M );
|
|
if( true == Train->mvOccupied->BrakeDelaySwitch( fasterbrakesetting ) ) {
|
|
// visual feedback
|
|
if( Train->ggBrakeProfileCtrl.SubModel != nullptr ) {
|
|
Train->ggBrakeProfileCtrl.UpdateValue(
|
|
( ( Train->mvOccupied->BrakeDelayFlag & bdelay_R ) != 0 ?
|
|
2.0 :
|
|
Train->mvOccupied->BrakeDelayFlag - 1 ),
|
|
Train->dsbSwitch );
|
|
}
|
|
if( Train->ggBrakeProfileG.SubModel != nullptr ) {
|
|
Train->ggBrakeProfileG.UpdateValue(
|
|
( Train->mvOccupied->BrakeDelayFlag == bdelay_G ?
|
|
1.0 :
|
|
0.0 ),
|
|
Train->dsbSwitch );
|
|
}
|
|
if( Train->ggBrakeProfileR.SubModel != nullptr ) {
|
|
Train->ggBrakeProfileR.UpdateValue(
|
|
( ( Train->mvOccupied->BrakeDelayFlag & bdelay_R ) != 0 ?
|
|
1.0 :
|
|
0.0 ),
|
|
Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_brakeactingspeeddecrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
if( Train->mvOccupied->BrakeDelayFlag == bdelay_G ) {
|
|
// can't slow it down any more than this
|
|
return;
|
|
}
|
|
auto const slowerbrakesetting = (
|
|
Train->mvOccupied->BrakeDelayFlag < bdelay_M ?
|
|
Train->mvOccupied->BrakeDelayFlag >> 1 :
|
|
Train->mvOccupied->BrakeDelayFlag ^ bdelay_M );
|
|
if( true == Train->mvOccupied->BrakeDelaySwitch( slowerbrakesetting ) ) {
|
|
// visual feedback
|
|
if( Train->ggBrakeProfileCtrl.SubModel != nullptr ) {
|
|
Train->ggBrakeProfileCtrl.UpdateValue(
|
|
( ( Train->mvOccupied->BrakeDelayFlag & bdelay_R ) != 0 ?
|
|
2.0 :
|
|
Train->mvOccupied->BrakeDelayFlag - 1 ),
|
|
Train->dsbSwitch );
|
|
}
|
|
if( Train->ggBrakeProfileG.SubModel != nullptr ) {
|
|
Train->ggBrakeProfileG.UpdateValue(
|
|
( Train->mvOccupied->BrakeDelayFlag == bdelay_G ?
|
|
1.0 :
|
|
0.0 ),
|
|
Train->dsbSwitch );
|
|
}
|
|
if( Train->ggBrakeProfileR.SubModel != nullptr ) {
|
|
Train->ggBrakeProfileR.UpdateValue(
|
|
( ( Train->mvOccupied->BrakeDelayFlag & bdelay_R ) != 0 ?
|
|
1.0 :
|
|
0.0 ),
|
|
Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_mubrakingindicatortoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->ggSignallingButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Braking Indicator switch is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
if( Train->mvControlled->TrainType != dt_EZT ) {
|
|
//
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->mvControlled->Signalling) {
|
|
// turn on
|
|
Train->mvControlled->Signalling = true;
|
|
// visual feedback
|
|
Train->ggSignallingButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->mvControlled->Signalling = false;
|
|
// visual feedback
|
|
Train->ggSignallingButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_reverserincrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
|
|
if( Train->mvOccupied->DirectionForward() ) {
|
|
// aktualizacja skrajnych pojazdów w składzie
|
|
if( ( Train->mvOccupied->ActiveDir )
|
|
&& ( Train->DynamicObject->Mechanik ) ) {
|
|
|
|
Train->DynamicObject->Mechanik->CheckVehicles( Change_direction );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_reverserdecrease( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
|
|
if( Train->mvOccupied->DirectionBackward() ) {
|
|
// aktualizacja skrajnych pojazdów w składzie
|
|
if( ( Train->mvOccupied->ActiveDir )
|
|
&& ( Train->DynamicObject->Mechanik ) ) {
|
|
|
|
Train->DynamicObject->Mechanik->CheckVehicles( Change_direction );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_alerteracknowledge( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// press or hold
|
|
Train->fCzuwakTestTimer += 0.035f;
|
|
if( Train->CAflag == false ) {
|
|
Train->CAflag = true;
|
|
Train->mvOccupied->SecuritySystemReset();
|
|
}
|
|
else {
|
|
if( Train->fCzuwakTestTimer > 1.0 ) {
|
|
SetFlag( Train->mvOccupied->SecuritySystem.Status, s_CAtest );
|
|
}
|
|
}
|
|
// visual feedback
|
|
Train->ggSecurityResetButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// release
|
|
Train->fCzuwakTestTimer = 0.0f;
|
|
if( TestFlag( Train->mvOccupied->SecuritySystem.Status, s_CAtest ) ) {
|
|
SetFlag( Train->mvOccupied->SecuritySystem.Status, -s_CAtest );
|
|
Train->mvOccupied->s_CAtestebrake = false;
|
|
Train->mvOccupied->SecuritySystem.SystemBrakeCATestTimer = 0.0;
|
|
}
|
|
Train->CAflag = false;
|
|
// visual feedback
|
|
Train->ggSecurityResetButton.UpdateValue( 0.0 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command )
|
|
{
|
|
if (Command.desired_state == command_data::ON && Train->mvOccupied->Battery)
|
|
return;
|
|
if (Command.desired_state == command_data::OFF && !Train->mvOccupied->Battery)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->mvOccupied->Battery ) {
|
|
// turn on
|
|
// wyłącznik jest też w SN61, ewentualnie załączać prąd na stałe z poziomu FIZ
|
|
if( Train->mvOccupied->BatterySwitch( true ) ) {
|
|
// bateria potrzebna np. do zapalenia świateł
|
|
if( Train->ggBatteryButton.SubModel ) {
|
|
Train->ggBatteryButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
// side-effects
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
Train->SetLights();
|
|
}
|
|
if( TestFlag( Train->mvOccupied->SecuritySystem.SystemType, 2 ) ) {
|
|
// Ra: znowu w kabinie jest coś, co być nie powinno!
|
|
SetFlag( Train->mvOccupied->SecuritySystem.Status, s_active );
|
|
SetFlag( Train->mvOccupied->SecuritySystem.Status, s_SHPalarm );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//turn off
|
|
if( Train->mvOccupied->BatterySwitch( false ) ) {
|
|
// ewentualnie zablokować z FIZ, np. w samochodach się nie odłącza akumulatora
|
|
if( Train->ggBatteryButton.SubModel ) {
|
|
Train->ggBatteryButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
// side-effects
|
|
if( false == Train->mvControlled->ConverterFlag ) {
|
|
// if there's no (low voltage) power source left, drop pantographs
|
|
Train->mvControlled->PantFront( false );
|
|
Train->mvControlled->PantRear( false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const &cmd )
|
|
{
|
|
command_data Command = cmd;
|
|
|
|
if (Train->mvOccupied->PantSwitchType != "impulse")
|
|
{
|
|
if (Command.desired_state == Command.ON && Train->mvControlled->PantFrontUp)
|
|
return;
|
|
if (Command.desired_state == Command.OFF && !Train->mvControlled->PantFrontUp)
|
|
return;
|
|
}
|
|
else if (Command.desired_state == Command.OFF)
|
|
Command.action = GLFW_RELEASE;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->mvControlled->PantFrontUp ) {
|
|
// turn on...
|
|
Train->mvControlled->PantFrontSP = false;
|
|
if( Train->mvControlled->PantFront( true ) ) {
|
|
if( Train->mvControlled->PantFrontStart != 1 ) {
|
|
// visual feedback
|
|
if( Train->ggPantFrontButton.SubModel )
|
|
Train->ggPantFrontButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedButton.SubModel )
|
|
Train->ggPantSelectedButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// pantograph control can have two-button setup
|
|
if( Train->ggPantFrontButtonOff.SubModel )
|
|
Train->ggPantFrontButtonOff.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedDownButton.SubModel )
|
|
Train->ggPantSelectedDownButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// ...or turn off
|
|
if( Train->mvOccupied->PantSwitchType == "impulse" ) {
|
|
if( ( Train->ggPantFrontButtonOff.SubModel == nullptr )
|
|
&& ( Train->ggPantSelectedDownButton.SubModel == nullptr ) ) {
|
|
// with impulse buttons we expect a dedicated switch to lower the pantograph, and if the cabin lacks it
|
|
// then another control has to be used (like pantographlowerall)
|
|
// TODO: we should have a way to define presense of cab controls without having to bind these to 3d submodels
|
|
return;
|
|
}
|
|
}
|
|
|
|
Train->mvControlled->PantFrontSP = false;
|
|
if( false == Train->mvControlled->PantFront( false ) ) {
|
|
if( Train->mvControlled->PantFrontStart != 0 ) {
|
|
// visual feedback
|
|
if( Train->ggPantFrontButton.SubModel )
|
|
Train->ggPantFrontButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedButton.SubModel )
|
|
Train->ggPantSelectedButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// pantograph control can have two-button setup
|
|
if( Train->ggPantFrontButtonOff.SubModel )
|
|
Train->ggPantFrontButtonOff.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedDownButton.SubModel )
|
|
Train->ggPantSelectedDownButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// impulse switches return automatically to neutral position
|
|
if( Train->mvOccupied->PantSwitchType == "impulse" ) {
|
|
if( Train->ggPantFrontButton.SubModel )
|
|
Train->ggPantFrontButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedButton.SubModel )
|
|
Train->ggPantSelectedButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// also the switch off button, in cabs which have it
|
|
if( Train->ggPantFrontButtonOff.SubModel )
|
|
Train->ggPantFrontButtonOff.UpdateValue( 0.0, Train->dsbSwitch );
|
|
if( Train->ggPantSelectedDownButton.SubModel ) {
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
Train->ggPantSelectedDownButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &cmd ) {
|
|
command_data Command = cmd;
|
|
|
|
if (Train->mvOccupied->PantSwitchType != "impulse")
|
|
{
|
|
if (Command.desired_state == Command.ON && Train->mvControlled->PantRearUp)
|
|
return;
|
|
if (Command.desired_state == Command.OFF && !Train->mvControlled->PantRearUp)
|
|
return;
|
|
}
|
|
else if (Command.desired_state == Command.OFF)
|
|
Command.action = GLFW_RELEASE;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->mvControlled->PantRearUp ) {
|
|
// turn on...
|
|
Train->mvControlled->PantRearSP = false;
|
|
if( Train->mvControlled->PantRear( true ) ) {
|
|
if( Train->mvControlled->PantRearStart != 1 ) {
|
|
// visual feedback
|
|
if( Train->ggPantRearButton.SubModel )
|
|
Train->ggPantRearButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedButton.SubModel )
|
|
Train->ggPantSelectedButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// pantograph control can have two-button setup
|
|
if( Train->ggPantRearButtonOff.SubModel )
|
|
Train->ggPantRearButtonOff.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedDownButton.SubModel )
|
|
Train->ggPantSelectedDownButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// ...or turn off
|
|
if( Train->mvOccupied->PantSwitchType == "impulse" ) {
|
|
if( ( Train->ggPantRearButtonOff.SubModel == nullptr )
|
|
&& ( Train->ggPantSelectedDownButton.SubModel == nullptr ) ) {
|
|
// with impulse buttons we expect a dedicated switch to lower the pantograph, and if the cabin lacks it
|
|
// then another control has to be used (like pantographlowerall)
|
|
// TODO: we should have a way to define presense of cab controls without having to bind these to 3d submodels
|
|
return;
|
|
}
|
|
}
|
|
|
|
Train->mvControlled->PantRearSP = false;
|
|
if( false == Train->mvControlled->PantRear( false ) ) {
|
|
if( Train->mvControlled->PantRearStart != 0 ) {
|
|
// visual feedback
|
|
if( Train->ggPantRearButton.SubModel )
|
|
Train->ggPantRearButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedButton.SubModel )
|
|
Train->ggPantSelectedButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// pantograph control can have two-button setup
|
|
if( Train->ggPantRearButtonOff.SubModel )
|
|
Train->ggPantRearButtonOff.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedDownButton.SubModel )
|
|
Train->ggPantSelectedDownButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// impulse switches return automatically to neutral position
|
|
if( Train->mvOccupied->PantSwitchType == "impulse" ) {
|
|
if( Train->ggPantRearButton.SubModel )
|
|
Train->ggPantRearButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
if( Train->ggPantSelectedButton.SubModel )
|
|
Train->ggPantSelectedButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// also the switch off button, in cabs which have it
|
|
if( Train->ggPantRearButtonOff.SubModel )
|
|
Train->ggPantRearButtonOff.UpdateValue( 0.0, Train->dsbSwitch );
|
|
if( Train->ggPantSelectedDownButton.SubModel ) {
|
|
// NOTE: currently we animate the selectable pantograph control based on standard key presses
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
Train->ggPantSelectedDownButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_pantographcompressorvalvetoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( ( Train->mvControlled->TrainType == dt_EZT ?
|
|
( Train->mvControlled != Train->mvOccupied ) :
|
|
( Train->mvOccupied->ActiveCab != 0 ) ) ) {
|
|
// tylko w maszynowym
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only react to press
|
|
if( Train->mvControlled->bPantKurek3 == false ) {
|
|
// connect pantographs with primary tank
|
|
Train->mvControlled->bPantKurek3 = true;
|
|
// visual feedback:
|
|
Train->ggPantCompressorValve.UpdateValue( 0.0 );
|
|
}
|
|
else {
|
|
// connect pantograps with pantograph compressor
|
|
Train->mvControlled->bPantKurek3 = false;
|
|
// visual feedback:
|
|
Train->ggPantCompressorValve.UpdateValue( 1.0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_pantographcompressoractivate( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( ( Train->mvControlled->TrainType == dt_EZT ?
|
|
( Train->mvControlled != Train->mvOccupied ) :
|
|
( Train->mvOccupied->ActiveCab != 0 ) ) ) {
|
|
// tylko w maszynowym
|
|
return;
|
|
}
|
|
|
|
if( ( Train->mvControlled->PantPress > 4.8 )
|
|
|| ( false == Train->mvControlled->Battery ) ) {
|
|
// needs live power source and low enough pressure to work
|
|
return;
|
|
}
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// press or hold to activate
|
|
Train->mvControlled->PantCompFlag = true;
|
|
// visual feedback:
|
|
Train->ggPantCompressorButton.UpdateValue( 1.0 );
|
|
}
|
|
else {
|
|
// release to disable
|
|
Train->mvControlled->PantCompFlag = false;
|
|
// visual feedback:
|
|
Train->ggPantCompressorButton.UpdateValue( 0.0 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_pantographlowerall( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( ( Train->ggPantAllDownButton.SubModel == nullptr )
|
|
&& ( Train->ggPantSelectedDownButton.SubModel == nullptr ) ) {
|
|
// TODO: expand definition of cab controls so we can know if the control is present without testing for presence of 3d switch
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Lower All Pantographs switch is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// press the button
|
|
// since we're just lowering all potential pantographs we don't need to test for state and effect
|
|
// front...
|
|
Train->mvControlled->PantFrontSP = false;
|
|
Train->mvControlled->PantFront( false );
|
|
// ...and rear
|
|
Train->mvControlled->PantRearSP = false;
|
|
Train->mvControlled->PantRear( false );
|
|
// visual feedback
|
|
if( Train->ggPantAllDownButton.SubModel )
|
|
Train->ggPantAllDownButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
if( Train->ggPantSelectedDownButton.SubModel ) {
|
|
Train->ggPantSelectedDownButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// release the button
|
|
// visual feedback
|
|
if( Train->ggPantAllDownButton.SubModel )
|
|
Train->ggPantAllDownButton.UpdateValue( 0.0 );
|
|
if( Train->ggPantSelectedDownButton.SubModel ) {
|
|
Train->ggPantSelectedDownButton.UpdateValue( 0.0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_linebreakertoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( ( Command.action == GLFW_PRESS )
|
|
&& ( Train->m_linebreakerstate == 1 )
|
|
&& ( false == Train->mvControlled->Mains )
|
|
&& ( Train->ggMainButton.GetValue() < 0.05 ) ) {
|
|
// crude way to catch cases where the main was knocked out and the user is trying to restart it
|
|
// because the state of the line breaker isn't changed to match, we need to do it here manually
|
|
Train->m_linebreakerstate = 0;
|
|
}
|
|
// NOTE: we don't have switch type definition for the line breaker switch
|
|
// so for the time being we have hard coded "impulse" switches for all EMUs
|
|
// TODO: have proper switch type config for all switches, and put it in the cab switch descriptions, not in the .fiz
|
|
if( ( Train->m_linebreakerstate == 1 )
|
|
&& ( Train->mvControlled->TrainType == dt_EZT ) ) {
|
|
// a single impulse switch can't open the circuit, only close it
|
|
return;
|
|
}
|
|
|
|
if( Command.action != GLFW_RELEASE ) {
|
|
// press or hold...
|
|
if ((Command.desired_state == command_data::TOGGLE && Train->m_linebreakerstate == 0)
|
|
|| Command.desired_state == command_data::ON) {
|
|
// ...to close the circuit
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// fresh press, start fresh closing delay calculation
|
|
Train->fMainRelayTimer = 0.0f;
|
|
}
|
|
if( Train->ggMainOnButton.SubModel != nullptr ) {
|
|
// two separate switches to close and break the circuit
|
|
// visual feedback
|
|
Train->ggMainOnButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else if( Train->ggMainButton.SubModel != nullptr ) {
|
|
// single two-state switch
|
|
// visual feedback
|
|
Train->ggMainButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
// keep track of period the button is held down, to determine when/if circuit closes
|
|
if( ( ( ( Train->mvControlled->EngineType != ElectricSeriesMotor )
|
|
&& ( Train->mvControlled->EngineType != ElectricInductionMotor ) ) )
|
|
|| ( Train->fHVoltage > 0.5 * Train->mvControlled->EnginePowerSource.MaxVoltage ) ) {
|
|
// prevent the switch from working if there's no power
|
|
// TODO: consider whether it makes sense for diesel engines and such
|
|
Train->fMainRelayTimer += 0.33f; // Command.time_delta * 5.0;
|
|
}
|
|
/*
|
|
if( Train->mvControlled->Mains != true ) {
|
|
// hunter-080812: poprawka
|
|
Train->mvControlled->ConverterSwitch( false );
|
|
Train->mvControlled->CompressorSwitch( false );
|
|
}
|
|
*/
|
|
if( Train->fMainRelayTimer > Train->mvControlled->InitialCtrlDelay ) {
|
|
// wlaczanie WSa z opoznieniem
|
|
Train->m_linebreakerstate = 2;
|
|
// for diesels, we complete the engine start here
|
|
// TODO: consider arranging a better way to start the diesel engines
|
|
if( Train->mvControlled->EngineType == DieselEngine ) {
|
|
if( Train->mvControlled->MainSwitch( true ) ) {
|
|
// sound feedback, engine start for diesel vehicle
|
|
Train->play_sound( Train->dsbDieselIgnition );
|
|
// side-effects
|
|
Train->mvControlled->ConverterSwitch( Train->ggConverterButton.GetValue() > 0.5 );
|
|
Train->mvControlled->CompressorSwitch( Train->ggCompressorButton.GetValue() > 0.5 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if ((Command.desired_state == command_data::TOGGLE && Train->m_linebreakerstate == 1)
|
|
|| Command.desired_state == command_data::OFF) {
|
|
// ...to open the circuit
|
|
Train->mvControlled->MainSwitch( false );
|
|
|
|
Train->m_linebreakerstate = -1;
|
|
|
|
if( Train->ggMainOffButton.SubModel != nullptr ) {
|
|
// two separate switches to close and break the circuit
|
|
// visual feedback
|
|
Train->ggMainOffButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else if( Train->ggMainButton.SubModel != nullptr ) {
|
|
// single two-state switch
|
|
{
|
|
// visual feedback
|
|
Train->ggMainButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
|
|
// play sound immediately when the switch is hit, not after release
|
|
if( Train->fMainRelayTimer > 0.0f ) {
|
|
Train->play_sound( Train->dsbRelay );
|
|
Train->fMainRelayTimer = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// release...
|
|
if( Train->m_linebreakerstate <= 0 ) {
|
|
// ...after opening circuit, or holding for too short time to close it
|
|
// hunter-091012: przeniesione z mover.pas, zeby dzwiek sie nie zapetlal,
|
|
if( Train->fMainRelayTimer > 0.0f ) {
|
|
Train->play_sound( Train->dsbRelay );
|
|
Train->fMainRelayTimer = 0.0f;
|
|
}
|
|
// we don't exactly know which of the two buttons was used, so reset both
|
|
// for setup with two separate swiches
|
|
if( Train->ggMainOnButton.SubModel != nullptr ) {
|
|
Train->ggMainOnButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
if( Train->ggMainOffButton.SubModel != nullptr ) {
|
|
Train->ggMainOffButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
// and the two-state switch too, for good measure
|
|
if( Train->ggMainButton.SubModel != nullptr ) {
|
|
// visual feedback
|
|
Train->ggMainButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
// finalize the state of the line breaker
|
|
Train->m_linebreakerstate = 0;
|
|
}
|
|
else {
|
|
// ...after closing the circuit
|
|
// we don't need to start the diesel twice, but the other types still need to be launched
|
|
if( Train->mvControlled->EngineType != DieselEngine ) {
|
|
if( Train->mvControlled->MainSwitch( true ) ) {
|
|
// side-effects
|
|
Train->mvControlled->ConverterSwitch( ( Train->ggConverterButton.GetValue() > 0.5 ) || ( Train->mvControlled->ConverterStart == start::automatic ) );
|
|
Train->mvControlled->CompressorSwitch( Train->ggCompressorButton.GetValue() > 0.5 );
|
|
}
|
|
}
|
|
// visual feedback
|
|
if( Train->ggMainOnButton.SubModel != nullptr ) {
|
|
// setup with two separate switches
|
|
Train->ggMainOnButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
// NOTE: we don't have switch type definition for the line breaker switch
|
|
// so for the time being we have hard coded "impulse" switches for all EMUs
|
|
// TODO: have proper switch type config for all switches, and put it in the cab switch descriptions, not in the .fiz
|
|
if( Train->mvControlled->TrainType == dt_EZT ) {
|
|
if( Train->ggMainButton.SubModel != nullptr ) {
|
|
// visual feedback
|
|
Train->ggMainButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
// finalize the state of the line breaker
|
|
Train->m_linebreakerstate = 1;
|
|
}
|
|
// on button release reset the closing timer, just in case something elsewhere tries to read it
|
|
Train->fMainRelayTimer = 0.0f;
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvControlled->ConverterStart == start::automatic ) {
|
|
// let the automatic thing do its automatic thing...
|
|
return;
|
|
}
|
|
|
|
if (Train->mvControlled->ConverterAllow && Command.desired_state == command_data::ON)
|
|
return;
|
|
if (!Train->mvControlled->ConverterAllow && Command.desired_state == command_data::OFF)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( ( false == Train->mvControlled->ConverterAllow )
|
|
&& ( Train->ggConverterButton.GetValue() < 0.5 ) ) {
|
|
// turn on
|
|
// visual feedback
|
|
Train->ggConverterButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
/*
|
|
if( ( Train->mvControlled->EnginePowerSource.SourceType != CurrentCollector )
|
|
|| ( Train->mvControlled->PantRearVolt != 0.0 )
|
|
|| ( Train->mvControlled->PantFrontVolt != 0.0 ) ) {
|
|
*/
|
|
// impulse type switch has no effect if there's no power
|
|
// NOTE: this is most likely setup wrong, but the whole thing is smoke and mirrors anyway
|
|
if( ( Train->mvOccupied->ConvSwitchType != "impulse" )
|
|
|| ( Train->mvControlled->Mains ) ) {
|
|
// won't start if the line breaker button is still held
|
|
if( true == Train->mvControlled->ConverterSwitch( true ) ) {
|
|
// side effects
|
|
// control the compressor, if it's paired with the converter
|
|
if( Train->mvControlled->CompressorPower == 2 ) {
|
|
// hunter-091012: tak jest poprawnie
|
|
Train->mvControlled->CompressorSwitch( true );
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
}
|
|
*/
|
|
}
|
|
else {
|
|
//turn off
|
|
// visual feedback
|
|
Train->ggConverterButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
if( Train->ggConverterOffButton.SubModel != nullptr ) {
|
|
Train->ggConverterOffButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
if( true == Train->mvControlled->ConverterSwitch( false ) ) {
|
|
// side effects
|
|
// control the compressor, if it's paired with the converter
|
|
if( Train->mvControlled->CompressorPower == 2 ) {
|
|
// hunter-091012: tak jest poprawnie
|
|
Train->mvControlled->CompressorSwitch( false );
|
|
}
|
|
if( ( Train->mvControlled->TrainType == dt_EZT )
|
|
&& ( !TestFlag( Train->mvControlled->EngDmgFlag, 4 ) ) ) {
|
|
Train->mvControlled->ConvOvldFlag = false;
|
|
}
|
|
// if there's no (low voltage) power source left, drop pantographs
|
|
if( false == Train->mvControlled->Battery ) {
|
|
Train->mvControlled->PantFront( false );
|
|
Train->mvControlled->PantRear( false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// on button release...
|
|
if( Train->mvOccupied->ConvSwitchType == "impulse" ) {
|
|
// ...return switches to start position if applicable
|
|
Train->ggConverterButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
Train->ggConverterOffButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_convertertogglelocal( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->ConverterStart == start::automatic ) {
|
|
// let the automatic thing do its automatic thing...
|
|
return;
|
|
}
|
|
if( Train->ggConverterLocalButton.SubModel == nullptr ) {
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( ( false == Train->mvOccupied->ConverterAllowLocal )
|
|
&& ( Train->ggConverterLocalButton.GetValue() < 0.5 ) ) {
|
|
// turn on
|
|
// visual feedback
|
|
Train->ggConverterLocalButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// effect
|
|
Train->mvOccupied->ConverterAllowLocal = true;
|
|
/*
|
|
if( true == Train->mvControlled->ConverterSwitch( true, range::local ) ) {
|
|
// side effects
|
|
// control the compressor, if it's paired with the converter
|
|
if( Train->mvControlled->CompressorPower == 2 ) {
|
|
// hunter-091012: tak jest poprawnie
|
|
Train->mvControlled->CompressorSwitch( true, range::local );
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
else {
|
|
//turn off
|
|
// visual feedback
|
|
Train->ggConverterLocalButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// effect
|
|
Train->mvOccupied->ConverterAllowLocal = false;
|
|
/*
|
|
if( true == Train->mvControlled->ConverterSwitch( false, range::local ) ) {
|
|
// side effects
|
|
// control the compressor, if it's paired with the converter
|
|
if( Train->mvControlled->CompressorPower == 2 ) {
|
|
// hunter-091012: tak jest poprawnie
|
|
Train->mvControlled->CompressorSwitch( false, range::local );
|
|
}
|
|
// if there's no (low voltage) power source left, drop pantographs
|
|
if( false == Train->mvControlled->Battery ) {
|
|
Train->mvControlled->PantFront( false, range::local );
|
|
Train->mvControlled->PantRear( false, range::local );
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_converteroverloadrelayreset( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->ggConverterFuseButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Converter Overload Relay Reset button is missing, or wasn't defined" );
|
|
}
|
|
// return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// press
|
|
if( ( Train->mvControlled->Mains == false )
|
|
&& ( Train->ggConverterButton.GetValue() < 0.05 )
|
|
&& ( Train->mvControlled->TrainType != dt_EZT ) ) {
|
|
Train->mvControlled->ConvOvldFlag = false;
|
|
}
|
|
// visual feedback
|
|
Train->ggConverterFuseButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// release
|
|
// visual feedback
|
|
Train->ggConverterFuseButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_compressortoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvControlled->CompressorPower >= 2 ) {
|
|
return;
|
|
}
|
|
|
|
if (Train->mvControlled->CompressorAllow && Command.desired_state == command_data::ON)
|
|
return;
|
|
if (!Train->mvControlled->CompressorAllow && Command.desired_state == command_data::OFF)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->mvControlled->CompressorAllow ) {
|
|
// turn on
|
|
// visual feedback
|
|
Train->ggCompressorButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// impulse type switch has no effect if there's no power
|
|
// NOTE: this is most likely setup wrong, but the whole thing is smoke and mirrors anyway
|
|
// (we're presuming impulse type switch for all EMUs for the time being)
|
|
// if( ( mvControlled->TrainType != dt_EZT )
|
|
// || ( mvControlled->Mains ) ) {
|
|
|
|
Train->mvControlled->CompressorSwitch( true );
|
|
// }
|
|
}
|
|
else {
|
|
//turn off
|
|
if( true == Train->mvControlled->CompressorSwitch( false ) ) {
|
|
// NOTE: we don't have switch type definition for the compresor switch
|
|
// so for the time being we have hard coded "impulse" switches for all EMUs
|
|
// TODO: have proper switch type config for all switches, and put it in the cab switch descriptions, not in the .fiz
|
|
// if( mvControlled->TrainType == dt_EZT ) {
|
|
// // visual feedback
|
|
// ggCompressorButton.UpdateValue( 1.0 );
|
|
// }
|
|
// else {
|
|
// visual feedback
|
|
Train->ggCompressorButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
// disabled because EMUs have basic switches. left in case impulse switch code is needed, so we don't have to reinvent the wheel
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// on button release...
|
|
// TODO: check if compressor switch is two-state or impulse type
|
|
// NOTE: we don't have switch type definition for the compresor switch
|
|
// so for the time being we have hard coded "impulse" switches for all EMUs
|
|
// TODO: have proper switch type config for all switches, and put it in the cab switch descriptions, not in the .fiz
|
|
if( mvControlled->TrainType == dt_EZT ) {
|
|
if( ggCompressorButton.SubModel != nullptr ) {
|
|
ggCompressorButton.UpdateValue( 0.0 );
|
|
// audio feedback
|
|
play_sound( dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
void TTrain::OnCommand_compressortogglelocal( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->CompressorPower >= 2 ) {
|
|
return;
|
|
}
|
|
if( Train->ggCompressorLocalButton.SubModel == nullptr ) {
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->mvOccupied->CompressorAllowLocal ) {
|
|
// turn on
|
|
// visual feedback
|
|
Train->ggCompressorLocalButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// effect
|
|
Train->mvOccupied->CompressorAllowLocal = true;
|
|
}
|
|
else {
|
|
// turn off
|
|
// visual feedback
|
|
Train->ggCompressorLocalButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
// effect
|
|
Train->mvOccupied->CompressorAllowLocal = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_motorconnectorsopen( TTrain *Train, command_data const &cmd ) {
|
|
command_data Command = cmd;
|
|
// TODO: don't rely on presense of 3d model to determine presence of the switch
|
|
if( Train->ggStLinOffButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Open Motor Power Connectors button is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (Train->mvControlled->StLinSwitchType == "toggle")
|
|
{
|
|
if (Command.desired_state == Command.ON && Train->mvControlled->StLinSwitchOff)
|
|
return;
|
|
if (Command.desired_state == Command.OFF && !Train->mvControlled->StLinSwitchOff)
|
|
return;
|
|
}
|
|
else if (Command.desired_state == Command.OFF)
|
|
Command.action = GLFW_RELEASE;
|
|
|
|
// NOTE: because we don't have modeled actual circuits this is a simplification of the real mechanics
|
|
// namely, pressing the button will flip it in the entire unit, which isn't exactly physically possible
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// button works while it's held down but we can only pay attention to initial press
|
|
if( false == Train->mvControlled->StLinSwitchOff ) {
|
|
// open the connectors
|
|
Train->mvControlled->StLinSwitchOff = true;
|
|
if( ( Train->mvControlled->TrainType == dt_ET41 )
|
|
|| ( Train->mvControlled->TrainType == dt_ET42 ) ) {
|
|
// crude implementation of the butto affecting entire unit for multi-unit engines
|
|
// TODO: rework it into part of standard command propagation system
|
|
if( ( Train->mvControlled->Couplers[ 0 ].Connected != nullptr )
|
|
&& ( true == TestFlag( Train->mvControlled->Couplers[ 0 ].CouplingFlag, coupling::permanent ) ) ) {
|
|
// the first unit isn't allowed to start its compressor until second unit can start its own as well
|
|
Train->mvControlled->Couplers[ 0 ].Connected->StLinSwitchOff = true;
|
|
}
|
|
if( ( Train->mvControlled->Couplers[ 1 ].Connected != nullptr )
|
|
&& ( true == TestFlag( Train->mvControlled->Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) {
|
|
// the first unit isn't allowed to start its compressor until second unit can start its own as well
|
|
Train->mvControlled->Couplers[ 1 ].Connected->StLinSwitchOff = true;
|
|
}
|
|
}
|
|
// visual feedback
|
|
Train->ggStLinOffButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// effect
|
|
if( true == Train->mvControlled->StLinFlag ) {
|
|
Train->play_sound( Train->dsbRelay );
|
|
}
|
|
// yBARC - zmienione na przeciwne, bo true to zalaczone
|
|
Train->mvControlled->StLinFlag = false;
|
|
if( ( Train->mvControlled->TrainType == dt_ET41 )
|
|
|| ( Train->mvControlled->TrainType == dt_ET42 ) ) {
|
|
// crude implementation of the butto affecting entire unit for multi-unit engines
|
|
// TODO: rework it into part of standard command propagation system
|
|
if( ( Train->mvControlled->Couplers[ 0 ].Connected != nullptr )
|
|
&& ( true == TestFlag( Train->mvControlled->Couplers[ 0 ].CouplingFlag, coupling::permanent ) ) ) {
|
|
// the first unit isn't allowed to start its compressor until second unit can start its own as well
|
|
Train->mvControlled->Couplers[ 0 ].Connected->StLinFlag = false;
|
|
}
|
|
if( ( Train->mvControlled->Couplers[ 1 ].Connected != nullptr )
|
|
&& ( true == TestFlag( Train->mvControlled->Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) {
|
|
// the first unit isn't allowed to start its compressor until second unit can start its own as well
|
|
Train->mvControlled->Couplers[ 1 ].Connected->StLinFlag = false;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if( Train->mvControlled->StLinSwitchType == "toggle" ) {
|
|
// default type of button (impulse) has only one effect on press, but the toggle type can toggle the state
|
|
Train->mvControlled->StLinSwitchOff = false;
|
|
if( ( Train->mvControlled->TrainType == dt_ET41 )
|
|
|| ( Train->mvControlled->TrainType == dt_ET42 ) ) {
|
|
// crude implementation of the butto affecting entire unit for multi-unit engines
|
|
// TODO: rework it into part of standard command propagation system
|
|
if( ( Train->mvControlled->Couplers[ 0 ].Connected != nullptr )
|
|
&& ( true == TestFlag( Train->mvControlled->Couplers[ 0 ].CouplingFlag, coupling::permanent ) ) ) {
|
|
// the first unit isn't allowed to start its compressor until second unit can start its own as well
|
|
Train->mvControlled->Couplers[ 0 ].Connected->StLinSwitchOff = false;
|
|
}
|
|
if( ( Train->mvControlled->Couplers[ 1 ].Connected != nullptr )
|
|
&& ( true == TestFlag( Train->mvControlled->Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) {
|
|
// the first unit isn't allowed to start its compressor until second unit can start its own as well
|
|
Train->mvControlled->Couplers[ 1 ].Connected->StLinSwitchOff = false;
|
|
}
|
|
}
|
|
// visual feedback
|
|
Train->ggStLinOffButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// button released
|
|
if( Train->mvControlled->StLinSwitchType != "toggle" ) {
|
|
// default button type (impulse) works on button release
|
|
Train->mvControlled->StLinSwitchOff = false;
|
|
if( ( Train->mvControlled->TrainType == dt_ET41 )
|
|
|| ( Train->mvControlled->TrainType == dt_ET42 ) ) {
|
|
// crude implementation of the butto affecting entire unit for multi-unit engines
|
|
// TODO: rework it into part of standard command propagation system
|
|
if( ( Train->mvControlled->Couplers[ 0 ].Connected != nullptr )
|
|
&& ( true == TestFlag( Train->mvControlled->Couplers[ 0 ].CouplingFlag, coupling::permanent ) ) ) {
|
|
// the first unit isn't allowed to start its compressor until second unit can start its own as well
|
|
Train->mvControlled->Couplers[ 0 ].Connected->StLinSwitchOff = false;
|
|
}
|
|
if( ( Train->mvControlled->Couplers[ 1 ].Connected != nullptr )
|
|
&& ( true == TestFlag( Train->mvControlled->Couplers[ 1 ].CouplingFlag, coupling::permanent ) ) ) {
|
|
// the first unit isn't allowed to start its compressor until second unit can start its own as well
|
|
Train->mvControlled->Couplers[ 1 ].Connected->StLinSwitchOff = false;
|
|
}
|
|
}
|
|
// visual feedback
|
|
Train->ggStLinOffButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_motordisconnect( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( ( Train->mvControlled->TrainType == dt_EZT ?
|
|
( Train->mvControlled != Train->mvOccupied ) :
|
|
( Train->mvOccupied->ActiveCab != 0 ) ) ) {
|
|
// tylko w maszynowym
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
Train->mvControlled->CutOffEngine();
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_motoroverloadrelaythresholdtoggle( TTrain *Train, command_data const &Command )
|
|
{
|
|
if (Train->mvControlled->Imax < Train->mvControlled->ImaxHi && Command.desired_state == command_data::OFF)
|
|
return;
|
|
if (!(Train->mvControlled->Imax < Train->mvControlled->ImaxHi) && Command.desired_state == command_data::ON)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( Train->mvControlled->Imax < Train->mvControlled->ImaxHi ) {
|
|
// turn on
|
|
if( true == Train->mvControlled->CurrentSwitch( true ) ) {
|
|
// visual feedback
|
|
Train->ggMaxCurrentCtrl.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
else {
|
|
//turn off
|
|
if( true == Train->mvControlled->CurrentSwitch( false ) ) {
|
|
// visual feedback
|
|
Train->ggMaxCurrentCtrl.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_motoroverloadrelayreset( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->ggFuseButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Motor Overload Relay Reset button is missing, or wasn't defined" );
|
|
}
|
|
// return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// press
|
|
Train->mvControlled->FuseOn();
|
|
// visual feedback
|
|
Train->ggFuseButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// release
|
|
// visual feedback
|
|
Train->ggFuseButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_headlighttoggleleft( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
0 :
|
|
1 );
|
|
|
|
bool current_state = (bool)(Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_left);
|
|
|
|
if (Command.desired_state == command_data::ON && current_state)
|
|
return;
|
|
if (Command.desired_state == command_data::OFF && !current_state)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( !current_state ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_left;
|
|
// visual feedback
|
|
Train->ggLeftLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// if the light is controlled by 3-way switch, disable marker light
|
|
if( Train->ggLeftEndLightButton.SubModel == nullptr ) {
|
|
Train->DynamicObject->iLights[ lightsindex ] &= ~TMoverParameters::light::redmarker_left;
|
|
}
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_left;
|
|
// visual feedback
|
|
Train->ggLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_headlighttoggleright( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
0 :
|
|
1 );
|
|
|
|
bool current_state = (bool)(Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_right);
|
|
|
|
if (Command.desired_state == command_data::ON && current_state)
|
|
return;
|
|
if (Command.desired_state == command_data::OFF && !current_state)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( !current_state ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_right;
|
|
// visual feedback
|
|
Train->ggRightLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
// if the light is controlled by 3-way switch, disable marker light
|
|
if( Train->ggRightEndLightButton.SubModel == nullptr ) {
|
|
Train->DynamicObject->iLights[ lightsindex ] &= ~TMoverParameters::light::redmarker_right;
|
|
}
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_right;
|
|
// visual feedback
|
|
Train->ggRightLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_headlighttoggleupper( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
0 :
|
|
1 );
|
|
|
|
bool current_state = (bool)(Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_upper);
|
|
|
|
if (Command.desired_state == command_data::ON && current_state)
|
|
return;
|
|
if (Command.desired_state == command_data::OFF && !current_state)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( !current_state ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_upper;
|
|
// visual feedback
|
|
Train->ggUpperLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_upper;
|
|
// visual feedback
|
|
Train->ggUpperLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_redmarkertoggleleft( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
0 :
|
|
1 );
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::redmarker_left ) == 0 ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::redmarker_left;
|
|
// visual feedback
|
|
if( Train->ggLeftEndLightButton.SubModel != nullptr ) {
|
|
Train->ggLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch
|
|
// this is crude, but for now will do
|
|
Train->ggLeftLightButton.UpdateValue( -1.0, Train->dsbSwitch );
|
|
// if the light is controlled by 3-way switch, disable the headlight
|
|
Train->DynamicObject->iLights[ lightsindex ] &= ~TMoverParameters::light::headlight_left;
|
|
}
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::redmarker_left;
|
|
// visual feedback
|
|
if( Train->ggLeftEndLightButton.SubModel != nullptr ) {
|
|
Train->ggLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch
|
|
// this is crude, but for now will do
|
|
Train->ggLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_redmarkertoggleright( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
0 :
|
|
1 );
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::redmarker_right ) == 0 ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::redmarker_right;
|
|
// visual feedback
|
|
if( Train->ggRightEndLightButton.SubModel != nullptr ) {
|
|
Train->ggRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch
|
|
// this is crude, but for now will do
|
|
Train->ggRightLightButton.UpdateValue( -1.0, Train->dsbSwitch );
|
|
// if the light is controlled by 3-way switch, disable the headlight
|
|
Train->DynamicObject->iLights[ lightsindex ] &= ~TMoverParameters::light::headlight_right;
|
|
}
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::redmarker_right;
|
|
// visual feedback
|
|
if( Train->ggRightEndLightButton.SubModel != nullptr ) {
|
|
Train->ggRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// we interpret lack of dedicated switch as a sign the light is controlled with 3-way switch
|
|
// this is crude, but for now will do
|
|
Train->ggRightLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_headlighttogglerearleft( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
1 :
|
|
0 );
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_right ) == 0 ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_right;
|
|
// visual feedback
|
|
Train->ggRearLeftLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_right;
|
|
// visual feedback
|
|
Train->ggRearLeftLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_headlighttogglerearright( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
1 :
|
|
0 );
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_left ) == 0 ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_left;
|
|
// visual feedback
|
|
Train->ggRearRightLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_left;
|
|
// visual feedback
|
|
Train->ggRearRightLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_headlighttogglerearupper( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
1 :
|
|
0 );
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_upper ) == 0 ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_upper;
|
|
// visual feedback
|
|
Train->ggRearUpperLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::headlight_upper;
|
|
// visual feedback
|
|
Train->ggRearUpperLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_redmarkertogglerearleft( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
1 :
|
|
0 );
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::redmarker_right ) == 0 ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::redmarker_right;
|
|
// visual feedback
|
|
Train->ggRearLeftEndLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::redmarker_right;
|
|
// visual feedback
|
|
Train->ggRearLeftEndLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_redmarkertogglerearright( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->LightsPosNo > 0 ) {
|
|
// lights are controlled by preset selector
|
|
return;
|
|
}
|
|
|
|
int const lightsindex =
|
|
( Train->mvOccupied->ActiveCab == 1 ?
|
|
1 :
|
|
0 );
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// NOTE: we toggle the light on opposite side, as 'rear right' is 'front left' on the rear end etc
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( ( Train->DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::redmarker_left ) == 0 ) {
|
|
// turn on
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::redmarker_left;
|
|
// visual feedback
|
|
Train->ggRearRightEndLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->iLights[ lightsindex ] ^= TMoverParameters::light::redmarker_left;
|
|
// visual feedback
|
|
Train->ggRearRightEndLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_headlightsdimtoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
// NOTE: the check is disabled, as we're presuming light control is present in every vehicle
|
|
// TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels
|
|
if( Train->ggDimHeadlightsButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Dim Headlights switch is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (Train->DynamicObject->DimHeadlights && Command.desired_state == command_data::ON)
|
|
return;
|
|
if (!Train->DynamicObject->DimHeadlights && Command.desired_state == command_data::OFF)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->DynamicObject->DimHeadlights ) {
|
|
// turn on
|
|
Train->DynamicObject->DimHeadlights = true;
|
|
// visual feedback
|
|
Train->ggDimHeadlightsButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->DynamicObject->DimHeadlights = false;
|
|
// visual feedback
|
|
Train->ggDimHeadlightsButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_interiorlighttoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
// NOTE: the check is disabled, as we're presuming light control is present in every vehicle
|
|
// TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels
|
|
if( Train->ggCabLightButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Interior Light switch is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->bCabLight ) {
|
|
// turn on
|
|
Train->bCabLight = true;
|
|
Train->btCabLight.TurnOn();
|
|
// visual feedback
|
|
Train->ggCabLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->bCabLight = false;
|
|
Train->btCabLight.TurnOff();
|
|
// visual feedback
|
|
Train->ggCabLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_interiorlightdimtoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
// TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels
|
|
if( Train->ggCabLightDimButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Dim Interior Light switch is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (Train->bCabLightDim && Command.desired_state == command_data::ON)
|
|
return;
|
|
if (!Train->bCabLightDim && Command.desired_state == command_data::OFF)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->bCabLightDim ) {
|
|
// turn on
|
|
Train->bCabLightDim = true;
|
|
// visual feedback
|
|
Train->ggCabLightDimButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->bCabLightDim = false;
|
|
// visual feedback
|
|
Train->ggCabLightDimButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_instrumentlighttoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
// NOTE: the check is disabled, as we're presuming light control is present in every vehicle
|
|
// TODO: proper control deviced definition for the interiors, that doesn't hinge of presence of 3d submodels
|
|
if( Train->ggInstrumentLightButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Instrument light switch is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
// NOTE: instrument lighting isn't fully implemented, so we have to rely on the state of the 'button' i.e. light itself
|
|
if( false == Train->InstrumentLightActive ) {
|
|
// turn on
|
|
Train->InstrumentLightActive = true;
|
|
// visual feedback
|
|
Train->ggInstrumentLightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->InstrumentLightActive = false;
|
|
// visual feedback
|
|
Train->ggInstrumentLightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_heatingtoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->ggTrainHeatingButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Train Heating switch is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (Train->mvControlled->Heating && Command.desired_state == command_data::ON)
|
|
return;
|
|
if (!Train->mvControlled->Heating && Command.desired_state == command_data::OFF)
|
|
return;
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( false == Train->mvControlled->Heating ) {
|
|
// turn on
|
|
Train->mvControlled->Heating = true;
|
|
// visual feedback
|
|
Train->ggTrainHeatingButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
//turn off
|
|
Train->mvControlled->Heating = false;
|
|
// visual feedback
|
|
Train->ggTrainHeatingButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
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 &item = Train->ggUniversals[ itemindex ];
|
|
|
|
if( item.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Train generic item " + std::to_string( itemindex ) + " is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the switch doesn't flip back and forth if key is held down
|
|
if( item.GetValue() < 0.25 ) {
|
|
// turn on
|
|
// visual feedback
|
|
item.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// turn off
|
|
// visual feedback
|
|
item.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_doorlocktoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->ggDoorSignallingButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Door Lock switch is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the sound can loop uninterrupted
|
|
if( false == Train->mvControlled->DoorSignalling ) {
|
|
// turn on
|
|
// TODO: check wheter we really need separate flags for this
|
|
Train->mvControlled->DoorSignalling = true;
|
|
Train->mvOccupied->DoorBlocked = true;
|
|
// visual feedback
|
|
Train->ggDoorSignallingButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// turn off
|
|
// TODO: check wheter we really need separate flags for this
|
|
Train->mvControlled->DoorSignalling = false;
|
|
Train->mvOccupied->DoorBlocked = false;
|
|
// visual feedback
|
|
Train->ggDoorSignallingButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_doortoggleleft( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->DoorOpenCtrl != 1 ) {
|
|
return;
|
|
}
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
|
|
if( false == (
|
|
Train->mvOccupied->ActiveCab == 1 ?
|
|
Train->mvOccupied->DoorLeftOpened :
|
|
Train->mvOccupied->DoorRightOpened ) ) {
|
|
// open
|
|
if( Train->mvOccupied->ActiveCab == 1 ) {
|
|
if( Train->mvOccupied->DoorLeft( true ) ) {
|
|
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
Train->play_sound( Train->dsbDoorOpen );
|
|
}
|
|
}
|
|
else {
|
|
// in the rear cab sides are reversed
|
|
if( Train->mvOccupied->DoorRight( true ) ) {
|
|
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
Train->play_sound( Train->dsbDoorOpen );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// close
|
|
if( Train->mvOccupied->ActiveCab == 1 ) {
|
|
if( Train->mvOccupied->DoorLeft( false ) ) {
|
|
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
Train->play_sound( Train->dsbDoorClose );
|
|
}
|
|
}
|
|
else {
|
|
// in the rear cab sides are reversed
|
|
if( Train->mvOccupied->DoorRight( false ) ) {
|
|
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
Train->play_sound( Train->dsbDoorClose );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_doortoggleright( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->mvOccupied->DoorOpenCtrl != 1 ) {
|
|
return;
|
|
}
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// NOTE: test how the door state check works with consists where the occupied vehicle doesn't have opening doors
|
|
if( false == (
|
|
Train->mvOccupied->ActiveCab == 1 ?
|
|
Train->mvOccupied->DoorRightOpened :
|
|
Train->mvOccupied->DoorLeftOpened ) ) {
|
|
// open
|
|
if( Train->mvOccupied->ActiveCab == 1 ) {
|
|
if( Train->mvOccupied->DoorRight( true ) ) {
|
|
Train->ggDoorRightButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
Train->play_sound( Train->dsbDoorOpen );
|
|
}
|
|
}
|
|
else {
|
|
// in the rear cab sides are reversed
|
|
if( Train->mvOccupied->DoorLeft( true ) ) {
|
|
Train->ggDoorLeftButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
Train->play_sound( Train->dsbDoorOpen );
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// close
|
|
if( Train->mvOccupied->ActiveCab == 1 ) {
|
|
if( Train->mvOccupied->DoorRight( false ) ) {
|
|
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
Train->play_sound( Train->dsbDoorClose );
|
|
}
|
|
}
|
|
else {
|
|
// in the rear cab sides are reversed
|
|
if( Train->mvOccupied->DoorLeft( false ) ) {
|
|
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
Train->play_sound( Train->dsbDoorClose );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_departureannounce( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->ggDepartureSignalButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Departure Signal button is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the sound can loop uninterrupted
|
|
if( false == Train->mvControlled->DepartureSignal ) {
|
|
// turn on
|
|
Train->mvControlled->DepartureSignal = true;
|
|
// visual feedback
|
|
Train->ggDepartureSignalButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// turn off
|
|
Train->mvControlled->DepartureSignal = false;
|
|
// visual feedback
|
|
Train->ggDepartureSignalButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_hornlowactivate( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( ( Train->ggHornButton.SubModel == nullptr )
|
|
&& ( Train->ggHornLowButton.SubModel == nullptr ) ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Horn button is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only need to react to press, sound will continue until stopped
|
|
if( false == TestFlag( Train->mvOccupied->WarningSignal, 1 ) ) {
|
|
// turn on
|
|
Train->mvOccupied->WarningSignal |= 1;
|
|
/*
|
|
if( true == TestFlag( Train->mvOccupied->WarningSignal, 2 ) ) {
|
|
// low and high horn are treated as mutually exclusive
|
|
Train->mvControlled->WarningSignal &= ~2;
|
|
}
|
|
*/
|
|
// visual feedback
|
|
Train->ggHornButton.UpdateValue( -1.0 );
|
|
Train->ggHornLowButton.UpdateValue( 1.0 );
|
|
}
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// turn off
|
|
/*
|
|
// NOTE: we turn off both low and high horn, due to unreliability of release event when shift key is involved
|
|
Train->mvOccupied->WarningSignal &= ~( 1 | 2 );
|
|
*/
|
|
Train->mvOccupied->WarningSignal &= ~1;
|
|
// visual feedback
|
|
Train->ggHornButton.UpdateValue( 0.0 );
|
|
Train->ggHornLowButton.UpdateValue( 0.0 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_hornhighactivate( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( ( Train->ggHornButton.SubModel == nullptr )
|
|
&& ( Train->ggHornHighButton.SubModel == nullptr ) ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Horn button is missing, or wasn't defined" );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only need to react to press, sound will continue until stopped
|
|
if( false == TestFlag( Train->mvOccupied->WarningSignal, 2 ) ) {
|
|
// turn on
|
|
Train->mvOccupied->WarningSignal |= 2;
|
|
/*
|
|
if( true == TestFlag( Train->mvOccupied->WarningSignal, 1 ) ) {
|
|
// low and high horn are treated as mutually exclusive
|
|
Train->mvControlled->WarningSignal &= ~1;
|
|
}
|
|
*/
|
|
// visual feedback
|
|
Train->ggHornButton.UpdateValue( 1.0 );
|
|
Train->ggHornHighButton.UpdateValue( 1.0 );
|
|
}
|
|
}
|
|
else if( Command.action == GLFW_RELEASE ) {
|
|
// turn off
|
|
/*
|
|
// NOTE: we turn off both low and high horn, due to unreliability of release event when shift key is involved
|
|
Train->mvOccupied->WarningSignal &= ~( 1 | 2 );
|
|
*/
|
|
Train->mvOccupied->WarningSignal &= ~2;
|
|
// visual feedback
|
|
Train->ggHornButton.UpdateValue( 0.0 );
|
|
Train->ggHornHighButton.UpdateValue( 0.0 );
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_radiotoggle( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Train->ggRadioButton.SubModel == nullptr ) {
|
|
if( Command.action == GLFW_PRESS ) {
|
|
WriteLog( "Radio switch is missing, or wasn't defined" );
|
|
}
|
|
/*
|
|
// NOTE: we ignore the lack of 3d model to allow system reset after receiving radio-stop signal
|
|
return;
|
|
*/
|
|
}
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
// only reacting to press, so the sound can loop uninterrupted
|
|
if( false == Train->mvOccupied->Radio ) {
|
|
// turn on
|
|
Train->mvOccupied->Radio = true;
|
|
// visual feedback
|
|
Train->ggRadioButton.UpdateValue( 1.0, Train->dsbSwitch );
|
|
}
|
|
else {
|
|
// turn off
|
|
Train->mvOccupied->Radio = false;
|
|
// visual feedback
|
|
Train->ggRadioButton.UpdateValue( 0.0, Train->dsbSwitch );
|
|
}
|
|
}
|
|
}
|
|
|
|
void TTrain::OnCommand_radiostoptest( TTrain *Train, command_data const &Command ) {
|
|
|
|
if( Command.action == GLFW_PRESS ) {
|
|
Train->Dynamic()->RadioStop();
|
|
}
|
|
}
|
|
|
|
void TTrain::OnKeyDown(int cKey)
|
|
{ // naciśnięcie klawisza
|
|
bool const isEztOer =
|
|
( ( mvControlled->TrainType == dt_EZT )
|
|
&& ( mvControlled->Battery == true )
|
|
&& ( mvControlled->EpFuse == true )
|
|
&& ( mvOccupied->BrakeSubsystem == ss_ESt )
|
|
&& ( mvControlled->ActiveDir != 0 ) ); // od yB
|
|
|
|
if (Global::shiftState)
|
|
{ // wciśnięty [Shift]
|
|
if( cKey == Global::Keys[ k_BrakeProfile ] ) // McZapkie-240302-B:
|
|
//-----------
|
|
|
|
// przelacznik opoznienia
|
|
// hamowania
|
|
{ // yB://ABu: male poprawki, zeby bylo mozna ustawic dowolny wagon
|
|
int CouplNr = -2;
|
|
if( !FreeFlyModeFlag )
|
|
{
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
if( Global::ctrlState )
|
|
if (mvOccupied->BrakeDelaySwitch(bdelay_R + bdelay_M))
|
|
{
|
|
play_sound( dsbPneumaticRelay );
|
|
}
|
|
else
|
|
;
|
|
else if (mvOccupied->BrakeDelaySwitch(bdelay_P))
|
|
{
|
|
play_sound( dsbPneumaticRelay );
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
TDynamicObject *temp;
|
|
temp = (DynamicObject->ABuScanNearestObject(DynamicObject->GetTrack(), -1, 1500, CouplNr));
|
|
if (temp == NULL)
|
|
{
|
|
CouplNr = -2;
|
|
temp = (DynamicObject->ABuScanNearestObject(DynamicObject->GetTrack(), 1, 1500, CouplNr));
|
|
}
|
|
if (temp)
|
|
{
|
|
if (Global::ctrlState)
|
|
if (temp->MoverParameters->BrakeDelaySwitch(bdelay_R + bdelay_M))
|
|
{
|
|
play_sound( dsbPneumaticRelay );
|
|
}
|
|
else
|
|
;
|
|
else if (temp->MoverParameters->BrakeDelaySwitch(bdelay_P))
|
|
{
|
|
play_sound( dsbPneumaticRelay );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( cKey == GLFW_KEY_Q ) // ze Shiftem - włączenie AI
|
|
{ // McZapkie-240302 - wlaczanie automatycznego pilota (zadziala tylko w
|
|
// trybie debugmode)
|
|
if (DynamicObject->Mechanik)
|
|
{
|
|
if (DebugModeFlag)
|
|
if (DynamicObject->Mechanik->AIControllFlag) //żeby nie trzeba było
|
|
// rozłączać dla
|
|
// zresetowania
|
|
DynamicObject->Mechanik->TakeControl(false);
|
|
DynamicObject->Mechanik->TakeControl(true);
|
|
}
|
|
}
|
|
else if (cKey == Global::Keys[k_UpperSign]) // ABu 060205: światło górne -
|
|
// włączenie
|
|
{
|
|
if (mvOccupied->LightsPosNo > 0) //kręciolek od swiatel
|
|
{
|
|
if ((mvOccupied->LightsPos < mvOccupied->LightsPosNo) || (mvOccupied->LightsWrap))
|
|
{
|
|
mvOccupied->LightsPos++;
|
|
if (mvOccupied->LightsPos > mvOccupied->LightsPosNo)
|
|
{
|
|
mvOccupied->LightsPos = 1;
|
|
}
|
|
play_sound( dsbSwitch );
|
|
SetLights();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else // McZapkie-240302 - klawisze bez shifta
|
|
{
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
if( cKey == Global::Keys[ k_IncLocalBrakeLevel ] )
|
|
{ // Ra 2014-09: w
|
|
// trybie latania
|
|
// obsługa jest w
|
|
// World.cpp
|
|
if (!FreeFlyModeFlag)
|
|
{
|
|
if (Global::ctrlState)
|
|
if ((mvOccupied->LocalBrake == ManualBrake) || (mvOccupied->MBrake == true))
|
|
{
|
|
mvOccupied->IncManualBrakeLevel(1);
|
|
}
|
|
else if (mvOccupied->LocalBrake != ManualBrake)
|
|
mvOccupied->IncLocalBrakeLevel(1);
|
|
}
|
|
}
|
|
else if (cKey == Global::Keys[k_DecLocalBrakeLevel])
|
|
{ // Ra 2014-06: wersja dla
|
|
// swobodnego latania
|
|
// przeniesiona do
|
|
// World.cpp
|
|
if (!FreeFlyModeFlag)
|
|
{
|
|
if (Global::ctrlState)
|
|
if ((mvOccupied->LocalBrake == ManualBrake) || (mvOccupied->MBrake == true))
|
|
mvOccupied->DecManualBrakeLevel(1);
|
|
else // Ra 1014-06: AI potrafi zahamować pomocniczym mimo jego braku -
|
|
// odhamować jakoś trzeba
|
|
if ((mvOccupied->LocalBrake != ManualBrake) || mvOccupied->LocalBrakePos)
|
|
mvOccupied->DecLocalBrakeLevel(1);
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
if (cKey == Global::Keys[k_Brake2]) {
|
|
if (Global::ctrlState)
|
|
mvOccupied->BrakeLevelSet(
|
|
mvOccupied->Handle->GetPos(bh_NP)); // yB: czy ten stos funkcji nie powinien być jako oddzielna funkcja movera?
|
|
}
|
|
else if (cKey == Global::Keys[k_Brake0])
|
|
{
|
|
if (Global::ctrlState)
|
|
{
|
|
mvOccupied->BrakeCtrlPos2 = 0; // wyrownaj kapturek
|
|
}
|
|
}
|
|
if (cKey == Global::Keys[k_BrakeProfile])
|
|
{ // yB://ABu: male poprawki, zeby
|
|
// bylo mozna ustawic dowolny
|
|
// wagon
|
|
int CouplNr = -2;
|
|
if( !FreeFlyModeFlag )
|
|
{
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
if( Global::ctrlState )
|
|
if (mvOccupied->BrakeDelaySwitch(bdelay_R))
|
|
{
|
|
play_sound( dsbPneumaticRelay );
|
|
}
|
|
else
|
|
;
|
|
else if (mvOccupied->BrakeDelaySwitch(bdelay_G))
|
|
{
|
|
play_sound( dsbPneumaticRelay );
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
TDynamicObject *temp;
|
|
temp = (DynamicObject->ABuScanNearestObject(DynamicObject->GetTrack(), -1, 1500, CouplNr));
|
|
if (temp == NULL)
|
|
{
|
|
CouplNr = -2;
|
|
temp = (DynamicObject->ABuScanNearestObject(DynamicObject->GetTrack(), 1, 1500, CouplNr));
|
|
}
|
|
if (temp)
|
|
{
|
|
if (Global::ctrlState)
|
|
if (temp->MoverParameters->BrakeDelaySwitch(bdelay_R))
|
|
{
|
|
play_sound( dsbPneumaticRelay );
|
|
}
|
|
else
|
|
;
|
|
else if (temp->MoverParameters->BrakeDelaySwitch(bdelay_G))
|
|
{
|
|
play_sound( dsbPneumaticRelay );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// McZapkie-240302 - wylaczanie automatycznego pilota (w trybie ~debugmode
|
|
// mozna tylko raz)
|
|
else if (cKey == GLFW_KEY_Q) // bez Shift
|
|
{
|
|
if (DynamicObject->Mechanik)
|
|
DynamicObject->Mechanik->TakeControl(false);
|
|
}
|
|
else if (cKey == Global::Keys[k_CabForward])
|
|
{
|
|
if( !CabChange( 1 ) ) {
|
|
if( TestFlag( DynamicObject->MoverParameters->Couplers[ 0 ].CouplingFlag,
|
|
ctrain_passenger ) ) { // przejscie do nastepnego pojazdu
|
|
Global::changeDynObj = DynamicObject->PrevConnected;
|
|
Global::changeDynObj->MoverParameters->ActiveCab =
|
|
DynamicObject->PrevConnectedNo ? -1 : 1;
|
|
}
|
|
}
|
|
/*
|
|
NOTE: disabled to allow 'prototypical' 'tricking' pantograph compressor to run unattended
|
|
if (DynamicObject->MoverParameters->ActiveCab)
|
|
mvControlled->PantCompFlag = false; // wyjście z maszynowego wyłącza sprężarkę
|
|
*/
|
|
}
|
|
else if (cKey == Global::Keys[k_CabBackward])
|
|
{
|
|
if (!CabChange(-1))
|
|
if (TestFlag(DynamicObject->MoverParameters->Couplers[1].CouplingFlag,
|
|
ctrain_passenger))
|
|
{ // przejscie do poprzedniego
|
|
Global::changeDynObj = DynamicObject->NextConnected;
|
|
Global::changeDynObj->MoverParameters->ActiveCab =
|
|
DynamicObject->NextConnectedNo ? -1 : 1;
|
|
}
|
|
/*
|
|
NOTE: disabled to allow 'prototypical' 'tricking' pantograph compressor to run unattended
|
|
if (DynamicObject->MoverParameters->ActiveCab)
|
|
mvControlled->PantCompFlag =
|
|
false; // wyjście z maszynowego wyłącza sprężarkę pomocniczą
|
|
*/
|
|
}
|
|
else if (cKey == Global::Keys[k_Couple])
|
|
{ // ABu051104: male zmiany, zeby mozna bylo laczyc odlegle wagony
|
|
// da sie zoptymalizowac, ale nie ma na to czasu :(
|
|
if (iCabn > 0)
|
|
{
|
|
if (!FreeFlyModeFlag) // tryb 'kabinowy'
|
|
{ /*
|
|
if (mvControlled->Couplers[iCabn-1].CouplingFlag==0)
|
|
{
|
|
if
|
|
(mvControlled->Attach(iCabn-1,mvControlled->Couplers[iCabn-1].Connected,ctrain_coupler))
|
|
{
|
|
dsbCouplerAttach->SetVolume(DSBVOLUME_MAX);
|
|
dsbCouplerAttach->Play(0,0,0);
|
|
//ABu: aha, a guzik, nie dziala i nie bedzie, a przydalo by sie
|
|
cos takiego:
|
|
//DynamicObject->NextConnected=mvControlled->Couplers[iCabn-1].Connected;
|
|
//DynamicObject->PrevConnected=mvControlled->Couplers[iCabn-1].Connected;
|
|
}
|
|
}
|
|
else
|
|
if
|
|
(!TestFlag(mvControlled->Couplers[iCabn-1].CouplingFlag,ctrain_pneumatic))
|
|
{
|
|
//ABu021104: zeby caly czas bylo widac sprzegi:
|
|
if
|
|
(mvControlled->Attach(iCabn-1,mvControlled->Couplers[iCabn-1].Connected,mvControlled->Couplers[iCabn-1].CouplingFlag+ctrain_pneumatic))
|
|
//if
|
|
(mvControlled->Attach(iCabn-1,mvControlled->Couplers[iCabn-1].Connected,ctrain_pneumatic))
|
|
{
|
|
rsHiss.Play(1,DSBPLAY_LOOPING,true,DynamicObject->GetPosition());
|
|
}
|
|
}*/
|
|
}
|
|
else
|
|
{ // tryb freefly
|
|
int CouplNr = -1; // normalnie żaden ze sprzęgów
|
|
TDynamicObject *tmp;
|
|
tmp = DynamicObject->ABuScanNearestObject(DynamicObject->GetTrack(), 1, 1500, CouplNr);
|
|
if (tmp == nullptr)
|
|
tmp = DynamicObject->ABuScanNearestObject(DynamicObject->GetTrack(), -1, 1500, CouplNr);
|
|
if( ( CouplNr != -1 )
|
|
&& ( tmp != nullptr )
|
|
&& ( tmp->MoverParameters->Couplers[ CouplNr ].Connected != nullptr ) )
|
|
{
|
|
if (tmp->MoverParameters->Couplers[CouplNr].CouplingFlag == 0) // najpierw hak
|
|
{
|
|
if ((tmp->MoverParameters->Couplers[CouplNr].Connected->Couplers[CouplNr].AllowedFlag
|
|
& tmp->MoverParameters->Couplers[CouplNr].AllowedFlag
|
|
& ctrain_coupler) == ctrain_coupler)
|
|
if (tmp->MoverParameters->Attach(
|
|
CouplNr, 2,
|
|
tmp->MoverParameters->Couplers[CouplNr].Connected,
|
|
ctrain_coupler))
|
|
{
|
|
// tmp->MoverParameters->Couplers[CouplNr].Render=true;
|
|
// //podłączony sprzęg będzie widoczny
|
|
if (DynamicObject->Mechanik) // na wszelki wypadek
|
|
DynamicObject->Mechanik->CheckVehicles(Connect); // aktualizacja flag kierunku w składzie
|
|
play_sound( dsbCouplerAttach );
|
|
// one coupling type per key press
|
|
return;
|
|
}
|
|
else
|
|
WriteLog("Mechanical coupling failed.");
|
|
}
|
|
if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_pneumatic)) // pneumatyka
|
|
{
|
|
if ((tmp->MoverParameters->Couplers[CouplNr].Connected->Couplers[CouplNr].AllowedFlag
|
|
& tmp->MoverParameters->Couplers[CouplNr].AllowedFlag
|
|
& ctrain_pneumatic) == ctrain_pneumatic)
|
|
if (tmp->MoverParameters->Attach(
|
|
CouplNr, 2,
|
|
tmp->MoverParameters->Couplers[CouplNr].Connected,
|
|
(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag | ctrain_pneumatic)))
|
|
{
|
|
// TODO: dedicated 'click' sound for connecting cable-type connections
|
|
play_sound( dsbCouplerDetach );
|
|
// rsHiss.Play( 1, DSBPLAY_LOOPING, true, tmp->GetPosition() );
|
|
DynamicObject->SetPneumatic(CouplNr != 0, true); // Ra: to mi się nie podoba !!!!
|
|
tmp->SetPneumatic(CouplNr != 0, true);
|
|
// one coupling type per key press
|
|
return;
|
|
}
|
|
}
|
|
if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_scndpneumatic)) // zasilajacy
|
|
{
|
|
if ((tmp->MoverParameters->Couplers[CouplNr].Connected->Couplers[CouplNr].AllowedFlag
|
|
& tmp->MoverParameters->Couplers[CouplNr].AllowedFlag
|
|
& ctrain_scndpneumatic) == ctrain_scndpneumatic)
|
|
if (tmp->MoverParameters->Attach(
|
|
CouplNr, 2,
|
|
tmp->MoverParameters->Couplers[CouplNr].Connected,
|
|
(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag | ctrain_scndpneumatic)))
|
|
{
|
|
// TODO: dedicated 'click' sound for connecting cable-type connections
|
|
play_sound( dsbCouplerDetach );
|
|
// rsHiss.Play( 1, DSBPLAY_LOOPING, true, tmp->GetPosition() );
|
|
DynamicObject->SetPneumatic( CouplNr != 0, false ); // Ra: to mi się nie podoba !!!!
|
|
tmp->SetPneumatic(CouplNr != 0, false);
|
|
// one coupling type per key press
|
|
return;
|
|
}
|
|
}
|
|
if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_controll)) // ukrotnionko
|
|
{
|
|
if ((tmp->MoverParameters->Couplers[CouplNr].Connected->Couplers[CouplNr].AllowedFlag &
|
|
tmp->MoverParameters->Couplers[CouplNr].AllowedFlag &
|
|
ctrain_controll) == ctrain_controll)
|
|
if (tmp->MoverParameters->Attach(
|
|
CouplNr, 2,
|
|
tmp->MoverParameters->Couplers[CouplNr].Connected,
|
|
(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag | ctrain_controll)))
|
|
{
|
|
// TODO: dedicated 'click' sound for connecting cable-type connections
|
|
play_sound( dsbCouplerAttach );
|
|
// one coupling type per key press
|
|
return;
|
|
}
|
|
}
|
|
if (!TestFlag(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag, ctrain_passenger)) // mostek
|
|
{
|
|
if ((tmp->MoverParameters->Couplers[CouplNr].Connected->Couplers[CouplNr].AllowedFlag &
|
|
tmp->MoverParameters->Couplers[CouplNr].AllowedFlag &
|
|
ctrain_passenger) == ctrain_passenger)
|
|
if (tmp->MoverParameters->Attach(
|
|
CouplNr, 2,
|
|
tmp->MoverParameters->Couplers[CouplNr].Connected,
|
|
(tmp->MoverParameters->Couplers[CouplNr].CouplingFlag | ctrain_passenger)))
|
|
{
|
|
play_sound( dsbCouplerAttach );
|
|
/*
|
|
DynamicObject->SetPneumatic(CouplNr != 0, false);
|
|
tmp->SetPneumatic(CouplNr != 0, false);
|
|
*/
|
|
// one coupling type per key press
|
|
return;
|
|
}
|
|
}
|
|
if( false == TestFlag( tmp->MoverParameters->Couplers[ CouplNr ].CouplingFlag, ctrain_heating ) ) {
|
|
// heating
|
|
if( ( tmp->MoverParameters->Couplers[ CouplNr ].Connected->Couplers[ CouplNr ].AllowedFlag
|
|
& tmp->MoverParameters->Couplers[ CouplNr ].AllowedFlag
|
|
& ctrain_heating ) == ctrain_heating )
|
|
if( tmp->MoverParameters->Attach(
|
|
CouplNr, 2,
|
|
tmp->MoverParameters->Couplers[ CouplNr ].Connected,
|
|
( tmp->MoverParameters->Couplers[ CouplNr ].CouplingFlag | ctrain_heating ) ) ) {
|
|
|
|
// TODO: dedicated 'click' sound for connecting cable-type connections
|
|
play_sound( dsbCouplerAttach );
|
|
// one coupling type per key press
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (cKey == Global::Keys[k_DeCouple])
|
|
{ // ABu051104: male zmiany,
|
|
// zeby mozna bylo rozlaczac
|
|
// odlegle wagony
|
|
if (iCabn > 0)
|
|
{
|
|
if (!FreeFlyModeFlag) // tryb 'kabinowy' (pozwala również rozłączyć sprzęgi zablokowane)
|
|
{
|
|
if (DynamicObject->DettachStatus(iCabn - 1) < 0) // jeśli jest co odczepić
|
|
if (DynamicObject->Dettach(iCabn - 1)) // iCab==1:przód,iCab==2:tył
|
|
{
|
|
play_sound( dsbCouplerDetach ); // w kabinie ten dźwięk?
|
|
}
|
|
}
|
|
else
|
|
{ // tryb freefly
|
|
int CouplNr = -1;
|
|
TDynamicObject *tmp;
|
|
tmp = DynamicObject->ABuScanNearestObject(DynamicObject->GetTrack(), 1, 1500, CouplNr);
|
|
if (tmp == NULL)
|
|
tmp = DynamicObject->ABuScanNearestObject(DynamicObject->GetTrack(), -1, 1500, CouplNr);
|
|
if (tmp && (CouplNr != -1))
|
|
{
|
|
if ((tmp->MoverParameters->Couplers[CouplNr].CouplingFlag & ctrain_depot) == 0) // jeżeli sprzęg niezablokowany
|
|
if (tmp->DettachStatus(CouplNr) < 0) // jeśli jest co odczepić i się da
|
|
if (!tmp->Dettach(CouplNr))
|
|
{ // dźwięk odczepiania
|
|
play_sound( dsbCouplerDetach );
|
|
}
|
|
}
|
|
}
|
|
if( DynamicObject->Mechanik ) {
|
|
// aktualizacja skrajnych pojazdów w składzie
|
|
DynamicObject->Mechanik->CheckVehicles( Disconnect );
|
|
}
|
|
}
|
|
}
|
|
else if (cKey == Global::Keys[k_UpperSign]) // ABu 060205: światło górne -
|
|
// wyłączenie
|
|
{
|
|
if (mvOccupied->LightsPosNo > 0) //kręciolek od swiatel
|
|
{
|
|
if ((mvOccupied->LightsPos > 1) || (mvOccupied->LightsWrap))
|
|
{
|
|
mvOccupied->LightsPos--;
|
|
if (mvOccupied->LightsPos < 1)
|
|
{
|
|
mvOccupied->LightsPos = mvOccupied->LightsPosNo;
|
|
}
|
|
play_sound( dsbSwitch );
|
|
SetLights();
|
|
}
|
|
}
|
|
}
|
|
// else
|
|
if (DebugModeFlag)
|
|
{ // przesuwanie składu o 100m
|
|
TDynamicObject *d = DynamicObject;
|
|
if (cKey == GLFW_KEY_LEFT_BRACKET)
|
|
{
|
|
while (d)
|
|
{
|
|
d->Move(100.0 * d->DirectionGet());
|
|
d = d->Next(); // pozostałe też
|
|
}
|
|
d = DynamicObject->Prev();
|
|
while (d)
|
|
{
|
|
d->Move(100.0 * d->DirectionGet());
|
|
d = d->Prev(); // w drugą stronę też
|
|
}
|
|
}
|
|
else if (cKey == GLFW_KEY_RIGHT_BRACKET)
|
|
{
|
|
while (d)
|
|
{
|
|
d->Move(-100.0 * d->DirectionGet());
|
|
d = d->Next(); // pozostałe też
|
|
}
|
|
d = DynamicObject->Prev();
|
|
while (d)
|
|
{
|
|
d->Move(-100.0 * d->DirectionGet());
|
|
d = d->Prev(); // w drugą stronę też
|
|
}
|
|
}
|
|
}
|
|
if (cKey == GLFW_KEY_MINUS)
|
|
{ // zmniejszenie numeru kanału radiowego
|
|
if (iRadioChannel > 0)
|
|
--iRadioChannel; // 0=wyłączony
|
|
}
|
|
else if (cKey == GLFW_KEY_EQUAL)
|
|
{ // zmniejszenie numeru kanału radiowego
|
|
if (iRadioChannel < 8)
|
|
++iRadioChannel; // 0=wyłączony
|
|
}
|
|
}
|
|
}
|
|
|
|
// cab movement update, fixed step part
|
|
void TTrain::UpdateMechPosition(double dt)
|
|
{ // Ra: mechanik powinien być
|
|
// telepany niezależnie od pozycji
|
|
// pojazdu
|
|
// Ra: trzeba zrobić model bujania głową i wczepić go do pojazdu
|
|
|
|
// DynamicObject->vFront=DynamicObject->GetDirection(); //to jest już
|
|
// policzone
|
|
|
|
// Ra: tu by się przydało uwzględnić rozkład sił:
|
|
// - na postoju horyzont prosto, kabina skosem
|
|
// - przy szybkiej jeździe kabina prosto, horyzont pochylony
|
|
|
|
Math3D::vector3 shake;
|
|
// McZapkie: najpierw policzę pozycję w/m kabiny
|
|
|
|
// ABu: rzucamy kabina tylko przy duzym FPS!
|
|
// Mala histereza, zeby bez przerwy nie przelaczalo przy FPS~17
|
|
// Granice mozna ustalic doswiadczalnie. Ja proponuje 14:20
|
|
double const iVel = std::min( DynamicObject->GetVelocity(), 150.0 );
|
|
|
|
if( !Global::iSlowMotion // musi być pełna prędkość
|
|
&& ( pMechOffset.y < 4.0 ) ) // Ra 15-01: przy oglądaniu pantografu bujanie przeszkadza
|
|
{
|
|
if( iVel > 0.5 ) {
|
|
// acceleration-driven base shake
|
|
shake += 1.25 * MechSpring.ComputateForces(
|
|
vector3(
|
|
-mvControlled->AccN * dt * 5.0, // highlight side sway
|
|
mvControlled->AccV * dt,
|
|
-mvControlled->AccS * dt * 1.25 ), // accent acceleration/deceleration
|
|
pMechShake );
|
|
|
|
if( Random( iVel ) > 25.0 ) {
|
|
// extra shake at increased velocity
|
|
shake += MechSpring.ComputateForces(
|
|
vector3(
|
|
( Random( iVel * 2 ) - iVel ) / ( ( iVel * 2 ) * 4 ) * fMechSpringX,
|
|
( Random( iVel * 2 ) - iVel ) / ( ( iVel * 2 ) * 4 ) * fMechSpringY,
|
|
( Random( iVel * 2 ) - iVel ) / ( ( iVel * 2 ) * 4 ) * fMechSpringZ )
|
|
* 1.25,
|
|
pMechShake );
|
|
// * (( 200 - DynamicObject->MyTrack->iQualityFlag ) * 0.0075 ); // scale to 75-150% based on track quality
|
|
}
|
|
// shake *= 0.85;
|
|
}
|
|
vMechVelocity -= ( shake + vMechVelocity * 100 ) * ( fMechSpringX + fMechSpringY + fMechSpringZ ) / ( 200 );
|
|
// shake *= 0.95 * dt; // shake damping
|
|
|
|
// McZapkie:
|
|
pMechShake += vMechVelocity * dt;
|
|
// Ra 2015-01: dotychczasowe rzucanie
|
|
pMechOffset += vMechMovement * dt;
|
|
if( ( pMechShake.y > fMechMaxSpring ) || ( pMechShake.y < -fMechMaxSpring ) )
|
|
vMechVelocity.y = -vMechVelocity.y;
|
|
// ABu011104: 5*pMechShake.y, zeby ladnie pudlem rzucalo :)
|
|
pMechPosition = pMechOffset + vector3( 1.5 * pMechShake.x, 2.0 * pMechShake.y, 1.5 * pMechShake.z );
|
|
// vMechMovement = 0.5 * vMechMovement;
|
|
}
|
|
else { // hamowanie rzucania przy spadku FPS
|
|
pMechShake -= pMechShake * std::min( dt, 1.0 ); // po tym chyba potrafią zostać jakieś ułamki, które powodują zjazd
|
|
pMechOffset += vMechMovement * dt;
|
|
vMechVelocity.y = 0.5 * vMechVelocity.y;
|
|
pMechPosition = pMechOffset + vector3( pMechShake.x, 5 * pMechShake.y, pMechShake.z );
|
|
// vMechMovement = 0.5 * vMechMovement;
|
|
}
|
|
// numer kabiny (-1: kabina B)
|
|
if( DynamicObject->Mechanik ) // może nie być?
|
|
if( DynamicObject->Mechanik->AIControllFlag ) // jeśli prowadzi AI
|
|
{ // Ra: przesiadka, jeśli AI zmieniło kabinę (a człon?)...
|
|
if( iCabn != ( DynamicObject->MoverParameters->ActiveCab == -1 ?
|
|
2 :
|
|
DynamicObject->MoverParameters->ActiveCab ) )
|
|
InitializeCab( DynamicObject->MoverParameters->ActiveCab,
|
|
DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName +
|
|
".mmd" );
|
|
}
|
|
iCabn = ( DynamicObject->MoverParameters->ActiveCab == -1 ?
|
|
2 :
|
|
DynamicObject->MoverParameters->ActiveCab );
|
|
if( !DebugModeFlag ) { // sprawdzaj więzy //Ra: nie tu!
|
|
if( pMechPosition.x < Cabine[ iCabn ].CabPos1.x )
|
|
pMechPosition.x = Cabine[ iCabn ].CabPos1.x;
|
|
if( pMechPosition.x > Cabine[ iCabn ].CabPos2.x )
|
|
pMechPosition.x = Cabine[ iCabn ].CabPos2.x;
|
|
if( pMechPosition.z < Cabine[ iCabn ].CabPos1.z )
|
|
pMechPosition.z = Cabine[ iCabn ].CabPos1.z;
|
|
if( pMechPosition.z > Cabine[ iCabn ].CabPos2.z )
|
|
pMechPosition.z = Cabine[ iCabn ].CabPos2.z;
|
|
if( pMechPosition.y > Cabine[ iCabn ].CabPos1.y + 1.8 )
|
|
pMechPosition.y = Cabine[ iCabn ].CabPos1.y + 1.8;
|
|
if( pMechPosition.y < Cabine[ iCabn ].CabPos1.y + 0.5 )
|
|
pMechPosition.y = Cabine[ iCabn ].CabPos2.y + 0.5;
|
|
|
|
if( pMechOffset.x < Cabine[ iCabn ].CabPos1.x )
|
|
pMechOffset.x = Cabine[ iCabn ].CabPos1.x;
|
|
if( pMechOffset.x > Cabine[ iCabn ].CabPos2.x )
|
|
pMechOffset.x = Cabine[ iCabn ].CabPos2.x;
|
|
if( pMechOffset.z < Cabine[ iCabn ].CabPos1.z )
|
|
pMechOffset.z = Cabine[ iCabn ].CabPos1.z;
|
|
if( pMechOffset.z > Cabine[ iCabn ].CabPos2.z )
|
|
pMechOffset.z = Cabine[ iCabn ].CabPos2.z;
|
|
if( pMechOffset.y > Cabine[ iCabn ].CabPos1.y + 1.8 )
|
|
pMechOffset.y = Cabine[ iCabn ].CabPos1.y + 1.8;
|
|
if( pMechOffset.y < Cabine[ iCabn ].CabPos1.y + 0.5 )
|
|
pMechOffset.y = Cabine[ iCabn ].CabPos2.y + 0.5;
|
|
}
|
|
};
|
|
|
|
// returns position of the mechanic in the scene coordinates
|
|
vector3
|
|
TTrain::GetWorldMechPosition() {
|
|
|
|
vector3 position = DynamicObject->mMatrix *pMechPosition; // położenie względem środka pojazdu w układzie scenerii
|
|
position += DynamicObject->GetPosition();
|
|
return position;
|
|
}
|
|
|
|
bool TTrain::Update( double const Deltatime )
|
|
{
|
|
// check for sent user commands
|
|
// NOTE: this is a temporary arrangement, for the transition period from old command setup to the new one
|
|
// eventually commands are going to be retrieved directly by the vehicle, filtered through active control stand
|
|
// and ultimately executed, provided the stand allows it.
|
|
command_data commanddata;
|
|
// NOTE: currently we're only storing commands for local vehicle and there's no id system in place,
|
|
// so we're supplying 'default' vehicle id of 0
|
|
while( simulation::Commands.pop( commanddata, static_cast<std::size_t>( command_target::vehicle ) | 0 ) ) {
|
|
|
|
auto lookup = m_commandhandlers.find( commanddata.command );
|
|
if( lookup != m_commandhandlers.end() ) {
|
|
// debug data
|
|
if( commanddata.action != GLFW_RELEASE ) {
|
|
WriteLog( mvOccupied->Name + " received command: [" + simulation::Commands_descriptions[ static_cast<std::size_t>( commanddata.command ) ].name + "]" );
|
|
}
|
|
// pass the command to the assigned handler
|
|
lookup->second( this, commanddata );
|
|
}
|
|
}
|
|
|
|
// update driver's position
|
|
{
|
|
vector3 Vec = Global::pCamera->Velocity * -2.0;// -7.5 * Timer::GetDeltaRenderTime();
|
|
Vec.y = -Vec.y;
|
|
if( mvOccupied->ActiveCab < 0 ) {
|
|
Vec *= -1.0f;
|
|
Vec.y = -Vec.y;
|
|
}
|
|
Vec.RotateY( Global::pCamera->Yaw );
|
|
vMechMovement = Vec;
|
|
}
|
|
|
|
DWORD stat;
|
|
double dt = Deltatime; // Timer::GetDeltaTime();
|
|
|
|
if (DynamicObject->mdKabina)
|
|
{ // Ra: TODO: odczyty klawiatury/pulpitu nie
|
|
// powinny być uzależnione od istnienia modelu
|
|
// kabiny
|
|
tor = DynamicObject->GetTrack(); // McZapkie-180203
|
|
// McZapkie: predkosc wyswietlana na tachometrze brana jest z obrotow kol
|
|
float maxtacho = 3;
|
|
fTachoVelocity = static_cast<float>( std::min( std::abs(11.31 * mvControlled->WheelDiameter * mvControlled->nrot), mvControlled->Vmax * 1.05) );
|
|
{ // skacze osobna zmienna
|
|
float ff = simulation::Time.data().wSecond; // skacze co sekunde - pol sekundy
|
|
// pomiar, pol sekundy ustawienie
|
|
if (ff != fTachoTimer) // jesli w tej sekundzie nie zmienial
|
|
{
|
|
if (fTachoVelocity > 1) // jedzie
|
|
fTachoVelocityJump = fTachoVelocity + (2.0 - Random(3) + Random(3)) * 0.5;
|
|
else
|
|
fTachoVelocityJump = 0; // stoi
|
|
fTachoTimer = ff; // juz zmienil
|
|
}
|
|
}
|
|
if (fTachoVelocity > 1) // McZapkie-270503: podkrecanie tachometru
|
|
{
|
|
if (fTachoCount < maxtacho)
|
|
fTachoCount += dt * 3; // szybciej zacznij stukac
|
|
}
|
|
else if (fTachoCount > 0)
|
|
fTachoCount -= dt * 0.66; // schodz powoli - niektore haslery to ze 4
|
|
// sekundy potrafia stukac
|
|
|
|
/* Ra: to by trzeba było przemyśleć, zmienione na szybko problemy robi
|
|
//McZapkie: predkosc wyswietlana na tachometrze brana jest z obrotow kol
|
|
double vel=fabs(11.31*mvControlled->WheelDiameter*mvControlled->nrot);
|
|
if (iSekunda!=floor(GlobalTime->mr)||(vel<1.0))
|
|
{fTachoVelocity=vel;
|
|
if (fTachoVelocity>1.0) //McZapkie-270503: podkrecanie tachometru
|
|
{
|
|
if (fTachoCount<maxtacho)
|
|
fTachoCount+=dt;
|
|
}
|
|
else
|
|
if (fTachoCount>0)
|
|
fTachoCount-=dt;
|
|
if (mvControlled->TrainType==dt_EZT)
|
|
//dla EZT wskazówka porusza się niestabilnie
|
|
if (fTachoVelocity>7.0)
|
|
{fTachoVelocity=floor(0.5+fTachoVelocity+random(5)-random(5));
|
|
//*floor(0.2*fTachoVelocity);
|
|
if (fTachoVelocity<0.0) fTachoVelocity=0.0;
|
|
}
|
|
iSekunda=floor(GlobalTime->mr);
|
|
}
|
|
*/
|
|
// Ra 2014-09: napięcia i prądy muszą być ustalone najpierw, bo wysyłane są ewentualnie na PoKeys
|
|
if ((mvControlled->EngineType != DieselElectric)
|
|
&& (mvControlled->EngineType != ElectricInductionMotor)) // Ra 2014-09: czy taki rozdzia? ma sens?
|
|
fHVoltage = mvControlled->RunningTraction.TractionVoltage; // Winger czy to nie jest zle?
|
|
// *mvControlled->Mains);
|
|
else
|
|
fHVoltage = mvControlled->Voltage;
|
|
if (ShowNextCurrent)
|
|
{ // jeśli pokazywać drugi człon
|
|
if (mvSecond)
|
|
{ // o ile jest ten drugi
|
|
fHCurrent[0] = mvSecond->ShowCurrent(0) * 1.05;
|
|
fHCurrent[1] = mvSecond->ShowCurrent(1) * 1.05;
|
|
fHCurrent[2] = mvSecond->ShowCurrent(2) * 1.05;
|
|
fHCurrent[3] = mvSecond->ShowCurrent(3) * 1.05;
|
|
}
|
|
else
|
|
fHCurrent[0] = fHCurrent[1] = fHCurrent[2] = fHCurrent[3] =
|
|
0.0; // gdy nie ma człona
|
|
}
|
|
else
|
|
{ // normalne pokazywanie
|
|
fHCurrent[0] = mvControlled->ShowCurrent(0);
|
|
fHCurrent[1] = mvControlled->ShowCurrent(1);
|
|
fHCurrent[2] = mvControlled->ShowCurrent(2);
|
|
fHCurrent[3] = mvControlled->ShowCurrent(3);
|
|
}
|
|
|
|
bool kier = (DynamicObject->DirectionGet() * mvOccupied->ActiveCab > 0);
|
|
TDynamicObject *p = DynamicObject->GetFirstDynamic(mvOccupied->ActiveCab < 0 ? 1 : 0, 4);
|
|
int in = 0;
|
|
fEIMParams[0][6] = 0;
|
|
iCarNo = 0;
|
|
iPowerNo = 0;
|
|
iUnitNo = 1;
|
|
|
|
for (int i = 0; i < 8; i++)
|
|
{
|
|
bMains[i] = false;
|
|
fCntVol[i] = 0.0f;
|
|
bPants[i][0] = false;
|
|
bPants[i][1] = false;
|
|
bFuse[i] = false;
|
|
bBatt[i] = false;
|
|
bConv[i] = false;
|
|
bComp[i][0] = false;
|
|
bComp[i][1] = false;
|
|
bHeat[i] = false;
|
|
}
|
|
for (int i = 0; i < 20; i++)
|
|
{
|
|
if (p)
|
|
{
|
|
fPress[i][0] = p->MoverParameters->BrakePress;
|
|
fPress[i][1] = p->MoverParameters->PipePress;
|
|
fPress[i][2] = p->MoverParameters->ScndPipePress;
|
|
bDoors[i][0] = (p->dDoorMoveL > 0.001) || (p->dDoorMoveR > 0.001);
|
|
bDoors[i][1] = (p->dDoorMoveR > 0.001);
|
|
bDoors[i][2] = (p->dDoorMoveL > 0.001);
|
|
iDoorNo[i] = p->iAnimType[ANIM_DOORS];
|
|
iUnits[i] = iUnitNo;
|
|
cCode[i] = p->MoverParameters->TypeName[p->MoverParameters->TypeName.length()];
|
|
asCarName[i] = p->GetName();
|
|
bPants[iUnitNo - 1][0] = (bPants[iUnitNo - 1][0] || p->MoverParameters->PantFrontUp);
|
|
bPants[iUnitNo - 1][1] = (bPants[iUnitNo - 1][1] || p->MoverParameters->PantRearUp);
|
|
bComp[iUnitNo - 1][0] = (bComp[iUnitNo - 1][0] || p->MoverParameters->CompressorAllow);
|
|
if (p->MoverParameters->CompressorSpeed > 0.00001)
|
|
{
|
|
bComp[iUnitNo - 1][1] = (bComp[iUnitNo - 1][1] || p->MoverParameters->CompressorFlag);
|
|
}
|
|
if ((in < 8) && (p->MoverParameters->eimc[eimc_p_Pmax] > 1))
|
|
{
|
|
fEIMParams[1 + in][0] = p->MoverParameters->eimv[eimv_Fr];
|
|
fEIMParams[1 + in][1] = Max0R(fEIMParams[1 + in][0], 0);
|
|
fEIMParams[1 + in][2] = -Min0R(fEIMParams[1 + in][0], 0);
|
|
fEIMParams[1 + in][3] = p->MoverParameters->eimv[eimv_Fr] /
|
|
Max0R(p->MoverParameters->eimv[eimv_Fful], 1);
|
|
fEIMParams[1 + in][4] = Max0R(fEIMParams[1 + in][3], 0);
|
|
fEIMParams[1 + in][5] = -Min0R(fEIMParams[1 + in][3], 0);
|
|
fEIMParams[1 + in][6] = p->MoverParameters->eimv[eimv_If];
|
|
fEIMParams[1 + in][7] = p->MoverParameters->eimv[eimv_U];
|
|
fEIMParams[1 + in][8] = p->MoverParameters->Itot;//p->MoverParameters->eimv[eimv_Ipoj];
|
|
fEIMParams[1 + in][9] = p->MoverParameters->Voltage;
|
|
fEIMParams[0][6] += fEIMParams[1 + in][8];
|
|
bMains[in] = p->MoverParameters->Mains;
|
|
fCntVol[in] = p->MoverParameters->BatteryVoltage;
|
|
bFuse[in] = p->MoverParameters->FuseFlag;
|
|
bBatt[in] = p->MoverParameters->Battery;
|
|
bConv[in] = p->MoverParameters->ConverterFlag;
|
|
bHeat[in] = p->MoverParameters->Heating;
|
|
in++;
|
|
iPowerNo = in;
|
|
}
|
|
// p = p->NextC(4); //prev
|
|
if ((kier ? p->NextC(128) : p->PrevC(128)) != (kier ? p->NextC(4) : p->PrevC(4)))
|
|
iUnitNo++;
|
|
p = (kier ? p->NextC(4) : p->PrevC(4));
|
|
iCarNo = i + 1;
|
|
}
|
|
else
|
|
{
|
|
fPress[i][0] = 0;
|
|
fPress[i][1] = 0;
|
|
fPress[i][2] = 0;
|
|
bDoors[i][0] = false;
|
|
bDoors[i][1] = false;
|
|
bDoors[i][2] = false;
|
|
iUnits[i] = 0;
|
|
cCode[i] = 0; //'0';
|
|
asCarName[i] = "";
|
|
}
|
|
}
|
|
|
|
if (mvControlled == mvOccupied)
|
|
fEIMParams[0][3] = mvControlled->eimv[eimv_Fzad]; // procent zadany
|
|
else
|
|
fEIMParams[0][3] =
|
|
mvControlled->eimv[eimv_Fzad] - mvOccupied->LocalBrakeRatio(); // procent zadany
|
|
fEIMParams[0][4] = Max0R(fEIMParams[0][3], 0);
|
|
fEIMParams[0][5] = -Min0R(fEIMParams[0][3], 0);
|
|
fEIMParams[0][1] = fEIMParams[0][4] * mvControlled->eimv[eimv_Fful];
|
|
fEIMParams[0][2] = fEIMParams[0][5] * mvControlled->eimv[eimv_Fful];
|
|
fEIMParams[0][0] = fEIMParams[0][1] - fEIMParams[0][2];
|
|
fEIMParams[0][7] = 0;
|
|
fEIMParams[0][8] = 0;
|
|
fEIMParams[0][9] = 0;
|
|
|
|
for (int i = in; i < 8; i++)
|
|
{
|
|
fEIMParams[1 + i][0] = 0;
|
|
fEIMParams[1 + i][1] = 0;
|
|
fEIMParams[1 + i][2] = 0;
|
|
fEIMParams[1 + i][3] = 0;
|
|
fEIMParams[1 + i][4] = 0;
|
|
fEIMParams[1 + i][5] = 0;
|
|
fEIMParams[1 + i][6] = 0;
|
|
fEIMParams[1 + i][7] = 0;
|
|
fEIMParams[1 + i][8] = 0;
|
|
fEIMParams[1 + i][9] = 0;
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
if (Global::iFeedbackMode == 4)
|
|
{ // wykonywać tylko gdy wyprowadzone na pulpit
|
|
Console::ValueSet(0,
|
|
mvOccupied->Compressor); // Ra: sterowanie miernikiem: zbiornik główny
|
|
Console::ValueSet(1,
|
|
mvOccupied->PipePress); // Ra: sterowanie miernikiem: przewód główny
|
|
Console::ValueSet(2, mvOccupied->BrakePress); // Ra: sterowanie miernikiem: cylinder hamulcowy
|
|
Console::ValueSet(3, fHVoltage); // woltomierz wysokiego napięcia
|
|
Console::ValueSet(4, fHCurrent[2]); // Ra: sterowanie miernikiem: drugi amperomierz
|
|
Console::ValueSet(5,
|
|
fHCurrent[(mvControlled->TrainType & dt_EZT) ? 0 : 1]); // pierwszy amperomierz; dla
|
|
// EZT prąd całkowity
|
|
Console::ValueSet(6, fTachoVelocity); ////Ra: prędkość na pin 43 - wyjście
|
|
/// analogowe (to nie jest PWM);
|
|
/// skakanie zapewnia mechanika
|
|
/// napędu
|
|
}
|
|
#endif
|
|
|
|
// 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 == ElectricSeriesMotor ) ) {
|
|
if( std::max( mvControlled->GetTrainsetVoltage(), std::fabs( 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
|
|
mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? range::unit : range::local ) );
|
|
}
|
|
}
|
|
|
|
// hunter-091012: swiatlo
|
|
if (bCabLight == true)
|
|
{
|
|
if (bCabLightDim == true)
|
|
iCabLightFlag = 1;
|
|
else
|
|
iCabLightFlag = 2;
|
|
}
|
|
else
|
|
iCabLightFlag = 0;
|
|
|
|
//------------------
|
|
// hunter-261211: nadmiarowy przetwornicy i ogrzewania
|
|
// Ra 15-01: to musi stąd wylecieć - zależności nie mogą być w kabinie
|
|
if (mvControlled->ConverterFlag == true)
|
|
{
|
|
fConverterTimer += dt;
|
|
if ((mvControlled->CompressorFlag == true) && (mvControlled->CompressorPower == 1) &&
|
|
((mvControlled->EngineType == ElectricSeriesMotor) ||
|
|
(mvControlled->TrainType == dt_EZT)) &&
|
|
(DynamicObject->Controller == Humandriver)) // hunter-110212: poprawka dla EZT
|
|
{ // hunter-091012: poprawka (zmiana warunku z CompressorPower /rozne od
|
|
// 0/ na /rowne 1/)
|
|
if (fConverterTimer < fConverterPrzekaznik)
|
|
{
|
|
mvControlled->ConvOvldFlag = true;
|
|
if (mvControlled->TrainType != dt_EZT)
|
|
mvControlled->MainSwitch( false, ( mvControlled->TrainType == dt_EZT ? range::unit : range::local ) );
|
|
}
|
|
else if( fConverterTimer >= fConverterPrzekaznik ) {
|
|
// changed switch from always true to take into account state of the compressor switch
|
|
mvControlled->CompressorSwitch( mvControlled->CompressorAllow );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
fConverterTimer = 0;
|
|
//------------------
|
|
|
|
double vol = 0;
|
|
double dfreq;
|
|
glm::vec3 dynpos;
|
|
{
|
|
vector3 v = DynamicObject->GetPosition();
|
|
dynpos = glm::make_vec3(&v.x);
|
|
}
|
|
|
|
// McZapkie-280302 - syczenie
|
|
if ((mvOccupied->BrakeHandle == FV4a) || (mvOccupied->BrakeHandle == FVel6))
|
|
{
|
|
if (rsHiss) // upuszczanie z PG
|
|
{
|
|
fPPress = (1 * fPPress + mvOccupied->Handle->GetSound(s_fv4a_b)) / (2);
|
|
if (fPPress > 0)
|
|
{
|
|
vol = 2.0 * fPPress;
|
|
}
|
|
if (vol * rsHiss->gain_mul > 0.001)
|
|
{
|
|
rsHiss->loop().gain(vol).position(dynpos).play();
|
|
}
|
|
else
|
|
{
|
|
rsHiss->stop();
|
|
}
|
|
}
|
|
if (rsHissU) // upuszczanie z PG
|
|
{
|
|
fNPress = (1 * fNPress + mvOccupied->Handle->GetSound(s_fv4a_u)) / (2);
|
|
vol = 0.0;
|
|
if (fNPress > 0)
|
|
{
|
|
vol = fNPress;
|
|
}
|
|
if (vol * rsHissU->gain_mul > 0.001)
|
|
{
|
|
rsHissU->loop().gain(vol).position(dynpos).play();
|
|
}
|
|
else
|
|
{
|
|
rsHissU->stop();
|
|
}
|
|
}
|
|
if (rsHissE) // upuszczanie przy naglym
|
|
{
|
|
vol = mvOccupied->Handle->GetSound(s_fv4a_e);
|
|
if (vol * rsHissE->gain_mul > 0.001)
|
|
{
|
|
rsHissE->loop().gain(vol).position(dynpos).play();
|
|
}
|
|
else
|
|
{
|
|
rsHissE->stop();
|
|
}
|
|
}
|
|
if (rsHissX) // upuszczanie sterujacego fala
|
|
{
|
|
vol = mvOccupied->Handle->GetSound(s_fv4a_x);
|
|
if (vol * rsHissX->gain_mul > 0.001)
|
|
{
|
|
rsHissX->loop().gain(vol).position(dynpos).play();
|
|
}
|
|
else
|
|
{
|
|
rsHissX->stop();
|
|
}
|
|
}
|
|
if (rsHissT) // upuszczanie z czasowego
|
|
{
|
|
vol = mvOccupied->Handle->GetSound(s_fv4a_t);
|
|
if (vol * rsHissT->gain_mul > 0.001)
|
|
{
|
|
rsHissT->loop().gain(vol).position(dynpos).play();
|
|
}
|
|
else
|
|
{
|
|
rsHissT->stop();
|
|
}
|
|
}
|
|
|
|
} // koniec FV4a
|
|
else // jesli nie FV4a
|
|
{
|
|
if (rsHiss) // upuszczanie z PG
|
|
{
|
|
fPPress = (4.0f * fPPress + std::max(mvOccupied->dpLocalValve, mvOccupied->dpMainValve)) / (4.0f + 1.0f);
|
|
if (fPPress > 0.0f)
|
|
{
|
|
vol = 2.0 * fPPress;
|
|
}
|
|
if (vol * rsHiss->gain_mul > 0.01)
|
|
{
|
|
rsHiss->loop().gain(vol).position(dynpos).play();
|
|
}
|
|
else
|
|
{
|
|
rsHiss->stop();
|
|
}
|
|
}
|
|
if (rsHissU) // napelnianie PG
|
|
{
|
|
fNPress = (4.0f * fNPress + Min0R(mvOccupied->dpLocalValve, mvOccupied->dpMainValve)) / (4.0f + 1.0f);
|
|
if (fNPress < 0.0f)
|
|
{
|
|
vol = -1.0 * fNPress;
|
|
}
|
|
if (vol * rsHissU->gain_mul > 0.01)
|
|
{
|
|
rsHissU->loop().gain(vol).position(dynpos).play();
|
|
}
|
|
else
|
|
{
|
|
rsHissU->stop();
|
|
}
|
|
}
|
|
} // koniec nie FV4a
|
|
|
|
// Winger-160404 - syczenie pomocniczego (luzowanie)
|
|
/* if (rsSBHiss->gain_mul!=0)
|
|
{
|
|
fSPPress=(mvOccupied->LocalBrakeRatio())-(mvOccupied->LocalBrakePos);
|
|
if (fSPPress>0)
|
|
{
|
|
vol=2*rsSBHiss->gain_mul*fSPPress;
|
|
}
|
|
if (vol>0.1)
|
|
{
|
|
rsSBHiss.Play(vol,DSBPLAY_LOOPING,true,DynamicObject->GetPosition());
|
|
}
|
|
else
|
|
{
|
|
rsSBHiss->stop();
|
|
}
|
|
}
|
|
*/
|
|
// szum w czasie jazdy
|
|
vol = 0.0;
|
|
dfreq = 1.0;
|
|
if (rsRunningNoise)
|
|
{
|
|
if (DynamicObject->GetVelocity() != 0)
|
|
{
|
|
if (!TestFlag(mvOccupied->DamageFlag,
|
|
dtrain_wheelwear)) // McZpakie-221103: halas zalezny od kola
|
|
{
|
|
dfreq = mvOccupied->Vel;
|
|
vol = mvOccupied->Vel;
|
|
switch (tor->eEnvironment)
|
|
{
|
|
case e_tunnel:
|
|
{
|
|
vol *= 3;
|
|
dfreq *= 0.95;
|
|
}
|
|
break;
|
|
case e_canyon:
|
|
{
|
|
vol *= 1.1;
|
|
}
|
|
break;
|
|
case e_bridge:
|
|
{
|
|
vol *= 2;
|
|
dfreq *= 0.98;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else // uszkodzone kolo (podkucie)
|
|
if (fabs(mvOccupied->nrot) > 0.01)
|
|
{
|
|
dfreq = mvOccupied->Vel;
|
|
vol = mvOccupied->Vel;
|
|
switch (tor->eEnvironment)
|
|
{
|
|
case e_tunnel:
|
|
{
|
|
vol *= 2;
|
|
}
|
|
break;
|
|
case e_canyon:
|
|
{
|
|
vol *= 1.1;
|
|
}
|
|
break;
|
|
case e_bridge:
|
|
{
|
|
vol *= 1.5;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (fabs(mvOccupied->nrot) > 0.01)
|
|
vol *= 1 +
|
|
mvOccupied->UnitBrakeForce /
|
|
(1 + mvOccupied->MaxBrakeForce); // hamulce wzmagaja halas
|
|
vol = vol * (20.0 + tor->iDamageFlag) / 21;
|
|
rsRunningNoise->pitch(dfreq).gain(vol).position(dynpos).loop().play();
|
|
}
|
|
else
|
|
rsRunningNoise->stop();
|
|
}
|
|
|
|
if (rsBrake)
|
|
{
|
|
if ((!mvOccupied->SlippingWheels) && (mvOccupied->UnitBrakeForce > 10.0) &&
|
|
(DynamicObject->GetVelocity() > 0.01))
|
|
{
|
|
// vol=rsBrake->gain_off+rsBrake->gain_mul*(DynamicObject->GetVelocity()*100+mvOccupied->UnitBrakeForce);
|
|
vol = sqrt((DynamicObject->GetVelocity() * mvOccupied->UnitBrakeForce));
|
|
dfreq = DynamicObject->GetVelocity();
|
|
rsBrake->pitch(dfreq).gain(vol).position(dynpos).loop().play();
|
|
}
|
|
else
|
|
{
|
|
rsBrake->stop();
|
|
}
|
|
}
|
|
|
|
if (rsEngageSlippery)
|
|
{
|
|
if /*((fabs(mvControlled->dizel_engagedeltaomega)>0.2) && */ (
|
|
mvControlled->dizel_engage > 0.1)
|
|
{
|
|
if (fabs(mvControlled->dizel_engagedeltaomega) > 0.2)
|
|
{
|
|
dfreq = fabs(mvControlled->dizel_engagedeltaomega);
|
|
vol = mvControlled->dizel_engage;
|
|
}
|
|
else
|
|
{
|
|
dfreq =
|
|
1; // rsEngageSlippery->pitch_off+0.7*rsEngageSlippery->pitch_mul*(fabs(mvControlled->enrot)+mvControlled->nmax);
|
|
if (mvControlled->dizel_engage > 0.2)
|
|
vol =
|
|
0.2 * (mvControlled->enrot / mvControlled->nmax);
|
|
else
|
|
vol = 0;
|
|
}
|
|
rsEngageSlippery->pitch(dfreq).gain(vol).position(dynpos).loop().play();
|
|
}
|
|
else
|
|
{
|
|
rsEngageSlippery->stop();
|
|
}
|
|
}
|
|
|
|
if (rsFadeSound)
|
|
{
|
|
if (FreeFlyModeFlag)
|
|
rsFadeSound->stop(); // wyłącz to cholerne cykanie!
|
|
else
|
|
rsFadeSound->loop().position(dynpos).play();
|
|
}
|
|
|
|
// McZapkie! - to wazne - SoundFlag wystawiane jest przez moje moduly
|
|
// gdy zachodza pewne wydarzenia komentowane dzwiekiem.
|
|
// Mysle ze wystarczy sprawdzac a potem zerowac SoundFlag tutaj
|
|
// a nie w DynObject - gdyby cos poszlo zle to po co szarpac dzwiekiem co
|
|
// 10ms.
|
|
|
|
if (TestFlag(mvOccupied->SoundFlag, sound_relay)) // przekaznik - gdy
|
|
// bezpiecznik,
|
|
// automatyczny rozruch
|
|
// itp
|
|
{
|
|
if (mvOccupied->EventFlag || TestFlag(mvOccupied->SoundFlag, sound_loud))
|
|
{
|
|
mvOccupied->EventFlag = false; // Ra: w kabinie?
|
|
if( dsbRelay != nullptr ) { dsbRelay->gain(1.0f); }
|
|
}
|
|
else
|
|
{
|
|
if( dsbRelay != nullptr ) { dsbRelay->gain(Global::soundgainmode == Global::compat ? 0.9f : 0.5f); }
|
|
}
|
|
if (!TestFlag(mvOccupied->SoundFlag, sound_manyrelay))
|
|
{
|
|
if (dsbRelay) dsbRelay->play();
|
|
}
|
|
else
|
|
{
|
|
if (TestFlag(mvOccupied->SoundFlag, sound_loud))
|
|
{
|
|
if (dsbWejscie_na_bezoporow)
|
|
dsbWejscie_na_bezoporow->play();
|
|
}
|
|
else
|
|
{
|
|
if (dsbWejscie_na_drugi_uklad)
|
|
dsbWejscie_na_drugi_uklad->play();
|
|
}
|
|
}
|
|
}
|
|
|
|
if( dsbBufferClamp != nullptr ) {
|
|
if( TestFlag( mvOccupied->SoundFlag, sound_bufferclamp ) ) // zderzaki uderzaja o siebie
|
|
{
|
|
if( TestFlag( mvOccupied->SoundFlag, sound_loud ) )
|
|
dsbBufferClamp->gain(1.0f);
|
|
else
|
|
dsbBufferClamp->gain(Global::soundgainmode == Global::compat ? 0.9f : 0.5f);
|
|
dsbBufferClamp->play();
|
|
}
|
|
}
|
|
if (dsbCouplerStretch)
|
|
if (TestFlag(mvOccupied->SoundFlag, sound_couplerstretch)) // sprzegi sie rozciagaja
|
|
{
|
|
if (TestFlag(mvOccupied->SoundFlag, sound_loud))
|
|
dsbCouplerStretch->gain(1.0f);
|
|
else
|
|
dsbCouplerStretch->gain(Global::soundgainmode == Global::compat ? 0.9f : 0.5f);
|
|
dsbCouplerStretch->play();
|
|
}
|
|
|
|
if (mvOccupied->SoundFlag == 0)
|
|
if (mvOccupied->EventFlag)
|
|
if (TestFlag(mvOccupied->DamageFlag, dtrain_wheelwear))
|
|
{ // Ra: przenieść do DynObj!
|
|
if (rsRunningNoise)
|
|
{
|
|
rsRunningNoise->stop();
|
|
// float aa=rsRunningNoise->gain_off;
|
|
float am = rsRunningNoise->gain_mul;
|
|
float fa = rsRunningNoise->pitch_off;
|
|
float fm = rsRunningNoise->pitch_mul;
|
|
|
|
// MC: zmiana szumu na lomot
|
|
sound_man->destroy_sound(&rsRunningNoise);
|
|
rsRunningNoise = sound_man->create_sound("lomotpodkucia.wav");
|
|
|
|
if (rsRunningNoise->gain_mul == 1)
|
|
rsRunningNoise->gain_mul = am;
|
|
rsRunningNoise->gain_off = 0.7;
|
|
rsRunningNoise->pitch_off = fa;
|
|
rsRunningNoise->pitch_mul = fm;
|
|
}
|
|
mvOccupied->EventFlag = false;
|
|
}
|
|
|
|
mvOccupied->SoundFlag = 0;
|
|
/*
|
|
for (int b=0; b<2; b++) //MC: aby zerowac stukanie przekaznikow w
|
|
czlonie silnikowym
|
|
if (TestFlag(mvControlled->Couplers[b].CouplingFlag,ctrain_controll))
|
|
if (mvControlled->Couplers[b].Connected.Power>0.01)
|
|
mvControlled->Couplers[b]->Connected->SoundFlag=0;
|
|
*/
|
|
|
|
// McZapkie! - koniec obslugi dzwiekow z mover.pas
|
|
|
|
// youBy - prad w drugim czlonie: galaz lub calosc
|
|
{
|
|
TDynamicObject *tmp;
|
|
tmp = NULL;
|
|
if (DynamicObject->NextConnected)
|
|
if ((TestFlag(mvControlled->Couplers[1].CouplingFlag, ctrain_controll)) &&
|
|
(mvOccupied->ActiveCab == 1))
|
|
tmp = DynamicObject->NextConnected;
|
|
if (DynamicObject->PrevConnected)
|
|
if ((TestFlag(mvControlled->Couplers[0].CouplingFlag, ctrain_controll)) &&
|
|
(mvOccupied->ActiveCab == -1))
|
|
tmp = DynamicObject->PrevConnected;
|
|
if (tmp)
|
|
if (tmp->MoverParameters->Power > 0)
|
|
{
|
|
if (ggI1B.SubModel)
|
|
{
|
|
ggI1B.UpdateValue(tmp->MoverParameters->ShowCurrent(1));
|
|
ggI1B.Update();
|
|
}
|
|
if (ggI2B.SubModel)
|
|
{
|
|
ggI2B.UpdateValue(tmp->MoverParameters->ShowCurrent(2));
|
|
ggI2B.Update();
|
|
}
|
|
if (ggI3B.SubModel)
|
|
{
|
|
ggI3B.UpdateValue(tmp->MoverParameters->ShowCurrent(3));
|
|
ggI3B.Update();
|
|
}
|
|
if (ggItotalB.SubModel)
|
|
{
|
|
ggItotalB.UpdateValue(tmp->MoverParameters->ShowCurrent(0));
|
|
ggItotalB.Update();
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
//McZapkie-240302 ggVelocity.UpdateValue(DynamicObject->GetVelocity());
|
|
//fHaslerTimer+=dt;
|
|
//if (fHaslerTimer>fHaslerTime)
|
|
{//Ra: ryzykowne jest to, gdyż może się nie uaktualniać prędkość
|
|
//Ra: prędkość się powinna zaokrąglać tam gdzie się liczy
|
|
fTachoVelocity
|
|
if (ggVelocity.SubModel)
|
|
{//ZiomalCl: wskazanie Haslera w kabinie A ze zwloka czasowa oraz odpowiednia
|
|
tolerancja
|
|
//Nalezy sie zastanowic na przyszlosc nad rozroznieniem predkosciomierzy
|
|
(dokladnosc wskazan, zwloka czasowa wskazania, inne funkcje)
|
|
//ZiomalCl: W ezt typu stare EN57 wskazania haslera sa mniej dokladne
|
|
(linka)
|
|
//ggVelocity.UpdateValue(fTachoVelocity>2?fTachoVelocity+0.5-random(mvControlled->TrainType==dt_EZT?5:2)/2:0);
|
|
ggVelocity.UpdateValue(Min0R(fTachoVelocity,mvControlled->Vmax*1.05));
|
|
//ograniczenie maksymalnego wskazania na analogowym
|
|
ggVelocity.Update();
|
|
}
|
|
if (ggVelocityDgt.SubModel)
|
|
{//Ra 2014-07: prędkościomierz cyfrowy
|
|
ggVelocityDgt.UpdateValue(fTachoVelocity);
|
|
ggVelocityDgt.Update();
|
|
}
|
|
if (ggVelocity_B.SubModel)
|
|
{//ZiomalCl: wskazanie Haslera w kabinie B ze zwloka czasowa oraz odpowiednia
|
|
tolerancja
|
|
//Nalezy sie zastanowic na przyszlosc nad rozroznieniem predkosciomierzy
|
|
(dokladnosc wskazan, zwloka czasowa wskazania, inne funkcje)
|
|
//Velocity_B.UpdateValue(fTachoVelocity>2?fTachoVelocity+0.5-random(mvControlled->TrainType==dt_EZT?5:2)/2:0);
|
|
ggVelocity_B.UpdateValue(fTachoVelocity);
|
|
ggVelocity_B.Update();
|
|
}
|
|
//fHaslerTimer-=fHaslerTime; //1.2s (???)
|
|
}
|
|
*/
|
|
// McZapkie-300302: zegarek
|
|
if (ggClockMInd.SubModel)
|
|
{
|
|
ggClockSInd.UpdateValue(simulation::Time.data().wSecond);
|
|
ggClockSInd.Update();
|
|
ggClockMInd.UpdateValue(simulation::Time.data().wMinute);
|
|
ggClockMInd.Update();
|
|
ggClockHInd.UpdateValue(simulation::Time.data().wHour + simulation::Time.data().wMinute / 60.0);
|
|
ggClockHInd.Update();
|
|
}
|
|
|
|
Cabine[iCabn].Update(); // nowy sposób ustawienia animacji
|
|
if (ggZbS.SubModel)
|
|
{
|
|
ggZbS.UpdateValue(mvOccupied->Handle->GetCP());
|
|
ggZbS.Update();
|
|
}
|
|
|
|
// youBy - napiecie na silnikach
|
|
if (ggEngineVoltage.SubModel)
|
|
{
|
|
if (mvControlled->DynamicBrakeFlag)
|
|
{
|
|
ggEngineVoltage.UpdateValue(abs(mvControlled->Im * 5));
|
|
}
|
|
else
|
|
{
|
|
int x;
|
|
if ((mvControlled->TrainType == dt_ET42) &&
|
|
(mvControlled->Imax == mvControlled->ImaxHi))
|
|
x = 1;
|
|
else
|
|
x = 2;
|
|
if ((mvControlled->RList[mvControlled->MainCtrlActualPos].Mn > 0) &&
|
|
(abs(mvControlled->Im) > 0))
|
|
{
|
|
ggEngineVoltage.UpdateValue(
|
|
(x * (mvControlled->RunningTraction.TractionVoltage -
|
|
mvControlled->RList[mvControlled->MainCtrlActualPos].R *
|
|
abs(mvControlled->Im)) /
|
|
mvControlled->RList[mvControlled->MainCtrlActualPos].Mn));
|
|
}
|
|
else
|
|
{
|
|
ggEngineVoltage.UpdateValue(0);
|
|
}
|
|
}
|
|
ggEngineVoltage.Update();
|
|
}
|
|
|
|
// Winger 140404 - woltomierz NN
|
|
if (ggLVoltage.SubModel)
|
|
{
|
|
// NOTE: since we don't have functional converter object, we're faking it here by simple check whether converter is on
|
|
// TODO: implement object-based circuits and power systems model so we can have this working more properly
|
|
ggLVoltage.UpdateValue(
|
|
std::max(
|
|
( mvControlled->ConverterFlag ?
|
|
mvControlled->NominalBatteryVoltage :
|
|
0.0 ),
|
|
( mvControlled->Battery ?
|
|
mvControlled->BatteryVoltage :
|
|
0.0 ) ) );
|
|
ggLVoltage.Update();
|
|
}
|
|
|
|
if (mvControlled->EngineType == DieselElectric)
|
|
{ // ustawienie zmiennych dla silnika spalinowego
|
|
fEngine[1] = mvControlled->ShowEngineRotation(1);
|
|
fEngine[2] = mvControlled->ShowEngineRotation(2);
|
|
}
|
|
|
|
else if (mvControlled->EngineType == DieselEngine)
|
|
{ // albo dla innego spalinowego
|
|
fEngine[1] = mvControlled->ShowEngineRotation(1);
|
|
fEngine[2] = mvControlled->ShowEngineRotation(2);
|
|
fEngine[3] = mvControlled->ShowEngineRotation(3);
|
|
if (ggMainGearStatus.SubModel)
|
|
{
|
|
if (mvControlled->Mains)
|
|
ggMainGearStatus.UpdateValue(1.1 - std::abs(mvControlled->dizel_automaticgearstatus));
|
|
else
|
|
ggMainGearStatus.UpdateValue(0.0);
|
|
ggMainGearStatus.Update();
|
|
}
|
|
if (ggIgnitionKey.SubModel)
|
|
{
|
|
ggIgnitionKey.UpdateValue(mvControlled->dizel_enginestart);
|
|
ggIgnitionKey.Update();
|
|
}
|
|
}
|
|
|
|
if (mvControlled->SlippingWheels)
|
|
{ // Ra 2014-12: lokomotywy 181/182
|
|
// dostają SlippingWheels po zahamowaniu
|
|
// powyżej 2.85 bara i buczały
|
|
double veldiff = (DynamicObject->GetVelocity() - fTachoVelocity) / mvControlled->Vmax;
|
|
if (veldiff < -0.01) // 1% Vmax rezerwy, żeby 181/182 nie buczały po
|
|
// zahamowaniu, ale to proteza
|
|
{
|
|
if (fabs(mvControlled->Im) > 10.0)
|
|
btLampkaPoslizg.TurnOn();
|
|
rsSlippery->gain(-veldiff).loop().position(dynpos).play();
|
|
if (mvControlled->TrainType == dt_181) // alarm przy poslizgu dla 181/182 - BOMBARDIER
|
|
if (dsbSlipAlarm)
|
|
dsbSlipAlarm->loop().play();
|
|
}
|
|
else
|
|
{
|
|
if ((mvOccupied->UnitBrakeForce > 100.0) && (DynamicObject->GetVelocity() > 1.0))
|
|
{
|
|
rsSlippery->gain(veldiff).loop().position(dynpos).play();
|
|
if (mvControlled->TrainType == dt_181)
|
|
if (dsbSlipAlarm)
|
|
dsbSlipAlarm->stop();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
btLampkaPoslizg.TurnOff();
|
|
rsSlippery->stop();
|
|
if (mvControlled->TrainType == dt_181)
|
|
if (dsbSlipAlarm)
|
|
dsbSlipAlarm->stop();
|
|
}
|
|
|
|
if ((mvControlled->Mains) || (mvControlled->TrainType == dt_EZT))
|
|
{
|
|
btLampkaNadmSil.Turn(mvControlled->FuseFlagCheck());
|
|
}
|
|
else
|
|
{
|
|
btLampkaNadmSil.TurnOff();
|
|
}
|
|
|
|
if (mvControlled->Battery || mvControlled->ConverterFlag)
|
|
{
|
|
btLampkaWylSzybki.Turn(
|
|
( ( (m_linebreakerstate > 0)
|
|
|| (true == mvControlled->Mains) ) ?
|
|
true :
|
|
false ) );
|
|
|
|
// hunter-261211: jakis stary kod (i niezgodny z prawda),
|
|
// zahaszowalem i poprawilem
|
|
// youBy-220913: ale przyda sie do lampki samej przetwornicy
|
|
btLampkaPrzetw.Turn( !mvControlled->ConverterFlag );
|
|
btLampkaNadmPrzetw.Turn( mvControlled->ConvOvldFlag );
|
|
|
|
btLampkaOpory.Turn(
|
|
mvControlled->StLinFlag ?
|
|
mvControlled->ResistorsFlagCheck() :
|
|
false );
|
|
|
|
btLampkaBezoporowa.Turn(mvControlled->ResistorsFlagCheck() ||
|
|
(mvControlled->MainCtrlActualPos == 0)); // do EU04
|
|
if ((mvControlled->Itot != 0) || (mvOccupied->BrakePress > 2) ||
|
|
(mvOccupied->PipePress < 3.6))
|
|
btLampkaStyczn.TurnOff(); // Ra: czy to jest udawanie działania
|
|
// styczników liniowych?
|
|
else if (mvOccupied->BrakePress < 1)
|
|
btLampkaStyczn.TurnOn(); // mozna prowadzic rozruch
|
|
if (((TestFlag(mvControlled->Couplers[1].CouplingFlag, ctrain_controll)) &&
|
|
(mvControlled->CabNo == 1)) ||
|
|
((TestFlag(mvControlled->Couplers[0].CouplingFlag, ctrain_controll)) &&
|
|
(mvControlled->CabNo == -1)))
|
|
btLampkaUkrotnienie.TurnOn();
|
|
else
|
|
btLampkaUkrotnienie.TurnOff();
|
|
|
|
// if
|
|
// ((TestFlag(mvControlled->BrakeStatus,+b_Rused+b_Ractive)))//Lampka drugiego stopnia hamowania
|
|
btLampkaHamPosp.Turn((TestFlag(mvOccupied->Hamulec->GetBrakeStatus(), 1))); // lampka drugiego stopnia hamowania
|
|
//TODO: youBy wyciągnąć flagę wysokiego stopnia
|
|
|
|
// hunter-121211: lampka zanikowo-pradowego wentylatorow:
|
|
btLampkaNadmWent.Turn( ( mvControlled->RventRot < 5.0 ) && ( mvControlled->ResistorsFlagCheck() ) );
|
|
//-------
|
|
|
|
btLampkaWysRozr.Turn(!(mvControlled->Imax < mvControlled->ImaxHi));
|
|
|
|
if (((mvControlled->ScndCtrlActualPos > 0) ||
|
|
((mvControlled->RList[mvControlled->MainCtrlActualPos].ScndAct != 0) &&
|
|
(mvControlled->RList[mvControlled->MainCtrlActualPos].ScndAct != 255))) &&
|
|
(!mvControlled->DelayCtrlFlag))
|
|
btLampkaBoczniki.TurnOn();
|
|
else
|
|
btLampkaBoczniki.TurnOff();
|
|
|
|
btLampkaNapNastHam.Turn(mvControlled->ActiveDir != 0); // napiecie na nastawniku hamulcowym
|
|
btLampkaSprezarka.Turn(mvControlled->CompressorFlag); // mutopsitka dziala
|
|
// boczniki
|
|
unsigned char scp; // Ra: dopisałem "unsigned"
|
|
// Ra: w SU45 boczniki wchodzą na MainCtrlPos, a nie na MainCtrlActualPos
|
|
// - pokićkał ktoś?
|
|
scp = mvControlled->RList[mvControlled->MainCtrlPos].ScndAct;
|
|
scp = (scp == 255 ? 0 : scp); // Ra: whatta hella is this?
|
|
if ((mvControlled->ScndCtrlPos > 0) || (mvControlled->ScndInMain != 0) && (scp > 0))
|
|
{ // boczniki pojedynczo
|
|
btLampkaBocznik1.TurnOn();
|
|
btLampkaBocznik2.Turn(mvControlled->ScndCtrlPos > 1);
|
|
btLampkaBocznik3.Turn(mvControlled->ScndCtrlPos > 2);
|
|
btLampkaBocznik4.Turn(mvControlled->ScndCtrlPos > 3);
|
|
}
|
|
else
|
|
{ // wyłączone wszystkie cztery
|
|
btLampkaBocznik1.TurnOff();
|
|
btLampkaBocznik2.TurnOff();
|
|
btLampkaBocznik3.TurnOff();
|
|
btLampkaBocznik4.TurnOff();
|
|
}
|
|
/*
|
|
{ //sprezarka w drugim wozie
|
|
bool comptemp=false;
|
|
if (DynamicObject->NextConnected)
|
|
if
|
|
(TestFlag(mvControlled->Couplers[1].CouplingFlag,ctrain_controll))
|
|
comptemp=DynamicObject->NextConnected->MoverParameters->CompressorFlag;
|
|
if ((DynamicObject->PrevConnected) && (!comptemp))
|
|
if
|
|
(TestFlag(mvControlled->Couplers[0].CouplingFlag,ctrain_controll))
|
|
comptemp=DynamicObject->PrevConnected->MoverParameters->CompressorFlag;
|
|
btLampkaSprezarkaB.Turn(comptemp);
|
|
*/
|
|
}
|
|
else // wylaczone
|
|
{
|
|
btLampkaWylSzybki.TurnOff();
|
|
btLampkaWysRozr.TurnOff();
|
|
btLampkaOpory.TurnOff();
|
|
btLampkaStyczn.TurnOff();
|
|
btLampkaUkrotnienie.TurnOff();
|
|
btLampkaHamPosp.TurnOff();
|
|
btLampkaBoczniki.TurnOff();
|
|
btLampkaNapNastHam.TurnOff();
|
|
btLampkaPrzetw.TurnOff();
|
|
btLampkaSprezarka.TurnOff();
|
|
btLampkaBezoporowa.TurnOff();
|
|
}
|
|
if (mvControlled->Signalling == true)
|
|
{
|
|
|
|
if ((mvOccupied->BrakePress >= 0.145f) && (mvControlled->Battery == true) &&
|
|
(mvControlled->Signalling == true))
|
|
{
|
|
btLampkaHamowanie1zes.TurnOn();
|
|
}
|
|
if (mvControlled->BrakePress < 0.075f)
|
|
{
|
|
btLampkaHamowanie1zes.TurnOff();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
btLampkaHamowanie1zes.TurnOff();
|
|
}
|
|
btLampkaBlokadaDrzwi.Turn(mvControlled->DoorSignalling ?
|
|
mvOccupied->DoorBlockedFlag() && mvControlled->Battery :
|
|
false);
|
|
|
|
{ // yB - wskazniki drugiego czlonu
|
|
TDynamicObject *tmp; //=mvControlled->mvSecond; //Ra 2014-07: trzeba to
|
|
// jeszcze wyjąć z kabiny...
|
|
// Ra 2014-07: no nie ma potrzeby szukać tego w każdej klatce
|
|
tmp = NULL;
|
|
if ((TestFlag(mvControlled->Couplers[1].CouplingFlag, ctrain_controll)) &&
|
|
(mvOccupied->ActiveCab > 0))
|
|
tmp = DynamicObject->NextConnected;
|
|
if ((TestFlag(mvControlled->Couplers[0].CouplingFlag, ctrain_controll)) &&
|
|
(mvOccupied->ActiveCab < 0))
|
|
tmp = DynamicObject->PrevConnected;
|
|
|
|
if (tmp)
|
|
if ( mvControlled->Battery || mvControlled->ConverterFlag )
|
|
{
|
|
btLampkaWylSzybkiB.Turn( tmp->MoverParameters->Mains );
|
|
|
|
btLampkaOporyB.Turn(tmp->MoverParameters->ResistorsFlagCheck());
|
|
btLampkaBezoporowaB.Turn(
|
|
tmp->MoverParameters->ResistorsFlagCheck() ||
|
|
(tmp->MoverParameters->MainCtrlActualPos == 0)); // do EU04
|
|
if ((tmp->MoverParameters->Itot != 0) ||
|
|
(tmp->MoverParameters->BrakePress > 0.2) ||
|
|
(tmp->MoverParameters->PipePress < 0.36))
|
|
btLampkaStycznB.TurnOff(); //
|
|
else if (tmp->MoverParameters->BrakePress < 0.1)
|
|
btLampkaStycznB.TurnOn(); // mozna prowadzic rozruch
|
|
|
|
//-----------------
|
|
// //hunter-271211: brak jazdy w drugim czlonie, gdy w
|
|
// pierwszym tez nie ma (i odwrotnie) - Ra: tutaj? w kabinie?
|
|
// if (tmp->MoverParameters->TrainType!=dt_EZT)
|
|
// if (((tmp->MoverParameters->BrakePress > 2) || (
|
|
// tmp->MoverParameters->PipePress < 3.6 )) && (
|
|
// tmp->MoverParameters->MainCtrlPos != 0 ))
|
|
// {
|
|
// tmp->MoverParameters->MainCtrlActualPos=0; //inaczej
|
|
// StLinFlag nie zmienia sie na false w drugim pojezdzie
|
|
// //tmp->MoverParameters->StLinFlag=true;
|
|
// mvControlled->StLinFlag=true;
|
|
// }
|
|
// if (mvControlled->StLinFlag==true)
|
|
// tmp->MoverParameters->MainCtrlActualPos=0;
|
|
// //tmp->MoverParameters->StLinFlag=true;
|
|
|
|
//-----------------
|
|
// hunter-271211: sygnalizacja poslizgu w pierwszym pojezdzie, gdy
|
|
// wystapi w drugim
|
|
btLampkaPoslizg.Turn(tmp->MoverParameters->SlippingWheels);
|
|
//-----------------
|
|
|
|
btLampkaSprezarkaB.Turn(
|
|
tmp->MoverParameters->CompressorFlag); // mutopsitka dziala
|
|
if ((tmp->MoverParameters->BrakePress >= 0.145f * 10) &&
|
|
(mvControlled->Battery == true) && (mvControlled->Signalling == true))
|
|
{
|
|
btLampkaHamowanie2zes.TurnOn();
|
|
}
|
|
if ((tmp->MoverParameters->BrakePress < 0.075f * 10) ||
|
|
(mvControlled->Battery == false) || (mvControlled->Signalling == false))
|
|
{
|
|
btLampkaHamowanie2zes.TurnOff();
|
|
}
|
|
btLampkaNadmPrzetwB.Turn(
|
|
tmp->MoverParameters->ConvOvldFlag); // nadmiarowy przetwornicy?
|
|
btLampkaPrzetwB.Turn(
|
|
!tmp->MoverParameters->ConverterFlag); // zalaczenie przetwornicy
|
|
}
|
|
else // wylaczone
|
|
{
|
|
btLampkaWylSzybkiB.TurnOff();
|
|
btLampkaOporyB.TurnOff();
|
|
btLampkaStycznB.TurnOff();
|
|
btLampkaSprezarkaB.TurnOff();
|
|
btLampkaBezoporowaB.TurnOff();
|
|
btLampkaHamowanie2zes.TurnOff();
|
|
btLampkaNadmPrzetwB.TurnOn();
|
|
btLampkaPrzetwB.TurnOff();
|
|
}
|
|
|
|
// hunter-261211: jakis stary kod (i niezgodny z prawda), zahaszowalem
|
|
// if (tmp)
|
|
// if (tmp->MoverParameters->ConverterFlag==true)
|
|
// btLampkaNadmPrzetwB.TurnOff();
|
|
// else
|
|
// btLampkaNadmPrzetwB.TurnOn();
|
|
|
|
} //**************************************************** */
|
|
if( mvControlled->Battery || mvControlled->ConverterFlag )
|
|
{
|
|
switch (mvControlled->TrainType)
|
|
{ // zależnie od typu lokomotywy
|
|
case dt_EZT:
|
|
btLampkaHamienie.Turn((mvControlled->BrakePress >= 0.2) &&
|
|
mvControlled->Signalling);
|
|
break;
|
|
case dt_ET41: // odhamowanie drugiego członu
|
|
if (mvSecond) // bo może komuś przyjść do głowy jeżdżenie jednym członem
|
|
btLampkaHamienie.Turn(mvSecond->BrakePress < 0.4);
|
|
break;
|
|
default:
|
|
btLampkaHamienie.Turn((mvOccupied->BrakePress >= 0.1) ||
|
|
mvControlled->DynamicBrakeFlag);
|
|
}
|
|
// KURS90
|
|
btLampkaMaxSila.Turn(abs(mvControlled->Im) >= 350);
|
|
btLampkaPrzekrMaxSila.Turn(abs(mvControlled->Im) >= 450);
|
|
btLampkaRadio.Turn(mvOccupied->Radio);
|
|
btLampkaHamulecReczny.Turn(mvOccupied->ManualBrakePos > 0);
|
|
// NBMX wrzesien 2003 - drzwi oraz sygnał odjazdu
|
|
btLampkaDoorLeft.Turn(mvOccupied->DoorLeftOpened);
|
|
btLampkaDoorRight.Turn(mvOccupied->DoorRightOpened);
|
|
btLampkaDepartureSignal.Turn( mvControlled->DepartureSignal );
|
|
btLampkaNapNastHam.Turn((mvControlled->ActiveDir != 0) && (mvOccupied->EpFuse)); // napiecie na nastawniku hamulcowym
|
|
btLampkaForward.Turn(mvControlled->ActiveDir > 0); // jazda do przodu
|
|
btLampkaBackward.Turn(mvControlled->ActiveDir < 0); // jazda do tyłu
|
|
btLampkaED.Turn(mvControlled->DynamicBrakeFlag); // hamulec ED
|
|
}
|
|
else
|
|
{ // gdy bateria wyłączona
|
|
btLampkaHamienie.TurnOff();
|
|
btLampkaMaxSila.TurnOff();
|
|
btLampkaPrzekrMaxSila.TurnOff();
|
|
btLampkaRadio.TurnOff();
|
|
btLampkaHamulecReczny.TurnOff();
|
|
btLampkaDoorLeft.TurnOff();
|
|
btLampkaDoorRight.TurnOff();
|
|
btLampkaDepartureSignal.TurnOff();
|
|
btLampkaNapNastHam.TurnOff();
|
|
btLampkaForward.TurnOff();
|
|
btLampkaBackward.TurnOff();
|
|
btLampkaED.TurnOff();
|
|
}
|
|
// McZapkie-080602: obroty (albo translacje) regulatorow
|
|
if (ggMainCtrl.SubModel) {
|
|
|
|
if( mvControlled->CoupledCtrl ) {
|
|
ggMainCtrl.UpdateValue(
|
|
double( mvControlled->MainCtrlPos + mvControlled->ScndCtrlPos ),
|
|
dsbNastawnikJazdy );
|
|
}
|
|
else {
|
|
ggMainCtrl.UpdateValue(
|
|
double( mvControlled->MainCtrlPos ),
|
|
dsbNastawnikJazdy );
|
|
}
|
|
ggMainCtrl.Update();
|
|
}
|
|
if (ggMainCtrlAct.SubModel)
|
|
{
|
|
if (mvControlled->CoupledCtrl)
|
|
ggMainCtrlAct.UpdateValue(
|
|
double(mvControlled->MainCtrlActualPos + mvControlled->ScndCtrlActualPos));
|
|
else
|
|
ggMainCtrlAct.UpdateValue(double(mvControlled->MainCtrlActualPos));
|
|
ggMainCtrlAct.Update();
|
|
}
|
|
if (ggScndCtrl.SubModel) {
|
|
// Ra: od byte odejmowane boolean i konwertowane potem na double?
|
|
ggScndCtrl.UpdateValue(
|
|
double( mvControlled->ScndCtrlPos
|
|
- ( ( mvControlled->TrainType == dt_ET42 ) && mvControlled->DynamicBrakeFlag ) ),
|
|
dsbNastawnikBocz );
|
|
ggScndCtrl.Update();
|
|
}
|
|
if (ggDirKey.SubModel) {
|
|
if (mvControlled->TrainType != dt_EZT)
|
|
ggDirKey.UpdateValue(
|
|
double(mvControlled->ActiveDir),
|
|
dsbReverserKey);
|
|
else
|
|
ggDirKey.UpdateValue(
|
|
double(mvControlled->ActiveDir) + double(mvControlled->Imin == mvControlled->IminHi),
|
|
dsbReverserKey);
|
|
ggDirKey.Update();
|
|
}
|
|
if (ggBrakeCtrl.SubModel)
|
|
{
|
|
#ifdef _WIN32
|
|
if (DynamicObject->Mechanik ?
|
|
(DynamicObject->Mechanik->AIControllFlag ? false :
|
|
(Global::iFeedbackMode == 4)) :
|
|
false) // nie blokujemy AI
|
|
{ // Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba
|
|
// Firleju: dlatego kasujemy i zastepujemy funkcją w Console
|
|
if (mvOccupied->BrakeHandle == FV4a)
|
|
{
|
|
double b = Console::AnalogCalibrateGet(0);
|
|
b = b * 8.0 - 2.0;
|
|
b = clamp<double>( b, -2.0, mvOccupied->BrakeCtrlPosNo ); // przycięcie zmiennej do granic
|
|
ggBrakeCtrl.UpdateValue(b); // przesów bez zaokrąglenia
|
|
mvOccupied->BrakeLevelSet(b);
|
|
}
|
|
if (mvOccupied->BrakeHandle == FVel6) // może można usunąć ograniczenie do FV4a i FVel6?
|
|
{
|
|
double b = Console::AnalogCalibrateGet(0);
|
|
b = b * 7.0 - 1.0;
|
|
b = clamp<double>( b, -1.0, mvOccupied->BrakeCtrlPosNo ); // przycięcie zmiennej do granic
|
|
ggBrakeCtrl.UpdateValue(b); // przesów bez zaokrąglenia
|
|
mvOccupied->BrakeLevelSet(b);
|
|
}
|
|
// else //standardowa prodedura z kranem powiązanym z klawiaturą
|
|
// ggBrakeCtrl.UpdateValue(double(mvOccupied->BrakeCtrlPos));
|
|
}
|
|
#endif
|
|
// else //standardowa prodedura z kranem powiązanym z klawiaturą
|
|
// ggBrakeCtrl.UpdateValue(double(mvOccupied->BrakeCtrlPos));
|
|
ggBrakeCtrl.UpdateValue(mvOccupied->fBrakeCtrlPos);
|
|
ggBrakeCtrl.Update();
|
|
}
|
|
if( ggLocalBrake.SubModel ) {
|
|
#ifdef _WIN32
|
|
if( ( DynamicObject->Mechanik != nullptr )
|
|
&& ( false == DynamicObject->Mechanik->AIControllFlag ) // nie blokujemy AI
|
|
&& ( mvOccupied->BrakeLocHandle == FD1 )
|
|
&& ( ( Global::iFeedbackMode == 4 ) ) ) {
|
|
// Ra: nie najlepsze miejsce, ale na początek gdzieś to dać trzeba
|
|
// Firleju: dlatego kasujemy i zastepujemy funkcją w Console
|
|
auto const b = clamp<double>(
|
|
Console::AnalogCalibrateGet( 1 ) * 10.0,
|
|
0.0,
|
|
ManualBrakePosNo );
|
|
ggLocalBrake.UpdateValue( b ); // przesów bez zaokrąglenia
|
|
mvOccupied->LocalBrakePos = int( 1.09 * b ); // sposób zaokrąglania jest do ustalenia
|
|
}
|
|
else // standardowa prodedura z kranem powiązanym z klawiaturą
|
|
#endif
|
|
ggLocalBrake.UpdateValue(double(mvOccupied->LocalBrakePos));
|
|
|
|
ggLocalBrake.Update();
|
|
}
|
|
if (ggManualBrake.SubModel != nullptr) {
|
|
ggManualBrake.UpdateValue(double(mvOccupied->ManualBrakePos));
|
|
ggManualBrake.Update();
|
|
}
|
|
ggAlarmChain.Update();
|
|
ggBrakeProfileCtrl.Update();
|
|
ggBrakeProfileG.Update();
|
|
ggBrakeProfileR.Update();
|
|
ggMaxCurrentCtrl.Update();
|
|
// NBMX wrzesien 2003 - drzwi
|
|
ggDoorLeftButton.Update();
|
|
ggDoorRightButton.Update();
|
|
ggDoorSignallingButton.Update();
|
|
// NBMX dzwignia sprezarki
|
|
ggCompressorButton.Update();
|
|
ggCompressorLocalButton.Update();
|
|
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
if( ( ( DynamicObject->iLights[ 0 ] ) == 0 ) && ( ( DynamicObject->iLights[ 1 ] ) == 0 ) )
|
|
{
|
|
ggRightLightButton.PutValue(0);
|
|
ggLeftLightButton.PutValue(0);
|
|
ggUpperLightButton.PutValue(0);
|
|
ggRightEndLightButton.PutValue(0);
|
|
ggLeftEndLightButton.PutValue(0);
|
|
}
|
|
|
|
// hunter-230112
|
|
// REFLEKTOR LEWY
|
|
// glowne oswietlenie
|
|
if ((DynamicObject->iLights[0] & 1) == 1)
|
|
if ((mvOccupied->ActiveCab) == 1)
|
|
ggLeftLightButton.PutValue(1);
|
|
else if ((mvOccupied->ActiveCab) == -1)
|
|
ggRearLeftLightButton.PutValue(1);
|
|
|
|
if ((DynamicObject->iLights[1] & 1) == 1)
|
|
if ((mvOccupied->ActiveCab) == -1)
|
|
ggLeftLightButton.PutValue(1);
|
|
else if ((mvOccupied->ActiveCab) == 1)
|
|
ggRearLeftLightButton.PutValue(1);
|
|
|
|
// końcówki
|
|
if ((DynamicObject->iLights[0] & 2) == 2)
|
|
if ((mvOccupied->ActiveCab) == 1)
|
|
{
|
|
if (ggLeftEndLightButton.SubModel)
|
|
{
|
|
ggLeftEndLightButton.PutValue(1);
|
|
ggLeftLightButton.PutValue(0);
|
|
}
|
|
else
|
|
ggLeftLightButton.PutValue(-1);
|
|
}
|
|
else if ((mvOccupied->ActiveCab) == -1)
|
|
{
|
|
if (ggRearLeftEndLightButton.SubModel)
|
|
{
|
|
ggRearLeftEndLightButton.PutValue(1);
|
|
ggRearLeftLightButton.PutValue(0);
|
|
}
|
|
else
|
|
ggRearLeftLightButton.PutValue(-1);
|
|
}
|
|
|
|
if ((DynamicObject->iLights[1] & 2) == 2)
|
|
if ((mvOccupied->ActiveCab) == -1)
|
|
{
|
|
if (ggLeftEndLightButton.SubModel)
|
|
{
|
|
ggLeftEndLightButton.PutValue(1);
|
|
ggLeftLightButton.PutValue(0);
|
|
}
|
|
else
|
|
ggLeftLightButton.PutValue(-1);
|
|
}
|
|
else if ((mvOccupied->ActiveCab) == 1)
|
|
{
|
|
if (ggRearLeftEndLightButton.SubModel)
|
|
{
|
|
ggRearLeftEndLightButton.PutValue(1);
|
|
ggRearLeftLightButton.PutValue(0);
|
|
}
|
|
else
|
|
ggRearLeftLightButton.PutValue(-1);
|
|
}
|
|
//--------------
|
|
// REFLEKTOR GORNY
|
|
if ((DynamicObject->iLights[0] & 4) == 4)
|
|
if ((mvOccupied->ActiveCab) == 1)
|
|
ggUpperLightButton.PutValue(1);
|
|
else if ((mvOccupied->ActiveCab) == -1)
|
|
ggRearUpperLightButton.PutValue(1);
|
|
|
|
if ((DynamicObject->iLights[1] & 4) == 4)
|
|
if ((mvOccupied->ActiveCab) == -1)
|
|
ggUpperLightButton.PutValue(1);
|
|
else if ((mvOccupied->ActiveCab) == 1)
|
|
ggRearUpperLightButton.PutValue(1);
|
|
//--------------
|
|
// REFLEKTOR PRAWY
|
|
// główne oświetlenie
|
|
if ((DynamicObject->iLights[0] & 16) == 16)
|
|
if ((mvOccupied->ActiveCab) == 1)
|
|
ggRightLightButton.PutValue(1);
|
|
else if ((mvOccupied->ActiveCab) == -1)
|
|
ggRearRightLightButton.PutValue(1);
|
|
|
|
if ((DynamicObject->iLights[1] & 16) == 16)
|
|
if ((mvOccupied->ActiveCab) == -1)
|
|
ggRightLightButton.PutValue(1);
|
|
else if ((mvOccupied->ActiveCab) == 1)
|
|
ggRearRightLightButton.PutValue(1);
|
|
|
|
// końcówki
|
|
if ((DynamicObject->iLights[0] & 32) == 32)
|
|
if ((mvOccupied->ActiveCab) == 1)
|
|
{
|
|
if (ggRightEndLightButton.SubModel)
|
|
{
|
|
ggRightEndLightButton.PutValue(1);
|
|
ggRightLightButton.PutValue(0);
|
|
}
|
|
else
|
|
ggRightLightButton.PutValue(-1);
|
|
}
|
|
else if ((mvOccupied->ActiveCab) == -1)
|
|
{
|
|
if (ggRearRightEndLightButton.SubModel)
|
|
{
|
|
ggRearRightEndLightButton.PutValue(1);
|
|
ggRearRightLightButton.PutValue(0);
|
|
}
|
|
else
|
|
ggRearRightLightButton.PutValue(-1);
|
|
}
|
|
|
|
if ((DynamicObject->iLights[1] & 32) == 32)
|
|
if ((mvOccupied->ActiveCab) == -1)
|
|
{
|
|
if (ggRightEndLightButton.SubModel)
|
|
{
|
|
ggRightEndLightButton.PutValue(1);
|
|
ggRightLightButton.PutValue(0);
|
|
}
|
|
else
|
|
ggRightLightButton.PutValue(-1);
|
|
}
|
|
else if ((mvOccupied->ActiveCab) == 1)
|
|
{
|
|
if (ggRearRightEndLightButton.SubModel)
|
|
{
|
|
ggRearRightEndLightButton.PutValue(1);
|
|
ggRearRightLightButton.PutValue(0);
|
|
}
|
|
else
|
|
ggRearRightLightButton.PutValue(-1);
|
|
}
|
|
#endif
|
|
if (ggLightsButton.SubModel)
|
|
{
|
|
ggLightsButton.PutValue(mvOccupied->LightsPos - 1);
|
|
ggLightsButton.Update();
|
|
}
|
|
ggDimHeadlightsButton.Update();
|
|
//---------
|
|
// hunter-080812: poprawka na ogrzewanie w elektrykach - usuniete uzaleznienie od przetwornicy
|
|
if ((((mvControlled->EngineType == ElectricSeriesMotor) && (mvControlled->Mains == true) &&
|
|
(mvControlled->ConvOvldFlag == false)) ||
|
|
(mvControlled->ConverterFlag)) &&
|
|
(mvControlled->Heating == true))
|
|
btLampkaOgrzewanieSkladu.TurnOn();
|
|
else
|
|
btLampkaOgrzewanieSkladu.TurnOff();
|
|
|
|
//----------
|
|
|
|
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
|
|
if (mvOccupied->SecuritySystem.Status > 0)
|
|
{
|
|
if (fBlinkTimer > fCzuwakBlink)
|
|
fBlinkTimer = -fCzuwakBlink;
|
|
else
|
|
fBlinkTimer += dt;
|
|
|
|
// hunter-091012: dodanie testu czuwaka
|
|
if ((TestFlag(mvOccupied->SecuritySystem.Status, s_aware)) ||
|
|
(TestFlag(mvOccupied->SecuritySystem.Status, s_CAtest)))
|
|
{
|
|
btLampkaCzuwaka.Turn(fBlinkTimer > 0);
|
|
}
|
|
else
|
|
btLampkaCzuwaka.TurnOff();
|
|
btLampkaSHP.Turn(TestFlag(mvOccupied->SecuritySystem.Status, s_active));
|
|
|
|
// hunter-091012: rozdzielenie alarmow
|
|
// if (TestFlag(mvOccupied->SecuritySystem.Status,s_alarm))
|
|
if (TestFlag(mvOccupied->SecuritySystem.Status, s_CAalarm) ||
|
|
TestFlag(mvOccupied->SecuritySystem.Status, s_SHPalarm))
|
|
{
|
|
if (dsbBuzzer)
|
|
{
|
|
dsbBuzzer->loop().play();
|
|
#ifdef _WIN32
|
|
Console::BitsSet(1 << 14); // ustawienie bitu 16 na PoKeys
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (dsbBuzzer)
|
|
{
|
|
dsbBuzzer->stop();
|
|
#ifdef _WIN32
|
|
Console::BitsClear(1 << 14); // ustawienie bitu 16 na PoKeys
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else // wylaczone
|
|
{
|
|
btLampkaCzuwaka.TurnOff();
|
|
btLampkaSHP.TurnOff();
|
|
if (dsbBuzzer)
|
|
{
|
|
dsbBuzzer->stop();
|
|
}
|
|
}
|
|
|
|
//******************************************
|
|
// przelaczniki
|
|
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
if( Console::Pressed( Global::Keys[ k_Horn ] ) )
|
|
{
|
|
if (Global::shiftState)
|
|
{
|
|
SetFlag(mvOccupied->WarningSignal, 2);
|
|
mvOccupied->WarningSignal &= (255 - 1);
|
|
if (ggHornButton.SubModel)
|
|
ggHornButton.UpdateValue(1);
|
|
}
|
|
else
|
|
{
|
|
SetFlag(mvOccupied->WarningSignal, 1);
|
|
mvOccupied->WarningSignal &= (255 - 2);
|
|
if (ggHornButton.SubModel)
|
|
ggHornButton.UpdateValue(-1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mvOccupied->WarningSignal = 0;
|
|
if (ggHornButton.SubModel)
|
|
ggHornButton.UpdateValue(0);
|
|
}
|
|
|
|
if (Console::Pressed(Global::Keys[k_Horn2]))
|
|
if (Global::Keys[k_Horn2] != Global::Keys[k_Horn])
|
|
{
|
|
SetFlag(mvOccupied->WarningSignal, 2);
|
|
}
|
|
//----------------
|
|
// hunter-141211: wyl. szybki zalaczony i wylaczony przeniesiony z
|
|
// OnKeyPress()
|
|
if (Global::shiftState && Console::Pressed(Global::Keys[k_Main]))
|
|
{
|
|
fMainRelayTimer += dt;
|
|
ggMainOnButton.PutValue(1);
|
|
if (mvControlled->Mains != true) // hunter-080812: poprawka
|
|
mvControlled->ConverterSwitch(false);
|
|
if (fMainRelayTimer > mvControlled->InitialCtrlDelay) // wlaczanie WSa z opoznieniem
|
|
if (mvControlled->MainSwitch(true))
|
|
{
|
|
// if (mvControlled->MainCtrlPos!=0) //zabezpieczenie, by po
|
|
// wrzuceniu pozycji przed wlaczonym
|
|
// mvControlled->StLinFlag=true; //WSem nie wrzucilo na ta
|
|
// pozycje po jego zalaczeniu //yBARC - co to tutaj robi?!
|
|
if (mvControlled->EngineType == DieselEngine)
|
|
dsbDieselIgnition->play();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ggConverterButton.GetValue() !=
|
|
0) // po puszczeniu przycisku od WSa odpalanie potwora
|
|
mvControlled->ConverterSwitch(true);
|
|
// hunter-091012: przeniesione z mover.pas, zeby dzwiek sie nie zapetlal,
|
|
// drugi warunek zeby nie odtwarzalo w nieskonczonosc i przeniesienie
|
|
// zerowania timera
|
|
if ((mvControlled->Mains != true) && (fMainRelayTimer > 0))
|
|
{
|
|
dsbRelay->play();
|
|
fMainRelayTimer = 0;
|
|
}
|
|
ggMainOnButton.UpdateValue(0);
|
|
}
|
|
//---
|
|
if (!Global::shiftState && Console::Pressed(Global::Keys[k_Main]))
|
|
{
|
|
ggMainOffButton.PutValue(1);
|
|
if (mvControlled->MainSwitch(false))
|
|
dsbRelay->play();
|
|
}
|
|
else
|
|
ggMainOffButton.UpdateValue(0);
|
|
/* if (cKey==Global::Keys[k_Main]) //z shiftem
|
|
{
|
|
ggMainOnButton.PutValue(1);
|
|
if (mvControlled->MainSwitch(true))
|
|
{
|
|
if (mvControlled->MainCtrlPos!=0) //hunter-131211: takie
|
|
zabezpieczenie
|
|
mvControlled->StLinFlag=true;
|
|
|
|
if (mvControlled->EngineType==DieselEngine)
|
|
dsbDieselIgnition->Play(0,0,0);
|
|
else
|
|
dsbNastawnikJazdy->Play(0,0,0);
|
|
}
|
|
}
|
|
else */
|
|
|
|
/* if (cKey==Global::Keys[k_Main]) //bez shifta
|
|
{
|
|
ggMainOffButton.PutValue(1);
|
|
if (mvControlled->MainSwitch(false))
|
|
{
|
|
dsbNastawnikJazdy->Play(0,0,0);
|
|
}
|
|
}
|
|
else */
|
|
//----------------
|
|
// hunter-131211: czuwak przeniesiony z OnKeyPress
|
|
// hunter-091012: zrobiony test czuwaka
|
|
if (Console::Pressed(Global::Keys[k_Czuwak]))
|
|
{ // czuwak testuje kierunek, ale podobno w
|
|
// EZT nie, więc może być w rozrządczym
|
|
fCzuwakTestTimer += dt;
|
|
ggSecurityResetButton.PutValue(1);
|
|
if (CAflag == false)
|
|
{
|
|
CAflag = true;
|
|
mvOccupied->SecuritySystemReset();
|
|
}
|
|
else if (fCzuwakTestTimer > 1.0)
|
|
SetFlag(mvOccupied->SecuritySystem.Status, s_CAtest);
|
|
}
|
|
else
|
|
{
|
|
fCzuwakTestTimer = 0;
|
|
ggSecurityResetButton.UpdateValue(0);
|
|
if (TestFlag(mvOccupied->SecuritySystem.Status,
|
|
s_CAtest)) //&&(!TestFlag(mvControlled->SecuritySystem.Status,s_CAebrake)))
|
|
{
|
|
SetFlag(mvOccupied->SecuritySystem.Status, -s_CAtest);
|
|
mvOccupied->s_CAtestebrake = false;
|
|
mvOccupied->SecuritySystem.SystemBrakeCATestTimer = 0;
|
|
// if ((!TestFlag(mvOccupied->SecuritySystem.Status,s_SHPebrake))
|
|
// ||(!TestFlag(mvOccupied->SecuritySystem.Status,s_CAebrake)))
|
|
// mvControlled->EmergencyBrakeFlag=false; //YB-HN
|
|
}
|
|
CAflag = false;
|
|
}
|
|
/*
|
|
if ( Console::Pressed(Global::Keys[k_Czuwak]) )
|
|
{
|
|
ggSecurityResetButton.PutValue(1);
|
|
if ((mvOccupied->SecuritySystem.Status&s_aware)&&
|
|
(mvOccupied->SecuritySystem.Status&s_active))
|
|
{
|
|
mvOccupied->SecuritySystem.SystemTimer=0;
|
|
mvOccupied->SecuritySystem.Status-=s_aware;
|
|
mvOccupied->SecuritySystem.VelocityAllowed=-1;
|
|
CAflag=1;
|
|
}
|
|
else if (CAflag!=1)
|
|
mvOccupied->SecuritySystemReset();
|
|
}
|
|
else
|
|
{
|
|
ggSecurityResetButton.UpdateValue(0);
|
|
CAflag=0;
|
|
}
|
|
*/
|
|
|
|
//-----------------
|
|
// hunter-201211: piasecznica przeniesiona z OnKeyPress, wlacza sie tylko,
|
|
// gdy trzymamy przycisk, a nie tak jak wczesniej (raz nacisnelo sie 's'
|
|
// i sypala caly czas)
|
|
/*
|
|
if (cKey==Global::Keys[k_Sand])
|
|
{
|
|
if (mvControlled->SandDoseOn())
|
|
if (mvControlled->SandDose)
|
|
{
|
|
dsbPneumaticRelay->SetVolume(-30);
|
|
dsbPneumaticRelay->Play(0,0,0);
|
|
}
|
|
}
|
|
*/
|
|
|
|
if( Console::Pressed( Global::Keys[ k_Sand ] ) )
|
|
{
|
|
if (mvControlled->TrainType != dt_EZT && ggSandButton.SubModel != NULL)
|
|
{
|
|
// dsbPneumaticRelay->SetVolume(-30);
|
|
// dsbPneumaticRelay->Play(0,0,0);
|
|
ggSandButton.PutValue(1);
|
|
mvControlled->SandDose = true;
|
|
// mvControlled->SandDoseOn(true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mvControlled->SandDose = false;
|
|
// mvControlled->SandDoseOn(false);
|
|
// dsbPneumaticRelay->SetVolume(-30);
|
|
// dsbPneumaticRelay->Play(0,0,0);
|
|
}
|
|
|
|
//-----------------
|
|
// hunter-221211: hamowanie przy poslizgu
|
|
if (Console::Pressed(Global::Keys[k_AntiSlipping]))
|
|
{
|
|
if (mvControlled->BrakeSystem != ElectroPneumatic)
|
|
{
|
|
ggAntiSlipButton.PutValue(1);
|
|
mvControlled->AntiSlippingBrake();
|
|
}
|
|
}
|
|
else
|
|
ggAntiSlipButton.UpdateValue(0);
|
|
//-----------------
|
|
// hunter-261211: przetwornica i sprezarka
|
|
if (Global::shiftState &&
|
|
Console::Pressed(Global::Keys[k_Converter])) // NBMX 14-09-2003: przetwornica wl
|
|
{ //(mvControlled->CompressorPower<2)
|
|
ggConverterButton.PutValue(1);
|
|
if ((mvControlled->PantFrontVolt != 0.0) || (mvControlled->PantRearVolt != 0.0) ||
|
|
(mvControlled->EnginePowerSource.SourceType !=
|
|
CurrentCollector) /*||(!Global::bLiveTraction)*/)
|
|
mvControlled->ConverterSwitch(true);
|
|
// if
|
|
// ((mvControlled->EngineType!=ElectricSeriesMotor)&&(mvControlled->TrainType!=dt_EZT))
|
|
// //hunter-110212: poprawka dla EZT
|
|
if (mvControlled->CompressorPower == 2) // hunter-091012: tak jest poprawnie
|
|
mvControlled->CompressorSwitch(true);
|
|
}
|
|
else
|
|
{
|
|
if (mvControlled->ConvSwitchType == "impulse")
|
|
{
|
|
ggConverterButton.PutValue(0);
|
|
ggConverterOffButton.PutValue(0);
|
|
}
|
|
}
|
|
// if (
|
|
// Global::shiftState&&Console::Pressed(Global::Keys[k_Compressor])&&((mvControlled->EngineType==ElectricSeriesMotor)||(mvControlled->TrainType==dt_EZT))
|
|
// ) //NBMX 14-09-2003: sprezarka wl
|
|
if (Global::shiftState && Console::Pressed(Global::Keys[k_Compressor]) &&
|
|
(mvControlled->CompressorPower < 2)) // hunter-091012: tak jest poprawnie
|
|
{ // hunter-110212: poprawka dla EZT
|
|
ggCompressorButton.PutValue(1);
|
|
mvControlled->CompressorSwitch(true);
|
|
}
|
|
if (!Global::shiftState &&
|
|
Console::Pressed(Global::Keys[k_Converter])) // NBMX 14-09-2003: przetwornica wl
|
|
{
|
|
ggConverterButton.PutValue(0);
|
|
ggConverterOffButton.PutValue(1);
|
|
mvControlled->ConverterSwitch(false);
|
|
if ((mvControlled->TrainType == dt_EZT) && (!TestFlag(mvControlled->EngDmgFlag, 4)))
|
|
mvControlled->ConvOvldFlag = false;
|
|
}
|
|
// if (
|
|
// !Global::shiftState&&Console::Pressed(Global::Keys[k_Compressor])&&((mvControlled->EngineType==ElectricSeriesMotor)||(mvControlled->TrainType==dt_EZT))
|
|
// ) //NBMX 14-09-2003: sprezarka wl
|
|
if (!Global::shiftState && Console::Pressed(Global::Keys[k_Compressor]) &&
|
|
(mvControlled->CompressorPower < 2)) // hunter-091012: tak jest poprawnie
|
|
{ // hunter-110212: poprawka dla EZT
|
|
ggCompressorButton.PutValue(0);
|
|
mvControlled->CompressorSwitch(false);
|
|
}
|
|
/*
|
|
bez szifta
|
|
if (cKey==Global::Keys[k_Converter]) //NBMX wyl przetwornicy
|
|
{
|
|
if (mvControlled->ConverterSwitch(false))
|
|
{
|
|
dsbSwitch->SetVolume(DSBVOLUME_MAX);
|
|
dsbSwitch->Play(0,0,0);;
|
|
}
|
|
}
|
|
else
|
|
if (cKey==Global::Keys[k_Compressor]) //NBMX wyl sprezarka
|
|
{
|
|
if (mvControlled->CompressorSwitch(false))
|
|
{
|
|
dsbSwitch->SetVolume(DSBVOLUME_MAX);
|
|
dsbSwitch->Play(0,0,0);;
|
|
}
|
|
}
|
|
else
|
|
*/
|
|
//-----------------
|
|
if ((!FreeFlyModeFlag) &&
|
|
(!(DynamicObject->Mechanik ? DynamicObject->Mechanik->AIControllFlag : false)))
|
|
{
|
|
if (Console::Pressed(Global::Keys[k_Releaser])) // yB: odluzniacz caly
|
|
// czas trzymany, warunki
|
|
// powinny byc takie same,
|
|
// jak przy naciskaniu.
|
|
// Wlasciwie stamtad mozna
|
|
// wyrzucic sprawdzanie
|
|
// nacisniecia.
|
|
{
|
|
if ((mvControlled->EngineType == ElectricSeriesMotor) ||
|
|
(mvControlled->EngineType == DieselElectric))
|
|
if (mvControlled->TrainType != dt_EZT)
|
|
if ((mvOccupied->BrakeCtrlPosNo > 0) && (mvControlled->ActiveDir != 0))
|
|
{
|
|
ggReleaserButton.PutValue(1);
|
|
mvOccupied->BrakeReleaser(1);
|
|
}
|
|
} // releaser
|
|
else
|
|
mvOccupied->BrakeReleaser(0);
|
|
} // FFMF
|
|
|
|
if (Console::Pressed(Global::Keys[k_Univ1]))
|
|
{
|
|
if (!DebugModeFlag)
|
|
{
|
|
if (ggUniversal1Button.SubModel)
|
|
if (Global::shiftState)
|
|
ggUniversal1Button.IncValue(dt / 2);
|
|
else
|
|
ggUniversal1Button.DecValue(dt / 2);
|
|
}
|
|
}
|
|
if (!Console::Pressed(Global::Keys[k_SmallCompressor]))
|
|
// Ra: przecieść to na zwolnienie klawisza
|
|
if (DynamicObject->Mechanik ? !DynamicObject->Mechanik->AIControllFlag :
|
|
false) // nie wyłączać, gdy AI
|
|
mvControlled->PantCompFlag = false; // wyłączona, gdy nie trzymamy klawisza
|
|
/*
|
|
// NOTE: disabled to allow 'prototypical' 'tricking' pantograph compressor into running unattended
|
|
if( ( ( DynamicObject->Mechanik != nullptr )
|
|
&& ( false == DynamicObject->Mechanik->AIControllFlag ) )
|
|
&& ( mvControlled->TrainType == dt_EZT ?
|
|
( mvControlled != mvOccupied ) :
|
|
( mvOccupied->ActiveCab != 0 ) ) ) {
|
|
// HACK: if we're in one of the cabs we can't be activating pantograph compressor
|
|
// NOTE: this will break in multiplayer setups, do a proper tracking of pantograph user then
|
|
mvControlled->PantCompFlag = false;
|
|
}
|
|
*/
|
|
if (Console::Pressed(Global::Keys[k_Univ2]))
|
|
{
|
|
if (!DebugModeFlag)
|
|
{
|
|
if (ggUniversal2Button.SubModel)
|
|
if (Global::shiftState)
|
|
ggUniversal2Button.IncValue(dt / 2);
|
|
else
|
|
ggUniversal2Button.DecValue(dt / 2);
|
|
}
|
|
}
|
|
|
|
// hunter-091012: zrobione z uwzglednieniem przelacznika swiatla
|
|
if (Console::Pressed(Global::Keys[k_Univ3]))
|
|
{
|
|
if (Global::shiftState)
|
|
{
|
|
if (Global::ctrlState)
|
|
{
|
|
bCabLight = true;
|
|
if (ggCabLightButton.SubModel)
|
|
{
|
|
ggCabLightButton.PutValue(1);
|
|
btCabLight.TurnOn();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ggInstrumentLightButton.SubModel)
|
|
{
|
|
ggInstrumentLightButton.PutValue(1); // hunter-131211: z UpdateValue na
|
|
// PutValue - by zachowywal sie jak
|
|
// pozostale przelaczniki
|
|
if (btInstrumentLight.Active())
|
|
InstrumentLightActive = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Global::ctrlState)
|
|
{
|
|
bCabLight = false;
|
|
if (ggCabLightButton.SubModel)
|
|
{
|
|
ggCabLightButton.PutValue(0);
|
|
btCabLight.TurnOff();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ggInstrumentLightButton.SubModel)
|
|
{
|
|
ggInstrumentLightButton.PutValue(0); // hunter-131211: z UpdateValue na
|
|
// PutValue - by zachowywal sie jak
|
|
// pozostale przelaczniki
|
|
if (btInstrumentLight.Active())
|
|
InstrumentLightActive = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
// ABu030405 obsluga lampki uniwersalnej:
|
|
if (btInstrumentLight.Active()) // w ogóle jest
|
|
if (InstrumentLightActive) // załączona
|
|
switch (InstrumentLightType)
|
|
{
|
|
case 0:
|
|
btInstrumentLight.Turn( mvControlled->Battery || mvControlled->ConverterFlag );
|
|
break;
|
|
case 1:
|
|
btInstrumentLight.Turn(mvControlled->Mains);
|
|
break;
|
|
case 2:
|
|
btInstrumentLight.Turn(mvControlled->ConverterFlag);
|
|
break;
|
|
default:
|
|
btInstrumentLight.TurnOff();
|
|
}
|
|
else
|
|
btInstrumentLight.TurnOff();
|
|
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
// hunter-091012: przepisanie univ4 i zrobione z uwzglednieniem przelacznika
|
|
// swiatla
|
|
if (Console::Pressed(Global::Keys[k_Univ4]))
|
|
{
|
|
if( Global::shiftState )
|
|
{
|
|
if (Global::ctrlState)
|
|
{
|
|
bCabLightDim = true;
|
|
if (ggCabLightDimButton.SubModel)
|
|
{
|
|
ggCabLightDimButton.PutValue(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Universal4Active = true;
|
|
// ggUniversal4Button.UpdateValue(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Global::ctrlState)
|
|
{
|
|
bCabLightDim = false;
|
|
if (ggCabLightDimButton.SubModel)
|
|
{
|
|
ggCabLightDimButton.PutValue(0); // hunter-131211: z UpdateValue na
|
|
// PutValue - by zachowywal sie jak
|
|
// pozostale przelaczniki
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Universal4Active = false;
|
|
// ggUniversal4Button.UpdateValue(0);
|
|
}
|
|
}
|
|
}
|
|
// Odskakiwanie hamulce EP
|
|
if ((!Console::Pressed(Global::Keys[k_DecBrakeLevel])) &&
|
|
(!Console::Pressed(Global::Keys[k_WaveBrake])) && (mvOccupied->BrakeCtrlPos == -1) &&
|
|
(mvOccupied->BrakeHandle == FVel6) && (DynamicObject->Controller != AIdriver) &&
|
|
(Global::iFeedbackMode != 4) && (!(Global::bMWDmasterEnable && Global::bMWDBreakEnable)))
|
|
{
|
|
// mvOccupied->BrakeCtrlPos=(mvOccupied->BrakeCtrlPos)+1;
|
|
// mvOccupied->IncBrakeLevel();
|
|
mvOccupied->BrakeLevelSet(mvOccupied->BrakeCtrlPos + 1);
|
|
keybrakecount = 0;
|
|
if ((mvOccupied->TrainType == dt_EZT) && (mvControlled->Mains) &&
|
|
(mvControlled->ActiveDir != 0))
|
|
{
|
|
dsbPneumaticSwitch->play();
|
|
}
|
|
}
|
|
#endif
|
|
/*
|
|
// NOTE: disabled, as it doesn't seem to be used.
|
|
// TODO: get rid of it altogether when we're cleaninng
|
|
// Ra: przeklejka z SPKS - płynne poruszanie hamulcem
|
|
// if
|
|
// ((mvOccupied->BrakeHandle==FV4a)&&(Console::Pressed(Global::Keys[k_IncBrakeLevel])))
|
|
if ((Console::Pressed(Global::Keys[k_IncBrakeLevel])))
|
|
{
|
|
if (Global::ctrlState)
|
|
{
|
|
// mvOccupied->BrakeCtrlPos2-=dt/20.0;
|
|
// if (mvOccupied->BrakeCtrlPos2<-1.5) mvOccupied->BrakeCtrlPos2=-1.5;
|
|
}
|
|
else
|
|
{
|
|
// mvOccupied->BrakeCtrlPosR+=(mvOccupied->BrakeCtrlPosR>mvOccupied->BrakeCtrlPosNo?0:dt*2);
|
|
// mvOccupied->BrakeCtrlPos= floor(mvOccupied->BrakeCtrlPosR+0.499);
|
|
}
|
|
}
|
|
// if
|
|
// ((mvOccupied->BrakeHandle==FV4a)&&(Console::Pressed(Global::Keys[k_DecBrakeLevel])))
|
|
if ((Console::Pressed(Global::Keys[k_DecBrakeLevel])))
|
|
{
|
|
if (Global::ctrlState)
|
|
{
|
|
// mvOccupied->BrakeCtrlPos2+=(mvOccupied->BrakeCtrlPos2>2?0:dt/20.0);
|
|
// if (mvOccupied->BrakeCtrlPos2<-3) mvOccupied->BrakeCtrlPos2=-3;
|
|
// mvOccupied->BrakeLevelAdd(mvOccupied->fBrakeCtrlPos<-1?0:dt*2);
|
|
}
|
|
else
|
|
{
|
|
// mvOccupied->BrakeCtrlPosR-=(mvOccupied->BrakeCtrlPosR<-1?0:dt*2);
|
|
// mvOccupied->BrakeCtrlPos= floor(mvOccupied->BrakeCtrlPosR+0.499);
|
|
// mvOccupied->BrakeLevelAdd(mvOccupied->fBrakeCtrlPos<-1?0:-dt*2);
|
|
}
|
|
}
|
|
*/
|
|
if ((mvOccupied->BrakeHandle == FV4a) && (Console::Pressed(Global::Keys[k_IncBrakeLevel])))
|
|
{
|
|
if (Global::ctrlState)
|
|
{
|
|
mvOccupied->BrakeCtrlPos2 -= dt / 20.0;
|
|
if (mvOccupied->BrakeCtrlPos2 < -1.5)
|
|
mvOccupied->BrakeCtrlPos2 = -1.5;
|
|
}
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
else
|
|
{
|
|
// mvOccupied->BrakeCtrlPosR+=(mvOccupied->BrakeCtrlPosR>mvOccupied->BrakeCtrlPosNo?0:dt*2);
|
|
mvOccupied->BrakeLevelAdd(dt * 2);
|
|
// mvOccupied->BrakeCtrlPos=
|
|
// floor(mvOccupied->BrakeCtrlPosR+0.499);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if ((mvOccupied->BrakeHandle == FV4a) && (Console::Pressed(Global::Keys[k_DecBrakeLevel])))
|
|
{
|
|
if (Global::ctrlState)
|
|
{
|
|
mvOccupied->BrakeCtrlPos2 += (mvOccupied->BrakeCtrlPos2 > 2 ? 0 : dt / 20.0);
|
|
if (mvOccupied->BrakeCtrlPos2 < -3)
|
|
mvOccupied->BrakeCtrlPos2 = -3;
|
|
}
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
else
|
|
{
|
|
// mvOccupied->BrakeCtrlPosR-=(mvOccupied->BrakeCtrlPosR<-1?0:dt*2);
|
|
// mvOccupied->BrakeCtrlPos=
|
|
// floor(mvOccupied->BrakeCtrlPosR+0.499);
|
|
mvOccupied->BrakeLevelAdd(-dt * 2);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// bool kEP;
|
|
// kEP=(mvOccupied->BrakeSubsystem==Knorr)||(mvOccupied->BrakeSubsystem==Hik)||(mvOccupied->BrakeSubsystem==Kk);
|
|
if ((mvOccupied->BrakeSystem == ElectroPneumatic) && ((mvOccupied->BrakeHandle == St113)) &&
|
|
(mvControlled->EpFuse == true))
|
|
if (Console::Pressed(Global::Keys[k_AntiSlipping])) // kEP
|
|
{
|
|
ggAntiSlipButton.UpdateValue(1);
|
|
if (mvOccupied->SwitchEPBrake(1))
|
|
{
|
|
dsbPneumaticSwitch->play();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mvOccupied->SwitchEPBrake(0))
|
|
{
|
|
dsbPneumaticSwitch->play();
|
|
}
|
|
}
|
|
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
if (Console::Pressed(Global::Keys[k_DepartureSignal]))
|
|
{
|
|
ggDepartureSignalButton.PutValue(1);
|
|
btLampkaDepartureSignal.TurnOn();
|
|
mvControlled->DepartureSignal = true;
|
|
}
|
|
else
|
|
{
|
|
btLampkaDepartureSignal.TurnOff();
|
|
if (DynamicObject->Mechanik) // może nie być?
|
|
if (!DynamicObject->Mechanik->AIControllFlag) // tylko jeśli nie prowadzi AI
|
|
mvControlled->DepartureSignal = false;
|
|
}
|
|
if (Console::Pressed(Global::Keys[k_Main])) //[]
|
|
{
|
|
if (Global::shiftState)
|
|
ggMainButton.PutValue(1);
|
|
else
|
|
ggMainButton.PutValue(0);
|
|
}
|
|
else
|
|
ggMainButton.PutValue(0);
|
|
if (Console::Pressed(Global::Keys[k_CurrentNext]))
|
|
{
|
|
if (mvControlled->TrainType != dt_EZT)
|
|
{
|
|
if (ShowNextCurrent == false)
|
|
{
|
|
if (ggNextCurrentButton.SubModel)
|
|
{
|
|
ggNextCurrentButton.UpdateValue(1);
|
|
dsbSwitch->play();
|
|
ShowNextCurrent = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Global::shiftState)
|
|
{
|
|
// if (Console::Pressed(k_CurrentNext))
|
|
{ // Ra: było pod GLFW_KEY_F3
|
|
if ((mvOccupied->EpFuseSwitch(true)))
|
|
{
|
|
dsbPneumaticSwitch->play();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if (Console::Pressed(k_CurrentNext))
|
|
{ // Ra: było pod GLFW_KEY_F3
|
|
if (Global::ctrlState)
|
|
{
|
|
if ((mvOccupied->EpFuseSwitch(false)))
|
|
{
|
|
dsbPneumaticSwitch->play();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ShowNextCurrent == true)
|
|
{
|
|
if (ggNextCurrentButton.SubModel)
|
|
{
|
|
ggNextCurrentButton.UpdateValue(0);
|
|
dsbSwitch->play();
|
|
ShowNextCurrent = false;
|
|
}
|
|
}
|
|
}
|
|
// Winger 010304 PantAllDownButton
|
|
if (Console::Pressed(Global::Keys[k_PantFrontUp]))
|
|
{
|
|
if (Global::shiftState)
|
|
ggPantFrontButton.PutValue(1);
|
|
else
|
|
ggPantAllDownButton.PutValue(1);
|
|
}
|
|
else if (mvControlled->PantSwitchType == "impulse")
|
|
{
|
|
ggPantFrontButton.PutValue(0);
|
|
ggPantAllDownButton.PutValue(0);
|
|
}
|
|
if (Console::Pressed(Global::Keys[k_PantRearUp]))
|
|
{
|
|
if (Global::shiftState)
|
|
ggPantRearButton.PutValue(1);
|
|
else
|
|
ggPantFrontButtonOff.PutValue(1);
|
|
}
|
|
else if (mvControlled->PantSwitchType == "impulse")
|
|
{
|
|
ggPantRearButton.PutValue(0);
|
|
ggPantFrontButtonOff.PutValue(0);
|
|
}
|
|
#endif
|
|
/* if ((mvControlled->Mains) &&
|
|
(mvControlled->EngineType==ElectricSeriesMotor))
|
|
{
|
|
//tu dac w przyszlosci zaleznosc od wlaczenia przetwornicy
|
|
if (mvControlled->ConverterFlag) //NBMX -obsluga przetwornicy
|
|
{
|
|
//glosnosc zalezna od nap. sieci
|
|
//-2000 do 0
|
|
long tmpVol;
|
|
int trackVol;
|
|
trackVol=3550-2000;
|
|
if (mvControlled->RunningTraction.TractionVoltage<2000)
|
|
{
|
|
tmpVol=0;
|
|
}
|
|
else
|
|
{
|
|
tmpVol=mvControlled->RunningTraction.TractionVoltage-2000;
|
|
}
|
|
sConverter.Volume(-2000*(trackVol-tmpVol)/trackVol);
|
|
|
|
if (!sConverter.Playing())
|
|
sConverter.TurnOn();
|
|
}
|
|
else //wyl przetwornicy
|
|
sConverter.TurnOff();
|
|
}
|
|
else
|
|
{
|
|
if (sConverter.Playing())
|
|
sConverter.TurnOff();
|
|
}
|
|
sConverter.Update();
|
|
*/
|
|
|
|
// if (fabs(DynamicObject->GetVelocity())>0.5)
|
|
if( dsbHasler != nullptr ) {
|
|
if( ( false == FreeFlyModeFlag ) && ( fTachoCount > maxtacho ) ) {
|
|
dsbHasler->loop().play();
|
|
}
|
|
else {
|
|
if( ( true == FreeFlyModeFlag ) || ( fTachoCount < 1 ) ) {
|
|
dsbHasler->stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
// koniec mieszania z dzwiekami
|
|
|
|
// guziki:
|
|
ggMainOffButton.Update();
|
|
ggMainOnButton.Update();
|
|
ggMainButton.Update();
|
|
ggSecurityResetButton.Update();
|
|
ggReleaserButton.Update();
|
|
ggAntiSlipButton.Update();
|
|
ggSandButton.Update();
|
|
ggFuseButton.Update();
|
|
ggConverterFuseButton.Update();
|
|
ggStLinOffButton.Update();
|
|
ggRadioButton.Update();
|
|
ggDepartureSignalButton.Update();
|
|
|
|
ggPantFrontButton.Update();
|
|
ggPantRearButton.Update();
|
|
ggPantSelectedButton.Update();
|
|
ggPantFrontButtonOff.Update();
|
|
ggPantRearButtonOff.Update();
|
|
ggPantSelectedDownButton.Update();
|
|
ggPantAllDownButton.Update();
|
|
ggPantCompressorButton.Update();
|
|
ggPantCompressorValve.Update();
|
|
|
|
ggUpperLightButton.Update();
|
|
ggLeftLightButton.Update();
|
|
ggRightLightButton.Update();
|
|
ggLeftEndLightButton.Update();
|
|
ggRightEndLightButton.Update();
|
|
// hunter-230112
|
|
ggRearUpperLightButton.Update();
|
|
ggRearLeftLightButton.Update();
|
|
ggRearRightLightButton.Update();
|
|
ggRearLeftEndLightButton.Update();
|
|
ggRearRightEndLightButton.Update();
|
|
//------------
|
|
ggConverterButton.Update();
|
|
ggConverterLocalButton.Update();
|
|
ggConverterOffButton.Update();
|
|
ggTrainHeatingButton.Update();
|
|
ggSignallingButton.Update();
|
|
ggNextCurrentButton.Update();
|
|
ggHornButton.Update();
|
|
ggHornLowButton.Update();
|
|
ggHornHighButton.Update();
|
|
/*
|
|
ggUniversal1Button.Update();
|
|
ggUniversal2Button.Update();
|
|
if( Universal4Active ) {
|
|
ggUniversal4Button.PermIncValue( dt );
|
|
}
|
|
ggUniversal4Button.Update();
|
|
*/
|
|
for( auto &universal : ggUniversals ) {
|
|
universal.Update();
|
|
}
|
|
// hunter-091012
|
|
ggInstrumentLightButton.Update();
|
|
ggCabLightButton.Update();
|
|
ggCabLightDimButton.Update();
|
|
ggBatteryButton.Update();
|
|
//------
|
|
#ifdef EU07_USE_OLD_COMMAND_SYSTEM
|
|
ggMainOffButton.UpdateValue(0);
|
|
ggMainOnButton.UpdateValue(0);
|
|
ggSecurityResetButton.UpdateValue(0);
|
|
ggReleaserButton.UpdateValue(0);
|
|
ggSandButton.UpdateValue(0);
|
|
ggAntiSlipButton.UpdateValue(0);
|
|
ggDepartureSignalButton.UpdateValue( 0 );
|
|
ggFuseButton.UpdateValue( 0 );
|
|
ggConverterFuseButton.UpdateValue(0);
|
|
#endif
|
|
pyScreens.update();
|
|
}
|
|
// wyprowadzenie sygnałów dla haslera na PoKeys (zaznaczanie na taśmie)
|
|
btHaslerBrakes.Turn(DynamicObject->MoverParameters->BrakePress > 0.4); // ciśnienie w cylindrach
|
|
btHaslerCurrent.Turn(DynamicObject->MoverParameters->Im != 0.0); // prąd na silnikach
|
|
|
|
// calculate current level of interior illumination
|
|
// TODO: organize it along with rest of train update in a more sensible arrangement
|
|
switch( iCabLightFlag ) // Ra: uzeleżnic od napięcia w obwodzie sterowania
|
|
{ // hunter-091012: uzaleznienie jasnosci od przetwornicy
|
|
case 0: {
|
|
//światło wewnętrzne zgaszone
|
|
DynamicObject->InteriorLightLevel = 0.0f;
|
|
break;
|
|
}
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// catch cases where the power goes out, and the linebreaker state is left as closed
|
|
if( ( m_linebreakerstate == 1 )
|
|
&& ( false == mvControlled->Mains )
|
|
&& ( ggMainButton.GetValue() < 0.05 ) ) {
|
|
// crude way to catch cases where the main was knocked out and the user is trying to restart it
|
|
// because the state of the line breaker isn't changed to match, we need to do it here manually
|
|
m_linebreakerstate = 0;
|
|
}
|
|
|
|
// NOTE: crude way to have the pantographs go back up if they're dropped due to insufficient pressure etc
|
|
// TODO: rework it into something more elegant, when redoing the whole consist/unit/cab etc arrangement
|
|
if( ( mvControlled->Battery )
|
|
|| ( mvControlled->ConverterFlag ) ) {
|
|
if( ggPantAllDownButton.GetValue() == 0.0 ) {
|
|
// the 'lower all' button overrides state of switches, while active itself
|
|
if( ( false == mvControlled->PantFrontUp )
|
|
&& ( ggPantFrontButton.GetValue() >= 1.0 ) ) {
|
|
mvControlled->PantFront( true );
|
|
}
|
|
if( ( false == mvControlled->PantRearUp )
|
|
&& ( ggPantRearButton.GetValue() >= 1.0 ) ) {
|
|
mvControlled->PantRear( true );
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
// NOTE: disabled while switch state isn't preserved while moving between compartments
|
|
// check whether we should raise the pantographs, based on volume in pantograph tank
|
|
if( mvControlled->PantPress > (
|
|
mvControlled->TrainType == dt_EZT ?
|
|
2.4 :
|
|
3.5 ) ) {
|
|
if( ( false == mvControlled->PantFrontUp )
|
|
&& ( ggPantFrontButton.GetValue() > 0.95 ) ) {
|
|
mvControlled->PantFront( true );
|
|
}
|
|
if( ( false == mvControlled->PantRearUp )
|
|
&& ( ggPantRearButton.GetValue() > 0.95 ) ) {
|
|
mvControlled->PantRear( true );
|
|
}
|
|
}
|
|
*/
|
|
|
|
m_updated = true;
|
|
return true; //(DynamicObject->Update(dt));
|
|
} // koniec update
|
|
|
|
bool TTrain::CabChange(int iDirection)
|
|
{ // McZapkie-090902: zmiana kabiny 1->0->2 i z powrotem
|
|
if (DynamicObject->Mechanik ? DynamicObject->Mechanik->AIControllFlag :
|
|
true) // jeśli prowadzi AI albo jest w innym członie
|
|
{ // jak AI prowadzi, to nie można mu mieszać
|
|
if (abs(DynamicObject->MoverParameters->ActiveCab + iDirection) > 1)
|
|
return false; // ewentualna zmiana pojazdu
|
|
DynamicObject->MoverParameters->ActiveCab =
|
|
DynamicObject->MoverParameters->ActiveCab + iDirection;
|
|
}
|
|
else
|
|
{ // jeśli pojazd prowadzony ręcznie albo wcale (wagon)
|
|
DynamicObject->MoverParameters->CabDeactivisation();
|
|
if (DynamicObject->MoverParameters->ChangeCab(iDirection))
|
|
if (InitializeCab(DynamicObject->MoverParameters->ActiveCab,
|
|
DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName +
|
|
".mmd"))
|
|
{ // zmiana kabiny w ramach tego samego pojazdu
|
|
DynamicObject->MoverParameters->CabActivisation(); // załączenie rozrządu (wirtualne kabiny)
|
|
DynamicObject->Mechanik->CheckVehicles( Change_direction );
|
|
return true; // udało się zmienić kabinę
|
|
}
|
|
// aktywizacja poprzedniej, bo jeszcze nie wiadomo, czy jakiś pojazd jest
|
|
DynamicObject->MoverParameters->CabActivisation();
|
|
}
|
|
return false; // ewentualna zmiana pojazdu
|
|
}
|
|
|
|
// McZapkie-310302
|
|
// wczytywanie pliku z danymi multimedialnymi (dzwieki, kontrolki, kabiny)
|
|
bool TTrain::LoadMMediaFile(std::string const &asFileName)
|
|
{
|
|
cParser parser(asFileName, cParser::buffer_FILE);
|
|
// NOTE: yaml-style comments are disabled until conflict in use of # is resolved
|
|
// parser.addCommentStyle( "#", "\n" );
|
|
//Wartości domyślne by nie wysypywało przy wybrakowanych mmd @240816 Stele
|
|
// NOTE: should be no longer needed as safety checks were added,
|
|
// but leaving the defaults for the sake of incomplete mmd files
|
|
dsbPneumaticSwitch = sound_man->create_sound("silence1.wav");
|
|
dsbBufferClamp = sound_man->create_sound("en57_bufferclamp.wav");
|
|
dsbCouplerDetach = sound_man->create_sound("couplerdetach.wav");
|
|
dsbCouplerStretch = sound_man->create_sound("en57_couplerstretch.wav");
|
|
dsbCouplerAttach = sound_man->create_sound("couplerattach.wav");
|
|
|
|
std::string token;
|
|
do
|
|
{
|
|
token = "";
|
|
parser.getTokens();
|
|
parser >> token;
|
|
} while ((token != "") && (token != "internaldata:"));
|
|
|
|
if (token == "internaldata:")
|
|
{
|
|
|
|
do
|
|
{
|
|
token = "";
|
|
parser.getTokens();
|
|
parser >> token;
|
|
// SEKCJA DZWIEKOW
|
|
if (token == "ctrl:")
|
|
{
|
|
// nastawnik:
|
|
dsbNastawnikJazdy =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "ctrlscnd:")
|
|
{
|
|
// hunter-081211: nastawnik bocznikowania
|
|
dsbNastawnikBocz =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "reverserkey:")
|
|
{
|
|
// hunter-131211: dzwiek kierunkowego
|
|
dsbReverserKey =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "buzzer:")
|
|
{
|
|
// bzyczek shp:
|
|
dsbBuzzer =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "slipalarm:")
|
|
{
|
|
// Bombardier 011010: alarm przy poslizgu:
|
|
dsbSlipAlarm =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "tachoclock:")
|
|
{
|
|
// cykanie rejestratora:
|
|
dsbHasler =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "switch:")
|
|
{
|
|
// przelaczniki:
|
|
dsbSwitch =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "pneumaticswitch:")
|
|
{
|
|
// stycznik EP:
|
|
dsbPneumaticSwitch =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "wejscie_na_bezoporow:")
|
|
{
|
|
// hunter-111211: wydzielenie wejscia na bezoporowa i na drugi uklad do pliku
|
|
dsbWejscie_na_bezoporow =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "wejscie_na_drugi_uklad:")
|
|
{
|
|
|
|
dsbWejscie_na_drugi_uklad =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "relay:")
|
|
{
|
|
// styczniki itp:
|
|
dsbRelay =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
if (!dsbWejscie_na_bezoporow)
|
|
{ // hunter-111211: domyslne, gdy brak
|
|
dsbWejscie_na_bezoporow =
|
|
sound_man->create_sound("wejscie_na_bezoporow.wav");
|
|
}
|
|
if (!dsbWejscie_na_drugi_uklad)
|
|
{
|
|
dsbWejscie_na_drugi_uklad =
|
|
sound_man->create_sound("wescie_na_drugi_uklad.wav");
|
|
}
|
|
}
|
|
else if (token == "pneumaticrelay:")
|
|
{
|
|
// wylaczniki pneumatyczne:
|
|
dsbPneumaticRelay =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "couplerattach:")
|
|
{
|
|
// laczenie:
|
|
dsbCouplerAttach =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "couplerstretch:")
|
|
{
|
|
// laczenie:
|
|
dsbCouplerStretch =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "couplerdetach:")
|
|
{
|
|
// rozlaczanie:
|
|
dsbCouplerDetach =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "bufferclamp:")
|
|
{
|
|
// laczenie:
|
|
dsbBufferClamp =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "ignition:")
|
|
{
|
|
// odpalanie silnika
|
|
dsbDieselIgnition =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "brakesound:")
|
|
{
|
|
// hamowanie zwykle:
|
|
rsBrake = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(4, false);
|
|
if (rsBrake)
|
|
{
|
|
parser >> rsBrake->gain_mul >> rsBrake->gain_off >> rsBrake->pitch_mul >> rsBrake->pitch_off;
|
|
rsBrake->gain_mul /= (1 + mvOccupied->MaxBrakeForce * 1000);
|
|
rsBrake->pitch_mul /= (1 + mvOccupied->Vmax);
|
|
}
|
|
}
|
|
else if (token == "slipperysound:")
|
|
{
|
|
// sanie:
|
|
rsSlippery = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(2, false);
|
|
if (rsSlippery)
|
|
{
|
|
parser >> rsSlippery->gain_mul >> rsSlippery->gain_off;
|
|
rsSlippery->pitch_mul = 0.0;
|
|
rsSlippery->pitch_off = 1.0;
|
|
rsSlippery->gain_mul /= (1 + mvOccupied->Vmax);
|
|
}
|
|
}
|
|
else if (token == "airsound:")
|
|
{
|
|
// syk:
|
|
rsHiss = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(2, false);
|
|
if (rsHiss)
|
|
{
|
|
parser >> rsHiss->gain_mul >> rsHiss->gain_off;
|
|
rsHiss->pitch_mul = 0.0;
|
|
rsHiss->pitch_off = 1.0;
|
|
}
|
|
}
|
|
else if (token == "airsound2:")
|
|
{
|
|
// syk:
|
|
rsHissU = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(2, false);
|
|
if (rsHissU)
|
|
{
|
|
parser >> rsHissU->gain_mul >> rsHissU->gain_off;
|
|
rsHissU->pitch_mul = 0.0;
|
|
rsHissU->pitch_off = 1.0;
|
|
}
|
|
}
|
|
else if (token == "airsound3:")
|
|
{
|
|
// syk:
|
|
rsHissE = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(2, false);
|
|
if (rsHissE)
|
|
{
|
|
parser >> rsHissE->gain_mul >> rsHissE->gain_off;
|
|
rsHissE->pitch_mul = 0.0;
|
|
rsHissE->pitch_off = 1.0;
|
|
}
|
|
}
|
|
else if (token == "airsound4:")
|
|
{
|
|
// syk:
|
|
rsHissX = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(2, false);
|
|
if (rsHissX)
|
|
{
|
|
parser >> rsHissX->gain_mul >> rsHissX->gain_off;
|
|
rsHissX->pitch_mul = 0.0;
|
|
rsHissX->pitch_off = 1.0;
|
|
}
|
|
}
|
|
else if (token == "airsound5:")
|
|
{
|
|
// syk:
|
|
rsHissT = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(2, false);
|
|
if (rsHissT)
|
|
{
|
|
parser >> rsHissT->gain_mul >> rsHissT->gain_off;
|
|
rsHissT->pitch_mul = 0.0;
|
|
rsHissT->pitch_off = 1.0;
|
|
}
|
|
}
|
|
else if (token == "fadesound:")
|
|
{
|
|
// syk:
|
|
rsFadeSound = sound_man->create_sound(parser.getToken<std::string>());
|
|
if (rsFadeSound)
|
|
{
|
|
rsFadeSound->gain_mul = 1.0;
|
|
rsFadeSound->gain_off = 1.0;
|
|
rsFadeSound->pitch_mul = 1.0;
|
|
rsFadeSound->pitch_off = 1.0;
|
|
}
|
|
}
|
|
else if (token == "localbrakesound:")
|
|
{
|
|
// syk:
|
|
rsSBHiss = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(2, false);
|
|
if (rsSBHiss)
|
|
{
|
|
parser >> rsSBHiss->gain_mul >> rsSBHiss->gain_off;
|
|
rsSBHiss->pitch_mul = 0.0;
|
|
rsSBHiss->pitch_off = 1.0;
|
|
}
|
|
}
|
|
else if (token == "runningnoise:")
|
|
{
|
|
// szum podczas jazdy:
|
|
rsRunningNoise = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(4, false);
|
|
if (rsRunningNoise)
|
|
{
|
|
parser >> rsRunningNoise->gain_mul >> rsRunningNoise->gain_off >> rsRunningNoise->pitch_mul >>
|
|
rsRunningNoise->pitch_off;
|
|
rsRunningNoise->gain_mul /= (1 + mvOccupied->Vmax);
|
|
rsRunningNoise->pitch_mul /= (1 + mvOccupied->Vmax);
|
|
}
|
|
}
|
|
else if (token == "engageslippery:")
|
|
{
|
|
// tarcie tarcz sprzegla:
|
|
rsEngageSlippery = sound_man->create_sound(parser.getToken<std::string>());
|
|
parser.getTokens(4, false);
|
|
if (rsEngageSlippery)
|
|
{
|
|
parser >> rsEngageSlippery->gain_mul >> rsEngageSlippery->gain_off >> rsEngageSlippery->pitch_mul >>
|
|
rsEngageSlippery->pitch_off;
|
|
rsEngageSlippery->pitch_mul /= (1 + mvOccupied->nmax);
|
|
}
|
|
}
|
|
else if (token == "mechspring:")
|
|
{
|
|
// parametry bujania kamery:
|
|
double ks, kd;
|
|
parser.getTokens(2, false);
|
|
parser >> ks >> kd;
|
|
MechSpring.Init(MechSpring.restLen, ks, kd);
|
|
parser.getTokens(6, false);
|
|
parser >> fMechSpringX >> fMechSpringY >> fMechSpringZ >> fMechMaxSpring >>
|
|
fMechRoll >> fMechPitch;
|
|
}
|
|
else if (token == "pantographup:")
|
|
{
|
|
// podniesienie patyka:
|
|
dsbPantUp =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "pantographdown:")
|
|
{
|
|
// podniesienie patyka:
|
|
dsbPantDown =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "doorclose:")
|
|
{
|
|
// zamkniecie drzwi:
|
|
dsbDoorClose =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
else if (token == "dooropen:")
|
|
{
|
|
// otwarcie drzwi:
|
|
dsbDoorOpen =
|
|
sound_man->create_sound(parser.getToken<std::string>());
|
|
}
|
|
|
|
} while (token != "");
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
} // nie znalazl sekcji internal
|
|
|
|
if (!InitializeCab(mvOccupied->ActiveCab, asFileName))
|
|
{
|
|
// zle zainicjowana kabina
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (DynamicObject->Controller == Humandriver)
|
|
{
|
|
// McZapkie-030303: mozliwosc wyswietlania kabiny, w przyszlosci dac opcje w mmd
|
|
DynamicObject->bDisplayCab = true;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName)
|
|
{
|
|
m_controlmapper.clear();
|
|
pyScreens.reset(this);
|
|
pyScreens.setLookupPath(DynamicObject->asBaseDir);
|
|
bool parse = false;
|
|
int cabindex = 0;
|
|
DynamicObject->mdKabina = NULL; // likwidacja wskaźnika na dotychczasową kabinę
|
|
switch (NewCabNo)
|
|
{ // ustalenie numeru kabiny do wczytania
|
|
case -1:
|
|
cabindex = 2;
|
|
break;
|
|
case 1:
|
|
cabindex = 1;
|
|
break;
|
|
case 0:
|
|
cabindex = 0;
|
|
break;
|
|
}
|
|
std::string cabstr("cab" + std::to_string(cabindex) + "definition:");
|
|
|
|
std::shared_ptr<cParser> parser = std::make_shared<cParser>(asFileName, cParser::buffer_FILE);
|
|
// NOTE: yaml-style comments are disabled until conflict in use of # is resolved
|
|
// parser.addCommentStyle( "#", "\n" );
|
|
std::string token;
|
|
do
|
|
{
|
|
// szukanie kabiny
|
|
token = "";
|
|
parser->getTokens();
|
|
*parser >> token;
|
|
|
|
} while ((token != "") && (token != cabstr));
|
|
|
|
if ((cabindex != 1) && (token != cabstr))
|
|
{
|
|
// jeśli nie znaleziony wpis kabiny, próba szukania kabiny 1
|
|
cabstr = "cab1definition:";
|
|
// crude way to start parsing from beginning
|
|
parser = std::make_shared<cParser>(asFileName, cParser::buffer_FILE);
|
|
// NOTE: yaml-style comments are disabled until conflict in use of # is resolved
|
|
// parser.addCommentStyle( "#", "\n" );
|
|
do
|
|
{
|
|
token = "";
|
|
parser->getTokens();
|
|
*parser >> token;
|
|
} while ((token != "") && (token != cabstr));
|
|
}
|
|
if (token == cabstr)
|
|
{
|
|
// jeśli znaleziony wpis kabiny
|
|
Cabine[cabindex].Load(*parser);
|
|
// NOTE: the next part is likely to break if sitpos doesn't follow pos
|
|
parser->getTokens();
|
|
*parser >> token;
|
|
if (token == std::string("driver" + std::to_string(cabindex) + "pos:"))
|
|
{
|
|
// pozycja poczatkowa maszynisty
|
|
parser->getTokens(3, false);
|
|
*parser >> pMechOffset.x >> pMechOffset.y >> pMechOffset.z;
|
|
pMechSittingPosition.x = pMechOffset.x;
|
|
pMechSittingPosition.y = pMechOffset.y;
|
|
pMechSittingPosition.z = pMechOffset.z;
|
|
}
|
|
// ABu: pozycja siedzaca mechanika
|
|
parser->getTokens();
|
|
*parser >> token;
|
|
if (token == std::string("driver" + std::to_string(cabindex) + "sitpos:"))
|
|
{
|
|
// ABu 180404 pozycja siedzaca maszynisty
|
|
parser->getTokens(3, false);
|
|
*parser >> pMechSittingPosition.x >> pMechSittingPosition.y >> pMechSittingPosition.z;
|
|
parse = true;
|
|
}
|
|
// else parse=false;
|
|
do
|
|
{
|
|
// ABu: wstawione warunki, wczesniej tylko to:
|
|
// str=Parser->GetNextSymbol().LowerCase();
|
|
if (parse == true) {
|
|
|
|
token = "";
|
|
parser->getTokens();
|
|
*parser >> token;
|
|
}
|
|
else
|
|
{
|
|
parse = true;
|
|
}
|
|
// inicjacja kabiny
|
|
// Ra 2014-08: zmieniamy zasady - zamiast przypisywać submodel do
|
|
// istniejących obiektów animujących
|
|
// będziemy teraz uaktywniać obiekty animujące z tablicy i podawać im
|
|
// submodel oraz wskaźnik na parametr
|
|
if (token == std::string("cab" + std::to_string(cabindex) + "model:"))
|
|
{
|
|
// model kabiny
|
|
parser->getTokens();
|
|
*parser >> token;
|
|
if (token != "none")
|
|
{
|
|
|
|
Global::asCurrentTexturePath =
|
|
DynamicObject->asBaseDir; // bieżąca sciezka do tekstur to dynamic/...
|
|
TModel3d *kabina =
|
|
TModelsManager::GetModel(DynamicObject->asBaseDir + token,
|
|
true); // szukaj kabinę jako oddzielny model
|
|
Global::asCurrentTexturePath =
|
|
szTexturePath; // z powrotem defaultowa sciezka do tekstur
|
|
// if (DynamicObject->mdKabina!=k)
|
|
if (kabina != nullptr)
|
|
{
|
|
DynamicObject->mdKabina = kabina; // nowa kabina
|
|
}
|
|
//(mdKabina) może zostać to samo po przejściu do innego członu bez
|
|
// zmiany kabiny, przy powrocie musi być wiązanie ponowne
|
|
// else
|
|
// break; //wyjście z pętli, bo model zostaje bez zmian
|
|
}
|
|
else if (cabindex == 1)
|
|
{
|
|
// model tylko, gdy nie ma kabiny 1
|
|
DynamicObject->mdKabina =
|
|
DynamicObject
|
|
->mdModel; // McZapkie-170103: szukaj elementy kabiny w glownym modelu
|
|
}
|
|
/*
|
|
Universal4Active = false;
|
|
*/
|
|
clear_cab_controls();
|
|
}
|
|
if (nullptr == DynamicObject->mdKabina)
|
|
{
|
|
// don't bother with other parts until the cab is initialised
|
|
continue;
|
|
}
|
|
else if (true == initialize_gauge(*parser, token, cabindex))
|
|
{
|
|
// matched the token, grab the next one
|
|
continue;
|
|
}
|
|
else if (true == initialize_button(*parser, token, cabindex))
|
|
{
|
|
// matched the token, grab the next one
|
|
continue;
|
|
}
|
|
else if (token == "pyscreen:")
|
|
{
|
|
pyScreens.init(*parser, DynamicObject->mdKabina, DynamicObject->GetName(),
|
|
NewCabNo);
|
|
}
|
|
// btLampkaUnknown.Init("unknown",mdKabina,false);
|
|
} while (token != "");
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
pyScreens.start();
|
|
if (DynamicObject->mdKabina)
|
|
{
|
|
DynamicObject->mdKabina->Init(); // obrócenie modelu oraz optymalizacja, również zapisanie binarnego
|
|
set_cab_controls();
|
|
return true;
|
|
}
|
|
return (token == "none");
|
|
}
|
|
|
|
void TTrain::MechStop()
|
|
{ // likwidacja ruchu kamery w kabinie (po powrocie przez [F4])
|
|
pMechPosition = vector3(0, 0, 0);
|
|
pMechShake = vector3(0, 0, 0);
|
|
vMechMovement = vector3(0, 0, 0);
|
|
vMechVelocity = vector3(0, 0, 0); // tu zostawały jakieś ułamki, powodujące uciekanie kamery
|
|
};
|
|
|
|
vector3 TTrain::MirrorPosition(bool lewe)
|
|
{ // zwraca współrzędne widoku kamery z lusterka
|
|
switch (iCabn)
|
|
{
|
|
case 1: // przednia (1)
|
|
return DynamicObject->mMatrix *
|
|
vector3(lewe ? Cabine[iCabn].CabPos2.x : Cabine[iCabn].CabPos1.x,
|
|
1.5 + Cabine[iCabn].CabPos1.y, Cabine[iCabn].CabPos2.z);
|
|
case 2: // tylna (-1)
|
|
return DynamicObject->mMatrix *
|
|
vector3(lewe ? Cabine[iCabn].CabPos1.x : Cabine[iCabn].CabPos2.x,
|
|
1.5 + Cabine[iCabn].CabPos1.y, Cabine[iCabn].CabPos1.z);
|
|
}
|
|
return DynamicObject->GetPosition(); // współrzędne środka pojazdu
|
|
};
|
|
|
|
void TTrain::DynamicSet(TDynamicObject *d)
|
|
{ // taka proteza: chcę podłączyć
|
|
// kabinę EN57 bezpośrednio z
|
|
// silnikowym, aby nie robić tego
|
|
// przez ukrotnienie
|
|
// drugi silnikowy i tak musi być ukrotniony, podobnie jak kolejna jednostka
|
|
// problem się robi ze światłami, które będą zapalane w silnikowym, ale muszą
|
|
// świecić się w rozrządczych
|
|
// dla EZT światła czołowe będą "zapalane w silnikowym", ale widziane z
|
|
// rozrządczych
|
|
// również wczytywanie MMD powinno dotyczyć aktualnego członu
|
|
// problematyczna może być kwestia wybranej kabiny (w silnikowym...)
|
|
// jeśli silnikowy będzie zapięty odwrotnie (tzn. -1), to i tak powinno
|
|
// jeździć dobrze
|
|
// również hamowanie wykonuje się zaworem w członie, a nie w silnikowym...
|
|
DynamicObject = d; // jedyne miejsce zmiany
|
|
mvOccupied = mvControlled = d ? DynamicObject->MoverParameters : NULL; // albo silnikowy w EZT
|
|
if (!DynamicObject)
|
|
return;
|
|
if (mvControlled->TrainType & dt_EZT) // na razie dotyczy to EZT
|
|
if (DynamicObject->NextConnected ? mvControlled->Couplers[1].AllowedFlag & ctrain_depot :
|
|
false)
|
|
{ // gdy jest człon od sprzęgu 1, a sprzęg łączony
|
|
// warsztatowo (powiedzmy)
|
|
if ((mvControlled->Power < 1.0) && (mvControlled->Couplers[1].Connected->Power >
|
|
1.0)) // my nie mamy mocy, ale ten drugi ma
|
|
mvControlled =
|
|
DynamicObject->NextConnected->MoverParameters; // będziemy sterować tym z mocą
|
|
}
|
|
else if (DynamicObject->PrevConnected ?
|
|
mvControlled->Couplers[0].AllowedFlag & ctrain_depot :
|
|
false)
|
|
{ // gdy jest człon od sprzęgu 0, a sprzęg łączony
|
|
// warsztatowo (powiedzmy)
|
|
if ((mvControlled->Power < 1.0) && (mvControlled->Couplers[0].Connected->Power >
|
|
1.0)) // my nie mamy mocy, ale ten drugi ma
|
|
mvControlled =
|
|
DynamicObject->PrevConnected->MoverParameters; // będziemy sterować tym z mocą
|
|
}
|
|
mvSecond = NULL; // gdyby się nic nie znalazło
|
|
if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo
|
|
if (mvOccupied->Couplers[1].Connected ?
|
|
mvOccupied->Couplers[1].AllowedFlag & ctrain_controll :
|
|
false)
|
|
{ // gdy jest człon od sprzęgu 1, a sprzęg łączony
|
|
// warsztatowo (powiedzmy)
|
|
if (mvOccupied->Couplers[1].Connected->Power > 1.0) // ten drugi ma moc
|
|
mvSecond =
|
|
(TMoverParameters *)mvOccupied->Couplers[1].Connected; // wskaźnik na drugiego
|
|
}
|
|
else if (mvOccupied->Couplers[0].Connected ?
|
|
mvOccupied->Couplers[0].AllowedFlag & ctrain_controll :
|
|
false)
|
|
{ // gdy jest człon od sprzęgu 0, a sprzęg łączony
|
|
// warsztatowo (powiedzmy)
|
|
if (mvOccupied->Couplers[0].Connected->Power > 1.0) // ale ten drugi ma moc
|
|
mvSecond =
|
|
(TMoverParameters *)mvOccupied->Couplers[0].Connected; // wskaźnik na drugiego
|
|
}
|
|
};
|
|
|
|
void TTrain::Silence()
|
|
{ // wyciszenie dźwięków przy wychodzeniu
|
|
if (dsbNastawnikJazdy)
|
|
dsbNastawnikJazdy->stop();
|
|
if (dsbNastawnikBocz)
|
|
dsbNastawnikBocz->stop();
|
|
if (dsbRelay)
|
|
dsbRelay->stop();
|
|
if (dsbPneumaticRelay)
|
|
dsbPneumaticRelay->stop();
|
|
if (dsbSwitch)
|
|
dsbSwitch->stop();
|
|
if (dsbPneumaticSwitch)
|
|
dsbPneumaticSwitch->stop();
|
|
if (dsbReverserKey)
|
|
dsbReverserKey->stop();
|
|
if (dsbCouplerAttach)
|
|
dsbCouplerAttach->stop();
|
|
if (dsbCouplerDetach)
|
|
dsbCouplerDetach->stop();
|
|
if (dsbDieselIgnition)
|
|
dsbDieselIgnition->stop();
|
|
if (dsbDoorClose)
|
|
dsbDoorClose->stop();
|
|
if (dsbDoorOpen)
|
|
dsbDoorOpen->stop();
|
|
if (dsbPantUp)
|
|
dsbPantUp->stop();
|
|
if (dsbPantDown)
|
|
dsbPantDown->stop();
|
|
if (dsbWejscie_na_bezoporow)
|
|
dsbWejscie_na_bezoporow->stop();
|
|
if (dsbWejscie_na_drugi_uklad)
|
|
dsbWejscie_na_drugi_uklad->stop();
|
|
if (rsBrake)
|
|
rsBrake->stop();
|
|
if (rsSlippery)
|
|
rsSlippery->stop();
|
|
if (rsHiss)
|
|
rsHiss->stop();
|
|
if (rsHissU)
|
|
rsHissU->stop();
|
|
if (rsHissE)
|
|
rsHissE->stop();
|
|
if (rsHissX)
|
|
rsHissX->stop();
|
|
if (rsHissT)
|
|
rsHissT->stop();
|
|
if (rsSBHiss)
|
|
rsSBHiss->stop();
|
|
if (rsRunningNoise)
|
|
rsRunningNoise->stop();
|
|
if (rsEngageSlippery)
|
|
rsEngageSlippery->stop();
|
|
if (rsFadeSound)
|
|
rsFadeSound->stop();
|
|
if (dsbHasler)
|
|
dsbHasler->stop(); // wyłączenie dźwięków opuszczanej kabiny
|
|
if (dsbBuzzer)
|
|
dsbBuzzer->stop();
|
|
if (dsbSlipAlarm)
|
|
dsbSlipAlarm->stop(); // dźwięk alarmu przy poślizgu
|
|
// sConverter->stop();
|
|
// sSmallCompressor->stop();
|
|
if (dsbCouplerStretch)
|
|
dsbCouplerStretch->stop();
|
|
if (dsbEN57_CouplerStretch)
|
|
dsbEN57_CouplerStretch->stop();
|
|
if (dsbBufferClamp)
|
|
dsbBufferClamp->stop();
|
|
};
|
|
|
|
void TTrain::SetLights()
|
|
{
|
|
TDynamicObject *p = DynamicObject->GetFirstDynamic(mvOccupied->ActiveCab < 0 ? 1 : 0, 4);
|
|
bool kier = (DynamicObject->DirectionGet() * mvOccupied->ActiveCab > 0);
|
|
int xs = (kier ? 0 : 1);
|
|
if (kier ? p->NextC(1) : p->PrevC(1)) // jesli jest nastepny, to tylko przod
|
|
{
|
|
p->RaLightsSet(mvOccupied->Lights[xs][mvOccupied->LightsPos - 1] * (1 - xs),
|
|
mvOccupied->Lights[1 - xs][mvOccupied->LightsPos - 1] * xs);
|
|
p = (kier ? p->NextC(4) : p->PrevC(4));
|
|
while (p)
|
|
{
|
|
if (kier ? p->NextC(1) : p->PrevC(1))
|
|
{
|
|
p->RaLightsSet(0, 0);
|
|
}
|
|
else
|
|
{
|
|
p->RaLightsSet(mvOccupied->Lights[xs][mvOccupied->LightsPos - 1] * xs,
|
|
mvOccupied->Lights[1 - xs][mvOccupied->LightsPos - 1] * (1 - xs));
|
|
}
|
|
p = (kier ? p->NextC(4) : p->PrevC(4));
|
|
}
|
|
}
|
|
else // calosc
|
|
{
|
|
p->RaLightsSet(mvOccupied->Lights[xs][mvOccupied->LightsPos - 1],
|
|
mvOccupied->Lights[1 - xs][mvOccupied->LightsPos - 1]);
|
|
}
|
|
};
|
|
|
|
// clears state of all cabin controls
|
|
void TTrain::clear_cab_controls()
|
|
{
|
|
ggMainCtrl.Clear();
|
|
ggMainCtrlAct.Clear();
|
|
ggScndCtrl.Clear();
|
|
ggDirKey.Clear();
|
|
ggBrakeCtrl.Clear();
|
|
ggLocalBrake.Clear();
|
|
ggManualBrake.Clear();
|
|
ggAlarmChain.Clear();
|
|
ggBrakeProfileCtrl.Clear();
|
|
ggBrakeProfileG.Clear();
|
|
ggBrakeProfileR.Clear();
|
|
ggMaxCurrentCtrl.Clear();
|
|
ggMainOffButton.Clear();
|
|
ggMainOnButton.Clear();
|
|
ggSecurityResetButton.Clear();
|
|
ggReleaserButton.Clear();
|
|
ggSandButton.Clear();
|
|
ggAntiSlipButton.Clear();
|
|
ggHornButton.Clear();
|
|
ggHornLowButton.Clear();
|
|
ggHornHighButton.Clear();
|
|
ggNextCurrentButton.Clear();
|
|
/*
|
|
ggUniversal1Button.Clear();
|
|
ggUniversal2Button.Clear();
|
|
ggUniversal4Button.Clear();
|
|
*/
|
|
for( auto &universal : ggUniversals ) {
|
|
universal.Clear();
|
|
}
|
|
ggInstrumentLightButton.Clear();
|
|
// hunter-091012
|
|
ggCabLightButton.Clear();
|
|
ggCabLightDimButton.Clear();
|
|
//-------
|
|
ggFuseButton.Clear();
|
|
ggConverterFuseButton.Clear();
|
|
ggStLinOffButton.Clear();
|
|
ggDoorLeftButton.Clear();
|
|
ggDoorRightButton.Clear();
|
|
ggDepartureSignalButton.Clear();
|
|
ggCompressorButton.Clear();
|
|
ggConverterButton.Clear();
|
|
ggPantFrontButton.Clear();
|
|
ggPantRearButton.Clear();
|
|
ggPantSelectedButton.Clear();
|
|
ggPantFrontButtonOff.Clear();
|
|
ggPantRearButtonOff.Clear();
|
|
ggPantSelectedDownButton.Clear();
|
|
ggPantAllDownButton.Clear();
|
|
ggPantCompressorButton.Clear();
|
|
ggPantCompressorValve.Clear();
|
|
ggZbS.Clear();
|
|
ggI1B.Clear();
|
|
ggI2B.Clear();
|
|
ggI3B.Clear();
|
|
ggItotalB.Clear();
|
|
|
|
ggClockSInd.Clear();
|
|
ggClockMInd.Clear();
|
|
ggClockHInd.Clear();
|
|
ggEngineVoltage.Clear();
|
|
ggLVoltage.Clear();
|
|
// ggLVoltage.Output(0); //Ra: sterowanie miernikiem: niskie napięcie
|
|
// ggEnrot1m.Clear();
|
|
// ggEnrot2m.Clear();
|
|
// ggEnrot3m.Clear();
|
|
// ggEngageRatio.Clear();
|
|
ggMainGearStatus.Clear();
|
|
ggIgnitionKey.Clear();
|
|
// Jeśli ustawiamy nową wartość dla PoKeys wolna jest 15
|
|
// Numer 14 jest używany dla buczka SHP w innym miejscu
|
|
btLampkaPoslizg.Clear(6);
|
|
btLampkaStyczn.Clear(5);
|
|
btLampkaNadmPrzetw.Clear((mvControlled->TrainType & (dt_EZT)) ? -1 :
|
|
7); // EN57 nie ma tej lampki
|
|
btLampkaPrzetw.Clear((mvControlled->TrainType & (dt_EZT)) ? 7 : -1); // za to ma tę
|
|
btLampkaPrzekRozn.Clear();
|
|
btLampkaPrzekRoznPom.Clear();
|
|
btLampkaNadmSil.Clear(4);
|
|
btLampkaUkrotnienie.Clear();
|
|
btLampkaHamPosp.Clear();
|
|
btLampkaWylSzybki.Clear(3);
|
|
btLampkaNadmWent.Clear(9);
|
|
btLampkaNadmSpr.Clear(8);
|
|
btLampkaOpory.Clear(2);
|
|
btLampkaWysRozr.Clear((mvControlled->TrainType & (dt_ET22)) ? -1 :
|
|
10); // ET22 nie ma tej lampki
|
|
btLampkaBezoporowa.Clear();
|
|
btLampkaBezoporowaB.Clear();
|
|
btLampkaMaxSila.Clear();
|
|
btLampkaPrzekrMaxSila.Clear();
|
|
btLampkaRadio.Clear();
|
|
btLampkaHamulecReczny.Clear();
|
|
btLampkaBlokadaDrzwi.Clear();
|
|
btInstrumentLight.Clear();
|
|
btLampkaWentZaluzje.Clear();
|
|
btLampkaOgrzewanieSkladu.Clear(11);
|
|
btLampkaSHP.Clear(0);
|
|
btLampkaCzuwaka.Clear(1);
|
|
btLampkaDoorLeft.Clear();
|
|
btLampkaDoorRight.Clear();
|
|
btLampkaDepartureSignal.Clear();
|
|
btLampkaRezerwa.Clear();
|
|
btLampkaBoczniki.Clear();
|
|
btLampkaBocznik1.Clear();
|
|
btLampkaBocznik2.Clear();
|
|
btLampkaBocznik3.Clear();
|
|
btLampkaBocznik4.Clear();
|
|
btLampkaRadiotelefon.Clear();
|
|
btLampkaHamienie.Clear();
|
|
btLampkaSprezarka.Clear();
|
|
btLampkaSprezarkaB.Clear();
|
|
btLampkaNapNastHam.Clear();
|
|
btLampkaJazda.Clear();
|
|
btLampkaStycznB.Clear();
|
|
btLampkaHamowanie1zes.Clear();
|
|
btLampkaHamowanie2zes.Clear();
|
|
btLampkaNadmPrzetwB.Clear();
|
|
btLampkaPrzetwB.Clear();
|
|
btLampkaWylSzybkiB.Clear();
|
|
btLampkaForward.Clear();
|
|
btLampkaBackward.Clear();
|
|
btCabLight.Clear(); // hunter-171012
|
|
ggLeftLightButton.Clear();
|
|
ggRightLightButton.Clear();
|
|
ggUpperLightButton.Clear();
|
|
ggDimHeadlightsButton.Clear();
|
|
ggLeftEndLightButton.Clear();
|
|
ggRightEndLightButton.Clear();
|
|
ggLightsButton.Clear();
|
|
// hunter-230112
|
|
ggRearLeftLightButton.Clear();
|
|
ggRearRightLightButton.Clear();
|
|
ggRearUpperLightButton.Clear();
|
|
ggRearLeftEndLightButton.Clear();
|
|
ggRearRightEndLightButton.Clear();
|
|
btHaslerBrakes.Clear(12); // ciśnienie w cylindrach do odbijania na haslerze
|
|
btHaslerCurrent.Clear(13); // prąd na silnikach do odbijania na haslerze
|
|
}
|
|
|
|
// NOTE: we can get rid of this function once we have per-cab persistent state
|
|
void TTrain::set_cab_controls() {
|
|
// switches
|
|
// battery
|
|
if( true == mvOccupied->Battery ) {
|
|
ggBatteryButton.PutValue( 1.0 );
|
|
}
|
|
// motor connectors
|
|
ggStLinOffButton.PutValue(
|
|
( mvControlled->StLinSwitchOff ?
|
|
1.0 :
|
|
0.0 ) );
|
|
// radio
|
|
if( true == mvOccupied->Radio ) {
|
|
ggRadioButton.PutValue( 1.0 );
|
|
}
|
|
// pantographs
|
|
if( mvOccupied->PantSwitchType != "impulse" ) {
|
|
ggPantFrontButton.PutValue(
|
|
( mvControlled->PantFrontUp ?
|
|
1.0 :
|
|
0.0 ) );
|
|
ggPantFrontButtonOff.PutValue(
|
|
( mvControlled->PantFrontUp ?
|
|
0.0 :
|
|
1.0 ) );
|
|
// NOTE: currently we animate the selectable pantograph control for both pantographs
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
ggPantSelectedButton.PutValue(
|
|
( mvControlled->PantFrontUp ?
|
|
1.0 :
|
|
0.0 ) );
|
|
ggPantSelectedDownButton.PutValue(
|
|
( mvControlled->PantFrontUp ?
|
|
0.0 :
|
|
1.0 ) );
|
|
}
|
|
if( mvOccupied->PantSwitchType != "impulse" ) {
|
|
ggPantRearButton.PutValue(
|
|
( mvControlled->PantRearUp ?
|
|
1.0 :
|
|
0.0 ) );
|
|
ggPantRearButtonOff.PutValue(
|
|
( mvControlled->PantRearUp ?
|
|
0.0 :
|
|
1.0 ) );
|
|
// NOTE: currently we animate the selectable pantograph control for both pantographs
|
|
// TODO: implement actual selection control, and refactor handling this control setup in a separate method
|
|
ggPantSelectedButton.PutValue(
|
|
( mvControlled->PantRearUp ?
|
|
1.0 :
|
|
0.0 ) );
|
|
ggPantSelectedDownButton.PutValue(
|
|
( mvControlled->PantRearUp ?
|
|
0.0 :
|
|
1.0 ) );
|
|
}
|
|
// auxiliary compressor
|
|
ggPantCompressorValve.PutValue(
|
|
mvControlled->bPantKurek3 ?
|
|
0.0 : // default setting is pantographs connected with primary tank
|
|
1.0 );
|
|
ggPantCompressorButton.PutValue(
|
|
mvControlled->PantCompFlag ?
|
|
1.0 :
|
|
0.0 );
|
|
// converter
|
|
if( mvOccupied->ConvSwitchType != "impulse" ) {
|
|
ggConverterButton.PutValue(
|
|
mvControlled->ConverterAllow ?
|
|
1.0 :
|
|
0.0 );
|
|
}
|
|
ggConverterLocalButton.PutValue(
|
|
mvControlled->ConverterAllowLocal ?
|
|
1.0 :
|
|
0.0 );
|
|
// compressor
|
|
ggCompressorButton.PutValue(
|
|
mvControlled->CompressorAllow ?
|
|
1.0 :
|
|
0.0 );
|
|
ggCompressorLocalButton.PutValue(
|
|
mvControlled->CompressorAllowLocal ?
|
|
1.0 :
|
|
0.0 );
|
|
// motor overload relay threshold / shunt mode
|
|
if( mvControlled->Imax == mvControlled->ImaxHi ) {
|
|
ggMaxCurrentCtrl.PutValue( 1.0 );
|
|
}
|
|
// lights
|
|
int const lightsindex =
|
|
( mvOccupied->ActiveCab == 1 ?
|
|
0 :
|
|
1 );
|
|
|
|
if( ( DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_left ) != 0 ) {
|
|
ggLeftLightButton.PutValue( 1.0 );
|
|
}
|
|
if( ( DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_right ) != 0 ) {
|
|
ggRightLightButton.PutValue( 1.0 );
|
|
}
|
|
if( ( DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::headlight_upper ) != 0 ) {
|
|
ggUpperLightButton.PutValue( 1.0 );
|
|
}
|
|
if( ( DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::redmarker_left ) != 0 ) {
|
|
if( ggLeftEndLightButton.SubModel != nullptr ) {
|
|
ggLeftEndLightButton.PutValue( 1.0 );
|
|
}
|
|
else {
|
|
ggLeftLightButton.PutValue( -1.0 );
|
|
}
|
|
}
|
|
if( ( DynamicObject->iLights[ lightsindex ] & TMoverParameters::light::redmarker_right ) != 0 ) {
|
|
if( ggRightEndLightButton.SubModel != nullptr ) {
|
|
ggRightEndLightButton.PutValue( 1.0 );
|
|
}
|
|
else {
|
|
ggRightLightButton.PutValue( -1.0 );
|
|
}
|
|
}
|
|
if( true == DynamicObject->DimHeadlights ) {
|
|
ggDimHeadlightsButton.PutValue( 1.0 );
|
|
}
|
|
// cab lights
|
|
if( true == bCabLight ) {
|
|
ggCabLightButton.PutValue( 1.0 );
|
|
}
|
|
if( true == bCabLightDim ) {
|
|
ggCabLightDimButton.PutValue( 1.0 );
|
|
}
|
|
if( true == InstrumentLightActive ) {
|
|
ggInstrumentLightButton.PutValue( 1.0 );
|
|
}
|
|
// doors
|
|
// NOTE: we're relying on the cab models to have switches reversed for the rear cab(?)
|
|
ggDoorLeftButton.PutValue( mvOccupied->DoorLeftOpened ? 1.0 : 0.0 );
|
|
ggDoorRightButton.PutValue( mvOccupied->DoorRightOpened ? 1.0 : 0.0 );
|
|
// door lock
|
|
if( true == mvControlled->DoorSignalling ) {
|
|
ggDoorSignallingButton.PutValue( 1.0 );
|
|
}
|
|
// heating
|
|
if( true == mvControlled->Heating ) {
|
|
ggTrainHeatingButton.PutValue( 1.0 );
|
|
}
|
|
// brake acting time
|
|
if( ggBrakeProfileCtrl.SubModel != nullptr ) {
|
|
ggBrakeProfileCtrl.PutValue(
|
|
( ( mvOccupied->BrakeDelayFlag & bdelay_R ) != 0 ?
|
|
2.0 :
|
|
mvOccupied->BrakeDelayFlag - 1 ) );
|
|
}
|
|
if( ggBrakeProfileG.SubModel != nullptr ) {
|
|
ggBrakeProfileG.PutValue(
|
|
mvOccupied->BrakeDelayFlag == bdelay_G ?
|
|
1.0 :
|
|
0.0 );
|
|
}
|
|
if( ggBrakeProfileR.SubModel != nullptr ) {
|
|
ggBrakeProfileR.PutValue(
|
|
( mvOccupied->BrakeDelayFlag & bdelay_R ) != 0 ?
|
|
1.0 :
|
|
0.0 );
|
|
}
|
|
// alarm chain
|
|
ggAlarmChain.PutValue(
|
|
mvControlled->AlarmChainFlag ?
|
|
1.0 :
|
|
0.0 );
|
|
// brake signalling
|
|
ggSignallingButton.PutValue(
|
|
mvControlled->Signalling ?
|
|
1.0 :
|
|
0.0 );
|
|
// multiple-unit current indicator source
|
|
ggNextCurrentButton.PutValue(
|
|
ShowNextCurrent ?
|
|
1.0 :
|
|
0.0 );
|
|
|
|
// we reset all indicators, as they're set during the update pass
|
|
// TODO: when cleaning up break setting indicator state into a separate function, so we can reuse it
|
|
}
|
|
|
|
// initializes a button matching provided label. returns: true if the label was found, false
|
|
// otherwise
|
|
// NOTE: this is temporary work-around for compiler else-if limit
|
|
// TODO: refactor the cabin controls into some sensible structure
|
|
bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int const Cabindex)
|
|
{
|
|
/*
|
|
TButton *bt; // roboczy wskaźnik na obiekt animujący lampkę
|
|
*/
|
|
// SEKCJA LAMPEK
|
|
if (Label == "i-maxft:")
|
|
{
|
|
btLampkaMaxSila.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-maxftt:")
|
|
{
|
|
btLampkaPrzekrMaxSila.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-radio:")
|
|
{
|
|
btLampkaRadio.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-manual_brake:")
|
|
{
|
|
btLampkaHamulecReczny.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-door_blocked:")
|
|
{
|
|
btLampkaBlokadaDrzwi.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-slippery:")
|
|
{
|
|
btLampkaPoslizg.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-contactors:")
|
|
{
|
|
btLampkaStyczn.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-conv_ovld:")
|
|
{
|
|
btLampkaNadmPrzetw.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-converter:")
|
|
{
|
|
btLampkaPrzetw.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-diff_relay:")
|
|
{
|
|
btLampkaPrzekRozn.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-diff_relay2:")
|
|
{
|
|
btLampkaPrzekRoznPom.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-motor_ovld:")
|
|
{
|
|
btLampkaNadmSil.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-train_controll:")
|
|
{
|
|
btLampkaUkrotnienie.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-brake_delay_r:")
|
|
{
|
|
btLampkaHamPosp.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-mainbreaker:")
|
|
{
|
|
btLampkaWylSzybki.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-vent_ovld:")
|
|
{
|
|
btLampkaNadmWent.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-comp_ovld:")
|
|
{
|
|
btLampkaNadmSpr.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-resistors:")
|
|
{
|
|
btLampkaOpory.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-no_resistors:")
|
|
{
|
|
btLampkaBezoporowa.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-no_resistors_b:")
|
|
{
|
|
btLampkaBezoporowaB.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-highcurrent:")
|
|
{
|
|
btLampkaWysRozr.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-instrumentlight:")
|
|
{
|
|
btInstrumentLight.Load(Parser, DynamicObject->mdKabina, DynamicObject->mdModel);
|
|
InstrumentLightType = 0;
|
|
}
|
|
else if (Label == "i-instrumentlight_M:")
|
|
{
|
|
btInstrumentLight.Load(Parser, DynamicObject->mdKabina, DynamicObject->mdModel);
|
|
InstrumentLightType = 1;
|
|
}
|
|
else if (Label == "i-instrumentlight_C:")
|
|
{
|
|
btInstrumentLight.Load(Parser, DynamicObject->mdKabina, DynamicObject->mdModel);
|
|
InstrumentLightType = 2;
|
|
}
|
|
else if (Label == "i-vent_trim:")
|
|
{
|
|
btLampkaWentZaluzje.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-trainheating:")
|
|
{
|
|
btLampkaOgrzewanieSkladu.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-security_aware:")
|
|
{
|
|
btLampkaCzuwaka.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-security_cabsignal:")
|
|
{
|
|
btLampkaSHP.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-door_left:")
|
|
{
|
|
btLampkaDoorLeft.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-door_right:")
|
|
{
|
|
btLampkaDoorRight.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-departure_signal:")
|
|
{
|
|
btLampkaDepartureSignal.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-reserve:")
|
|
{
|
|
btLampkaRezerwa.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-scnd:")
|
|
{
|
|
btLampkaBoczniki.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-scnd1:")
|
|
{
|
|
btLampkaBocznik1.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-scnd2:")
|
|
{
|
|
btLampkaBocznik2.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-scnd3:")
|
|
{
|
|
btLampkaBocznik3.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-scnd4:")
|
|
{
|
|
btLampkaBocznik4.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-braking:")
|
|
{
|
|
btLampkaHamienie.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if( Label == "i-dynamicbrake:" ) {
|
|
|
|
btLampkaED.Load( Parser, DynamicObject->mdKabina );
|
|
}
|
|
else if (Label == "i-braking-ezt:")
|
|
{
|
|
btLampkaHamowanie1zes.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-braking-ezt2:")
|
|
{
|
|
btLampkaHamowanie2zes.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-compressor:")
|
|
{
|
|
btLampkaSprezarka.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-compressorb:")
|
|
{
|
|
btLampkaSprezarkaB.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-voltbrake:")
|
|
{
|
|
btLampkaNapNastHam.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-mainbreakerb:")
|
|
{
|
|
btLampkaWylSzybkiB.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-resistorsb:")
|
|
{
|
|
btLampkaOporyB.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-contactorsb:")
|
|
{
|
|
btLampkaStycznB.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-conv_ovldb:")
|
|
{
|
|
btLampkaNadmPrzetwB.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-converterb:")
|
|
{
|
|
btLampkaPrzetwB.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-forward:")
|
|
{
|
|
btLampkaForward.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-backward:")
|
|
{
|
|
btLampkaBackward.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-cablight:")
|
|
{ // hunter-171012
|
|
btCabLight.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "i-doors:")
|
|
{
|
|
int i = Parser.getToken<int>() - 1;
|
|
auto &button = Cabine[Cabindex].Button(-1); // pierwsza wolna lampka
|
|
button.Load(Parser, DynamicObject->mdKabina);
|
|
button.AssignBool(bDoors[0] + 3 * i);
|
|
}
|
|
else
|
|
{
|
|
// failed to match the label
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// initializes a gauge matching provided label. returns: true if the label was found, false
|
|
// otherwise
|
|
// NOTE: this is temporary work-around for compiler else-if limit
|
|
// TODO: refactor the cabin controls into some sensible structure
|
|
bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int const Cabindex) {
|
|
|
|
/*
|
|
TGauge *gg { nullptr }; // roboczy wskaźnik na obiekt animujący gałkę
|
|
*/
|
|
std::unordered_map<std::string, TGauge &> gauges = {
|
|
{ "mainctrl:", ggMainCtrl },
|
|
{ "scndctrl:", ggScndCtrl },
|
|
{ "dirkey:" , ggDirKey },
|
|
{ "brakectrl:", ggBrakeCtrl },
|
|
{ "localbrake:", ggLocalBrake },
|
|
{ "manualbrake:", ggManualBrake },
|
|
{ "alarmchain:", ggAlarmChain },
|
|
{ "brakeprofile_sw:", ggBrakeProfileCtrl },
|
|
{ "brakeprofileg_sw:", ggBrakeProfileG },
|
|
{ "brakeprofiler_sw:", ggBrakeProfileR },
|
|
{ "maxcurrent_sw:", ggMaxCurrentCtrl },
|
|
{ "main_off_bt:", ggMainOffButton },
|
|
{ "main_on_bt:", ggMainOnButton },
|
|
{ "security_reset_bt:", ggSecurityResetButton },
|
|
{ "releaser_bt:", ggReleaserButton },
|
|
{ "sand_bt:", ggSandButton },
|
|
{ "antislip_bt:", ggAntiSlipButton },
|
|
{ "horn_bt:", ggHornButton },
|
|
{ "hornlow_bt:", ggHornLowButton },
|
|
{ "hornhigh_bt:", ggHornHighButton },
|
|
{ "fuse_bt:", ggFuseButton },
|
|
{ "converterfuse_bt:", ggConverterFuseButton },
|
|
{ "stlinoff_bt:", ggStLinOffButton },
|
|
{ "door_left_sw:", ggDoorLeftButton },
|
|
{ "door_right_sw:", ggDoorRightButton },
|
|
{ "departure_signal_bt:", ggDepartureSignalButton },
|
|
{ "upperlight_sw:", ggUpperLightButton },
|
|
{ "leftlight_sw:", ggLeftLightButton },
|
|
{ "rightlight_sw:", ggRightLightButton },
|
|
{ "dimheadlights_sw:", ggDimHeadlightsButton },
|
|
{ "leftend_sw:", ggLeftEndLightButton },
|
|
{ "rightend_sw:", ggRightEndLightButton },
|
|
{ "lights_sw:", ggLightsButton },
|
|
{ "rearupperlight_sw:", ggRearUpperLightButton },
|
|
{ "rearleftlight_sw:", ggRearLeftLightButton },
|
|
{ "rearrightlight_sw:", ggRearRightLightButton },
|
|
{ "rearleftend_sw:", ggRearLeftEndLightButton },
|
|
{ "rearrightend_sw:", ggRearRightEndLightButton },
|
|
{ "compressor_sw:", ggCompressorButton },
|
|
{ "compressorlocal_sw:", ggCompressorLocalButton },
|
|
{ "converter_sw:", ggConverterButton },
|
|
{ "converterlocal_sw:", ggConverterLocalButton },
|
|
{ "converteroff_sw:", ggConverterOffButton },
|
|
{ "main_sw:", ggMainButton },
|
|
{ "radio_sw:", ggRadioButton },
|
|
{ "pantfront_sw:", ggPantFrontButton },
|
|
{ "pantrear_sw:", ggPantRearButton },
|
|
{ "pantfrontoff_sw:", ggPantFrontButtonOff },
|
|
{ "pantrearoff_sw:", ggPantRearButtonOff },
|
|
{ "pantalloff_sw:", ggPantAllDownButton },
|
|
{ "pantselected_sw:", ggPantSelectedButton },
|
|
{ "pantselectedoff_sw:", ggPantSelectedDownButton },
|
|
{ "pantcompressor_sw:", ggPantCompressorButton },
|
|
{ "pantcompressorvalve_sw:", ggPantCompressorValve },
|
|
{ "trainheating_sw:", ggTrainHeatingButton },
|
|
{ "signalling_sw:", ggSignallingButton },
|
|
{ "door_signalling_sw:", ggDoorSignallingButton },
|
|
{ "nextcurrent_sw:", ggNextCurrentButton },
|
|
{ "instrumentlight_sw:", ggInstrumentLightButton },
|
|
{ "cablight_sw:", ggCabLightButton },
|
|
{ "cablightdim_sw:", ggCabLightDimButton },
|
|
{ "battery_sw:", ggBatteryButton },
|
|
{ "universal0:", ggUniversals[ 0 ] },
|
|
{ "universal1:", ggUniversals[ 1 ] },
|
|
{ "universal2:", ggUniversals[ 2 ] },
|
|
{ "universal3:", ggUniversals[ 3 ] },
|
|
{ "universal4:", ggUniversals[ 4 ] },
|
|
{ "universal5:", ggUniversals[ 5 ] },
|
|
{ "universal6:", ggUniversals[ 6 ] },
|
|
{ "universal7:", ggUniversals[ 7 ] },
|
|
{ "universal8:", ggUniversals[ 8 ] },
|
|
{ "universal9:", ggUniversals[ 9 ] }
|
|
};
|
|
auto lookup = gauges.find( Label );
|
|
if( lookup != gauges.end() ) {
|
|
lookup->second.Load( Parser, DynamicObject->mdKabina );
|
|
m_controlmapper.insert( lookup->second, lookup->first );
|
|
}
|
|
// ABu 090305: uniwersalne przyciski lub inne rzeczy
|
|
else if( Label == "mainctrlact:" ) {
|
|
ggMainCtrlAct.Load( Parser, DynamicObject->mdKabina, DynamicObject->mdModel );
|
|
}
|
|
// SEKCJA WSKAZNIKOW
|
|
else if ((Label == "tachometer:") || (Label == "tachometerb:"))
|
|
{
|
|
// predkosciomierz wskaźnikowy z szarpaniem
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(&fTachoVelocityJump);
|
|
}
|
|
else if (Label == "tachometern:")
|
|
{
|
|
// predkosciomierz wskaźnikowy bez szarpania
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(&fTachoVelocity);
|
|
}
|
|
else if (Label == "tachometerd:")
|
|
{
|
|
// predkosciomierz cyfrowy
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(&fTachoVelocity);
|
|
}
|
|
else if ((Label == "hvcurrent1:") || (Label == "hvcurrent1b:"))
|
|
{
|
|
// 1szy amperomierz
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(fHCurrent + 1);
|
|
}
|
|
else if ((Label == "hvcurrent2:") || (Label == "hvcurrent2b:"))
|
|
{
|
|
// 2gi amperomierz
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(fHCurrent + 2);
|
|
}
|
|
else if ((Label == "hvcurrent3:") || (Label == "hvcurrent3b:"))
|
|
{
|
|
// 3ci amperomierz
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałska
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(fHCurrent + 3);
|
|
}
|
|
else if ((Label == "hvcurrent:") || (Label == "hvcurrentb:"))
|
|
{
|
|
// amperomierz calkowitego pradu
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(fHCurrent);
|
|
}
|
|
else if (Label == "eimscreen:")
|
|
{
|
|
// amperomierz calkowitego pradu
|
|
int i, j;
|
|
Parser.getTokens(2, false);
|
|
Parser >> i >> j;
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(&fEIMParams[i][j]);
|
|
}
|
|
else if (Label == "brakes:")
|
|
{
|
|
// amperomierz calkowitego pradu
|
|
int i, j;
|
|
Parser.getTokens(2, false);
|
|
Parser >> i >> j;
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(&fPress[i - 1][j]);
|
|
}
|
|
else if ((Label == "brakepress:") || (Label == "brakepressb:"))
|
|
{
|
|
// manometr cylindrow hamulcowych
|
|
// Ra 2014-08: przeniesione do TCab
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina, nullptr, 0.1);
|
|
gauge.AssignDouble(&mvOccupied->BrakePress);
|
|
}
|
|
else if ((Label == "pipepress:") || (Label == "pipepressb:"))
|
|
{
|
|
// manometr przewodu hamulcowego
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina, nullptr, 0.1);
|
|
gauge.AssignDouble(&mvOccupied->PipePress);
|
|
}
|
|
else if (Label == "limpipepress:")
|
|
{
|
|
// manometr zbiornika sterujacego zaworu maszynisty
|
|
ggZbS.Load(Parser, DynamicObject->mdKabina, nullptr, 0.1);
|
|
}
|
|
else if (Label == "cntrlpress:")
|
|
{
|
|
// manometr zbiornika kontrolnego/rorz�du
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina, nullptr, 0.1);
|
|
gauge.AssignDouble(&mvControlled->PantPress);
|
|
}
|
|
else if ((Label == "compressor:") || (Label == "compressorb:"))
|
|
{
|
|
// manometr sprezarki/zbiornika glownego
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina, nullptr, 0.1);
|
|
gauge.AssignDouble(&mvOccupied->Compressor);
|
|
}
|
|
// yB - dla drugiej sekcji
|
|
else if (Label == "hvbcurrent1:")
|
|
{
|
|
// 1szy amperomierz
|
|
ggI1B.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "hvbcurrent2:")
|
|
{
|
|
// 2gi amperomierz
|
|
ggI2B.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "hvbcurrent3:")
|
|
{
|
|
// 3ci amperomierz
|
|
ggI3B.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "hvbcurrent:")
|
|
{
|
|
// amperomierz calkowitego pradu
|
|
ggItotalB.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
//*************************************************************
|
|
else if (Label == "clock:")
|
|
{
|
|
// zegar analogowy
|
|
if (Parser.getToken<std::string>() == "analog")
|
|
{
|
|
// McZapkie-300302: zegarek
|
|
ggClockSInd.Init(DynamicObject->mdKabina->GetFromName("ClockShand"), gt_Rotate, 1.0/60.0, 0, 0);
|
|
ggClockMInd.Init(DynamicObject->mdKabina->GetFromName("ClockMhand"), gt_Rotate, 1.0/60.0, 0, 0);
|
|
ggClockHInd.Init(DynamicObject->mdKabina->GetFromName("ClockHhand"), gt_Rotate, 1.0/12.0, 0, 0);
|
|
}
|
|
}
|
|
else if (Label == "evoltage:")
|
|
{
|
|
// woltomierz napiecia silnikow
|
|
ggEngineVoltage.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "hvoltage:")
|
|
{
|
|
// woltomierz wysokiego napiecia
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(&fHVoltage);
|
|
}
|
|
else if (Label == "lvoltage:")
|
|
{
|
|
// woltomierz niskiego napiecia
|
|
ggLVoltage.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "enrot1m:")
|
|
{
|
|
// obrotomierz
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(fEngine + 1);
|
|
} // ggEnrot1m.Load(Parser,DynamicObject->mdKabina);
|
|
else if (Label == "enrot2m:")
|
|
{
|
|
// obrotomierz
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(fEngine + 2);
|
|
} // ggEnrot2m.Load(Parser,DynamicObject->mdKabina);
|
|
else if (Label == "enrot3m:")
|
|
{ // obrotomierz
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignFloat(fEngine + 3);
|
|
} // ggEnrot3m.Load(Parser,DynamicObject->mdKabina);
|
|
else if (Label == "engageratio:")
|
|
{
|
|
// np. ciśnienie sterownika sprzęgła
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignDouble(&mvControlled->dizel_engage);
|
|
} // ggEngageRatio.Load(Parser,DynamicObject->mdKabina);
|
|
else if (Label == "maingearstatus:")
|
|
{
|
|
// np. ciśnienie sterownika skrzyni biegów
|
|
ggMainGearStatus.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "ignitionkey:")
|
|
{
|
|
ggIgnitionKey.Load(Parser, DynamicObject->mdKabina);
|
|
}
|
|
else if (Label == "distcounter:")
|
|
{
|
|
// Ra 2014-07: licznik kilometrów
|
|
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
|
|
gauge.Load(Parser, DynamicObject->mdKabina);
|
|
gauge.AssignDouble(&mvControlled->DistCounter);
|
|
}
|
|
else
|
|
{
|
|
// failed to match the label
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void
|
|
TTrain::play_sound( sound* Sound, float gain ) {
|
|
|
|
if( Sound ) {
|
|
Sound->gain(gain).play();
|
|
}
|
|
}
|
|
|
|
void
|
|
TTrain::play_sound( sound* Sound, sound* Fallbacksound, float gain ) {
|
|
|
|
if( Sound )
|
|
play_sound( Sound, gain);
|
|
else if( Fallbacksound )
|
|
play_sound( Fallbacksound, gain );
|
|
}
|
|
|
|
float TTrain::get_tacho()
|
|
{
|
|
return fTachoVelocity;
|
|
}
|
|
|
|
float TTrain::get_tank_pressure()
|
|
{
|
|
return mvOccupied->Compressor;
|
|
}
|
|
|
|
float TTrain::get_pipe_pressure()
|
|
{
|
|
return mvOccupied->PipePress;
|
|
}
|
|
|
|
float TTrain::get_brake_pressure()
|
|
{
|
|
return mvOccupied->BrakePress;
|
|
}
|
|
|
|
float TTrain::get_hv_voltage()
|
|
{
|
|
return fHVoltage;
|
|
}
|
|
|
|
std::array<float, 3> TTrain::get_current()
|
|
{
|
|
return { fHCurrent[(mvControlled->TrainType & dt_EZT) ? 0 : 1], fHCurrent[2], fHCurrent[3] };
|
|
}
|
|
|
|
bool TTrain::get_alarm()
|
|
{
|
|
return (TestFlag(mvOccupied->SecuritySystem.Status, s_CAalarm) ||
|
|
TestFlag(mvOccupied->SecuritySystem.Status, s_SHPalarm));
|
|
}
|
|
|
|
void TTrain::set_mainctrl(int pos)
|
|
{
|
|
if (pos < mvControlled->MainCtrlPos)
|
|
mvControlled->DecMainCtrl(1);
|
|
else if (pos > mvControlled->MainCtrlPos)
|
|
mvControlled->IncMainCtrl(1);
|
|
}
|
|
|
|
void TTrain::set_scndctrl(int pos)
|
|
{
|
|
if (pos < mvControlled->ScndCtrlPos)
|
|
mvControlled->DecScndCtrl(1);
|
|
else if (pos > mvControlled->ScndCtrlPos)
|
|
mvControlled->IncScndCtrl(1);
|
|
}
|
|
|
|
void TTrain::set_trainbrake(float val)
|
|
{
|
|
val = std::min(1.0f, std::max(0.0f, val));
|
|
float min = mvControlled->Handle->GetPos(bh_MIN);
|
|
float max = mvControlled->Handle->GetPos(bh_MAX);
|
|
mvControlled->BrakeLevelSet(min + val * (max - min));
|
|
}
|
|
|
|
void TTrain::set_localbrake(float val)
|
|
{
|
|
val = std::min(1.0f, std::max(0.0f, val));
|
|
float min = 0.0f;
|
|
float max = (float)LocalBrakePosNo;
|
|
mvControlled->LocalBrakePos = std::round(min + val * (max - min));
|
|
}
|
|
|
|
int TTrain::get_drive_direction()
|
|
{
|
|
return mvOccupied->ActiveDir * mvOccupied->CabNo;
|
|
}
|