Priemyselná stavba s viac tovarmi

1.  Modelovanie hlavnej časti
2.  Pomocné body pre koľaje a tovar
3.  Config.txt
4.  Script gs
5.  Stručne o oríprave 3D textúr pre budovu skladu
6.  Modelovanie detailného skladu
7.  Doplňujúce meshe
8.  Doplnenie - ďalšie možnosti

V tomto tútoriále by som vám chcel ukázať ako si postaviť priemyselnú stavbu v ktorej sa bude manipulovať s viac druhmi tovarov na jednej koľaji. Základnou priemyselnou stavbou je taká kde je jedna koľaj, ktorá buď generuje, alebo pohlcuje tovar. Z nej potom vychádza ostatné kde v rámci jednej koľaje je zároveň nakládka aj vykládka, dvojkoľajová stavba kde na jednej koľaji sa prevádza vykládka a na druhej nakládka a samozrejme viac koľajová stavba s rôznou kombináciou operácii pričom zároveň sa môže pracovať s jedným druhom tovaru vrátane pasažierov alebo viac druhmi. V prvom tútoriale o priemyselnej stavbe som popísal jednoduchú dvojkoľajovú stavbu kde na jednej koľaji sa prevádza nakládka a na druhej vykládka jedného a toho istého tovaru. Teraz popíšem tiež dvojkoľajovú stavbu, pričom ale na jednej koľaji sa bude pracovať s dvoma rôznymi druhmi tovaru. Pre mnoho otázok tu aj trocha hlbšie rozpíšem štruktúru config txt a gs scriptu. Odtiaľ už je totiž iba krôčik k viac koľajovej stavbe, ktorej kľúčové špecifiká scriptu tu tiež čiastočne spomeniem. Cieľom je detailná stavba prekladiska ako na nasledujúcom obrázku ktorá obsahuje tri koľaje. Dve sú priebežné pre manipuláciu s tovarom pričom na jednej sa vykladajú dva druhy tovaru a na druhej sa nakladá jeden druh tovaru. Tretia koľaj je slepá, doplňujúca a neskôr možná použiť ako ďalšia manipulačná koľaj pre ďalší typ tovaru buď ako vykládka alebo nakládka




Základné textúry, ktoré budeme potrebovať pre samotnú rampu sú betón pre boky, asfalt pre vrchnú časť, plech a hrdzavý plech pre rôzne detaily, žlto-čierne lemovanie a špeciálnu textúru pre lesk kovových časti a prirodzený odraz materiálov v exteriéry.











1. Modelovanie hlavnej časti

Začneme tak, že y kriviek si vytvoríme pôdorys rampy. Jej rozmer je závislý od dĺžky manipulačných koľají a prípadne predlohy. Každopádne by manipulačná koľaj nemala byť menšia ako 50m. V našom prípade je celková dĺžka 130m a šírka 12 a 22 metrov. Zmeníme ju pravou myšou na CONVERT TO EDITABLE SPLINE a po výbere bodov, ich označení na objekte kliknutím pravej myši ich zmeníme na CORNER pre pravouhlé posúvanie. Z pôdorysu potom vytvoríme kópiu, ktorú odsunieme na bok.




Z prvého pôdorysu vycentrovaného na stred plochy (x = 0.0, y = 0.0, z = 0.0) vyberieme čiaru (spline) a v políčku outline zadáme hodnotu -0.1 čím zdvojíme čiaru smerom von a vytvoríme tak hrúbku steny. Táto hrúbka z ktorej využijeme iba hornú a vonkajšie steny v tomto prípade bude slúžiť pre jednoduchšie textúrovanie žlto-čierneho pásu na okraji hornej plochy.
Ak sme to spravili, vyberieme znova čiaru a v hornom menu MODIFIERS - MESH EDITING vyberieme EXTRUDE pričom v pravej časti okna v políčku AMOUNT zadáme výšku rampy 1.4m.
Teraz vezmeme kópiu objektu a spravíme to iste (ale bez zdvojenia čiary - hrúbky steny) tak, že výšku pri extrude určíme na 0.0. Vytvoríme tak obojstranné plane, ktoré bude slúžiť ako horná strana rampy pričom bude takto presne sedieť so stenami a presne zapadne k žlto-čiernej lište. Výškovo ju teda umiestnime na z = 1.4m
Nakoniec odstránime všetky nepotrebné polygóny. Otočíme si objekt zo spodku a označíme si polygóny. Na objekte potom vyberieme všetky vnútorné z boku rampy, spodnú plochu a z tej kópie označíme spodnú plochu a aj tenké krajné plochy s výškou 0.0 ktoré nieje vidieť, ale sú prítomné.




Všetky odstránime a hornú stranu s bočnou pomocou spoločných vertexov zvaríme do jedného objektu. Ako posledné si na objekte vyberieme FACE a odstránime v zadnej časti na bokoch po jednom a oba na zadnej strane. Posunutím vertexov na pozíciu z = 0.0 túto časť zošikmíme a vytvoríme tak šikmý nábeh na rampu. Vertexy opäť zvaríme.




Objekt uložíme a vytvoríme si nový projekt. Tu z hranolu (box), dvoch rúr (tube) a dvoch valcov (cylinder) si vymodelujeme koncový nárazník. Opäť je jednoduchšie vytvoriť si iba jeden a jeho kópiu posunúť na druhú pozíciu a modelovať každý zvlášť.



Objekt uložíme ako samostatný súbor naraznik.gmax, otvoríme si znova rampu a pomocou MERGE ho importujeme do scény na jeho miesto. Tak isto si vymodelujeme samostatne pracovné koľajnice (ak už nemáme), ktoré tiež umiestnime do scény tam kde budú v budúcnosti koľajnice. Má to význam pre lepšiu predstavivosť konečnej scény a presné umiestňovanie pomocných bodov pre skutočné koľajnice.



Teraz otextúrujeme všetky plochy. Pri textúrovaní používajte funkciu MODIFIERS - UV COORDINATES - UVW MAP. Značne vám to zjednoduší prácu a v podstate samé správne namapuje textúru na objekt.  Musíte akurát  zvoliť podľa objektu typ natiahnutia na povrch, nastaviť orientáciu a posun. Prípadne aj ostatné parametre. Po otextúrovaní môžeme objekt kontrolne exportovať ako bežný statický scenery objekt.





2. Pomocné body pre koľaje a tovar

Nato aby sme mohli k objektu priradiť koľajnice a miesta kde sa budú zobrazovať palety s tovarom musíme pre TRS do objektu vložiť pomocné body. Najskôr umiestnime body pre koľajnice.
Každá koľaj potrebuje 3 vnútorné body pre stred a  ohraničenie nakládky alebo vykládky (triggre) a dva krajné pre pripojenie bežnej koľaje. Dôležité je ich jednoznačné pomenovanie a u krajných aj orientácia tak aby os Y smerovala vždy smerom von k pripojeniu. Zistíte to podľa popisu, alebo po klíknutí na ikonu HIERARCHY a AFFECT PIVOT ONLY kam smeruje zelená os Y pivotu (centrálneho bodu objektu určujúceho jeho otáčaní, umiestnenie a orientáciu). 
Vyberte teda v pravom okne HELPERS



Označte POINT a umiestnite ho presne na stredovú čiaru pracovnej koľajnice. Jeho výška musí byť z = 0.0.



