Activity készítés OpenBVE-ben – avagy ha és akkor

This Hungarian language article looks at how to use the $If(), $Else(), $Endif(), $Include(), $Sub() and $Rnd(;) commands in routebuilding. It also presents a way of using these commands to create activities for OpenBVE routes, somewhat similar to Microsoft Train Simulator activities, basically to add more variety to the quite static routes. I also suggest a way to let users easily configure such activities even in routes where the license does not allow modification.

Furcsán hangzik, ugye? Activityket MSTS-hez szokás készíteni, OpenBVE esetében erről eddig nem igazán beszéltünk. Ez azért jutott eszembe, mert a BVE Train fórumon egy kolléga csodálkozással említette, hogy OpenBVE-ben a pályaépítés során használhatunk $If(), $Else() és $Endif(), vagyis ha… akkor… parancsokat. Valószínűleg nem mindenki ismeri ezeket, így aztán ebben a cikkben szeretném röviden bemutatni őket és megmutatni, hogy a $Sub(), $Rnd(;) és $Include() parancsokkal együtt hogyan használhatóak ezek activity készítéshez.

Szóval mi is az az if?

Az $If(), $Else() és $Endif() parancsokkal olyan szakaszokat építhetünk a pályába, amelyek csak valamilyen feltétel teljesülése esetén jelennek meg, ha nem teljesül a feltétel, akkor valami mást jelenítünk meg. Nézzük részletesen.

Ha… akkor…

$If(feltétel) – a feltétel helyére egy szám, vagy egy számot eredményező kifejezés kerül. Ha a feltétel értéke nulla lesz, akkor hamisnak tekintjük az eredményt, ha nem nulla, akkor igaznak. Nézzünk példát:

$If(1) – ez igaz lesz
$If(0) – ez hamis lesz

A feltétel persze nem csak egy egyszerűen beírt szám lehet, kerülhet ide $Sub() vagy $Rnd(;) parancs is. Előbbivel helyettesíteni tudunk egy kifejezést, utóbbival pedig véletlen számot tudunk készíteni adott határok között. Nézzünk ilyen példát is:

$If($Rnd(0;2)) – itt az $Rnd(0;2) miatt 0, 1 és 2 lehet az eredmény, vagyis 2/3 esélye van annak, hogy ez a kifejezés igaz legyen, 1/3 esélye van annak, hogy hamis legyen.

$Sub(100)=0
$If($Sub(100)) – ez hamis lesz, mert a $Sub(100) értékét előtte nullában állapítottuk meg.

$Sub(100)=1
$If($Sub(100)) – ez viszont igaz lesz, mert a $Sub(100) értékét nullától eltérő számban határoztuk meg.

Hogyan működik ez OpenBVE-ben?

Az $If() parancs után adhatjuk meg, hogy mi történjen, ha a feltétel igaz eredményt adott:

$If($Rnd(0;2))
  1250,.Freeobj 0;501;-5;0;0, ;M61 020 van a szomszédos vágányon

Most adjuk meg azt is, hogy mi történjen, ha a feltétel hamis értéket mutat, ehhez szükséges az $Else() parancs:

$If($Rnd(0;2))
  1250,.Freeobj 0;501;-5.6;0;0, ;M61 020 van a szomszédos vágányon
$Else()
  1250,.Freeobj 0;502;-5.6;0;0, ;M62 187 van a szomszédos vágányon

Az $If() szakaszt az $EndIf() paranccsal zárjuk le. Most nézzük a példánkban levő $If() szakaszt teljes egészében:

$If($Rnd(0;2))
  1250,.Freeobj 0;501;-5.6;0;0, ;M61 020 van a szomszédos vágányon
$Else()
  1250,.Freeobj 0;502;-5.6;0;0, ;M62 187 van a szomszédos vágányon
$EndIf()

Eszerint feltételként megadunk egy véletlen számot 0 és 2 között, vagyis vagy 0-t, vagy 1-et vagy 2-t. Ha 1 vagy 2 lesz az eredmény, akkor a 020-as Nohabot állítjuk a szomszéd vágányra, ha 0, akkor a 187-es Szergejt. Nézzünk még egy példát, ezúttal $Sub() paranccsal:

$Sub(50)=1
$If($Sub(50))
  1250,.Freeobj 0;503;-5.6;0;0, ;M41 2211 van a szomszédos vágányon
  1270,.Freeobj 0;505;-5.6;0;0, ;Bhv-t húz a Csörgő
$Else()
  1250,.Freeobj 0;504;-5.6;0;0, ;M41 2335 van a szomszédos vágányon
  1270,.Freeobj 0;506;-5.6;0;0, ;Bp-t húz a Csörgő
$EndIf()

Itt létrehoztunk 50-es számmal egy helyettesítő kifejezést, aminek most értéknek 1-et adtunk. Azután ezt egy $If() parancsban feltételként adtuk meg, az 1-es $Sub(50) érték miatt most az $If() parancs utáni két sor kerül a pályába, vagyis a 2211-es Csörgő Bhv kocsival. Ha a $Sub(50) értékét nullára állítottuk volna, akkor viszont a 2335-ös Csörgő és Bp kocsi került volna a pályába. Pont ez az, amit az activity készítéshez használni akarunk!

