Add new speed limitations types

SetVelocity - semaphor
RoadVelocity - track speed limit
SectionVelocity - track speed limit for some distance
This commit is contained in:
Firleju
2015-06-20 16:11:42 +02:00
parent 54cb9159e6
commit d3ab168499
4 changed files with 100 additions and 50 deletions

View File

@@ -48,9 +48,11 @@ typedef enum
{ // binarne odpowiedniki komend w komórce pamiêci
cm_Unknown, // ci¹g nierozpoznany (nie jest komend¹)
cm_Ready, // W4 zezwala na odjazd, ale semafor mo¿e zatrzymaæ
cm_SetVelocity,
cm_ShuntVelocity,
cm_SetProximityVelocity,
cm_SetVelocity, // prêdkoœæ poci¹gowa zadawana na semaforze
cm_RoadVelocity, // prêdkoœæ drogowa
cm_SectionVelocity, //ograniczenie prêdkoœci na odcinku
cm_ShuntVelocity, // prêdkoœæ manewrowa na semaforze
cm_SetProximityVelocity, // informacja wstêpna o ograniczeniu
cm_ChangeDirection,
cm_PassengerStopPoint,
cm_OutsideStation,

View File

@@ -122,46 +122,61 @@ void TSpeedPos::CommandCheck()
TCommandType command = evEvent->Command();
double value1 = evEvent->ValueGet(1);
double value2 = evEvent->ValueGet(2);
if (command == cm_ShuntVelocity)
{ // prędkość manewrową zapisać, najwyżej AI zignoruje przy analizie tabelki
switch (command)
{
case cm_ShuntVelocity:
// prędkość manewrową zapisać, najwyżej AI zignoruje przy analizie tabelki
fVelNext = value1; // powinno być value2, bo druga określa "za"?
iFlags |= 0x200;
}
else if (command == cm_SetVelocity)
{ // w semaforze typu "m" jest ShuntVelocity dla Ms2 i SetVelocity dla S1
iFlags |= spShuntSemaphor;
break;
case cm_SetVelocity:
// w semaforze typu "m" jest ShuntVelocity dla Ms2 i SetVelocity dla S1
// SetVelocity * 0 -> można jechać, ale stanąć przed
// SetVelocity 0 20 -> stanąć przed, potem można jechać 20 (SBL)
// SetVelocity -1 100 -> można jechać, przy następnym ograniczenie (SBL)
// SetVelocity 40 -1 -> PutValues: jechać 40 aż do minięcia (koniec ograniczenia(
fVelNext = value1;
iFlags &= ~0xE00; // nie manewrowa, nie przystanek, nie zatrzymać na SBL
iFlags &= ~(spShuntSemaphor | spPassengerStopPoint | spStopOnSBL);
iFlags |= spSemaphor;// nie manewrowa, nie przystanek, nie zatrzymać na SBL, ale semafor
if (value1 == 0.0) // jeśli pierwsza zerowa
if (value2 != 0.0) // a druga nie
{ // S1 na SBL, można przejechać po zatrzymaniu (tu nie mamy prędkości ani odległości)
fVelNext = value2; // normalnie będzie zezwolenie na jazdę, aby się usunął z tabelki
iFlags |= 0x800; // flaga, że ma zatrzymać; na pewno nie zezwoli na manewry
iFlags |= spStopOnSBL; // flaga, że ma zatrzymać; na pewno nie zezwoli na manewry
}
}
else if (command == cm_PassengerStopPoint) // nie ma dostępu do rozkładu
{ // przystanek, najwyżej AI zignoruje przy analizie tabelki
if ((iFlags & 0x400) == 0)
break;
case cm_SectionVelocity:
// odcinek z ograniczeniem prędkości
fVelNext = value1;
iFlags |= spSectionVel;
break;
case cm_RoadVelocity:
// prędkość drogowa (od tej pory będzie jako domyślna najwyższa
fVelNext = value1;
iFlags |= spRoadVel;
break;
case cm_PassengerStopPoint:
// nie ma dostępu do rozkładu
// przystanek, najwyżej AI zignoruje przy analizie tabelki
if ((iFlags & spPassengerStopPoint) == 0)
fVelNext = 0.0; // TrainParams->IsStop()?0.0:-1.0; //na razie tak
iFlags |= 0x400; // niestety nie da się w tym miejscu współpracować z rozkładem
}
else if (command == cm_SetProximityVelocity)
{ // ignorować
iFlags |= spPassengerStopPoint; // niestety nie da się w tym miejscu współpracować z rozkładem
break;
case cm_SetProximityVelocity:
// ignorować
fVelNext = -1;
}
else if (command == cm_OutsideStation)
{ // w trybie manewrowym: skanować od niej wstecz i stanąć po wyjechaniu za sygnalizator i
break;
case cm_OutsideStation:
// w trybie manewrowym: skanować od niej wstecz i stanąć po wyjechaniu za sygnalizator i
// zmienić kierunek
// w trybie pociągowym: można przyspieszyć do wskazanej prędkości (po zjechaniu z rozjazdów)
fVelNext = -1;
iFlags |= 0x2100; // W5
}
else
{ // inna komenda w evencie skanowanym powoduje zatrzymanie i wysłanie tej komendy
iFlags &= ~0xE00; // nie manewrowa, nie przystanek, nie zatrzymać na SBL
iFlags |= spOutsideStation; // W5
break;
default:
// inna komenda w evencie skanowanym powoduje zatrzymanie i wysłanie tej komendy
iFlags &= ~(spShuntSemaphor | spPassengerStopPoint |
spStopOnSBL); // nie manewrowa, nie przystanek, nie zatrzymać na SBL
fVelNext = 0; // jak nieznana komenda w komórce sygnałowej, to ma stać
}
};
@@ -180,17 +195,17 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
if (iska < 0.0) // iloczyn skalarny jest ujemny, gdy punkt jest z tyłu
{ // jeśli coś jest z tyłu, to dokładna odległość nie ma już większego znaczenia
fDist = -fDist; // potrzebne do badania wyjechania składem poza ograniczenie
if (iFlags & 32) // 32 ustawione, gdy obiekt już został minięty
if (iFlags & spElapsed) // 32 ustawione, gdy obiekt już został minięty
{ // jeśli minięty (musi być minięty również przez końcówkę składu)
}
else
{
iFlags ^= 32; // 32-minięty - będziemy liczyć odległość względem przeciwnego końca
iFlags ^= spElapsed; // 32-minięty - będziemy liczyć odległość względem przeciwnego końca
// toru (nadal może być z przodu i ogdaniczać)
if ((iFlags & 0x43) == 3) // tylko jeśli (istotny) tor, bo eventy są punktowe
if (trTrack) // może być NULL, jeśli koniec toru (????)
vPos =
(iFlags & 4) ?
(iFlags & spReverse) ?
trTrack->CurrentSegment()->FastGetPoint_0() :
trTrack->CurrentSegment()->FastGetPoint_1(); // drugi koniec istotny
}
@@ -201,14 +216,14 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
// dokładniejsze wartości
}
if (fDist > 0.0) // nie może być 0.0, a przypadkiem mogło by się trafić i było by źle
if ((iFlags & 32) == 0) // 32 ustawione, gdy obiekt już został minięty
if ((iFlags & spElapsed) == 0) // 32 ustawione, gdy obiekt już został minięty
{ // jeśli obiekt nie został minięty, można od niego zliczać narastająco (inaczej może być
// problem z wektorem kierunku)
len = fDist = len + fDist; // zliczanie dlugości narastająco
*p = vPos; // nowy punkt odniesienia
*dir = Normalize(v); // nowy wektor kierunku od poprzedniego obiektu do aktualnego
}
if (iFlags & 2) // jeśli tor
if (iFlags & spTrack) // jeśli tor
{
if (trTrack) // może być NULL, jeśli koniec toru (???)
{
@@ -221,25 +236,25 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
// głównej drogi - chyba że jest równorzędne...
fVelNext = 30.0; // uzależnić prędkość od promienia; albo niech będzie
// ograniczona w skrzyżowaniu (velocity z ujemną wartością)
if ((iFlags & 32) == 0) // jeśli nie wjechał
if ((iFlags & spElapsed) == 0) // jeśli nie wjechał
if (trTrack->iNumDynamics > 0) // a skrzyżowanie zawiera pojazd
fVelNext =
0.0; // to zabronić wjazdu (chyba że ten z przodu też jedzie prosto)
}
if (iFlags & 8) // jeśli odcinek zmienny
if (iFlags & spSwitch) // jeśli odcinek zmienny
{
if (bool(trTrack->GetSwitchState() & 1) !=
bool(iFlags & 16)) // czy stan się zmienił?
bool(iFlags & spSwitchStatus)) // czy stan się zmienił?
{ // Ra: zakładam, że są tylko 2 możliwe stany
iFlags ^= 16;
iFlags ^= spSwitchStatus;
// fVelNext=trTrack->VelocityGet(); //nowa prędkość
if ((iFlags & 32) == 0)
if ((iFlags & spElapsed) == 0)
return true; // jeszcze trzeba skanowanie wykonać od tego toru
// problem jest chyba, jeśli zwrotnica się przełoży zaraz po zjechaniu z niej
// na Mydelniczce potrafi skanować na wprost mimo pojechania na bok
}
// poniższe nie dotyczy trybu łączenia?
if ((iFlags & 32) ? false :
if ((iFlags & spElapsed) ? false :
trTrack->iNumDynamics >
0) // jeśli jeszcze nie wjechano na tor, a coś na nim jest
fDist -= 30.0, fVelNext = 0.0; // to niech stanie w zwiększonej odległości
@@ -248,7 +263,7 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
}
}
}
else if (iFlags & 0x100) // jeśli event
else if (iFlags & spEvent) // jeśli event
{ // odczyt komórki pamięci najlepiej by było zrobić jako notyfikację, czyli zmiana komórki
// wywoła jakąś podaną funkcję
CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości
@@ -258,12 +273,12 @@ bool TSpeedPos::Update(vector3 *p, vector3 *dir, double &len)
AnsiString TSpeedPos::TableText()
{ // pozycja tabelki prędkości
if (iFlags & 0x1)
if (iFlags & spEnabled)
{ // o ile pozycja istotna
if (iFlags & 0x2) // jeśli tor
if (iFlags & spTrack) // jeśli tor
return "Flags=#" + IntToHex(iFlags, 8) + ", Dist=" + FloatToStrF(fDist, ffFixed, 7, 1) +
", Vel=" + AnsiString(fVelNext) + ", Track=" + trTrack->NameGet();
else if (iFlags & 0x100) // jeśli event
else if (iFlags & spEvent) // jeśli event
return "Flags=#" + IntToHex(iFlags, 8) + ", Dist=" + FloatToStrF(fDist, ffFixed, 7, 1) +
", Vel=" + AnsiString(fVelNext) + ", Event=" + evEvent->asName;
}
@@ -273,7 +288,7 @@ AnsiString TSpeedPos::TableText()
bool TSpeedPos::Set(TEvent *e, double d)
{ // zapamiętanie zdarzenia
fDist = d;
iFlags = 0x101; // event+istotny
iFlags = spEnabled | spEvent; // event+istotny
evEvent = e;
vPos = e->PositionGet(); // współrzędne eventu albo komórki pamięci (zrzutować na tor?)
CommandCheck(); // sprawdzenie typu komendy w evencie i określenie prędkości
@@ -287,17 +302,17 @@ void TSpeedPos::Set(TTrack *t, double d, int f)
if (trTrack)
{
iFlags = f | (trTrack->eType == tt_Normal ? 2 : 10); // zapamiętanie kierunku wraz z typem
if (iFlags & 8)
if (iFlags & spSwitch)
if (trTrack->GetSwitchState() & 1)
iFlags |= 16;
iFlags |= spSwitchStatus;
fVelNext = trTrack->VelocityGet();
if (trTrack->iDamageFlag & 128)
fVelNext = 0.0; // jeśli uszkodzony, to też stój
if (iFlags & 64)
if (iFlags & spEnd)
fVelNext = (trTrack->iCategoryFlag & 1) ?
0.0 :
20.0; // jeśli koniec, to pociąg stój, a samochód zwolnij
vPos = (bool(iFlags & 4) != bool(iFlags & 64)) ?
vPos = (bool(iFlags & spReverse) != bool(iFlags & spEnd)) ?
trTrack->CurrentSegment()->FastGetPoint_1() :
trTrack->CurrentSegment()->FastGetPoint_0();
}
@@ -344,7 +359,8 @@ bool TController::TableNotFound(TEvent *e)
{ // sprawdzenie, czy nie został już dodany do tabelki (np. podwójne W4 robi problemy)
int i, j = (iLast + 1) % iSpeedTableSize; // j, aby sprawdzić też ostatnią pozycję
for (i = iFirst; i != j; i = (i + 1) % iSpeedTableSize)
if ((sSpeedTable[i].iFlags & 0x101) == 0x101) // o ile używana pozycja
if ((sSpeedTable[i].iFlags & (spEnabled | spEvent)) == spEnabled |
spEvent) // o ile używana pozycja
if (sSpeedTable[i].evEvent == e)
return false; // już jest, drugi raz dodawać nie ma po co
return true; // nie ma, czyli można dodać

View File

@@ -92,17 +92,39 @@ enum TAction
actTrial // próba hamulca (na postoju)
};
enum TSpeedPosFlag
{ // wartości dla iFlag w TSpeedPos
spEnabled = 0x1, // pozycja brana pod uwagę
spTrack = 0x2, // to jest tor
spReverse = 0x4, // odwrotnie
spSwitch = 0x8, // to zwrotnica
spSwitchStatus = 0x10, // stan zwrotnicy
spElapsed = 0x20, // pozycja minięta przez pojazd
spEnd = 0x40, // koniec
spCurve = 0x80, // łuk
spEvent = 0x100, // event
spShuntSemaphor = 0x200, // tarcza manewrowa
spPassengerStopPoint = 0x400, // przystanek osobowy (wskaźnik W4)
spStopOnSBL = 0x800, // zatrzymanie na SBL
spCommandSent = 0x1000, // komenda wysłana
spOutsideStation = 0x2000, // wskaźnik końca manewrów
spSemaphor = 0x4000, // semafor pociągowy
spRoadVel = 0x8000, // zadanie prędkości drogowej
spSectionVel = 0x20000, // odcinek z ograniczeniem
spEndOfTable = 0x10000 // zatkanie tabelki
};
class TSpeedPos
{ // pozycja tabeli prędkości dla AI
public:
double fDist; // aktualna odległość (ujemna gdy minięte)
double fVelNext; // prędkość obowiązująca od tego miejsca
// double fAcc;
int iFlags;
int iFlags; //flagi typu wpisu do tabelki
// 1=istotny,2=tor,4=odwrotnie,8-zwrotnica (może się zmienić),16-stan
// zwrotnicy,32-minięty,64=koniec,128=łuk
// 0x100=event,0x200=manewrowa,0x400=przystanek,0x800=SBL,0x1000=wysłana komenda,0x2000=W5
// 0x10000=zatkanie
// 0x4000=semafor,0x10000=zatkanie
vector3 vPos; // współrzędne XYZ do liczenia odległości
struct
{

View File

@@ -338,6 +338,16 @@ void TEvent::Load(cParser *parser, vector3 *org)
bEnabled = false;
Params[6].asCommand = cm_SetVelocity;
}
else if (str == "RoadVelocity")
{
bEnabled = false;
Params[6].asCommand = cm_RoadVelocity;
}
else if (str == "SectionVelocity")
{
bEnabled = false;
Params[6].asCommand = cm_SectionVelocity;
}
else if (str == "ShuntVelocity")
{
bEnabled = false;