Ďalší bod umiestnite na opačný koniec tak že z tohoto vytvoríte kópiu a posunom po ose Y ho presuňte. Zabezpečíte tak umiestnenie v rovine. Ďalší bod umiestnite asi 10m od okraju tam kde bude začínať nakládka, ďalší do miesta kde bude končiť nakládka a nakoniec jeden do stredu medzi tieto ohraničujúce nakládku. Tento môže byť posunutý v smere predpokladaného smerovania vlakov pre lepšie zastavovanie. Pokiaľ je predpoklad obojsmerného prechodu vlakov, mal by byť v strede. Body z kraja označte z jednej strany do druhej ako a.track0a, a.track0b, a.track0c, a.track0d a a.track0e. Toto označenie je ľubovolné. Musí byť iba jedinečné v scéne a malo by jasne definovať koľaj ak je v scéne viac koľají. Rovnakým spôsobom potom prideľte body aj ostatným koľajniciam, pričom pre slepú doplňujúcu postačuje umiestniť iba dva krajné body.




Podobne ako body pre koľajnice treba vytvoriť aj body pre tovar. Budú to body určujúce umiestnenie a priestorovú orientáciu. Preto je tu mimoriadne dôležité aj presné orientovanie bodov ktoré by nemalo byť jednosmerné pre pestrejšie realistickejšie zobrazenie scény. Na pomoc pre lepšie predstavenie si scény nám dobre poslúžia jednoduché boxy s hranou 1.2x1.2x1.2 metra ktoré rozmiestnime na rampe tak ako by sme chceli aby sa zobrazoval tovar vrátane jeho orientácie v priestore. Podmienkou je boxy mať rozdelené v pôdoryse na 2 a 2 strany aby priesečník - stredový kríž nám určoval neskôr miesto kam umiestnime pomocný bod. Pre náš  prípad takto umiestnime 2 x 25 boxov pre vykládku a  1 x 50 boxov pre vykládku.



Teraz umiestnite prvý bod na stredový kríž boxu a otočte ho v smere boxu tak aby sa s krížom prekríval.



Postupne umiestnite takto všetky body pre tovar nakládky i vykládky. Ich označenie aj tu musí byť jednoznačné a jasné. Napríklad pre vykladanie z vlaku prvý tovar os a.goods_in101 až po a.goods_in125, pre druhy tovar a.goods_in201 až po a.goods_in225 a pre nakládku do vlaku od a.goods_out101 až po a.goods_out150.




Takto máme hlavnú funkčnú časť rampy dokončenú a môžeme pristúpiť k testovaniu.

3. Config.txt

Config txt je kľúčový a musí byť tvorený ako INDUSTRY.  Rozdiel medzi TRS2004 a TRS2006 je minimálny a preto uvádzam hlavne spoločné parametre a tie ktoré v oboch verziách majú rovnaký účel.
Skladá sa z viacej častí. V úvodnej časti sú všeobecné identifikácie. kde je asi najdôležitejší parameter kuid objektu ktorý ho identifikuje. Na identifikáciu do skupiny v ponuke a zaradenie je dôležitý parameter category-class definovaný ako BINkind definovaný ako industry. Parameter region slúži na lepšiu identifikáciu a zaradenie do skupiny objektov rovnako ako parameter type. Oba sa najviac využívajú v staršej štruktúre ponuky v TRS04.  Parameter light určuje reagovanie na denné svetlo (1 - zapnutý a 0 vypnutý). Parameter script a class určujú externý script a triedu. Musia sa zhodovať s názvom scriptového súboru gs v priradenom adresáre objektu a definíciou v ňom. Parameter icon-texture určuje externú ikonu ktorá sa zobrazí v hre v cestovnom poriadku kam vlak smeruje. A nakoniec parameter asset-filename určuje názov hlavného im súboru kde je exportovaný objekt do TRS.

kuid                                                                          <kuid:XXXXXX:XXXXXX>
region                                                                        TEST
type                                                                         "Prekladka"
category-class                                                           "BIN"
kind                                                                         "industry"
light                                                                          1
script                                                                        "gentovar"
class                                                                         "gentovar"
icon-texture                                                              "ico_rampa.bmp"
asset-filename                                                           "rampa"

Sekcia kuid-table {} nám ohraničuje a definuje nevyhnutne nutné a použité externé kuid (objekty). V našom prípade tovar pričom v tomto prípade je dôležité aj ich pomenovanie ktoré je vlastne deklaráciou a priradením kuid k textovému označeniu v scripte. V našom prípade in_gen_goods - prvý tovar pre vykladanie z vlaku, in_gen_goods2 - druhý tovar pre vykladanie z vlaku a out_gen_goods - tovar čo sa bude nakladať na vlak. Pomenovanie je ľubovolné. Musí ale byť jedinečné pre celý objekt a všetko čo s nim súvisí.

kuid-table {
                           in_gen_goods                  <kuid:XXXXX:XXXXX>
                           in_gen_goods2                <kuid:XXXXX:XXXXX>
                           out_gen_goods                <kuid:XXXXX:XXXXX>
}

Ďalšia časť definuje použité externé meshe ako sú napríklad šipky ohraničujúce fixné koľajnice. Kľúčová je deklarácia mesh-table {} a v nej vnorená  default {} obsahujúca základné všeobecné deklarácie a deklaráciu samotných šipiek. Je to štandartná bloková logika. Parameter mesh určuje (priraďuje) názov im súboru v ktorom je objekt exportovaný do TRS a parameter auto-create určuje či sa majú definované meshe automaticky vygenerovať (0 vypnuté, 1 zapnuté).
Samotné priradené meshe sú definovane v parametroch arrow0 {} až arrow3 {}.  V nich sú bližšie identifikácie ku každej šipke. Parameter kind určuje skupinu podobne ako kind v hlavnej deklarácii objektu ako celku, att určuje meno pomocného bodu v objekte ku ktorému sa má priradiť a na ktorého mieste sa má zobraziť. Tu je dôležité to pred tým jednoznačné pomenovanie pri modelovaní v gmax a jeho orientácia podľa ktorej sa mesh vygeneruje a natočí. Parameter default-mesh určuje kuid samotného meshu a surveyor-only určuje či sa má zobraziť iba v editore (1 áno, 0 nie). Podobne sú definované všetky ostatné šipky pričom každá je priradená k jednému krajnému bodu koľajníc

mesh-table {
    default {
        mesh                    "rampa.im"
        auto-create                1
        effects {
            arrow0 {
                kind            "attachment"
                att            "a.track0a"
                default-mesh        <kuid:-3:10092>
                surveyor-only        1
            }
            arrow1 {
                kind            "attachment"
                att            "a.track0e"
                default-mesh        <kuid:-3:10092>
                surveyor-only        1
            }
            arrow2 {
                kind            "attachment"
                att            "a.track1a"
                default-mesh        <kuid:-3:10092>
                surveyor-only        1
            }
            arrow3 {
                kind            "attachment"
                att            "a.track1e"
                default-mesh        <kuid:-3:10092>
                surveyor-only        1
            }
        }
    }
}

V ďalšej časti sa priradia koľajnice k pomocným bodom v objekte, ktoré sme definovali pri modelovaní. Kľúčový je parameter  attached-track {} v ktorom sú vnorené jednotlivé koľaje. Dôležité je ich jedinečné pomenovanie, ktoré tiež bude používať neskôr script. Označme icch teda ako out_track {} pre koľaj na ktorej sa bude nakladať na vlak z rampy ,  in_track {} ako koľaj na ktorej sa bude vykladať tovar z vlaku na rampu a nakoniec odstavná {} pre doplňujúcu odstavnú koľaj.  V každej potom zadefinujeme parametrom track kuid základnej koľaje čo sa zobrazí ako prvá (bude nahradená podľa pripojenej skutočnej koľaje) a v bloku vertices {} samotne pomocné body celej koľaje (všetky na nej definované), ktoré sme definovali v gmaxe podľa ich jedinečného pomenovania a príslušnej koľaje. Každému treba prideliť jednoznačné číslo od 0 po v našom prípade 4 podľa ich počtu.