Hogy lesz ebből activity?

Nos, könnyen! Hozzunk létre egy szövegfájlt tetszőleges névvel, én itt most activity.cfg néven mentem el. Ezt rakhatjuk a route fájlunk mellé, vagy az Object könyvtáron belül egy külön mappába, ahogy tetszik. Most hívjuk be ezt a fájlt a route fájlunkba egy $Include() paranccsal, még a With Track szakasz előtt:

$Include(activity.cfg)

Most nyissuk meg Notepad++-ban az activity.cfg fájlt (kerüljük a Jegyzettömb használatát)! A Notepad++ azért ajánlott különösen, mert azzal egyszerre több fájlt is tudunk szerkeszteni és fülekkel tudunk váltani a fájlok között, úgy, mint a böngészőkben, illetve egy gomnyomással minden éppen szerkesztett fájlt menthetünk – erre itt pedig nagy szükségünk lesz. Példának a Sólyomvár-Királyliget pályát fogjuk használni. Nézzük!

Írjuk be az activity.cfg-be az alábbiakat:

;Veresd - első vagy második vágányról induljunk - 1 első 0 második
$Sub(100)=1

Szóval az activitynkben most szeretnénk beállítani, hogy az 1. vagy a 2. vágányról induljunk, valamint meghatározzuk, hogy az 1 az első, a 0 a második vágányt fogja jelenteni. Aztán megadunk egy $Sub() kifejezést 100-as azonosítószámmal, aminek itt 1-et adunk értéknek. Ahhoz, hogy ez beállítható legyen, el kell készítenünk a pályát úgy, hogy a vonat az első vágányról indul és úgy is, hogy a másodikról. Ez plusz munka, viszont ha hajlandóak vagyunk időt áldozni erre, akkor változatos pályánk lehet, ami mindig kicsit máshogy mutatja önmagát!

Most menjünk vissza a route fájlba Veresd állomáshoz és az állomás kezdeténél helyezzünk el egy $If() parancsot, amelyben azt fogjuk vizsgálni, hogy az activity.cfg-ben meghatározott $Sub(100) milyen értéket kapott.

$If($Sub(100))

Az $If() parancs felépítése miatt most kell beírnunk azokat a parancsokat, amelyeket az 1. vágányról történő induláshoz használni akarunk, vagyis idejön egy csomó .Freeobj, .Wall, .Curve, .Railstart, .Railend és hasonló parancs a saját méteradatával. Ez sok-sok sor lesz, de nyugodjunk meg, nem lesz belőle probléma, bírja a program. A sok sor miatt egy idő után nehéz lesz kiigazodni azon, hogy mi tartozik az $If()-hez és mi nem, így kezdjük beljebb az $If()-hez tartozó sorokat vagy akár $Include() parancsokkal helyezzük ki ezeket külön fájlokba.

Ha ez megvan, írjuk be az $Else() parancsot, majd írjuk be azokat a parancsokat, amelyek a második vágányról induláshoz szükségesek. Más lesz a felvételi épület, a padok távolsága, más lesz a .Curve parancsok működése, máshogy indítunk vágányt, hiszen most pár méterrel odébbról, a második vágányról indulunk.

$If($Sub(100))
  0,
  .Freeobj 0;500;-6,    ;Pad 6 m bal
  .Freeobj 0;600;-10,   ;Felvételi épület 10 m bal
$Else()
  0,
  .Freeobj 0;500;-11.6, ;Pad 11.6 m bal
  .Freeobj 0;600;-15.6, ;Felvételi épület 15.6 m bal
$EndIf()

A valóságban ide természetesen nem csak két-két sor kerül, hanem kb. 200 vagy akár 400, vagy mégtöbb, attól függően, hogy mennyire részletes pályát szeretnénk építeni.

Ugyanezen a módon még rengeteg mindenre adhatunk lehetőséget a pályánkban, így végül jó kis activity készítés sülhet ki belőle, amit a játékosok is könnyen el tudnak végezni, mi pályaépítőként pedig nyugodtan dőlhetünk hátra: olyan pályát adtunk ki a kezünkből, amit nem fognak három vezetés után meguntként félredobni.

If az if-ben

Az $If() parancsokat egymásba is lehet ágyazni, vagyis egy $If() szakasz tartalmazhat egy (vagy több) másik $If() szakaszt. Célszerű az ilyen beágyazott $If() szakaszokat még beljebb kezdeni, hogy átláthatóak legyenek. Nézzük meg az előbbi példát, most már egy beágyazott második $If() szakasszal:

$If($Sub(100))
  0,
  .Freeobj 0;500;-6,    ;Pad 6 m bal
  .Freeobj 0;600;-10,   ;Felvételi épület 10 m bal
  $If($Sub(101))
    50,
    .Freeobj 0;510;-15, ;Lada 15 m bal
    .Freeobj 0;610;-20, ;Trabant 20 m bal
  $Else()
    50,
    .Freeobj 0;511;-15, ;Skoda 15 m bal
    .Freeobj 0;611;-20, ;Suzuki 20 m bal
  $EndIf()
