mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 19:49:19 +02:00
basic train station object, rudimentary passenger loading/unloading on stops, load percentage based submodel visibility
This commit is contained in:
84
Driver.cpp
84
Driver.cpp
@@ -892,8 +892,6 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
mvOccupied->DoorLeft(true);
|
mvOccupied->DoorLeft(true);
|
||||||
if (p2 & prawe)
|
if (p2 & prawe)
|
||||||
mvOccupied->DoorRight(true);
|
mvOccupied->DoorRight(true);
|
||||||
// if (p2&3) //żeby jeszcze poczekał chwilę, zanim zamknie
|
|
||||||
// WaitingSet(10); //10 sekund (wziąć z rozkładu????)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -917,50 +915,62 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
|
|||||||
// pojazd podłączony z tyłu (patrząc od czoła)
|
// pojazd podłączony z tyłu (patrząc od czoła)
|
||||||
p = p->Next();
|
p = p->Next();
|
||||||
}
|
}
|
||||||
// if (p7&3) //żeby jeszcze poczekał chwilę, zanim zamknie
|
|
||||||
// WaitingSet(10); //10 sekund (wziąć z rozkładu????)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (TrainParams->UpdateMTable( simulation::Time, asNextStop) ) {
|
||||||
|
// to się wykona tylko raz po zatrzymaniu na W4
|
||||||
|
|
||||||
if( fStopTime > -5 ) // na końcu rozkładu się ustawia 60s i tu by było skrócenie
|
// perform loading/unloading
|
||||||
WaitingSet( 15.0 + Random( 15.0 ) ); // 10 sekund (wziąć z rozkładu????) - czekanie
|
auto const exchangetime { simulation::Station.update_load( pVehicles[ 0 ], *TrainParams ) };
|
||||||
// niezależne od sposobu obsługi drzwi, bo opóźnia również kierownika
|
// TBD: adjust time to load exchange size
|
||||||
|
if( fStopTime > -55 ) {
|
||||||
|
// na końcu rozkładu się ustawia 60s i tu by było skrócenie
|
||||||
|
// WaitingSet( 15.0 + Random( 15.0 ) ); // 10 sekund (wziąć z rozkładu????) - czekanie
|
||||||
|
// with door open on both sides calculated loading time is halved
|
||||||
|
// p7=platform side (1:left, 2:right, 3:both)
|
||||||
|
auto const platformside = static_cast<int>( std::floor( sSpeedTable[ i ].evEvent->ValueGet( 2 ) ) ) % 10;
|
||||||
|
WaitingSet(
|
||||||
|
platformside == 3 ?
|
||||||
|
exchangetime * 0.5 :
|
||||||
|
exchangetime );
|
||||||
}
|
}
|
||||||
if (TrainParams->UpdateMTable( simulation::Time, asNextStop) )
|
if( TrainParams->CheckTrainLatency() < 0.0 ) {
|
||||||
{ // to się wykona tylko raz po zatrzymaniu na W4
|
// odnotowano spóźnienie
|
||||||
if (TrainParams->CheckTrainLatency() < 0.0)
|
iDrivigFlags |= moveLate;
|
||||||
iDrivigFlags |= moveLate; // odnotowano spóźnienie
|
}
|
||||||
else
|
else {
|
||||||
iDrivigFlags &= ~moveLate; // przyjazd o czasie
|
// przyjazd o czasie
|
||||||
if (TrainParams->DirectionChange()) // jeśli "@" w rozkładzie, to
|
iDrivigFlags &= ~moveLate;
|
||||||
// wykonanie dalszych komend
|
}
|
||||||
{ // wykonanie kolejnej komendy, nie dotyczy ostatniej stacji
|
if (TrainParams->DirectionChange()) {
|
||||||
if (iDrivigFlags & movePushPull) // SN61 ma się też nie ruszać,
|
// jeśli "@" w rozkładzie, to wykonanie dalszych komend
|
||||||
// chyba że ma wagony
|
// wykonanie kolejnej komendy, nie dotyczy ostatniej stacji
|
||||||
{
|
if (iDrivigFlags & movePushPull) {
|
||||||
|
// SN61 ma się też nie ruszać, chyba że ma wagony
|
||||||
iDrivigFlags |= moveStopHere; // EZT ma stać przy peronie
|
iDrivigFlags |= moveStopHere; // EZT ma stać przy peronie
|
||||||
if (OrderNextGet() != Change_direction)
|
if (OrderNextGet() != Change_direction) {
|
||||||
{
|
|
||||||
OrderPush(Change_direction); // zmiana kierunku
|
OrderPush(Change_direction); // zmiana kierunku
|
||||||
OrderPush(TrainParams->StationIndex <
|
OrderPush(
|
||||||
TrainParams->StationCount ?
|
TrainParams->StationIndex < TrainParams->StationCount ?
|
||||||
Obey_train :
|
Obey_train :
|
||||||
Shunt); // to dalej wg rozkładu
|
Shunt); // to dalej wg rozkładu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // a dla lokomotyw...
|
else {
|
||||||
iDrivigFlags &=
|
// a dla lokomotyw...
|
||||||
~(moveStopPoint | moveStopHere); // pozwolenie na
|
// pozwolenie na przejechanie za W4 przed czasem i nie ma stać
|
||||||
// przejechanie za W4
|
iDrivigFlags &= ~( moveStopPoint | moveStopHere );
|
||||||
// przed czasem i nie
|
}
|
||||||
// ma stać
|
// przejście do kolejnego rozkazu (zmiana kierunku, odczepianie)
|
||||||
JumpToNextOrder(); // przejście do kolejnego rozkazu (zmiana
|
JumpToNextOrder();
|
||||||
// kierunku, odczepianie)
|
// ma nie podjeżdżać pod W4 po przeciwnej stronie
|
||||||
iDrivigFlags &= ~moveStopCloser; // ma nie podjeżdżać pod W4 po
|
iDrivigFlags &= ~moveStopCloser;
|
||||||
// przeciwnej stronie
|
// ten W4 nie liczy się już zupełnie (nie wyśle SetVelocity)
|
||||||
sSpeedTable[i].iFlags = 0; // ten W4 nie liczy się już zupełnie
|
sSpeedTable[i].iFlags = 0;
|
||||||
// (nie wyśle SetVelocity)
|
// jechać
|
||||||
sSpeedTable[i].fVelNext = -1; // jechać
|
sSpeedTable[i].fVelNext = -1;
|
||||||
continue; // nie analizować prędkości
|
// nie analizować prędkości
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (OrderCurrentGet() == Shunt)
|
if (OrderCurrentGet() == Shunt)
|
||||||
|
|||||||
116
DynObj.cpp
116
DynObj.cpp
@@ -976,6 +976,10 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
|
|||||||
section.load->SetLightLevel( section.level, true );
|
section.load->SetLightLevel( section.level, true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// load chunks visibility
|
||||||
|
for( auto const §ion : SectionLoadVisibility ) {
|
||||||
|
section.submodel->iVisible = section.visible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// ABu 29.01.05 koniec przeklejenia *************************************
|
// ABu 29.01.05 koniec przeklejenia *************************************
|
||||||
|
|
||||||
@@ -2010,9 +2014,9 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
// check the low poly interior for potential compartments of interest, ie ones which can be individually lit
|
// check the low poly interior for potential compartments of interest, ie ones which can be individually lit
|
||||||
// TODO: definition of relevant compartments in the .mmd file
|
// TODO: definition of relevant compartments in the .mmd file
|
||||||
TSubModel *submodel { nullptr };
|
TSubModel *submodel { nullptr };
|
||||||
if( ( submodel = mdLowPolyInt->GetFromName( "cab1" ) ) != nullptr ) { SectionLightLevels.emplace_back( submodel, nullptr, 0.0f ); }
|
if( ( submodel = mdLowPolyInt->GetFromName( "cab1" ) ) != nullptr ) { SectionLightLevels.push_back( { submodel, nullptr, 0.0f } ); }
|
||||||
if( ( submodel = mdLowPolyInt->GetFromName( "cab2" ) ) != nullptr ) { SectionLightLevels.emplace_back( submodel, nullptr, 0.0f ); }
|
if( ( submodel = mdLowPolyInt->GetFromName( "cab2" ) ) != nullptr ) { SectionLightLevels.push_back( { submodel, nullptr, 0.0f } ); }
|
||||||
if( ( submodel = mdLowPolyInt->GetFromName( "cab0" ) ) != nullptr ) { SectionLightLevels.emplace_back( submodel, nullptr, 0.0f ); }
|
if( ( submodel = mdLowPolyInt->GetFromName( "cab0" ) ) != nullptr ) { SectionLightLevels.push_back( { submodel, nullptr, 0.0f } ); }
|
||||||
// passenger car compartments
|
// passenger car compartments
|
||||||
std::vector<std::string> nameprefixes = { "corridor", "korytarz", "compartment", "przedzial" };
|
std::vector<std::string> nameprefixes = { "corridor", "korytarz", "compartment", "przedzial" };
|
||||||
int compartmentindex;
|
int compartmentindex;
|
||||||
@@ -2027,19 +2031,17 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
std::to_string( compartmentindex ) );
|
std::to_string( compartmentindex ) );
|
||||||
submodel = mdLowPolyInt->GetFromName( compartmentname );
|
submodel = mdLowPolyInt->GetFromName( compartmentname );
|
||||||
if( submodel != nullptr ) {
|
if( submodel != nullptr ) {
|
||||||
// if specified compartment was found we check also for potential matching section in the currently assigned load
|
SectionLightLevels.push_back( {
|
||||||
// NOTE: if the load gets changed this will invalidate stored pointers. TODO: rebuild the table on load change
|
|
||||||
SectionLightLevels.emplace_back(
|
|
||||||
submodel,
|
submodel,
|
||||||
( mdLoad != nullptr ?
|
nullptr, // pointers to load sections are generated afterwards
|
||||||
mdLoad->GetFromName( compartmentname ):
|
0.0f } );
|
||||||
nullptr ),
|
|
||||||
0.0f );
|
|
||||||
}
|
}
|
||||||
++compartmentindex;
|
++compartmentindex;
|
||||||
} while( ( submodel != nullptr )
|
} while( ( submodel != nullptr )
|
||||||
|| ( compartmentindex < 2 ) ); // chain can start from prefix00 or prefix01
|
|| ( compartmentindex < 2 ) ); // chain can start from prefix00 or prefix01
|
||||||
}
|
}
|
||||||
|
update_load_sections();
|
||||||
|
update_load_visibility();
|
||||||
}
|
}
|
||||||
// wyszukiwanie zderzakow
|
// wyszukiwanie zderzakow
|
||||||
if( mdModel ) {
|
if( mdModel ) {
|
||||||
@@ -2428,31 +2430,83 @@ bool TDynamicObject::UpdateForce(double dt, double dt1, bool FullVer)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TDynamicObject::LoadUpdate()
|
void TDynamicObject::LoadUpdate() {
|
||||||
{ // przeładowanie modelu ładunku
|
// przeładowanie modelu ładunku
|
||||||
// Ra: nie próbujemy wczytywać modeli miliony razy podczas renderowania!!!
|
// Ra: nie próbujemy wczytywać modeli miliony razy podczas renderowania!!!
|
||||||
if ((mdLoad == NULL) && (MoverParameters->Load > 0))
|
if( ( mdLoad == nullptr )
|
||||||
{
|
&& ( MoverParameters->Load > 0 ) ) {
|
||||||
std::string asLoadName =
|
|
||||||
asBaseDir + MoverParameters->LoadType + ".t3d"; // zapamiętany katalog pojazdu
|
if( false == MoverParameters->LoadType.empty() ) {
|
||||||
// asLoadName=MoverParameters->LoadType;
|
|
||||||
// if (MoverParameters->LoadType!=AnsiString("passengers"))
|
|
||||||
Global.asCurrentTexturePath = asBaseDir; // bieżąca ścieżka do tekstur to dynamic/...
|
Global.asCurrentTexturePath = asBaseDir; // bieżąca ścieżka do tekstur to dynamic/...
|
||||||
mdLoad = TModelsManager::GetModel(asLoadName.c_str()); // nowy ładunek
|
|
||||||
Global.asCurrentTexturePath =
|
// try first specialized version of the load model, vehiclename_loadname
|
||||||
std::string(szTexturePath); // z powrotem defaultowa sciezka do tekstur
|
auto const specializedloadfilename { asBaseDir + MoverParameters->TypeName + "_" + MoverParameters->LoadType };
|
||||||
// Ra: w MMD można by zapisać położenie modelu ładunku (np. węgiel) w
|
if( ( true == FileExists( specializedloadfilename + ".e3d" ) )
|
||||||
// zależności od
|
|| ( true == FileExists( specializedloadfilename + ".t3d" ) ) ) {
|
||||||
// załadowania
|
mdLoad = TModelsManager::GetModel( specializedloadfilename, true );
|
||||||
|
}
|
||||||
|
if( mdLoad == nullptr ) {
|
||||||
|
// if this fails, try generic load model
|
||||||
|
mdLoad = TModelsManager::GetModel( asBaseDir + MoverParameters->LoadType, true );
|
||||||
|
}
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
// 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 ) {
|
||||||
|
// nie ma ładunku
|
||||||
|
mdLoad = nullptr;
|
||||||
|
// erase bindings between lowpoly sections and potential load chunks placed inside them
|
||||||
|
update_load_sections();
|
||||||
}
|
}
|
||||||
else if (MoverParameters->Load == 0)
|
|
||||||
mdLoad = NULL; // nie ma ładunku
|
|
||||||
// if ((mdLoad==NULL)&&(MoverParameters->Load>0))
|
|
||||||
// {
|
|
||||||
// mdLoad=NULL; //Ra: to jest tu bez sensu - co autor miał na myśli?
|
|
||||||
// }
|
|
||||||
MoverParameters->LoadStatus &= 3; // po zakończeniu będzie równe zero
|
MoverParameters->LoadStatus &= 3; // po zakończeniu będzie równe zero
|
||||||
};
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TDynamicObject::update_load_sections() {
|
||||||
|
|
||||||
|
SectionLoadVisibility.clear();
|
||||||
|
|
||||||
|
for( auto §ion : SectionLightLevels ) {
|
||||||
|
|
||||||
|
section.load = (
|
||||||
|
mdLoad != nullptr ?
|
||||||
|
mdLoad->GetFromName( section.compartment->pName ) :
|
||||||
|
nullptr );
|
||||||
|
|
||||||
|
if( section.load != nullptr ) {
|
||||||
|
SectionLoadVisibility.push_back( { section.load, false } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::shuffle( std::begin( SectionLoadVisibility ), std::end( SectionLoadVisibility ), Global.random_engine );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TDynamicObject::update_load_visibility() {
|
||||||
|
|
||||||
|
if( Random() < 0.25 ) {
|
||||||
|
std::shuffle( std::begin( SectionLoadVisibility ), std::end( SectionLoadVisibility ), Global.random_engine );
|
||||||
|
}
|
||||||
|
|
||||||
|
auto loadpercentage { (
|
||||||
|
MoverParameters->MaxLoad == 0.0 ?
|
||||||
|
0.0 :
|
||||||
|
100.0 * MoverParameters->Load / MoverParameters->MaxLoad ) };
|
||||||
|
auto const sectionloadpercentage { (
|
||||||
|
SectionLoadVisibility.empty() ?
|
||||||
|
0.0 :
|
||||||
|
100.0 / SectionLoadVisibility.size() ) };
|
||||||
|
// set as many sections as we can, given overall load percentage and how much of full percentage is covered by each chunk
|
||||||
|
std::for_each(
|
||||||
|
std::begin( SectionLoadVisibility ), std::end( SectionLoadVisibility ),
|
||||||
|
[&]( section_visibility §ion ) {
|
||||||
|
section.visible = ( loadpercentage > 0.0 );
|
||||||
|
loadpercentage -= sectionloadpercentage; } );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Ra:
|
Ra:
|
||||||
|
|||||||
10
DynObj.h
10
DynObj.h
@@ -194,13 +194,15 @@ public:
|
|||||||
TSubModel *compartment;
|
TSubModel *compartment;
|
||||||
TSubModel *load;
|
TSubModel *load;
|
||||||
float level;
|
float level;
|
||||||
section_light( TSubModel *Compartment, TSubModel *Load, float const Level ) :
|
|
||||||
compartment(Compartment), load(Load), level(Level)
|
|
||||||
{}
|
|
||||||
};
|
};
|
||||||
std::vector<section_light> SectionLightLevels; // table of light levels for specific compartments of associated 3d model
|
std::vector<section_light> SectionLightLevels; // table of light levels for specific compartments of associated 3d model
|
||||||
bool SectionLightsActive { false }; // flag indicating whether section lights were set.
|
bool SectionLightsActive { false }; // flag indicating whether section lights were set.
|
||||||
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
|
float fShade; // zacienienie: 0:normalnie, -1:w ciemności, +1:dodatkowe światło (brak koloru?)
|
||||||
|
struct section_visibility {
|
||||||
|
TSubModel *submodel;
|
||||||
|
bool visible;
|
||||||
|
};
|
||||||
|
std::vector<section_visibility> SectionLoadVisibility; // visibility of specific sections of the load 3d model
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe
|
// zmienne i metody do animacji submodeli; Ra: sprzatam animacje w pojeździe
|
||||||
@@ -464,6 +466,8 @@ private:
|
|||||||
void AttachPrev(TDynamicObject *Object, int iType = 1);
|
void AttachPrev(TDynamicObject *Object, int iType = 1);
|
||||||
bool UpdateForce(double dt, double dt1, bool FullVer);
|
bool UpdateForce(double dt, double dt1, bool FullVer);
|
||||||
void LoadUpdate();
|
void LoadUpdate();
|
||||||
|
void update_load_sections();
|
||||||
|
void update_load_visibility();
|
||||||
bool Update(double dt, double dt1);
|
bool Update(double dt, double dt1);
|
||||||
bool FastUpdate(double dt);
|
bool FastUpdate(double dt);
|
||||||
void Move(double fDistance);
|
void Move(double fDistance);
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ namespace simulation {
|
|||||||
|
|
||||||
simulation_time Time;
|
simulation_time Time;
|
||||||
|
|
||||||
|
basic_station Station;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
@@ -1338,7 +1339,7 @@ TWorld::Update_UI() {
|
|||||||
if( ( vehicle->MoverParameters->BrakeDelayFlag & bdelay_M ) == bdelay_M )
|
if( ( vehicle->MoverParameters->BrakeDelayFlag & bdelay_M ) == bdelay_M )
|
||||||
uitextline2 += "+Mg";
|
uitextline2 += "+Mg";
|
||||||
|
|
||||||
uitextline2 += ", Load: " + to_string( vehicle->MoverParameters->LoadFlag, 0 );
|
uitextline2 += ", Load: " + to_string( vehicle->MoverParameters->LoadFlag, 0 ) + " (" + to_string( vehicle->MoverParameters->Load, 0 ) + ")";
|
||||||
|
|
||||||
uitextline2 +=
|
uitextline2 +=
|
||||||
"; Pant: "
|
"; Pant: "
|
||||||
|
|||||||
3
World.h
3
World.h
@@ -20,6 +20,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "stars.h"
|
#include "stars.h"
|
||||||
#include "skydome.h"
|
#include "skydome.h"
|
||||||
#include "messaging.h"
|
#include "messaging.h"
|
||||||
|
#include "station.h"
|
||||||
|
|
||||||
// wrapper for simulation time
|
// wrapper for simulation time
|
||||||
class simulation_time {
|
class simulation_time {
|
||||||
@@ -59,6 +60,8 @@ namespace simulation {
|
|||||||
|
|
||||||
extern simulation_time Time;
|
extern simulation_time Time;
|
||||||
|
|
||||||
|
extern basic_station Station; // temporary object, for station functionality tests
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrapper for environment elements -- sky, sun, stars, clouds etc
|
// wrapper for environment elements -- sky, sun, stars, clouds etc
|
||||||
|
|||||||
@@ -237,6 +237,9 @@
|
|||||||
<ClCompile Include="uart.cpp">
|
<ClCompile Include="uart.cpp">
|
||||||
<Filter>Source Files\input</Filter>
|
<Filter>Source Files\input</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="station.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Globals.h">
|
<ClInclude Include="Globals.h">
|
||||||
@@ -461,6 +464,9 @@
|
|||||||
<ClInclude Include="uart.h">
|
<ClInclude Include="uart.h">
|
||||||
<Filter>Header Files\input</Filter>
|
<Filter>Header Files\input</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="station.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="maszyna.rc">
|
<ResourceCompile Include="maszyna.rc">
|
||||||
|
|||||||
72
station.cpp
Normal file
72
station.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
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/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "station.h"
|
||||||
|
|
||||||
|
#include "dynobj.h"
|
||||||
|
#include "mtable.h"
|
||||||
|
|
||||||
|
// exchanges load with consist attached to specified vehicle, operating on specified schedule
|
||||||
|
double
|
||||||
|
basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule ) {
|
||||||
|
|
||||||
|
auto const firststop { Schedule.StationIndex == 1 };
|
||||||
|
auto const laststop { Schedule.StationIndex == Schedule.StationCount };
|
||||||
|
// HACK: determine whether current station is a (small) stop from the presence of "po" at the name end
|
||||||
|
auto const stationname { Schedule.TimeTable[ Schedule.StationIndex ].StationName };
|
||||||
|
auto const stationequipment { Schedule.TimeTable[ Schedule.StationIndex ].StationWare };
|
||||||
|
auto const trainstop { (
|
||||||
|
( ( stationname.size() >= 2 ) && ( stationname.substr( stationname.size() - 2 ) == "po" ) )
|
||||||
|
|| ( stationequipment.find( "po" ) != std::string::npos ) ) };
|
||||||
|
// train stops exchange smaller groups than regular stations
|
||||||
|
// NOTE: this is crude and unaccurate, but for now will do
|
||||||
|
auto const stationsizemodifier { ( trainstop ? 1.0 : 2.0 ) };
|
||||||
|
// go through all vehicles and update their load
|
||||||
|
// NOTE: for the time being we limit ourselves to passenger-carrying cars only
|
||||||
|
auto exchangetime { 0.0 };
|
||||||
|
|
||||||
|
auto *vehicle { First };
|
||||||
|
while( vehicle != nullptr ) {
|
||||||
|
|
||||||
|
auto ¶meters { *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 == "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 loadcount = static_cast<int>(
|
||||||
|
laststop ?
|
||||||
|
0 :
|
||||||
|
Random( parameters.MaxLoad * 0.15 * stationsizemodifier ) );
|
||||||
|
if( true == firststop ) {
|
||||||
|
// slightly larger group at the initial station
|
||||||
|
loadcount *= 2;
|
||||||
|
}
|
||||||
|
auto unloadcount = static_cast<int>(
|
||||||
|
firststop ? 0 :
|
||||||
|
laststop ? parameters.Load :
|
||||||
|
Random( parameters.MaxLoad * 0.10 * stationsizemodifier ) );
|
||||||
|
|
||||||
|
parameters.Load = clamp<int>( parameters.Load + loadcount - unloadcount, 0, parameters.MaxLoad );
|
||||||
|
vehicle->LoadUpdate();
|
||||||
|
vehicle->update_load_visibility();
|
||||||
|
|
||||||
|
exchangetime = std::max( exchangetime, loadcount / parameters.LoadSpeed + unloadcount / parameters.UnLoadSpeed );
|
||||||
|
}
|
||||||
|
vehicle = vehicle->Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
return exchangetime;
|
||||||
|
}
|
||||||
22
station.h
Normal file
22
station.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
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/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "classes.h"
|
||||||
|
|
||||||
|
// a simple station, performs freight and passenger exchanges with visiting consists
|
||||||
|
class basic_station {
|
||||||
|
|
||||||
|
public:
|
||||||
|
// methods
|
||||||
|
// exchanges load with consist attached to specified vehicle, operating on specified schedule; returns: time needed for exchange, in seconds
|
||||||
|
double
|
||||||
|
update_load( TDynamicObject *First, Mtable::TTrainParameters &Schedule );
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user