attached-track {
    out_track {
        track                    <kuid:-1:15>
        vertices {
            0                "a.track2a"
            1                "a.track2b"
            2                "a.track2c"
            3                "a.track2d"
            4                "a.track2e"
        }
    }
    in_track {
        track                    <kuid:-1:15>
        vertices {
            0                "a.track0a"
            1                "a.track0b"
            2                "a.track0c"
            3                "a.track0d"
            4                "a.track0e"
        }
    }
           odstavna {
        track                    <kuid:-1:15>
        vertices {
            0                "a.track1a"
            1                "a.track1b"
        }
    }
}

V nasledujúcej časti sa definujú zdroje - tovar. Základný je parameter  queues {} a v ňom vnorené samotné bloky tovarov. Aj tu je dôležité jednoznačné a jedinečné pomenovanie, ktoré bude nutne pre správne fungovanie scriptu. Pomenovanie je ľubovolné ale musí byť jedinečné. V našom prípade to bude goods_in_q {} a goods_in_q2 {} pre dva druhy tovaru a jeho pomocné body v gmax objekte, ktorý sa bude vykladať z vlaku a goods_out_q {} pre jeden tovar a body ktorý sa bude na vlak nakladať s rampy.
V každom je potom samostatná vnorená deklarácia kde size určuje maximálny počet tovarov čo sa bude môcť naložiť, alebo vyložiť pre daný tovar a zároveň zobrazovať na rampe. Toto číslo nesmie byť väčšie ako existujúci počet bodov priradených danému tovaru pri modelovaní objektu v gmax. V našom prípade to bude pre vykladané tovary 25 + 25 a 50 pre nakladaný tovar na vlak.
Parameter initial-count určuje počiatočný počet tovarov pri načítaní objektu v editore. Tento parameter sa dá neskôr meniť v editore pri vyvolaní editačného okna objektu s otáznikom.
Parameter product-kuid definuje kuid samotného tovaru pre danú skupinu a operáciu a musí byť totožný s kuidom pri  predchádzajúcej deklarácii v kuid-table.
Nakoniec v bloku attachment-points {} definujeme všetky pomocné body definované v gmax pričom každý musí byť označený číslom od 0 po n podľa ich počtu. Tieto názvy bodov v úvodzovkách musia byť zhodné s jedinečnými názvami bodov  v gmax modely. 

queues {
    goods_in_q {
        size                    25
        initial-count                2
        product-kuid                <kuid:193885:830003>
        attachment-points {
            0                "a.goods_in101"
            1                "a.goods_in102"
            2                "a.goods_in103"
            3                "a.goods_in104"
            4                "a.goods_in105"
            5                "a.goods_in106"
            6                "a.goods_in107"
            7                "a.goods_in108"
            8                "a.goods_in109"
            9                "a.goods_in110"
            10                "a.goods_in111"
            11                "a.goods_in112"
            12                "a.goods_in113"
            13                "a.goods_in114"
            14                "a.goods_in115"
            15                "a.goods_in116"
            16                "a.goods_in117"
            17                "a.goods_in118"
            18                "a.goods_in119"
            19                "a.goods_in120"
            20                "a.goods_in121"
            21                "a.goods_in122"
            22                "a.goods_in123"
            23                "a.goods_in124"
            24                "a.goods_in125"
        }
    }
    goods_in_q2 {
        size                    25
        initial-count                2
        product-kuid                <kuid:193885:830009>
        attachment-points {
            0                "a.goods_in201"
            1                "a.goods_in202"
            2                "a.goods_in203"
            3                "a.goods_in204"
            4                "a.goods_in205"
            5                "a.goods_in206"
            6                "a.goods_in207"
            7                "a.goods_in208"
            8                "a.goods_in209"
            9                "a.goods_in210"
            10                "a.goods_in211"
            11                "a.goods_in212"
            12                "a.goods_in213"
            13                "a.goods_in214"
            14                "a.goods_in215"
            15                "a.goods_in216"
            16                "a.goods_in217"
            17                "a.goods_in218"
            18                "a.goods_in219"
            19                "a.goods_in220"
            20                "a.goods_in221"
            21                "a.goods_in222"
            22                "a.goods_in223"
            23                "a.goods_in224"
            24                "a.goods_in225"
        }
    }
    goods_out_q {
        size                    25
        initial-count                5
        product-kuid                <kuid:-3:10013>
        attachment-points {
            0                "a.goods_out101"
            1                "a.goods_out102"
            2                "a.goods_out103"
            3                "a.goods_out104"
            4                "a.goods_out105"
            5                "a.goods_out106"
            6                "a.goods_out107"
            7                "a.goods_out108"
            8                "a.goods_out109"
            9                "a.goods_out110"
                    10                "a.goods_out111"
                    11                "a.goods_out112"
                    12                "a.goods_out113"
                    13                "a.goods_out114"
                    14                "a.goods_out115"
                    15                "a.goods_out116"
                    16                "a.goods_out117"
                    17                "a.goods_out118"
                    18                "a.goods_out119"
                    19                "a.goods_out120"
                    20                "a.goods_out121"
                    21                "a.goods_out122"
                    22                "a.goods_out123"
                    23                "a.goods_out124"
                    24                "a.goods_out125"
                    25                "a.goods_out126"
                    26                "a.goods_out127"
                    27                "a.goods_out128"
                    28                "a.goods_out129"
                    29                "a.goods_out130"
                    30                "a.goods_out131"
                    31                "a.goods_out132"
                    32                "a.goods_out133"
                    33                "a.goods_out134"
                    34                "a.goods_out135"
                    35                "a.goods_out136"
                    36                "a.goods_out137"
                    37                "a.goods_out138"
                    38                "a.goods_out139"
                    39                "a.goods_out140"
                    40                "a.goods_out141"
                    41                "a.goods_out142"
                    42                "a.goods_out143"
                    43                "a.goods_out144"
                    44                "a.goods_out145"
                    45                "a.goods_out146"
                    46                "a.goods_out147"
                    47                "a.goods_out148"
                    48                "a.goods_out149"
                    49                "a.goods_out150"
        }
    }
}

Ďalšou časťou je časť kde sa definujú procesy prebiehajúce na rampe s tovarmi. Kľúčové slovo je processes {} v ktorom je vnorený niečo čo by sa dalo označiť ako majiteľ operácii so skupinou tovarov. Jeho názov môže byť ľubovolný. Musí ale byť jedinečný pretože sa naň odvoláva aj script. My si ho označíme ako goodsshed_consumer {}. V ňom sú vnorené všeobecné parametre ako start-enabled určujúce či má byť aktívny a duration určujúci trvanie. V sekcii za kľúčovým slovom inputs {} sú definované vstupy do procesu operácii s tovarom, teda tovary a v sekcii outputs {} naopak výstupy z operácii. V každom vstupe označenom ako 0 {} pre prvý tovar a 1 {} pre druhý tovar sú jeho špecifikácie rovnako ako s 0 {} označeným jedným tovarom pre výstup, teda nakladanie na vlak.  V nich je definované s amount - neskôr v hre zmeniteľný stupeň (množstvo) spotreby, alebo produkcie za jednotku času a s queue zdroj tovaru. Jeho názov v úvodzovkách musí byť totožný s deklaráciou v queues {} kde sme priraďovali body z gmax modelu. Tak sa vytvorí väzba. 

processes {
    goodsshed_consumer {
        start-enabled                1
        duration                30
        inputs {
            0 {
                amount            3
                queue            "goods_in_q"
            }
            1 {
                amount            3
                queue            "goods_in_q2"
            }
        }
        outputs {
            0 {
                amount            3
                queue            "goods_out_q"
            }
        }
    }
}