$Else()
  0,
  .Freeobj 0;500;-11.6, ;Pad 11.6 m bal
  .Freeobj 0;600;-15.6, ;Felvételi épület 15.6 m bal
$EndIf()

Bonyolultnak tűnik? Nem annyira az! Először is ebben megvan minden az előbbi példából: a $Sub(100) értékének függvényében ugye vagy az 1. vagy a 2. vágányról indulunk. Abban az esetben, ha az 1. vágányról indulunk még teszünk két autót is a pálya mellé, a beágyazott $If() paranccsal, itt pedig a 101-es számú $Sub() parancs értéke dönti majd el, hogy Lada és Trabant vagy pedig Skoda és Suzuki legyen ezen a helyen. Lehetne ezt is véletlenszerűvé tenni természetesen!

Példa egy activity.cfg fájlra

Végezetül álljon itt egy példa a Sólyomvár-Királyliget pálya képzeletbeli activity.cfg fájljából.

;Veresd - első vagy második vágányról induljunk - 1 első 0 második
$Sub(100)=1

;Veresd kijárati jelző vörös vagy szabad - 1 szabad 0 vörös
$Sub(101)=1

;Szentistvántelep - első vagy második vágányra érkezzünk - 1 első 0 második
$Sub(200)=0

;Sok utas várjon Cseberkiben - 1 sok 0 kevés
$Sub(300)=1

;Essen az eső Cseberki után - 1 igen 0 nem
$Sub(301)=1

;Sólyomváron második harmadik negyedik vagy ötödik vágányra érkezzünk
$Sub(410)=1
$Sub(411)=0
$Sub(412)=0

;Sólyomváron a szomszéd vágányon MDmot vagy BDVmot - 1 MDmot 0 BDVmot
$Sub(420)=0

;Sólyomváron női vagy férfi bemondó - 1 női 0 férfi - Rnd-vel lehet véletlenszerűre is
$Sub(430)=1

;Magyarszentpéter-Mártonszállás között helyes vagy helytelen vágányon haladjunk - 1 helyes 0 helytelen
$Sub(550)=0

;Mártonszállás utáni viadukton IC gyors tartály vagy konténervonat halad
$Sub(780)=1
$Sub(781)=0
$Sub(782)=0

Folytathatnám a sort a végtelenségig, rengeteg dolgot meg lehet csinálni, csak idő és kedv kérdése, hogy mennyire bővítjük a lehetőségeket.

További variáció: véletlenszerűség

Ezen túl lehet természetesen az $Rnd() paranccsal véletlenszerűséget is vinni a pályánkba:

With Structure
.Freeobj(901) Trabant.b3d
.Freeobj(902) Lada.b3d
.Freeobj(903) Ford.b3d
With Track
2500,
.Freeobj 0;90$Rnd(1;3);-10;0;0,

Mivel itt az objektum azonosítószámának a 3. karakterét az $Rnd(1;3) paranccsal határozzuk meg, vagy a 901-es Trabant, vagy a 902-es Lada vagy pedig a 903-as Ford jelenik majd meg – mondjuk az útátjárónál vonatunk elhaladását várva.

Még egy példa a véletlenszerűségre:

;Meddig álljunk Szentistvántelepen
.Sta Szentistvántelep;08.0815;08.0845;;-1;1;;;$Rnd(15;60);15;,

Itt az $Rnd(15;60) miatt véletlenszerűen dől el, hogy mennyi lesz a várakozási idő az állomáson, 15 és 60 mp között bármennyi lehet.

If-re fel!

Az $If() és a hozzá kapcsolódó parancsok sokmindenre használhatóak, az itt bemutatott activity készítés csak egy lehetőség a sok közül. Próbáljuk a saját elgondolásunk szerint kreatívan használni őket!

Néhányan talán felhúztátok a szemöldökötöket: miért kell a külön activity.cfg fájl? Nos, tényleg nem kell, csak célszerű. Ha így építünk, a játékosoknak nem kell a route fájlban turkálniuk, elég lesz az activity.cfg-t módosítani, így kevésbé valószínű, hogy a pálya esetleg összeborul. Néhányan nem is engedik a route fájl módosítását, számukra szintén nagyon praktikus ez a megoldás. Mellékelhetünk többféle előregyártott activityt a pályánkhoz, ezeket ilyenkor nyilván külön route fájlként fogjuk kiadni, de az itt leírtak alapján lehetőséget tudunk adni a játékosoknak is arra, hogy kedvük szerint alakíthassák a játékot.

Innen már csak egy lépés egy Activity Editor létrehozása, vagyis egy grafikus activity szerkesztő programé, amivel a felsorolt lehetőségeket grafikus felületen állíthatjuk be.

Pályát már építettem, de én ezt nem értem!

Semmi gond! A cikk után a hozzászólás részben kérdezz nyugodtan, ha tudok, válaszolok a kérdésedre!