mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-23 06:19:18 +02:00
vehicle visualization config file parameters, vehicle attachments support, axle clatter fix, disabled vehicles smoke fix
This commit is contained in:
16
Driver.cpp
16
Driver.cpp
@@ -1784,8 +1784,7 @@ void TController::OrdersClear()
|
|||||||
|
|
||||||
void TController::Activation()
|
void TController::Activation()
|
||||||
{ // umieszczenie obsady w odpowiednim członie, wykonywane wyłącznie gdy steruje AI
|
{ // umieszczenie obsady w odpowiednim członie, wykonywane wyłącznie gdy steruje AI
|
||||||
iDirection = iDirectionOrder; // kierunek (względem sprzęgów pojazdu z AI) właśnie został
|
iDirection = iDirectionOrder; // kierunek (względem sprzęgów pojazdu z AI) właśnie został ustalony (zmieniony)
|
||||||
// ustalony (zmieniony)
|
|
||||||
if (iDirection)
|
if (iDirection)
|
||||||
{ // jeśli jest ustalony kierunek
|
{ // jeśli jest ustalony kierunek
|
||||||
TDynamicObject *old = pVehicle, *d = pVehicle; // w tym siedzi AI
|
TDynamicObject *old = pVehicle, *d = pVehicle; // w tym siedzi AI
|
||||||
@@ -1794,7 +1793,7 @@ void TController::Activation()
|
|||||||
ZeroSpeed();
|
ZeroSpeed();
|
||||||
ZeroDirection();
|
ZeroDirection();
|
||||||
mvOccupied->SpringBrakeActivate(true);
|
mvOccupied->SpringBrakeActivate(true);
|
||||||
if (TestFlag(d->MoverParameters->Couplers[iDirectionOrder < 0 ? 1 : 0].CouplingFlag, ctrain_controll)) {
|
if (TestFlag(d->MoverParameters->Couplers[iDirectionOrder < 0 ? end::rear : end::front].CouplingFlag, ctrain_controll)) {
|
||||||
mvControlling->MainSwitch( false); // dezaktywacja czuwaka, jeśli przejście do innego członu
|
mvControlling->MainSwitch( false); // dezaktywacja czuwaka, jeśli przejście do innego członu
|
||||||
mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca w opuszczanym pojeździe
|
mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca w opuszczanym pojeździe
|
||||||
// mvOccupied->BrakeLevelSet((mvOccupied->BrakeHandle==FVel6)?4:-2); //odcięcie na
|
// mvOccupied->BrakeLevelSet((mvOccupied->BrakeHandle==FVel6)?4:-2); //odcięcie na
|
||||||
@@ -1806,20 +1805,17 @@ void TController::Activation()
|
|||||||
mvOccupied->ActiveCab = mvOccupied->CabNo; // użytkownik moze zmienić ActiveCab wychodząc
|
mvOccupied->ActiveCab = mvOccupied->CabNo; // użytkownik moze zmienić ActiveCab wychodząc
|
||||||
mvOccupied->CabDeactivisation(); // tak jest w Train.cpp
|
mvOccupied->CabDeactivisation(); // tak jest w Train.cpp
|
||||||
// przejście AI na drugą stronę EN57, ET41 itp.
|
// przejście AI na drugą stronę EN57, ET41 itp.
|
||||||
while (TestFlag(d->MoverParameters->Couplers[iDirection < 0 ? 1 : 0].CouplingFlag, ctrain_controll))
|
while (TestFlag(d->MoverParameters->Couplers[iDirection < 0 ? end::rear : end::front].CouplingFlag, ctrain_controll))
|
||||||
{ // jeśli pojazd z przodu jest ukrotniony, to przechodzimy do niego
|
{ // jeśli pojazd z przodu jest ukrotniony, to przechodzimy do niego
|
||||||
d = iDirection * d->DirectionGet() < 0 ? d->Next() :
|
d = iDirection * d->DirectionGet() < 0 ? d->Next() :
|
||||||
d->Prev(); // przechodzimy do następnego członu
|
d->Prev(); // przechodzimy do następnego członu
|
||||||
if (d)
|
if (d)
|
||||||
{
|
{
|
||||||
drugi = d->Mechanik; // zapamiętanie tego, co ewentualnie tam siedzi, żeby w razie
|
drugi = d->Mechanik; // zapamiętanie tego, co ewentualnie tam siedzi, żeby w razie dwóch zamienić miejscami
|
||||||
// dwóch zamienić miejscami
|
|
||||||
d->Mechanik = this; // na razie bilokacja
|
d->Mechanik = this; // na razie bilokacja
|
||||||
d->MoverParameters->SetInternalCommand(
|
d->MoverParameters->SetInternalCommand("", 0, 0); // usunięcie ewentualnie zalegającej komendy (Change_direction?)
|
||||||
"", 0, 0); // usunięcie ewentualnie zalegającej komendy (Change_direction?)
|
|
||||||
if (d->DirectionGet() != pVehicle->DirectionGet()) // jeśli są przeciwne do siebie
|
if (d->DirectionGet() != pVehicle->DirectionGet()) // jeśli są przeciwne do siebie
|
||||||
iDirection = -iDirection; // to będziemy jechać w drugą stronę względem
|
iDirection = -iDirection; // to będziemy jechać w drugą stronę względem zasiedzianego pojazdu
|
||||||
// zasiedzianego pojazdu
|
|
||||||
pVehicle->Mechanik = drugi; // wsadzamy tego, co ewentualnie był (podwójna trakcja)
|
pVehicle->Mechanik = drugi; // wsadzamy tego, co ewentualnie był (podwójna trakcja)
|
||||||
pVehicle->MoverParameters->CabNo = 0; // wyłączanie kabin po drodze
|
pVehicle->MoverParameters->CabNo = 0; // wyłączanie kabin po drodze
|
||||||
pVehicle->MoverParameters->ActiveCab = 0; // i zaznaczenie, że nie ma tam nikogo
|
pVehicle->MoverParameters->ActiveCab = 0; // i zaznaczenie, że nie ma tam nikogo
|
||||||
|
|||||||
139
DynObj.cpp
139
DynObj.cpp
@@ -2009,12 +2009,18 @@ TDynamicObject::Init(std::string Name, // nazwa pojazdu, np. "EU07-424"
|
|||||||
smBuforPrawy[ i ]->WillBeAnimated();
|
smBuforPrawy[ i ]->WillBeAnimated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( auto &axle : m_axlesounds ) {
|
if( Track->fSoundDistance > 0.f ) {
|
||||||
// wyszukiwanie osi (0 jest na końcu, dlatego dodajemy długość?)
|
for( auto &axle : m_axlesounds ) {
|
||||||
axle.distance = (
|
// wyszukiwanie osi (0 jest na końcu, dlatego dodajemy długość?)
|
||||||
Reversed ?
|
axle.distance =
|
||||||
-axle.offset :
|
clamp_circular<double>(
|
||||||
( axle.offset + MoverParameters->Dim.L ) ) + fDist;
|
( Reversed ?
|
||||||
|
-axle.offset :
|
||||||
|
axle.offset )
|
||||||
|
- 0.5 * MoverParameters->Dim.L
|
||||||
|
+ fDist,
|
||||||
|
Track->fSoundDistance );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// McZapkie-250202 end.
|
// McZapkie-250202 end.
|
||||||
Track->AddDynamicObject(this); // wstawiamy do toru na pozycję 0, a potem przesuniemy
|
Track->AddDynamicObject(this); // wstawiamy do toru na pozycję 0, a potem przesuniemy
|
||||||
@@ -3155,12 +3161,19 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
if( MyTrack->fSoundDistance != -1 ) {
|
if( MyTrack->fSoundDistance != -1 ) {
|
||||||
|
|
||||||
if( MyTrack->fSoundDistance != dRailLength ) {
|
if( MyTrack->fSoundDistance != dRailLength ) {
|
||||||
dRailLength = MyTrack->fSoundDistance;
|
if( dRailLength > 0.0 ) {
|
||||||
for( auto &axle : m_axlesounds ) {
|
for( auto &axle : m_axlesounds ) {
|
||||||
axle.distance = axle.offset + MoverParameters->Dim.L;
|
axle.distance =
|
||||||
|
clamp_circular<double>(
|
||||||
|
axle.distance - dRailLength
|
||||||
|
+ axle.offset
|
||||||
|
/* - 0.5 * MoverParameters->Dim.L */,
|
||||||
|
MyTrack->fSoundDistance );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
dRailLength = MyTrack->fSoundDistance;
|
||||||
}
|
}
|
||||||
if( dRailLength != -1 ) {
|
if( dRailLength > 0.0 ) {
|
||||||
if( MoverParameters->Vel > 0 ) {
|
if( MoverParameters->Vel > 0 ) {
|
||||||
// TODO: track quality and/or environment factors as separate subroutine
|
// TODO: track quality and/or environment factors as separate subroutine
|
||||||
auto volume =
|
auto volume =
|
||||||
@@ -3182,35 +3195,37 @@ bool TDynamicObject::Update(double dt, double dt1)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if( dRailLength > 0.0 ) {
|
||||||
auto axleindex { 0 };
|
auto axleindex { 0 };
|
||||||
for( auto &axle : m_axlesounds ) {
|
for( auto &axle : m_axlesounds ) {
|
||||||
axle.distance -= dDOMoveLen * Sign( dDOMoveLen );
|
axle.distance += dDOMoveLen * DirectionGet();
|
||||||
if( axle.distance < 0 ) {
|
if( ( axle.distance < 0 )
|
||||||
axle.distance += dRailLength;
|
|| ( axle.distance > dRailLength ) ) {
|
||||||
if( MoverParameters->Vel > 2.5 ) {
|
axle.distance = clamp_circular( axle.distance, dRailLength );
|
||||||
// NOTE: for combined clatter sound we supply 1/100th of actual value, as the sound module converts does the opposite, converting received (typically) 0-1 values to 0-100 range
|
if( MoverParameters->Vel > 0.1 ) {
|
||||||
auto const frequency = (
|
// NOTE: for combined clatter sound we supply 1/100th of actual value, as the sound module converts does the opposite, converting received (typically) 0-1 values to 0-100 range
|
||||||
true == axle.clatter.is_combined() ?
|
auto const frequency = (
|
||||||
MoverParameters->Vel * 0.01 :
|
true == axle.clatter.is_combined() ?
|
||||||
1.0 );
|
MoverParameters->Vel * 0.01 :
|
||||||
axle.clatter
|
1.0 );
|
||||||
.pitch( frequency )
|
axle.clatter
|
||||||
.gain( volume )
|
.pitch( frequency )
|
||||||
.play();
|
.gain( volume )
|
||||||
// crude bump simulation, drop down on even axles, move back up on the odd ones
|
.play();
|
||||||
MoverParameters->AccVert +=
|
// crude bump simulation, drop down on even axles, move back up on the odd ones
|
||||||
interpolate(
|
MoverParameters->AccVert +=
|
||||||
0.01, 0.05,
|
interpolate(
|
||||||
clamp(
|
0.01, 0.05,
|
||||||
GetVelocity() / ( 1 + MoverParameters->Vmax ),
|
clamp(
|
||||||
0.0, 1.0 ) )
|
GetVelocity() / ( 1 + MoverParameters->Vmax ),
|
||||||
* ( ( axleindex % 2 ) != 0 ?
|
0.0, 1.0 ) )
|
||||||
1 :
|
* ( ( axleindex % 2 ) != 0 ?
|
||||||
-1 );
|
1 :
|
||||||
|
-1 );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
++axleindex;
|
||||||
}
|
}
|
||||||
++axleindex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4268,11 +4283,24 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
std::string asAnimName;
|
std::string asAnimName;
|
||||||
bool Stop_InternalData = false;
|
bool Stop_InternalData = false;
|
||||||
pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów
|
pants = NULL; // wskaźnik pierwszego obiektu animującego dla pantografów
|
||||||
cParser parser( TypeName + ".mmd", cParser::buffer_FILE, asBaseDir );
|
{
|
||||||
if( false == parser.ok() ) {
|
// preliminary check whether the file exists
|
||||||
ErrorLog( "Failed to load appearance data for vehicle " + MoverParameters->Name );
|
cParser parser( TypeName + ".mmd", cParser::buffer_FILE, asBaseDir );
|
||||||
return;
|
if( false == parser.ok() ) {
|
||||||
|
ErrorLog( "Failed to load appearance data for vehicle " + MoverParameters->Name );
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// use #include wrapper to access the appearance data file
|
||||||
|
// this allows us to provide the file content with user-defined parameters
|
||||||
|
cParser parser(
|
||||||
|
"include " + TypeName + ".mmd"
|
||||||
|
+ " " + asName // (p1)
|
||||||
|
+ " " + TypeName // (p2)
|
||||||
|
+ " " + ReplacableSkin // (p3)
|
||||||
|
+ " end",
|
||||||
|
cParser::buffer_TEXT,
|
||||||
|
asBaseDir );
|
||||||
std::string token;
|
std::string token;
|
||||||
do {
|
do {
|
||||||
token = "";
|
token = "";
|
||||||
@@ -4430,15 +4458,30 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
parser.getTokens();
|
parser.getTokens();
|
||||||
parser >> asModel;
|
parser >> asModel;
|
||||||
replace_slashes( asModel );
|
replace_slashes( asModel );
|
||||||
if( asModel[ 0 ] == '/' ) {
|
erase_leading_slashes( asModel );
|
||||||
// filename can potentially begin with a slash, and we don't need it
|
|
||||||
asModel.erase( 0, 1 );
|
|
||||||
}
|
|
||||||
asModel = asBaseDir + asModel; // McZapkie-200702 - dynamics maja swoje modele w dynamic/basedir
|
asModel = asBaseDir + asModel; // McZapkie-200702 - dynamics maja swoje modele w dynamic/basedir
|
||||||
Global.asCurrentTexturePath = asBaseDir; // biezaca sciezka do tekstur to dynamic/...
|
Global.asCurrentTexturePath = asBaseDir; // biezaca sciezka do tekstur to dynamic/...
|
||||||
mdLowPolyInt = TModelsManager::GetModel(asModel, true);
|
mdLowPolyInt = TModelsManager::GetModel(asModel, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if(token == "attachments:") {
|
||||||
|
// additional 3d models attached to main body
|
||||||
|
// content provided as a series of values together enclosed in "{}"
|
||||||
|
// each value is a name of additional 3d model
|
||||||
|
// value can be optionally set of values enclosed in "[]" in which case one value will be picked randomly
|
||||||
|
// TBD: reconsider something more yaml-compliant and/or ability to define offset and rotation
|
||||||
|
while( ( ( token = parser.getToken<std::string>() ) != "" )
|
||||||
|
&& ( token != "}" ) ) {
|
||||||
|
auto attachmentmodelname { deserialize_random_set( parser ) };
|
||||||
|
replace_slashes( attachmentmodelname );
|
||||||
|
Global.asCurrentTexturePath = asBaseDir; // biezaca sciezka do tekstur to dynamic/...
|
||||||
|
auto *attachmentmodel { TModelsManager::GetModel( asBaseDir + attachmentmodelname, true ) };
|
||||||
|
if( attachmentmodel != nullptr ) {
|
||||||
|
mdAttachments.emplace_back( attachmentmodel );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else if(token == "loads:") {
|
else if(token == "loads:") {
|
||||||
// default load visualization models overrides
|
// default load visualization models overrides
|
||||||
// content provided as "key: value" pairs together enclosed in "{}"
|
// content provided as "key: value" pairs together enclosed in "{}"
|
||||||
@@ -4982,18 +5025,18 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
|
|||||||
// add another axle entry to the list
|
// add another axle entry to the list
|
||||||
axle_sounds axle {
|
axle_sounds axle {
|
||||||
0,
|
0,
|
||||||
std::atof( token.c_str() ),
|
std::atof( token.c_str() ) * -1.0, // for axle locations negative value means ahead of centre but vehicle faces +Z in 'its' space
|
||||||
{ sound_placement::external, static_cast<float>( dSDist ) } };
|
{ sound_placement::external, static_cast<float>( dSDist ) } };
|
||||||
axle.clatter.deserialize( parser, sound_type::single );
|
axle.clatter.deserialize( parser, sound_type::single );
|
||||||
axle.clatter.owner( this );
|
axle.clatter.owner( this );
|
||||||
axle.clatter.offset( { 0, 0, -axle.offset } ); // vehicle faces +Z in 'its' space, for axle locations negative value means ahead of centre
|
axle.clatter.offset( { 0, 0, axle.offset } );
|
||||||
m_axlesounds.emplace_back( axle );
|
m_axlesounds.emplace_back( axle );
|
||||||
}
|
}
|
||||||
// arrange the axles in case they're listed out of order
|
// arrange the axles in case they're listed out of order
|
||||||
std::sort(
|
std::sort(
|
||||||
std::begin( m_axlesounds ), std::end( m_axlesounds ),
|
std::begin( m_axlesounds ), std::end( m_axlesounds ),
|
||||||
[]( axle_sounds const &Left, axle_sounds const &Right ) {
|
[]( axle_sounds const &Left, axle_sounds const &Right ) {
|
||||||
return ( Left.offset < Right.offset ); } );
|
return ( Left.offset > Right.offset ); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( ( token == "engine:" )
|
else if( ( token == "engine:" )
|
||||||
|
|||||||
1
DynObj.h
1
DynObj.h
@@ -200,6 +200,7 @@ public:
|
|||||||
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
|
TModel3d *mdLowPolyInt; // ABu 010305: wnetrze lowpoly
|
||||||
std::array<TSubModel *, 3> LowPolyIntCabs {}; // pointers to low fidelity version of individual driver cabs
|
std::array<TSubModel *, 3> LowPolyIntCabs {}; // pointers to low fidelity version of individual driver cabs
|
||||||
bool JointCabs{ false }; // flag for vehicles with multiple virtual 'cabs' sharing location and 3d model(s)
|
bool JointCabs{ false }; // flag for vehicles with multiple virtual 'cabs' sharing location and 3d model(s)
|
||||||
|
std::vector<TModel3d *> mdAttachments; // additional models attached to main body
|
||||||
struct destination_data {
|
struct destination_data {
|
||||||
TSubModel *sign { nullptr }; // submodel mapped with replacable texture -4
|
TSubModel *sign { nullptr }; // submodel mapped with replacable texture -4
|
||||||
bool has_light { false }; // the submodel was originally configured with self-illumination attribute
|
bool has_light { false }; // the submodel was originally configured with self-illumination attribute
|
||||||
|
|||||||
42
EvLaunch.cpp
42
EvLaunch.cpp
@@ -78,25 +78,6 @@ bool TEventLauncher::Load(cParser *parser)
|
|||||||
}
|
}
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> DeltaTime;
|
*parser >> DeltaTime;
|
||||||
if (DeltaTime < 0)
|
|
||||||
DeltaTime = -DeltaTime; // dla ujemnego zmieniamy na dodatni
|
|
||||||
else if (DeltaTime > 0)
|
|
||||||
{ // wartość dodatnia oznacza wyzwalanie o określonej godzinie
|
|
||||||
iMinute = int(DeltaTime) % 100; // minuty są najmłodszymi cyframi dziesietnymi
|
|
||||||
iHour = int(DeltaTime - iMinute) / 100; // godzina to setki
|
|
||||||
DeltaTime = 0; // bez powtórzeń
|
|
||||||
// potentially shift the provided time by requested offset
|
|
||||||
auto const timeoffset { static_cast<int>( Global.ScenarioTimeOffset * 60 ) };
|
|
||||||
if( timeoffset != 0 ) {
|
|
||||||
auto const adjustedtime { clamp_circular( iHour * 60 + iMinute + timeoffset, 24 * 60 ) };
|
|
||||||
iHour = ( adjustedtime / 60 ) % 24;
|
|
||||||
iMinute = adjustedtime % 60;
|
|
||||||
}
|
|
||||||
WriteLog(
|
|
||||||
"EventLauncher at "
|
|
||||||
+ std::to_string( iHour ) + ":"
|
|
||||||
+ ( iMinute < 10 ? "0" : "" ) + to_string( iMinute ) ); // wyświetlenie czasu
|
|
||||||
}
|
|
||||||
parser->getTokens();
|
parser->getTokens();
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
asEvent1Name = token; // pierwszy event
|
asEvent1Name = token; // pierwszy event
|
||||||
@@ -145,6 +126,29 @@ bool TEventLauncher::Load(cParser *parser)
|
|||||||
parser->getTokens(); // słowo zamykające
|
parser->getTokens(); // słowo zamykające
|
||||||
*parser >> token;
|
*parser >> token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( DeltaTime < 0 )
|
||||||
|
DeltaTime = -DeltaTime; // dla ujemnego zmieniamy na dodatni
|
||||||
|
else if( DeltaTime > 0 ) { // wartość dodatnia oznacza wyzwalanie o określonej godzinie
|
||||||
|
iMinute = int( DeltaTime ) % 100; // minuty są najmłodszymi cyframi dziesietnymi
|
||||||
|
iHour = int( DeltaTime - iMinute ) / 100; // godzina to setki
|
||||||
|
DeltaTime = 0; // bez powtórzeń
|
||||||
|
// potentially shift the provided time by requested offset
|
||||||
|
auto const timeoffset{ static_cast<int>( Global.ScenarioTimeOffset * 60 ) };
|
||||||
|
if( timeoffset != 0 ) {
|
||||||
|
auto const adjustedtime{ clamp_circular( iHour * 60 + iMinute + timeoffset, 24 * 60 ) };
|
||||||
|
iHour = ( adjustedtime / 60 ) % 24;
|
||||||
|
iMinute = adjustedtime % 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteLog(
|
||||||
|
"EventLauncher at "
|
||||||
|
+ std::to_string( iHour ) + ":"
|
||||||
|
+ ( iMinute < 10 ? "0" : "" ) + to_string( iMinute )
|
||||||
|
+ " (" + asEvent1Name
|
||||||
|
+ ( asEvent2Name != "none" ? " / " + asEvent2Name : "" )
|
||||||
|
+ ")" ); // wyświetlenie czasu
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
|
|||||||
{ // gdy zostaje na tym samym torze (przesuwanie już nie zmienia toru)
|
{ // gdy zostaje na tym samym torze (przesuwanie już nie zmienia toru)
|
||||||
if (bPrimary)
|
if (bPrimary)
|
||||||
{ // tylko gdy początkowe ustawienie, dodajemy eventy stania do kolejki
|
{ // tylko gdy początkowe ustawienie, dodajemy eventy stania do kolejki
|
||||||
if (Owner->MoverParameters->CabNo != 0) {
|
if (Owner->MoverParameters->ActiveCab != 0) {
|
||||||
|
|
||||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner, -1.0 );
|
pCurrentTrack->QueueEvents( pCurrentTrack->m_events1, Owner, -1.0 );
|
||||||
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner, -1.0 );
|
pCurrentTrack->QueueEvents( pCurrentTrack->m_events2, Owner, -1.0 );
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ drivingaid_panel::update() {
|
|||||||
|
|
||||||
auto const *mover = controlled->MoverParameters;
|
auto const *mover = controlled->MoverParameters;
|
||||||
auto const *driver = controlled->Mechanik;
|
auto const *driver = controlled->Mechanik;
|
||||||
|
auto const *owner = ( controlled->ctOwner != nullptr ? controlled->ctOwner : controlled->Mechanik );
|
||||||
|
|
||||||
{ // throttle, velocity, speed limits and grade
|
{ // throttle, velocity, speed limits and grade
|
||||||
std::string expandedtext;
|
std::string expandedtext;
|
||||||
@@ -60,8 +61,8 @@ drivingaid_panel::update() {
|
|||||||
gradetext = m_buffer.data();
|
gradetext = m_buffer.data();
|
||||||
}
|
}
|
||||||
// next speed limit
|
// next speed limit
|
||||||
auto const speedlimit { static_cast<int>( std::floor( driver->VelDesired ) ) };
|
auto const speedlimit { static_cast<int>( std::floor( owner->VelDesired ) ) };
|
||||||
auto const nextspeedlimit { static_cast<int>( std::floor( driver->VelNext ) ) };
|
auto const nextspeedlimit { static_cast<int>( std::floor( owner->VelNext ) ) };
|
||||||
std::string nextspeedlimittext;
|
std::string nextspeedlimittext;
|
||||||
if( nextspeedlimit != speedlimit ) {
|
if( nextspeedlimit != speedlimit ) {
|
||||||
std::snprintf(
|
std::snprintf(
|
||||||
@@ -117,7 +118,7 @@ drivingaid_panel::update() {
|
|||||||
{ // alerter, hints
|
{ // alerter, hints
|
||||||
std::string expandedtext;
|
std::string expandedtext;
|
||||||
if( is_expanded ) {
|
if( is_expanded ) {
|
||||||
auto const stoptime { static_cast<int>( std::ceil( -1.0 * controlled->Mechanik->fStopTime ) ) };
|
auto const stoptime { static_cast<int>( std::ceil( -1.0 * owner->fStopTime ) ) };
|
||||||
if( stoptime > 0 ) {
|
if( stoptime > 0 ) {
|
||||||
std::snprintf(
|
std::snprintf(
|
||||||
m_buffer.data(), m_buffer.size(),
|
m_buffer.data(), m_buffer.size(),
|
||||||
@@ -126,7 +127,7 @@ drivingaid_panel::update() {
|
|||||||
expandedtext = m_buffer.data();
|
expandedtext = m_buffer.data();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto const trackblockdistance{ std::abs( controlled->Mechanik->TrackBlock() ) };
|
auto const trackblockdistance{ std::abs( owner->TrackBlock() ) };
|
||||||
if( trackblockdistance <= 75.0 ) {
|
if( trackblockdistance <= 75.0 ) {
|
||||||
std::snprintf(
|
std::snprintf(
|
||||||
m_buffer.data(), m_buffer.size(),
|
m_buffer.data(), m_buffer.size(),
|
||||||
|
|||||||
6
parser.h
6
parser.h
@@ -50,20 +50,24 @@ class cParser //: public std::stringstream
|
|||||||
bool
|
bool
|
||||||
expectToken( std::string const &Value ) {
|
expectToken( std::string const &Value ) {
|
||||||
return readToken() == Value; };
|
return readToken() == Value; };
|
||||||
|
inline
|
||||||
bool
|
bool
|
||||||
eof() {
|
eof() {
|
||||||
return mStream->eof(); };
|
return mStream->eof(); };
|
||||||
|
inline
|
||||||
bool
|
bool
|
||||||
ok() {
|
ok() {
|
||||||
return !mStream->fail(); };
|
return ( !mStream->fail() ); };
|
||||||
cParser &
|
cParser &
|
||||||
autoclear( bool const Autoclear );
|
autoclear( bool const Autoclear );
|
||||||
|
inline
|
||||||
bool
|
bool
|
||||||
autoclear() const {
|
autoclear() const {
|
||||||
return m_autoclear; }
|
return m_autoclear; }
|
||||||
bool
|
bool
|
||||||
getTokens( unsigned int Count = 1, bool ToLower = true, char const *Break = "\n\r\t ;" );
|
getTokens( unsigned int Count = 1, bool ToLower = true, char const *Break = "\n\r\t ;" );
|
||||||
// returns next incoming token, if any, without removing it from the set
|
// returns next incoming token, if any, without removing it from the set
|
||||||
|
inline
|
||||||
std::string
|
std::string
|
||||||
peek() const {
|
peek() const {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -167,10 +167,16 @@ smoke_source::update( double const Timedelta, bool const Onlydespawn ) {
|
|||||||
std::min<float>(
|
std::min<float>(
|
||||||
m_spawncount + ( m_spawnrate * Timedelta * Global.SmokeFidelity ),
|
m_spawncount + ( m_spawnrate * Timedelta * Global.SmokeFidelity ),
|
||||||
m_max_particles ) );
|
m_max_particles ) );
|
||||||
// HACK: don't spawn particles in tunnels, to prevent smoke clipping through 'terrain' outside
|
// consider special spawn rate cases
|
||||||
if( ( m_ownertype == owner_type::vehicle )
|
if( m_ownertype == owner_type::vehicle ) {
|
||||||
&& ( m_owner.vehicle->RaTrackGet()->eEnvironment == e_tunnel ) ) {
|
// HACK: don't spawn particles in tunnels, to prevent smoke clipping through 'terrain' outside
|
||||||
|
if( m_owner.vehicle->RaTrackGet()->eEnvironment == e_tunnel ) {
|
||||||
m_spawncount = 0.f;
|
m_spawncount = 0.f;
|
||||||
|
}
|
||||||
|
if( false == m_owner.vehicle->bEnabled ) {
|
||||||
|
// don't spawn particles for vehicles which left the scenario
|
||||||
|
m_spawncount = 0.f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// update spawned particles
|
// update spawned particles
|
||||||
for( auto particleiterator { std::begin( m_particles ) }; particleiterator != std::end( m_particles ); ++particleiterator ) {
|
for( auto particleiterator { std::begin( m_particles ) }; particleiterator != std::end( m_particles ); ++particleiterator ) {
|
||||||
|
|||||||
30
renderer.cpp
30
renderer.cpp
@@ -2393,8 +2393,13 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( Dynamic->mdModel ) {
|
if( Dynamic->mdModel ) {
|
||||||
|
// main model
|
||||||
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
||||||
}
|
}
|
||||||
|
// optional attached models
|
||||||
|
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||||
|
Render( attachment, Dynamic->Material(), squaredistance );
|
||||||
|
}
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
m_renderspecular = false;
|
m_renderspecular = false;
|
||||||
if( Dynamic->fShade > 0.0f ) {
|
if( Dynamic->fShade > 0.0f ) {
|
||||||
@@ -2411,10 +2416,18 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
|||||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
if( Dynamic->mdModel )
|
if( Dynamic->mdModel ) {
|
||||||
|
// main model
|
||||||
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
||||||
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
|
}
|
||||||
|
// optional attached models
|
||||||
|
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||||
|
Render( attachment, Dynamic->Material(), squaredistance );
|
||||||
|
}
|
||||||
|
if( Dynamic->mdLoad ) {
|
||||||
|
// renderowanie nieprzezroczystego ładunku
|
||||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||||
|
}
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3523,11 +3536,18 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
if( Dynamic->mdModel )
|
if( Dynamic->mdModel ) {
|
||||||
|
// main model
|
||||||
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
||||||
|
}
|
||||||
if( Dynamic->mdLoad ) // renderowanie nieprzezroczystego ładunku
|
// optional attached models
|
||||||
|
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||||
|
Render_Alpha( attachment, Dynamic->Material(), squaredistance );
|
||||||
|
}
|
||||||
|
if( Dynamic->mdLoad ) {
|
||||||
|
// renderowanie nieprzezroczystego ładunku
|
||||||
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||||
|
}
|
||||||
|
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
m_renderspecular = false;
|
m_renderspecular = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user