Aby nám to všetko fungovalo potrebujeme ešte definovať kľúčové body - rozhrania - pôsobnosti vplyvu - triggre. Definujú sa v kľúčovom slove attached-trigger {}. V ňom sú vnorené samotné triggre ktorých počet je zhodný s počtom troch vnútorných bodov na každej koľajnici. Každému pomocnému bodu z tejto trojice bodov definovaných pred tým pri modelovaní v gmax je pridelený jeden trigger. Tento môže mať síce ľubovolné, ale jedinečné pomenovanie pre script.  My si ich označíme ako goods_out_t0 {}goods_out_t1 {}, goods_out_t2 {} pre body a koľaj nakladania na vlak a goods_in_t0 {}, goods_in_t1 {}, goods_in_t2 {} pre body a koľaj z ktorej sa bude vkladať vlak. V každom bode potom treba presne priradiť aj jedinečný názov konkrétneho bodu z modelu ktorý sme definovali počas modelovania za kľúčovým slovom att a pomocou identifikátora radius určíme polomer jeho pôsobenia - vplyvu na vlak.




attached-trigger {
    goods_out_t0 {
        att                    "a.track0b"
        radius                    5
    }
    goods_out_t1 {
        att                    "a.track0c"
        radius                    5
    }
    goods_out_t2 {
        att                    "a.track0d"
        radius                    5
    }
    goods_in_t0 {
        att                    "a.track1b"
        radius                    5
    }
    goods_in_t1 {
        att                    "a.track1c"
        radius                    5
    }
    goods_in_t2 {
        att                    "a.track1d"
        radius                    5
    }
}

Nakoniec config obsahuje ešte doplňujúce informácie o objekte ako celku ktoré sú predpokladám všeobecne známe a jasné.

category-region-0                        "SK"
category-era-0                           1990
username                                    "Rampa"
thumbnail                                    "screen.jpg"
author                                         "JaBr"
organisation                                "JB Software"
contact-email                              "jbsoft2@gmail.com"
contact-website                           "http://trainz.dino.sk"
license                                        "To include as a payware or fee item, you must have permission to use."


4. Script

Script je externý textový súbor bez ktorého mnohé  procesy TRS vôbec nemôžu fungovať. Využíva vlastný programovaci jazyk ktorý je dobré si naštudovať aspoň v základoch . Pretože by popis činností všetkých funkcii a syntaxu zabral viac ako jeden ďalší samostatný tútorial a keďže to je slušne popísane v dokumentácii k hre nebudem sa s tým zaoberať v detailoch ale pokúsim sa vám aspoň trocha zjednodušene priblížiť logiku fungovania a odkazov pomenovaní a väzieb z config.txt. 

include "GenericIndustry.gs"


class goodsshed_gengoods isclass GenericIndustry
{
  ProductQueue goodsOutQueue, goodsInQueue, goodsInQueue2;
  bool scriptletEnabled = true;

  int lumberWBRemain = 0;

  thread void ViewDetails(void)
  {
    if (!info)
    {
      info = Constructors.NewBrowser();
            info.LoadHTMLString(HTMLWindow.GetCompleteIndustryViewDetailsHTMLCode(me, scriptletEnabled));
    info.SetWindowRect(100, 80, 500, 545);
    }
  }


  bool TriggerSupportsStoppedLoad(Vehicle vehicle, string triggerName)
  {
    if (itc.IsTrainCommand(vehicle.GetMyTrain(), Industry.LOAD_COMMAND))
    {
      bool vehicleToTrain = vehicle.GetFacingRelativeToTrain();
      int direction = vehicle.GetRelationToTrack(me, "out_track");
      if (!vehicleToTrain)
        direction = -direction;
      if (direction == Vehicle.DIRECTION_BACKWARD and triggerName == "goods_out_t0")
        return true;
      if (direction == Vehicle.DIRECTION_FORWARD and triggerName == "goods_out_t2")
        return true;
      if (triggerName == "goods_out_t0" or triggerName == "goods_out_t1" or triggerName == "goods_out_t2")
        if (vehicle.GetMyTrain().IsStopped())
          return true;
     }
   
    if (itc.IsTrainCommand(vehicle.GetMyTrain(), Industry.UNLOAD_COMMAND))
    {
      bool vehicleToTrain = vehicle.GetFacingRelativeToTrain();
      int direction = vehicle.GetRelationToTrack(me, "in_track");
      if (!vehicleToTrain)
        direction = -direction;
      if (direction == Vehicle.DIRECTION_BACKWARD and triggerName == "goods_in_t2")
        return true;
      if (direction == Vehicle.DIRECTION_FORWARD and triggerName == "goods_in_t0")
        return true;
      if (triggerName == "goods_in_t0" or triggerName == "goods_in_t1" or triggerName == "goods_in_t2")
        if (vehicle.GetMyTrain().IsStopped())
          return true;
    }

    return false;
  }


  void PerformStoppedLoad(Vehicle vehicle, string triggerName)
  {
    if (triggerName == "goods_out_t0" or triggerName == "goods_out_t1" or triggerName == "goods_out_t2")
    {
      int available = goodsOutQueue.GetQueueCount();
      LoadingReport report = CreateLoadingReport(goodsOutQueue, available);
      vehicle.LoadProduct(report);
    }
    if (triggerName == "goods_in_t0" or triggerName == "goods_in_t1" or triggerName == "goods_in_t2")
    {
      int available = goodsInQueue.GetQueueSpace();
      LoadingReport report = CreateUnloadingReport(goodsInQueue, available);
      vehicle.UnloadProduct(report);
    }

    if (triggerName == "goods_in_t0" or triggerName == "goods_in_t1" or triggerName == "goods_in_t2")
    {
      int available = goodsInQueue2.GetQueueSpace();
      LoadingReport report = CreateUnloadingReport(goodsInQueue2, available);
      vehicle.UnloadProduct(report);
    }

  }

  thread void GoodsShedMain(void)
  {
    Message msg;

    wait()
    {
      Vehicle vehicle;
      string triggerName;
      on "Scriptlet-Enabled", "1":
      {
        if (!scriptletEnabled)
        {
          scriptletEnabled = true;
          SetProcessEnabled("goodsshed_consumer", true);
        }
        continue;
      }

      on "Scriptlet-Enabled", "0":
      {
        if (scriptletEnabled)
        {
          scriptletEnabled = false;
          SetProcessEnabled("goodsshed_consumer", false);
        }
        continue;
      }
    }
  }


  public void Init(void)
  {
    inherited();

    goodsOutQueue = GetQueue("goods_out_q");
    goodsInQueue   = GetQueue("goods_in_q");
    goodsInQueue2 = GetQueue("goods_in_q2");

    AddAssetToIndustryProductInfo("in_gen_goods", "goods_in_q", "goodsshed_consumer", true);
    AddAssetToIndustryProductInfo("in_gen_goods2", "goods_in_q2", "goodsshed_consumer", true);
    AddAssetToIndustryProductInfo("out_gen_goods", "goods_out_q", "goodsshed_consumer", false);
    GoodsShedMain();
  }

