16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-21 04:39:18 +02:00

basic cargo attributes system, minor cargo enhancements and fixes

This commit is contained in:
tmj-fstate
2018-09-19 19:12:53 +02:00
parent 4c7d254539
commit 38591a09f2
8 changed files with 253 additions and 245 deletions

View File

@@ -1783,7 +1783,7 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
asBaseDir = szDynamicPath + BaseDir + "/"; // McZapkie-310302
replace_slashes( asBaseDir );
asName = Name;
std::string asAnimName = ""; // zmienna robocza do wyszukiwania osi i wózków
std::string asAnimName; // zmienna robocza do wyszukiwania osi i wózków
// Ra: zmieniamy znaczenie obsady na jednoliterowe, żeby dosadzić kierownika
if (DriverType == "headdriver")
DriverType = "1"; // sterujący kabiną +1
@@ -1810,7 +1810,7 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
}
*/
// utworzenie parametrów fizyki
MoverParameters = new TMoverParameters(iDirection ? fVel : -fVel, Type_Name, asName, Load, LoadType, Cab);
MoverParameters = new TMoverParameters(iDirection ? fVel : -fVel, Type_Name, asName, Cab);
iLights = MoverParameters->iLights; // wskaźnik na stan własnych świateł
// McZapkie: TypeName musi byc nazwą CHK/MMD pojazdu
if (!MoverParameters->LoadFIZ(asBaseDir))
@@ -1822,6 +1822,9 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
}
return 0.0; // zerowa długość to brak pojazdu
}
// load the cargo now that we know whether the vehicle will allow it
MoverParameters->AssignLoad( LoadType, Load );
bool driveractive = (fVel != 0.0); // jeśli prędkość niezerowa, to aktywujemy ruch
if (!MoverParameters->CheckLocomotiveParameters(
driveractive,
@@ -2095,7 +2098,8 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
iAxles = std::min( MoverParameters->NAxles, MaxAxles ); // ilość osi
*/
// wczytywanie z pliku nazwatypu.mmd, w tym model
LoadMMediaFile(asBaseDir, Type_Name, asReplacableSkin);
erase_extension( asReplacableSkin );
LoadMMediaFile(Type_Name, asReplacableSkin);
// McZapkie-100402: wyszukiwanie submodeli sprzegów
btCoupler1.Init( "coupler1", mdModel, false ); // false - ma być wyłączony
btCoupler2.Init( "coupler2", mdModel, false);
@@ -2612,13 +2616,13 @@ void TDynamicObject::update_exchange( double const Deltatime ) {
auto const exchangesize = std::min( m_exchange.unload_count, MoverParameters->UnLoadSpeed * m_exchange.speed_factor );
m_exchange.unload_count -= exchangesize;
MoverParameters->LoadStatus = 1;
MoverParameters->Load = std::max( 0.f, MoverParameters->Load - exchangesize );
MoverParameters->LoadAmount = std::max( 0.f, MoverParameters->LoadAmount - exchangesize );
update_load_visibility();
}
if( m_exchange.unload_count < 0.01 ) {
// finish any potential unloading operation before adding new load
// don't load more than can fit
m_exchange.load_count = std::min( m_exchange.load_count, MoverParameters->MaxLoad - MoverParameters->Load );
m_exchange.load_count = std::min( m_exchange.load_count, MoverParameters->MaxLoad - MoverParameters->LoadAmount );
while( ( m_exchange.load_count > 0.01 )
&& ( m_exchange.time >= 1.0 ) ) {
@@ -2626,7 +2630,7 @@ void TDynamicObject::update_exchange( double const Deltatime ) {
auto const exchangesize = std::min( m_exchange.load_count, MoverParameters->LoadSpeed * m_exchange.speed_factor );
m_exchange.load_count -= exchangesize;
MoverParameters->LoadStatus = 2;
MoverParameters->Load = std::min( MoverParameters->MaxLoad, MoverParameters->Load + exchangesize ); // std::max not strictly needed but, eh
MoverParameters->LoadAmount = std::min( MoverParameters->MaxLoad, MoverParameters->LoadAmount + exchangesize ); // std::max not strictly needed but, eh
update_load_visibility();
}
}
@@ -2664,34 +2668,28 @@ void TDynamicObject::LoadUpdate() {
// przeładowanie modelu ładunku
// Ra: nie próbujemy wczytywać modeli miliony razy podczas renderowania!!!
if( ( mdLoad == nullptr )
&& ( MoverParameters->Load > 0 ) ) {
&& ( MoverParameters->LoadAmount > 0 ) ) {
if( false == MoverParameters->LoadType.empty() ) {
if( false == MoverParameters->LoadType.name.empty() ) {
// bieżąca ścieżka do tekstur to dynamic/...
Global.asCurrentTexturePath = asBaseDir;
Global.asCurrentTexturePath = asBaseDir; // bieżąca ścieżka do tekstur to dynamic/...
// try first specialized version of the load model, vehiclename_loadname
auto const specializedloadfilename { asBaseDir + MoverParameters->TypeName + "_" + MoverParameters->LoadType };
mdLoad = TModelsManager::GetModel( specializedloadfilename, true );
if( mdLoad == nullptr ) {
// if this fails, try generic load model
auto const genericloadfilename { asBaseDir + MoverParameters->LoadType };
mdLoad = TModelsManager::GetModel( genericloadfilename, true );
}
mdLoad = LoadMMediaFile_mdload( MoverParameters->LoadType.name );
// TODO: discern from vehicle component which merely uses vehicle directory and has no animations, so it can be initialized outright
// and actual vehicles which get their initialization after their animations are set up
if( mdLoad != nullptr ) {
// TODO: discern from vehicle component which merely uses vehicle directory and has no animations, so it can be initialized outright
// and actual vehicles which get their initialization after their animations are set up
mdLoad->Init();
}
// update bindings between lowpoly sections and potential load chunks placed inside them
update_load_sections();
Global.asCurrentTexturePath = std::string( szTexturePath ); // z powrotem defaultowa sciezka do tekstur
// z powrotem defaultowa sciezka do tekstur
Global.asCurrentTexturePath = std::string( szTexturePath );
}
// Ra: w MMD można by zapisać położenie modelu ładunku (np. węgiel) w zależności od załadowania
}
else if( MoverParameters->Load == 0 ) {
else if( MoverParameters->LoadAmount == 0 ) {
// nie ma ładunku
MoverParameters->AssignLoad( "" );
mdLoad = nullptr;
// erase bindings between lowpoly sections and potential load chunks placed inside them
update_load_sections();
@@ -2729,7 +2727,7 @@ TDynamicObject::update_load_visibility() {
auto loadpercentage { (
MoverParameters->MaxLoad == 0.0 ?
0.0 :
100.0 * MoverParameters->Load / MoverParameters->MaxLoad ) };
100.0 * MoverParameters->LoadAmount / MoverParameters->MaxLoad ) };
auto const sectionloadpercentage { (
SectionLoadVisibility.empty() ?
0.0 :
@@ -2758,14 +2756,14 @@ TDynamicObject::update_load_visibility() {
void
TDynamicObject::update_load_offset() {
if( MoverParameters->LoadMinOffset == 0.f ) { return; }
if( MoverParameters->LoadType.offset_min == 0.f ) { return; }
auto const loadpercentage { (
MoverParameters->MaxLoad == 0.0 ?
0.0 :
100.0 * MoverParameters->Load / MoverParameters->MaxLoad ) };
100.0 * MoverParameters->LoadAmount / MoverParameters->MaxLoad ) };
LoadOffset = interpolate( MoverParameters->LoadMinOffset, 0.f, clamp( 0.0, 1.0, loadpercentage * 0.01 ) );
LoadOffset = interpolate( MoverParameters->LoadType.offset_min, 0.f, clamp( 0.0, 1.0, loadpercentage * 0.01 ) );
}
void
@@ -4479,20 +4477,14 @@ TDynamicObject::tracing_offset() const {
// McZapkie-250202
// wczytywanie pliku z danymi multimedialnymi (dzwieki)
void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName, std::string ReplacableSkin ) {
replace_slashes( BaseDir );
Global.asCurrentDynamicPath = BaseDir;
std::string asFileName = BaseDir + TypeName + ".mmd";
std::string asLoadName;
if( false == MoverParameters->LoadType.empty() ) {
asLoadName = BaseDir + MoverParameters->LoadType;
}
void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string const &ReplacableSkin ) {
Global.asCurrentDynamicPath = asBaseDir;
std::string asFileName = asBaseDir + TypeName + ".mmd";
std::string asAnimName;
bool Stop_InternalData = false;
pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów
cParser parser( TypeName + ".mmd", cParser::buffer_FILE, BaseDir );
cParser parser( TypeName + ".mmd", cParser::buffer_FILE, asBaseDir );
if( false == parser.ok() ) {
ErrorLog( "Failed to load appearance data for vehicle " + MoverParameters->Name );
return;
@@ -4526,8 +4518,8 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
}
m_materialdata.multi_textures = clamp( m_materialdata.multi_textures, 0, 1 ); // na razie ustawiamy na 1
}
asModel = BaseDir + asModel; // McZapkie 2002-07-20: dynamics maja swoje modele w dynamics/basedir
Global.asCurrentTexturePath = BaseDir; // biezaca sciezka do tekstur to dynamic/...
asModel = asBaseDir + asModel; // McZapkie 2002-07-20: dynamics maja swoje modele w dynamics/basedir
Global.asCurrentTexturePath = asBaseDir; // biezaca sciezka do tekstur to dynamic/...
mdModel = TModelsManager::GetModel(asModel, true);
if (ReplacableSkin != "none")
{
@@ -4553,7 +4545,6 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
}
else {
// otherwise try the basic approach
erase_extension( ReplacableSkin );
int skinindex = 0;
do {
material_handle material = GfxRenderer.Fetch_Material( ReplacableSkin + "," + std::to_string( skinindex + 1 ), true );
@@ -4598,53 +4589,9 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
m_materialdata.textures_alpha |= 0x08080008;
}
}
if( !MoverParameters->LoadAccepted.empty() ) {
if( ( MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector )
&& ( asLoadName == "pantstate" ) ) {
// wartość niby "pantstate" - nazwa dla formalności, ważna jest ilość
if( MoverParameters->Load == 1 ) {
MoverParameters->PantFront( true );
}
else if( MoverParameters->Load == 2 ) {
MoverParameters->PantRear( true );
}
else if( MoverParameters->Load == 3 ) {
MoverParameters->PantFront( true );
MoverParameters->PantRear( true );
}
else if( MoverParameters->Load == 4 ) {
MoverParameters->DoubleTr = -1;
}
else if( MoverParameters->Load == 5 ) {
MoverParameters->DoubleTr = -1;
MoverParameters->PantRear( true );
}
else if( MoverParameters->Load == 6 ) {
MoverParameters->DoubleTr = -1;
MoverParameters->PantFront( true );
}
else if( MoverParameters->Load == 7 ) {
MoverParameters->DoubleTr = -1;
MoverParameters->PantFront( true );
MoverParameters->PantRear( true );
}
}
else {
// Ra: tu wczytywanie modelu ładunku jest w porządku
if( false == asLoadName.empty() ) {
// try first specialized version of the load model, vehiclename_loadname
auto const specializedloadfilename { BaseDir + TypeName + "_" + MoverParameters->LoadType };
if( ( true == FileExists( specializedloadfilename + ".e3d" ) )
|| ( true == FileExists( specializedloadfilename + ".t3d" ) ) ) {
mdLoad = TModelsManager::GetModel( specializedloadfilename, true );
}
if( mdLoad == nullptr ) {
// if this fails, try generic load model
mdLoad = TModelsManager::GetModel( asLoadName, true );
}
}
}
if( false == MoverParameters->LoadAttributes.empty() ) {
// Ra: tu wczytywanie modelu ładunku jest w porządku
mdLoad = LoadMMediaFile_mdload( MoverParameters->LoadType.name );
}
Global.asCurrentTexturePath = szTexturePath; // z powrotem defaultowa sciezka do tekstur
do {
@@ -4707,8 +4654,8 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
// filename can potentially begin with a slash, and we don't need it
asModel.erase( 0, 1 );
}
asModel = BaseDir + asModel; // McZapkie-200702 - dynamics maja swoje modele w dynamic/basedir
Global.asCurrentTexturePath = BaseDir; // biezaca sciezka do tekstur to dynamic/...
asModel = asBaseDir + asModel; // McZapkie-200702 - dynamics maja swoje modele w dynamic/basedir
Global.asCurrentTexturePath = asBaseDir; // biezaca sciezka do tekstur to dynamic/...
mdLowPolyInt = TModelsManager::GetModel(asModel, true);
}
@@ -5925,6 +5872,25 @@ void TDynamicObject::LoadMMediaFile( std::string BaseDir, std::string TypeName,
m_couplersounds[ side::rear ].dsbBufferClamp_loud.offset( rearcoupleroffset );
}
TModel3d *
TDynamicObject::LoadMMediaFile_mdload( std::string const &Name ) const {
if( Name.empty() ) { return nullptr; }
// try first specialized version of the load model, vehiclename_loadname
TModel3d *loadmodel { nullptr };
auto const specializedloadfilename { asBaseDir + MoverParameters->TypeName + "_" + Name };
if( ( true == FileExists( specializedloadfilename + ".e3d" ) )
|| ( true == FileExists( specializedloadfilename + ".t3d" ) ) ) {
loadmodel = TModelsManager::GetModel( specializedloadfilename, true );
}
if( loadmodel == nullptr ) {
// if this fails, try generic load model
loadmodel = TModelsManager::GetModel( asBaseDir + Name, true );
}
return loadmodel;
}
//---------------------------------------------------------------------------
void TDynamicObject::RadioStop()
{ // zatrzymanie pojazdu
@@ -7029,7 +6995,8 @@ vehicle_table::erase_disabled() {
&& ( true == vehicle->MyTrack->RemoveDynamicObject( vehicle ) ) ) {
vehicle->MyTrack = nullptr;
}
if( simulation::Train->Dynamic() == vehicle ) {
if( ( simulation::Train != nullptr )
&& ( simulation::Train->Dynamic() == vehicle ) ) {
// clear potential train binding
// TBD, TODO: manually eject the driver first ?
SafeDelete( simulation::Train );

View File

@@ -458,7 +458,7 @@ private:
public:
void ABuScanObjects(int ScanDir, double ScanDist);
protected:
private:
TDynamicObject *ABuFindObject( int &Foundcoupler, double &Distance, TTrack const *Track, int const Direction, int const Mycoupler );
void ABuCheckMyTrack();
@@ -580,7 +580,8 @@ private:
Axle0.GetTrack()); };
// McZapkie-260202
void LoadMMediaFile(std::string BaseDir, std::string TypeName, std::string ReplacableSkin);
void LoadMMediaFile(std::string const &TypeName, std::string const &ReplacableSkin);
TModel3d *LoadMMediaFile_mdload( std::string const &Name ) const;
inline double ABuGetDirection() const { // ABu.
return (Axle1.GetTrack() == MyTrack ? Axle1.GetDirection() : Axle0.GetDirection()); };

View File

@@ -913,15 +913,15 @@ whois_event::run_() {
else {
// jeśli parametry ładunku
targetcell->UpdateValues(
m_activator->MoverParameters->LoadType, // nazwa ładunku
m_activator->MoverParameters->Load, // aktualna ilość
m_activator->MoverParameters->LoadType.name, // nazwa ładunku
m_activator->MoverParameters->LoadAmount, // aktualna ilość
m_activator->MoverParameters->MaxLoad, // maksymalna ilość
m_input.flags & ( flags::text | flags::value_1 | flags::value_2 ) );
WriteLog(
"Type: WhoIs (" + to_string( m_input.flags ) + ") - "
+ "[load type: " + m_activator->MoverParameters->LoadType + "], "
+ "[current load: " + to_string( m_activator->MoverParameters->Load, 2 ) + "], "
+ "[load type: " + m_activator->MoverParameters->LoadType.name + "], "
+ "[current load: " + to_string( m_activator->MoverParameters->LoadAmount, 2 ) + "], "
+ "[max load: " + to_string( m_activator->MoverParameters->MaxLoad, 2 ) + "]" );
}
}

View File

@@ -944,11 +944,19 @@ public:
double MED_EPVC_Time = 7; // czas korekcji sily hamowania EP, gdy nie ma dostepnego ED
bool MED_Ncor = 0; // czy korekcja sily hamowania z uwzglednieniem nacisku
/*-dla wagonow*/
struct load_attributes {
std::string name; // name of the cargo
float offset_min { 0.f }; // offset applied to cargo model when load amount is 0
load_attributes() = default;
load_attributes( std::string const &Name, float const Offsetmin ) :
name( Name ), offset_min( Offsetmin )
{}
};
std::vector<load_attributes> LoadAttributes;
float MaxLoad = 0.f; /*masa w T lub ilosc w sztukach - ladownosc*/
std::string LoadAccepted; std::string LoadQuantity; /*co moze byc zaladowane, jednostki miary*/
double OverLoadFactor = 0.0; /*ile razy moze byc przekroczona ladownosc*/
float LoadMinOffset { 0.f }; // offset applied to cargo model when load amount is 0
float LoadSpeed = 0.f; float UnLoadSpeed = 0.f;/*szybkosc na- i rozladunku jednostki/s*/
double OverLoadFactor = 0.0; /*ile razy moze byc przekroczona ladownosc*/
float LoadSpeed = 0.f; float UnLoadSpeed = 0.f;/*szybkosc na- i rozladunku jednostki/s*/
int DoorOpenCtrl = 0; int DoorCloseCtrl = 0; /*0: przez pasazera, 1: przez maszyniste, 2: samoczynne (zamykanie)*/
double DoorStayOpen = 0.0; /*jak dlugo otwarte w przypadku DoorCloseCtrl=2*/
bool DoorClosureWarning = false; /*czy jest ostrzeganie przed zamknieciem*/
@@ -1167,9 +1175,10 @@ public:
double eAngle = M_PI * 0.5;
/*-dla wagonow*/
float Load = 0.f; /*masa w T lub ilosc w sztukach - zaladowane*/
std::string LoadType; /*co jest zaladowane*/
int LoadStatus = 0; //+1=trwa rozladunek,+2=trwa zaladunek,+4=zakończono,0=zaktualizowany model
float LoadAmount = 0.f; /*masa w T lub ilosc w sztukach - zaladowane*/
load_attributes LoadType;
std::string LoadQuantity; // jednostki miary
int LoadStatus = 0; //+1=trwa rozladunek,+2=trwa zaladunek,+4=zakończono,0=zaktualizowany model
double LastLoadChangeTime = 0.0; //raz (roz)ładowania
bool DoorBlocked = false; //Czy jest blokada drzwi
@@ -1211,7 +1220,7 @@ private:
double CouplerDist(int Coupler);
public:
TMoverParameters(double VelInitial, std::string TypeNameInit, std::string NameInit, int LoadInitial, std::string LoadTypeInitial, int Cab);
TMoverParameters(double VelInitial, std::string TypeNameInit, std::string NameInit, int Cab);
// obsługa sprzęgów
double Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2);
/* double Distance(const vector3 &Loc1, const vector3 &Loc2, const vector3 &Dim1, const vector3 &Dim2);
@@ -1375,7 +1384,8 @@ public:
bool dizel_Update(double dt);
/* funckje dla wagonow*/
bool LoadingDone(double LSpeed, std::string LoadInit);
bool AssignLoad( std::string const &Name, float const Amount = 0.f );
bool LoadingDone(double LSpeed, std::string const &Loadname);
bool DoorLeft(bool State, range_t const Notify = range_t::consist ); //obsluga drzwi lewych
bool DoorRight(bool State, range_t const Notify = range_t::consist ); //obsluga drzwi prawych
bool DoorBlockedFlag(void); //sprawdzenie blokady drzwi

View File

@@ -278,21 +278,14 @@ double TMoverParameters::Current(double n, double U)
// *************************************************************************************************
// główny konstruktor
// *************************************************************************************************
TMoverParameters::TMoverParameters(double VelInitial, std::string TypeNameInit,
std::string NameInit, int LoadInitial,
std::string LoadTypeInitial,
int Cab) ://: T_MoverParameters(VelInitial, TypeNameInit,
//NameInit, LoadInitial, LoadTypeInitial, Cab)
TMoverParameters::TMoverParameters(double VelInitial, std::string TypeNameInit, std::string NameInit, int Cab) :
TypeName( TypeNameInit ),
Name( NameInit ),
ActiveCab( Cab ),
Load( LoadInitial ),
LoadType( LoadTypeInitial )
ActiveCab( Cab )
{
WriteLog(
"------------------------------------------------------");
WriteLog("init default physic values for " + NameInit + ", [" + TypeNameInit + "], [" +
LoadTypeInitial + "]");
WriteLog("init default physic values for " + NameInit + ", [" + TypeNameInit + "]");
Dim = TDimension();
// BrakeLevelSet(-2); //Pascal ustawia na 0, przestawimy na odcięcie (CHK jest jeszcze nie wczytane!)
@@ -354,10 +347,6 @@ LoadType( LoadTypeInitial )
}
eimc[eimc_p_eped] = 1.5;
// inicjalizacja zmiennych}
// Loc:=LocInitial; //Ra: to i tak trzeba potem przesunąć, po ustaleniu pozycji na torze
// (potrzebna długość)
// Rot:=RotInitial;
for (int b = 0; b < 2; ++b)
{
Couplers[b].AllowedFlag = 3; // domyślnie hak i hamulec, inne trzeba włączyć jawnie w FIZ
@@ -409,20 +398,6 @@ LoadType( LoadTypeInitial )
SecuritySystem.RadioStop = false; // domyślnie nie ma
SecuritySystem.AwareMinSpeed = 0.1 * Vmax;
s_CAtestebrake = false;
// ABu 240105:
// CouplerNr[0]:=1;
// CouplerNr[1]:=0;
// TO POTEM TU UAKTYWNIC A WYWALIC Z CHECKPARAM}
//{
// if Pos(LoadTypeInitial,LoadAccepted)>0 then
// begin
//}
//{
// end
// else Load:=0;
// }
};
double TMoverParameters::Distance(const TLocation &Loc1, const TLocation &Loc2,
@@ -3758,27 +3733,25 @@ void TMoverParameters::ComputeConstans(void)
// *************************************************************************************************
double TMoverParameters::ComputeMass(void)
{
double M;
LoadType = ToLower(LoadType); // po co zakładać jak można mieć na pewno
if (Load > 0)
{ // zakładamy, że ładunek jest pisany małymi literami
double M { 0.0 };
// TODO: unit weight table, pulled from external data file
if( LoadAmount > 0 ) {
if (ToLower(LoadQuantity) == "tonns")
M = Load * 1000;
else if (LoadType == "passengers")
M = Load * 80;
else if (LoadType == "luggage")
M = Load * 100;
else if (LoadType == "cars")
M = Load * 1200; // 800 kilo to miał maluch
else if (LoadType == "containers")
M = Load * 8000;
else if (LoadType == "transformers")
M = Load * 50000;
M = LoadAmount * 1000;
else if (LoadType.name == "passengers")
M = LoadAmount * 80;
else if (LoadType.name == "luggage")
M = LoadAmount * 100;
else if (LoadType.name == "cars")
M = LoadAmount * 1200; // 800 kilo to miał maluch
else if (LoadType.name == "containers")
M = LoadAmount * 8000;
else if (LoadType.name == "transformers")
M = LoadAmount * 50000;
else
M = Load * 1000;
M = LoadAmount * 1000;
}
else
M = 0;
// Ra: na razie tak, ale nie wszędzie masy wirujące się wliczają
return Mass + M + Mred;
}
@@ -6458,58 +6431,105 @@ void TMoverParameters::dizel_Heat( double const dt ) {
*/
}
bool
TMoverParameters::AssignLoad( std::string const &Name, float const Amount ) {
if( Name == "pantstate" ) {
if( EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) {
// wartość niby "pantstate" - nazwa dla formalności, ważna jest ilość
auto const pantographsetup { static_cast<int>( Amount ) };
if( pantographsetup & ( 1 << 2 ) ) {
DoubleTr = -1;
}
if( pantographsetup & ( 1 << 0 ) ) {
if( DoubleTr == 1 ) { PantFront( true ); }
else { PantRear( true ); }
}
if( pantographsetup & ( 1 << 1 ) ) {
if( DoubleTr == 1 ) { PantRear( true ); }
else { PantFront( true ); }
}
return true;
}
else {
return false;
}
}
// can't mix load types, at least for the time being
if( ( LoadAmount > 0 ) && ( LoadType.name != Name ) ) { return false; }
if( Name.empty() ) {
// empty the vehicle
LoadType = load_attributes();
LoadAmount = 0.f;
return true;
}
for( auto const &loadattributes : LoadAttributes ) {
if( Name == loadattributes.name ) {
LoadType = loadattributes;
LoadAmount = Amount;
return true;
}
}
// didn't find matching load configuration, this type is unsupported
return false;
}
// *************************************************************************************************
// Q: 20160713
// Test zakończenia załadunku / rozładunku
// *************************************************************************************************
bool TMoverParameters::LoadingDone(double LSpeed, std::string LoadInit)
{
// test zakończenia załadunku/rozładunku
long LoadChange = 0;
bool LD = false;
bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadname) {
// ClearPendingExceptions; // zabezpieczenie dla Trunc()
// LoadingDone:=false; //nie zakończone
if (!LoadInit.empty()) // nazwa ładunku niepusta
{
if (Load > MaxLoad)
LoadChange = abs(long(LSpeed * LastLoadChangeTime / 2.0)); // przeładowanie?
else
LoadChange = abs(long(LSpeed * LastLoadChangeTime));
if (LSpeed < 0) // gdy rozładunek
{
LoadStatus = 2; // trwa rozładunek (włączenie naliczania czasu)
if (LoadChange != 0) // jeśli coś przeładowano
{
LastLoadChangeTime = 0; // naliczony czas został zużyty
Load -= LoadChange; // zmniejszenie ilości ładunku
CommandIn.Value1 =
CommandIn.Value1 - LoadChange; // zmniejszenie ilości do rozładowania
if (Load < 0)
Load = 0; //ładunek nie może być ujemny
if ((Load == 0) || (CommandIn.Value1 < 0)) // pusto lub rozładowano żądaną ilość
LoadStatus = 4; // skończony rozładunek
if (Load == 0)
LoadType.clear(); // jak nic nie ma, to nie ma też nazwy
}
}
else if (LSpeed > 0) // gdy załadunek
{
LoadStatus = 1; // trwa załadunek (włączenie naliczania czasu)
if (LoadChange != 0) // jeśli coś przeładowano
{
LastLoadChangeTime = 0; // naliczony czas został zużyty
LoadType = LoadInit; // nazwa
Load += LoadChange; // zwiększenie ładunku
CommandIn.Value1 = CommandIn.Value1 - LoadChange;
if ((Load >= MaxLoad * (1.0 + OverLoadFactor)) || (CommandIn.Value1 < 0))
LoadStatus = 4; // skończony załadunek
}
}
else
LoadStatus = 4; // zerowa prędkość zmiany, to koniec
if( LSpeed == 0.0 ) {
// zerowa prędkość zmiany, to koniec
LoadStatus = 4;
return true;
}
return (LoadStatus >= 4);
if( Loadname.empty() ) { return ( LoadStatus >= 4 ); }
if( Loadname != LoadType.name ) { return ( LoadStatus >= 4 ); }
// test zakończenia załadunku/rozładunku
// load exchange speed is reduced if the wagon is overloaded
auto const loadchange { static_cast<float>( std::abs( LSpeed * LastLoadChangeTime ) * ( LoadAmount > MaxLoad ? 0.5 : 1.0 ) ) };
if( LSpeed < 0 ) {
// gdy rozładunek
LoadStatus = 2; // trwa rozładunek (włączenie naliczania czasu)
if( loadchange > 0 ) // jeśli coś przeładowano
{
LastLoadChangeTime = 0; // naliczony czas został zużyty
LoadAmount -= loadchange; // zmniejszenie ilości ładunku
CommandIn.Value1 -= loadchange; // zmniejszenie ilości do rozładowania
if( ( LoadAmount <= 0 ) || ( CommandIn.Value1 <= 0 ) ) {
// pusto lub rozładowano żądaną ilość
LoadStatus = 4; // skończony rozładunek
LoadAmount = std::max( 0.f, LoadAmount ); //ładunek nie może być ujemny
}
if( LoadAmount == 0.f ) {
AssignLoad(""); // jak nic nie ma, to nie ma też nazwy
}
}
}
else if( LSpeed > 0 ) {
// gdy załadunek
LoadStatus = 1; // trwa załadunek (włączenie naliczania czasu)
if( loadchange > 0 ) // jeśli coś przeładowano
{
LastLoadChangeTime = 0; // naliczony czas został zużyty
LoadAmount += loadchange; // zwiększenie ładunku
CommandIn.Value1 -= loadchange;
if( ( LoadAmount >= MaxLoad * ( 1.0 + OverLoadFactor ) ) || ( CommandIn.Value1 <= 0 ) ) {
LoadStatus = 4; // skończony załadunek
LoadAmount = std::min<float>( MaxLoad * ( 1.0 + OverLoadFactor ), LoadAmount );
}
}
}
return ( LoadStatus >= 4 );
}
// *************************************************************************************************
@@ -7593,19 +7613,30 @@ void TMoverParameters::LoadFIZ_Param( std::string const &line ) {
void TMoverParameters::LoadFIZ_Load( std::string const &line ) {
extract_value( LoadAccepted, "LoadAccepted", line, "" );
if( true == LoadAccepted.empty() ) {
return;
auto const acceptedloads { Split( extract_value( "LoadAccepted", line ), ',' ) };
if( acceptedloads.empty() ) { return; }
auto const minoffsets { Split( extract_value( "LoadMinOffset", line ), ',' ) };
auto minoffset { 0.f };
auto minoffsetsiterator { std::begin( minoffsets ) };
// NOTE: last (if any) offset parameter retrieved from the list applies to the remainder of the list
// TBD, TODO: include other load parameters in this system
for( auto &load : acceptedloads ) {
if( minoffsetsiterator != std::end( minoffsets ) ) {
minoffset = std::stof( *minoffsetsiterator );
++minoffsetsiterator;
}
LoadAttributes.emplace_back(
ToLower( load ),
minoffset );
}
LoadAccepted = ToLower( LoadAccepted );
extract_value( MaxLoad, "MaxLoad", line, "" );
extract_value( LoadQuantity, "LoadQ", line, "" );
extract_value( OverLoadFactor, "OverLoadFactor", line, "" );
extract_value( LoadSpeed, "LoadSpeed", line, "" );
extract_value( UnLoadSpeed, "UnLoadSpeed", line, "" );
extract_value( LoadMinOffset, "LoadMinOffset", line, "" );
}
void TMoverParameters::LoadFIZ_Dimensions( std::string const &line ) {
@@ -8651,11 +8682,6 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
// WriteLogSS("aa ok", BoolToYN(OK));
}
if( ( LoadType.empty() == false ) && ( LoadAccepted.find( LoadType ) == std::string::npos ) ) {
// remove load if the type isn't supported
Load = 0.0;
}
if (BrakeSystem == TBrakeSystem::Individual)
if (BrakeSubsystem != TBrakeSubSystem::ss_None)
OK = false; //!
@@ -8889,16 +8915,16 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
if( LoadFlag > 0 ) {
if( Load < MaxLoad * 0.45 ) {
if( LoadAmount < MaxLoad * 0.45 ) {
IncBrakeMult();
IncBrakeMult();
DecBrakeMult(); // TODO: przeinesiono do mover.cpp
if( Load < MaxLoad * 0.35 )
if( LoadAmount < MaxLoad * 0.35 )
DecBrakeMult();
}
else {
IncBrakeMult(); // TODO: przeinesiono do mover.cpp
if( Load >= MaxLoad * 0.55 )
if( LoadAmount >= MaxLoad * 0.55 )
IncBrakeMult();
}
}
@@ -9479,39 +9505,44 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
OK = true; // true, gdy można usunąć komendę
}
/*naladunek/rozladunek*/
else if ( issection( "Load=", Command ) )
// TODO: have these commands leverage load exchange system instead
else if ( issection( "Load=", Command ) )
{
OK = false; // będzie powtarzane aż się załaduje
if( ( Vel < 0.01 )
if( ( Vel < 0.1 ) // tolerance margin for small vehicle movements in the consist
&& ( MaxLoad > 0 )
&& ( Load < MaxLoad * ( 1.0 + OverLoadFactor ) ) ) {
// czy można ładowac?
if( Distance( Loc, CommandIn.Location, Dim, Dim ) < 10 ) {
// ten peron/rampa
auto const testload { ToLower( extract_value( "Load", Command ) ) };
if( LoadAccepted.find( testload ) != std::string::npos ) // nazwa jest obecna w CHK
OK = LoadingDone( Min0R( CValue2, LoadSpeed ), testload ); // zmienia LoadStatus
&& ( LoadAmount < MaxLoad * ( 1.0 + OverLoadFactor ) )
&& ( Distance( Loc, CommandIn.Location, Dim, Dim ) < 10 ) ) { // ten peron/rampa
auto const loadname { ToLower( extract_value( "Load", Command ) ) };
if( LoadAmount == 0.f ) {
AssignLoad( loadname );
}
OK = LoadingDone(
std::min<float>( CValue2, LoadSpeed ),
loadname ); // zmienia LoadStatus
}
else {
// no loading can be done if conditions aren't met
LastLoadChangeTime = 0.0;
}
// if OK then LoadStatus:=0; //nie udalo sie w ogole albo juz skonczone
}
else if( issection( "UnLoad=", Command ) )
{
OK = false; // będzie powtarzane aż się rozładuje
if( ( Vel < 0.01 )
&& ( Load > 0 ) ) {
// czy jest co rozladowac?
if( Distance( Loc, CommandIn.Location, Dim, Dim ) < 10 ) {
// ten peron
auto const testload { ToLower( extract_value( "UnLoad", Command ) ) }; // zgodność nazwy ładunku z CHK
if( LoadType == testload ) {
/*mozna to rozladowac*/
OK = LoadingDone( -Min0R( CValue2, LoadSpeed ), testload );
}
}
if( ( Vel < 0.1 ) // tolerance margin for small vehicle movements in the consist
&& ( LoadAmount > 0 ) // czy jest co rozladowac?
&& ( Distance( Loc, CommandIn.Location, Dim, Dim ) < 10 ) ) { // ten peron
/*mozna to rozladowac*/
OK = LoadingDone(
-1.f * std::min<float>( CValue2, LoadSpeed ),
ToLower( extract_value( "UnLoad", Command ) ) );
}
// if OK then LoadStatus:=0;
}
else {
// no loading can be done if conditions aren't met
LastLoadChangeTime = 0.0;
}
}
else if (Command == "SpeedCntrl")
{
if ((EngineType == TEngineType::ElectricInductionMotor))

View File

@@ -79,12 +79,12 @@ TSubModel::SetLightLevel( float const Level, bool const Includechildren, bool co
if( true == Includesiblings ) {
auto sibling { this };
while( ( sibling = sibling->Next ) != nullptr ) {
sibling->f4Emision.a = Level;
sibling->SetLightLevel( Level, Includechildren, false ); // no need for all siblings to duplicate the work
}
}
if( ( true == Includechildren )
&& ( Child != nullptr ) ) {
Child->SetLightLevel( Level, true, true ); // node's children include child's siblings and children
Child->SetLightLevel( Level, Includechildren, true ); // node's children include child's siblings and children
}
}

View File

@@ -385,8 +385,8 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
locale::strings[ locale::string::debug_vehicle_nameloadstatuscouplers ].c_str(),
mover.Name.c_str(),
std::string( isowned ? locale::strings[ locale::string::debug_vehicle_owned ].c_str() + vehicle.ctOwner->OwnerName() : "" ).c_str(),
mover.Load,
mover.LoadType.c_str(),
mover.LoadAmount,
mover.LoadType.name.c_str(),
mover.EngineDescription( 0 ).c_str(),
// TODO: put wheel flat reporting in the enginedescription()
std::string( mover.WheelFlat > 0.01 ? " Flat: " + to_string( mover.WheelFlat, 1 ) + " mm" : "" ).c_str(),

View File

@@ -49,20 +49,19 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
auto &parameters { *vehicle->MoverParameters };
if( ( true == parameters.LoadType.empty() )
&& ( parameters.LoadAccepted.find( "passengers" ) != std::string::npos ) ) {
// set the type for empty cars
parameters.LoadType = "passengers";
if( parameters.LoadType.name.empty() ) {
// (try to) set the cargo type for empty cars
parameters.AssignLoad( "passengers" );
}
if( parameters.LoadType == "passengers" ) {
if( parameters.LoadType.name == "passengers" ) {
// NOTE: for the time being we're doing simple, random load change calculation
// TODO: exchange driven by station parameters and time of the day
auto unloadcount = static_cast<int>(
laststop ? parameters.Load :
laststop ? parameters.LoadAmount :
firststop ? 0 :
std::min<float>(
parameters.Load,
parameters.LoadAmount,
Random( parameters.MaxLoad * 0.10 * stationsizemodifier ) ) );
auto loadcount = static_cast<int>(
laststop ?