  public Requirement[] GetRequirements(void)
  {
    Requirement[] ret = new Requirement[0];

    if (goodsInQueue.GetQueueCount() < 4 or lumberWBRemain > 0) 
    {
      ResourceRequirement req = new ResourceRequirement();
      req.resource = goodsInQueue.GetProductFilter().GetProducts()[0];
      req.amount = 10;       
      if (goodsInQueue.GetQueueCount() < 2 and lumberWBRemain == 0)
        lumberWBRemain = 10;
      req.dst = me;
      req.dstQueue = goodsInQueue;
      ret[ret.size()] = req;
    }


    if (goodsInQueue2.GetQueueCount() < 4 or lumberWBRemain > 0) 
    {
      ResourceRequirement req = new ResourceRequirement();
      req.resource = goodsInQueue2.GetProductFilter().GetProducts()[0];
      req.amount = 10;       
      if (goodsInQueue2.GetQueueCount() < 2 and lumberWBRemain == 0)
        lumberWBRemain = 10;
      req.dst = me;
      req.dstQueue = goodsInQueue2;
      ret[ret.size()] = req;
    }

    return ret;
  }

  public void AppendDriverDestinations(string[] destNames, string[] destTracks)
  {
    destNames[destNames.size()] = "Naloz";
    destTracks[destTracks.size()] = "out_track";

    destNames[destNames.size()] = "Vyloz";
    destTracks[destTracks.size()] = "in_track";

  }
};

V základe treba povedať že sa jedná o bloky ohraničené s { na  začiatku a s } na jeho konci. Každý blok aj vnorený musí byť takto ohraničený pričom jeden blok je akási časť scriptu zaoberajúca sa konkrétnou úlohou, platnosťou podmienky a pod. Ako každý programovací jazyk aj tu je deklaračná časť a programová časť.
include "GenericIndustry.gs" je deklarácia gs scriptu k priemyslu od Auranu prítomného v hre. Rovnako deklarácia class goodsshed_gengoods isclass GenericIndustry je priradenie Auran triedy GenericIndustry k nami vytvorenému súboru goodsshed_gengoods cez kľúčové slovo .
Hneď za prvou zátvorkou začiatku hlavného bloku je dôležitá definícia ProductQueue goodsOutQueue, goodsInQueue, goodsInQueue2; ktorá definuje identifikátory tovarových zdrojov  pre nakládku na vlak ako goodsOutQueue a dva  goodsInQueue, goodsInQueue2 pre vykládku z vlaku. Ich pomenovanie je ľubovolné, ale musí byť jednoznačné. Na ne sa neskôr bude script odvolávať.
Blok za thread void ViewDetails(void) definuje obrazovku, dialógové okno, texty a všetko čo má niečo spoločné s komunikáciou a dialógovým nastavovaním v editore a hre.
Dôležitý je ale blok za bool TriggerSupportsStoppedLoad(Vehicle vehicle, string triggerName) kde objekt Industry.LOAD_COMMAND určuje samostatný blok čo sa má prevádzať ak príde k nakladaniu a Industry.UNLOAD_COMMAND pri vykladaní.
Všimnite si tu použitie označení z config.txt  out_track pre vstupnú koľaj a in_track pre koľaj vykladania z vlaku vo funkci vehicle.GetRelationToTrack(me, "out_track"). Ak by sme použili aj ďalšiu koľaj pre vykladanie iného ďalšieho tovaru označenú ako napr. in_track2 tak by sme ju museli pridať pravé tu ako ďalší samostatný blok do príslušného bloku UNLOAD_COMMAND. 
V bloku je použitý objekt ktorý vracia pravdu ak sedí v preklade presne smer vlaku a vlak dosiahne triger označený ako goods_in_t2  alebo goods_in_t0 čo sú ak sa pametáte krajné triggre - body na koľaji ohraničujúce jeho aktívnu časť.  Je to dôležite pre správne zastavovanie aj v závislosti od smerovania vlaku ( if (direction == Vehicle.DIRECTION_BACKWARD and triggerName == "goods_in_t2")  ). A nakoniec je v bloku if (triggerName == "goods_out_t0" or triggerName == "goods_out_t1" or triggerName == "goods_out_t2") ktoré testuje dosiahnutie niektorého z triggrov - bodov na príslušnej koľaji goods_out_t0, goods_out_t1, goods_out_t2 vlakom a stav vlaku v tom okamihu objektom if  (vehicle.GetMyTrain().IsStopped()). To iste platí a je použité aj v časti UNLOAD_COMMAND pre vykladanie avšak už pre príslušné triggre - body na vykladacej koľajnici definovanej v config.txt ako in_track a body goods_in_t0, goods_in_t1 a goods_in_t2.  V zásade by sa dalo povedať že tato celá časť je definovaná funkcia vracajúca stav pravdy alebo nepravdy  a súčasne časť zaoberajúca sa pohybom a lokalizáciou vlaku na koľaji.
Ďalšou časťou je časť zaoberajúca sa manipuláciou s tovarom zisťuje príslušné množstvo k dispozícii pre naloženie a priestor pre možné vyloženie z vlaku. Začína blokom za void PerformStoppedLoad(Vehicle vehicle, string triggerName).  Zas tu je identifikácia pozície vlaku na triggroch príslušných koľajníc goods_out_t0, goods_out_t1goods_out_t2 a zisťuje počet tovarov k dispozícii cez goodsOutQueue.GetQueueCount() kde goodsOutQueue je ak sa pamätáte deklarácia produktov z úvodu scriptu. To isté pre druhú koľaj a triggre goods_in_t0, goods_in_t1 a goods_in_t2 a miesto pre vyloženie  na začiatku deklarovaného goodsInQueue ako prvého tovaru vykládky a nakoniec aj pre druhý tovar vykládky deklarovaného na začiatku scriptu ako goodsInQueue2  na tej samej koľaji a triggrov.
Dôležitá vo vzťahu k definíciám je aj časť za public void Init(void) kde sú práve spomenutým identifikátorom priradené konkrétne identifikácie z config.txt čím vzniká medzi nimi vlastne nutná väzba. Všimnite si, že k goodsOutQueue sú priradené body pre tovar nakladaný na vlak zhrnuté pod goods_out_q v config.txt a pre goodsInQueue a goodsInQueue2 zas príslušné skupiny tovarov pod goods_in_q a goods_in_q2. Ako ďalšie nasleduje prepojenie produkcie v AddAssetToIndustryProductInfo("in_gen_goods", "goods_in_q", "goodsshed_consumer", true); kde  in_gen_goods je definícia z kuid-table v config.txt goods_in_q je definícia bodov tovaru na rampe a goodsshed_consumer je ten spomenutý "majiteľ".
Časť za public Requirement[] GetRequirements(void) slúži pre správu zásob a ak si všimnete aj tu je použité priradenie goodsInQueue a goodsInQueue2 (body tovaru - jeho stav na rampe).
Ako posledné sú dialógové a reťazcové definície začínajúce za public void AppendDriverDestinations(string[] destNames, string[] destTracks) kde sa v okne nastavenie v editore ku koľaji nakladania tovaru out_track priradí a zobrazí text v okne Naloz a ku koľaji vykladania in_track text Vyloz.
Ak ste to pochopili môžete si napísať vlastný dôslednejší a presnejší script. Ak ste to nepochopili kľudne použite tento jednoduchý základ, alebo iný. Aj tak ho ale budete musieť zmeniť ak nepoužijete navlas to iste čo je v danom objekte počnúc druhom tovaru, počtom koľajníc, pomocnými bodmi v objekte až po deklarácie  v config.txt 



5. Stručne o príprave 3D textúr pre sklad


Opäť sa vrátim k 3D textúre, ktorá je veľmi dobrou pomôckou ak nemáte vhodnú vlastnú foto-textúru a chcete ušetriť nejaký ten polygón na 3D modelovaní. Podrobne som postup popísal v samostatnom tútoriale. Tu sa iba v stručnosti zastavím u najsvietení.
Na úvod je dobré povedať že nemusíte modelovať presne rozmerovo a hĺbka okna môže byť kľudne miesto 20cm aj 2m. Ide o lepšie zvýraznenie plastičnosti a aj jednoduchšie nasvecovanie ak ste začiatočník. Treba však zachovávať aspoň aké také proporcionality celku.




Pointa nasvecovania je hlavne v použití viacerých svetiel ktoré aj vďaka dominancie niektorej farby upravia aj celkovú farbu objektu. Zmenou farby svetla a intenzity môžete dosiahnuť vcelku pekné efekty napríklad poobedňajšieho slnka ale napríklad aj veľmi efektne potlačiť prípadne chyby textúry.
Nasvecujte vždy aspoň troma svetlami. Všetky by mali smerovať skôr zhora na dol oproti objektu ako slnečné lúče v reálu. Musíte ale brať do úvah aj to či sa na objekt budete pozerať zdola, alebo zhora. Môžete tak mnohé zvýrazniť. Ak použijete tri svetlá mali by dve smerovať z protiľahlých strán, mali by ak tak zvýrazňovať pokiaľ možno každé inú farbu ale hlavne polotiene pričom tretie svetlo by malo tvoriť hlavný tvrdší tieň ktorý celú scénu dokresli. Toto tretie svetlo by teda malo dopadať aj pod nižším uhlom ako ostatné (v ose z). 



Ak používate gmax nemôžete scénu renderovať čo je ideálne pre tvorbu vlastných a dosť rozdielne čo do kvalít textúr pre rozdiel v kvalite zobrazovania. V gmax musíte scénu zosnímať a ak ju snímate bežným spôsobom musíte teda svetla rozmiestniť tak aby vám do obrázku nezavadzalo nič čo tam nemá čo hľadať. Museli by ste to neskôr pracne opravovať.



O mapovaní textúr sa rozpisovať nebudem, pretože o tom som už napísal dosť v iných tútorialoch a aj na internete či nejednej publikácii o 3D modelovaní v 3Dmax toho nájdete vôbec hodne. Spomeniem akurát prípravu textúry s odrazom. 
Na jej použitie si načítate bežným spôsobom novú základnú textúru (difuze), ktorú zadefinujete ako napríklad plech




Po nej si do tej istej textúry plech načítame do REFLECTION druhú špeciálnu textúru s leskom




Dostaneme odraz kovu na textúre ktorého intenzitu nastavíme vizuálne podľa vzorky v hornom okne, alebo priamo v percentách na 30 čo plne postačuje. Hodnota nad 30pre plech je už neprirodzená. Záleží to od základnej textúry, jej tmavosti a prirodzenej matnosti, a tiež od toho čo s ňou budeme mapovať. Viac treba dávať napríklad na tmavohnedý porcelánový izolátor ako na plech. Na hrdzavý plech sa napríklad lesk nedáva vôbec.




Doporučujem vôbec si odskúšať jednotlivé funkcie ktorými môžete dosiahnuť zaujímavé efekty a zmeny textúr.


6. Modelovanie detailného skladu

Ako doplnok našej rampy si ešte vymodelujeme pomerne detailný sklad na rampe z obdobia prelomu storočím z červených tehál. Použijeme naše vygenerované 3D textúry steny, okna a plechových vát, z internetu volne stiahnutelnú textúru eternitovej strechy, dreva na trámy a oxidovaného zinkového plechu.











V novom prázdnom projekte si z kriviek teda vymodelujte pôdorys o dĺžke 30m a šírke 8m tak ako na nasledujúcom obrázku s nosnými stopami medzi každou časťou. Podľa mňa najjednoduchší spôsob je vymodelovanie štvorca, pridanie vertexov, úprava do finálneho stavu  jednej časti aj s nosnými stĺpmi a následným klonovaním a spájaním častí v mieste spoločných vertexov potom vytvoriť celý pôdorys.




Tento pôdorys potom podobne ako rampu s funkciou EXTRUDE vytiahneme do výšky 3.5m čím vytvoríme hlavné telo skladu.
Následne si vytvorte dva jednoduché kvádre o profile dverí 2,7 m výšky a 2,5m  šírky. Dĺžka by mala byť 10m tak aby sme ho mohli presunúť cez objekt. Z neho si potom vytvoríme kópiu a pomocou boolean funkcii vytvoríme do tela skladu dva otvory. Tie budú slúžiť pre lepšie zvýraznenie 3D efektu mierne zapustených dverí a môžeme ich neskôr použiť aj pri prípadnej animácii otvárania a zatvárania dverí a viditeľného interiéru skladu.



Pokiaľ by ste nevygenerovali 3D textúru okien je môže presne takto postupovať aj u okien. Narástol by však dosť značne už aj tak dosť vysoký počet polygónov. Fantázii sa však medze nekladú.
Ako ďalšie odstránime všetky nepotrebné polygóny, teda všetky spodné a inak neviditeľné. Horné zatiaľ nechajte tak.



Ako ďalšie s jednoduchého kvádra rozdeleného na dve polovice vymodelujte nosný trám strechy, odstráňte z neho všetky nepotrebné polygóny a umiestnite na stred tak ako na obrázku.




Vzhľadom na to že ďalšie trámy budeme tvoriť klonovaním z jedného východzieho je lepšie si teraz priamo namapovať všetky textúry aby sme mapovanie neskôr nemuseli opakovať pre každý trám. Po štandartnom namapovaní textúr nakoniec trám naklonujte a umiestnite na každú rozšírenú časť jeden klon. Teraz si zvýraznite hornú časť hlavného tela skladu a odmažte všetky nepotrebné polygóny okrem krajných tak ako na obrázku.




Teraz si vyberte FACE a zvýraznite dva celkom krajné trojuholníky ktoré oddelíte od ostatku objektu.




Odmažte ostatne časti hornej strany pričom nevadí že odstránite aj hornú stranu posledného výčnelku. Je tak malá a na takom mieste, že pri bežnom pohľade si to nik ani nevšimne. Ak chcete tak ju tam samozrejme nechajte.
Zmenou hodnôt x,z a z zmeňte horný vertex oddelených trojuholníkov tak aby zapadol do trámu a spodne prirovnajte k okrajom trámu a upravte mapovanie textúry tak aby korešpondovalo so spodnou stenou.




Teraz si vytvorte jednoduchý kváder o dĺžke 32m a šírke 11m rozdeleného na dve časti. Zdvihnutím jeho horných vertexov na úroveň vrchu trámu dostanete strechu. Tú namapujte nakoniec textúrou strechy zhora a zo spodnej časti a bokov textúrou dreva. Dbajte na správnu orientáciu dreva tak aby ste minimalizovali kresbu dreva.



Ako ďalšie tiež z kvádra o hrane 0.2 x 0.2 x 32 m vytvorte rímsu. Tú môžete samozrejme vytvoriť aj z cylindrom alebo z kriviek a tak vernejšie vymodelovať rímsu ako zjednodušene z hranola. Vo svojej podstate ale hranol stačí pretože staršie odkvapy aj tak boli hranaté. Namapujte ho textúrou pozinkovaného plechu s kovovým odrazom a prisuňte k okraju strechy.  Vytvorte klon a ten premiestnite na opačnú stranu. Nakoniec odmažte zo strechy a aj rímsy spoločné vnútorné plochy, ktoré nieje vidieť.




K rímse nakoniec z cylindru - šesťuholníka - rozdeleného výškou na 5 častí vymodelujte odkvap. Ten pomocou nakláňania a posúvania vertexov vymodelujte do požadovaného tvaru a prirovnajte k rímse. Po namapovaní s rovnakou textúrou, odmazaní horných a spodných plôch vytvorte štyri klony a rozmiestnite ich na okraje ríms.



Tým máme celý sklad hotový. Otvorte si znova rampu a pomocou MERGE importujte externe vymodelovaný sklad.



Objekt je vlastne hotový. Aby však fungoval celkom aj s koncovou koľajnicou potrebujeme ešte doplniť jeden mesh.



Potrebujeme dorazovú koncovú koľaj ako neviditeľný objekt. Netreba modelovať nič zložité stačí si v gmaxe vytvoriť jeden hranol z ktorého odstránime spodný polygón a ktorý potiahneme akoukoľvek textúrou.



Musíme ho exportovať ako samostatný objekt so samostatným kuid a config.tzxt a typom ako traťový objekt mosignal.


kuid                            <kuid:XXXXX:XXXXX>
region                            "MESHE"
type                              "Invisible"
kind                               "mosignal"
function                          "TrackSignal"
buffer-speed                   40
light                                1
trackside                        0
grounded                       0.2
mesh-table {
    default {
        mesh                    "objekt.im"
        auto-create                1
    }
}
kuid-table {
}
category-class                        "WA"
asset-filename                        "objekt"
trainz-build                           2
username                              "Nev. zarazadlo"
category-region-0                  "SK"
category-era-0                        1990s

Potom stačí v hlavnom configu objektu pridať do deklarácie meshov toto zaražadlo

           doraz1 {
                kind            "attachment"
                att            "a.track1a"
                default-mesh        <kuid:XXXXX:XXXXX>
                surveyor-only        1
            }

a objekt je hotový.  Stačí ho vyexportovať do TRS a môžete ho použiť vo svojich mapách.  Celý objekt má 1379 polygónov z čoho 641 polygónov má samotná rampa vrátane schodov a nárazníkov a 738 polygónov má budova skladu. Samozrejme s menej detailmi či jednoduchším tvarom to bude aj menej polygónov a naopak.  Všade je možné aj iné riešenie. Ak napríklad nahradíte každý trám obojstrannou alfa textúrou  pri 10 trámoch (každý po 18 polygónov) teda 180 polygónov, tak ušetríte pri rovnakom počte 10 2 polygónových trámov  160 polygónov. Ak zjednodušíte 3D na časti s dverami tak ušetríte ďalších 42 polygónov. To same zjednodušením rýms, ale aj samotnej rampy napriklad odstránením extra plôch pre žlto-čierny pás a nahradením ho priamo ako súčasť textúry bočného betónu. V zásade sa kludne dostanete aj na menej ako 1/3 súčasných polygónov. Berte totiž na vedomie že všetky tútoriale su iba ukážkou jednej z možnosťí a nie udaním smeru.






8. Iné možnosti.

Ako doplnenie prvej časti tútorialu o modelovaní priemyselnej stavby s viac tovarmi by som chcel ešte spomenúť niekoľko slov o iných možnostiach.
Popíšem to pri podobným spôsobom postavenej ďalšej stavby nakladacej rampy,  ale s odlišne riešeným configom a scriptom.



Táto nakladacia rampa generuje na troch samostatných koľajniciach rôzny druh paliet s plechom. Oproti prvej stavbe je v nej pridaných niekoľko ďalších bodov na rôznych miestach na povrchu označených ako a.paleta01a.paleta30. Tieto body sú v modele vytvoré obdobne ako body pre zobrazovanie sa tovaru. Sú rozmiestnené a otáčané tak aby posobili reálne a slúžia na zobrazenie externých mesh objektov - scenery objektov - paliet s tovarom - rozložených po ploche rampy nezávislých od samotného tovaru a slúžiacich ako dekorácia scény.  K tomu treba jednak vopred vytvoriť tovar ako scenery objekt a ten následne v config.txt pridať ako mesh do sekcie  mesh-table za definíciu šipiek na koľajniciach. Parameter att určuje existujúci bod v modely gmax a default-mesh kuid objektu ktorý sa na danom mieste zobrazí.


            palet0 {
                kind            "attachment"
                att            "a.paleta01"
                default-mesh        <kuid:XXXXX:XXXXX>
            }
            palet1 {
                kind            "attachment"
                att            "a.paleta02"
                default-mesh        <kuid:XXXXX:XXXXX>
            }
            palet2 {
                kind            "attachment"
                att            "a.paleta03"
                default-mesh        <kuid:XXXXX:XXXXX>
            }
 
Do tejto časti mimochodom sa pridáva aj prípadná animácia stavby napr.

mesh-table {
    default {
        mesh                    "main.im"
        auto-create                1
        anim                    "anim.kin"
        animation-loop-speed            1
        effects {

kde anim určuje animačný súbor kin a animation-loop-speed je parameter opakovania. Treba však brať na zreteľ, že animácia je síce pekná a efektná, ale je to záťaž na váš počítač naviac. Preto jej prítomnosť pri objekte treba dôsledne zvážiť.  Podobne aj efekt dymu. Ten je namieste pri továrni, ale pri dome v letnom prevedení  sa aspoň mne zdá rovnako zbytočný.

Ďalší rozdiel oproti predchádzajúcemu modelu je v mieste definície procesov. Táto rampa totiž neprimá žiaden tovar a tovar iba generuje. A tak časť inputs bude prázdna.


processes {
    nakladkaprocess {
        start-enabled                1
        duration                    30
        inputs {
        }
        outputs {
            0 {
                amount            3
                queue            "plech_kotuc_q"
            }
            1 {
                amount            3
                queue            "plech_platy_q"
            }
            2 {
                amount            3
                queue            "plech_rury_q"
            }
        }
    }
}

Ďalší rozdiel je v samotnom modely čo do počtu bodov pre koľaje, V prvom modelu bolo pre každú koľaj použitých 5 bodov pričom tri stredné určovali pomocou triggrov manipulačnú oblasť koľaje. Tu sú pre rovnaký úsek koľaje použité iba 3 body (označené ako a.track0a, a.track0b a a.track0c pre koľaj 0 ) pričom iba stredný (a.track0b) bude mať úlohu triggra. Tento spôsob je možné použiť aj na kusový tovar kde pri nakládke, alebo vykládke vlak zastavuje, ale hlavne na sypký tovar kde vlak spomalene prechádza nakladacím, alebo vykladacím priestorom. Tu aj config.txt bude vyzerať inak v časti attached-trigger

attached-trigger {
    naklplech_kotuctrig1 {
        att                    "a.track0b"
        radius                    5
    }
    naklplech_platytrig1 {
        att                    "a.track1b"
        radius                    5
    }
    naklplech_rurytrig1 {
        att                    "a.track2b"
        radius                    5
    }
}

Dôležitý je parameter rádius. Ako som už spomenul určuje rozsah vplyvu. Ak vlak dosiahne túto oblasť (kruh okolo jeho stredu) zaberie trigger. Ak teda máte napríklad vedľa seba viac manipulačných koľají a tie sú tesne vedľa seba nesmie toto číslo byť menšie ako je ich vzdialenosť. Ak napríklad máte koľaje od seba vzdialené 2m a dáte radius 10m je viac ako isté že prechodom vlaku po jednej koľaji sa vám nechtiac môže naložiť tovar z vedľajšej koľaje ktorý naložiť ale povedzme práve  nechcete.  Niekedy sa to môže hodiť, ale obvykle nie. Preto ak staviate viac koľajové priemyselné stavby buď umiestňujte triggrové body nie v jednej rovine vedľa seba, alebo nastavte ich rádius tak aby do seba nezasahovali.





Podobne inak bude vyzerať aj gs script. Hlavný rozdiel je v časti

bool TriggerSupportsMovingLoad(Vehicle vehicle, string triggerName)
{
if (itc.IsTrainCommand(vehicle.GetMyTrain(), Industry.LOAD_COMMAND))
if (triggerName == "naklplech_kotuctrig1" or triggerName == "naklplech_platytrig1" or triggerName == "naklplech_rurytrig1" )
     return true;

if (itc.IsTrainCommand(vehicle.GetMyTrain(), Industry.UNLOAD_COMMAND))
if (triggerName == "" )
     return true;

 return false;
}

Objekt TriggerSupportsMovingLoad určuje že sa bude nakladať či vykladať bez zastavovania na rozdiel od TriggerSupportsStoppedLoad. Ďalej si všimnite že pre celú nakládku je iba jedna podmienka test pozície vlaku na triggroch pričom za každú koľaj už nie sú vymenované všetky vnútorné ale za každú koľaj jeden centrálny. No a nakoniec sekcia UNLOAD_COMMAND je prázdna.
Rozdiel je čiastočne aj v ďalšej časti


void PerformMovingLoad(Vehicle vehicle, string triggerName)
  {
 float speed = vehicle.GetVelocity();
 if (speed > -5.0f and speed < 5.0f)
 {

if (triggerName == "naklplech_kotuctrig1" )
{
  int plech_kotucavailable;
  LoadingReport plech_kotucreport;
  plech_kotucavailable = plech_kotucQueue.GetQueueCount();
  plech_kotucreport = CreateLoadingReport(plech_kotucQueue,plech_kotucavailable);
  direction = vehicle.GetRelationToTrack(me, "naklplech_kotuc");
  if (direction == Vehicle.DIRECTION_FORWARD)
     plech_kotucreport.sideFlags = LoadingReport.LEFT_SIDE;
  else if (direction == Vehicle.DIRECTION_BACKWARD)
     plech_kotucreport.sideFlags = LoadingReport.RIGHT_SIDE;
  vehicle.LoadProduct(plech_kotucreport);
}

if (triggerName == "naklplech_platytrig1" )
{
  int plech_platyavailable;
  LoadingReport plech_platyreport;
  plech_platyavailable = plech_platyQueue.GetQueueCount();
  plech_platyreport = CreateLoadingReport(plech_platyQueue,plech_platyavailable);
  direction = vehicle.GetRelationToTrack(me, "naklplech_platy");
  if (direction == Vehicle.DIRECTION_FORWARD)
      plech_platyreport.sideFlags = LoadingReport.LEFT_SIDE;
  else if (direction == Vehicle.DIRECTION_BACKWARD)
      plech_platyreport.sideFlags = LoadingReport.RIGHT_SIDE;
   vehicle.LoadProduct(plech_platyreport);
}

if (triggerName == "naklplech_rurytrig1" )
{
  int plech_ruryavailable;
  LoadingReport plech_ruryreport;
  plech_ruryavailable = plech_ruryQueue.GetQueueCount();
  plech_ruryreport = CreateLoadingReport(plech_ruryQueue,plech_ruryavailable);
  direction = vehicle.GetRelationToTrack(me, "naklplech_rury");
  if (direction == Vehicle.DIRECTION_FORWARD)
      plech_ruryreport.sideFlags = LoadingReport.LEFT_SIDE;
  else if (direction == Vehicle.DIRECTION_BACKWARD)
      plech_ruryreport.sideFlags = LoadingReport.RIGHT_SIDE;
  vehicle.LoadProduct(plech_ruryreport);
   }
  }
}

kde je na začiatku časť vzťahu k príjazdovej rýchlosti a neskôr pre každú manipulačnú koľaj a hlavne každý jedinečný trigger na nej, sekcia testu množstva tovaru k dispozícii ako v predošlom scripte s však inak využitým smerovaním vlaku a podľa toho určením aktívnej strany - plech_ruryreport.sideFlags = LoadingReport.LEFT_SIDE,
alebo plech_ruryreport.sideFlags = LoadingReport.RIGHT_SIDE
v spojitosti s nakladaním v  vehicle.LoadProduct(plech_ruryreport)




Ďalšou možnosťou je použitie tiež jedného triggra na každej koľaji, ale so zastavovaním vlaku na ňom. Je použitý v ďalšom rozšírenom modelu predošlej stavby kde je naviac pridaná jedna koľaj na ktorej sa z vlaku vykladajú prázdne palety.



Rozdiel v configu je hlavne v pridaných definíciách novej koľajnice pre vykládku paliet v sekcii attached-track {}

    kolajvykl_paliet {
        track                    <kuid:-1:15>
        vertices {
            0                "a.track3a"
            1                "a.track3b"
            2                "a.track3c"
            3                "a.track3d"
            4                "a.track3e"
        }
    }

v sekcii queues {} pridané body z modelu kde sa bude zobrazovať tovar.

    prazdne_palety_q {
        size                    30
        initial-count                15
        product-kuid                <kuid:XXXXX:XXXXX>
        attachment-points {
            0                "a.prazdne_palety01"
            1                "a.prazdne_palety02"
            2                "a.prazdne_palety03"
            3                "a.prazdne_palety04"
            4                "a.prazdne_palety05"
            5                "a.prazdne_palety06"
            6                "a.prazdne_palety07"
            7                "a.prazdne_palety08"
            8                "a.prazdne_palety09"
            9                "a.prazdne_palety10"
            10                "a.prazdne_palety11"
            11                "a.prazdne_palety12"
            12                "a.prazdne_palety13"
            13                "a.prazdne_palety14"
            14                "a.prazdne_palety15"
            15                "a.prazdne_palety16"
            16                "a.prazdne_palety17"
            17                "a.prazdne_palety18"
            18                "a.prazdne_palety19"
            19                "a.prazdne_palety20"
            20                "a.prazdne_palety21"
            21                "a.prazdne_palety22"
            22                "a.prazdne_palety23"
            23                "a.prazdne_palety24"
            24                "a.prazdne_palety25"
            25                "a.prazdne_palety26"
            26                "a.prazdne_palety27"
            27                "a.prazdne_palety28"
            28                "a.prazdne_palety29"
            29                "a.prazdne_palety30"
            30                "a.prazdne_palety31
            31                "a.prazdne_palety32"
            32                "a.prazdne_palety33"
            33                "a.prazdne_palety34"
            34                "a.prazdne_palety35"
        }
    }

v
v sekcii processes {} pridaný príjem paliet

        inputs {
            0 {
                amount            6
                queue            "prazdne_palety_q"
            }
        }

tak isto v sekcii attached-trigger {} bude pridaný aj trigger pre novú koľaj

    prazdne_paletytrig1 {
        att                    "a.track3b"
        radius                    10
    }

a nakoniec časť  string-table {} v ktorej sa definujú dialógove a komunikačné reťazce textov. Konkrétne ponuka v rolovacom menu koľají stavby.

string-table {
    container_naklplech_kotuc                       "Nakladka kotuc plechu"
    container_naklplech_platy                         "Nakladka platy plechu"
    container_naklplech_rury                          "Nakladka rury plechu"
    container_prazdne_palety                          "Vykladka prazdnych paliet"
}

Hlavný rozdiel v scripte je v definícii nakladania a vykladania pri zastavení vlaku a v definícii nielen nakladania na vlak ale aj vykladania prázdnych paliet.

  bool TriggerSupportsStoppedLoad(Vehicle vehicle, string triggerName)
  {
    if (itc.IsTrainCommand(vehicle.GetMyTrain(), Industry.LOAD_COMMAND))
      if (triggerName == "naklplech_kotuctrig1" or triggerName == "naklplech_platytrig1" or triggerName == "naklplech_rurytrig1")
        return true;
    if (itc.IsTrainCommand(vehicle.GetMyTrain(), Industry.UNLOAD_COMMAND))
      if (triggerName == "prazdne_paletytrig1")
        return true;
    
    return false;
  }


Ak budete mať otázky kľudne mi pošlite email.



Všetky použité a popísané objekty je možné si stiahnúť v sekcii download.