-
Notifications
You must be signed in to change notification settings - Fork 0
globalFunctions
![]() EN PL |
Funkcje globalne w m4nfo mogą być używane ze wszystkimi funkcjami TTD (pojazdy, stacje, domy, ...). Służą do sprawdzania rzeczywistych danych gry w łańcuchu kontrolnym:
| Funkcja | Opis |
|---|---|
| anim_counter([<shiftmask>,] <block>) | Ogólny licznik animacji, zwiększany przy każdym takcie gry |
| calculate(<expression>, <block>) | Szacuje wyrażenia |
| cargotranslationtable(<List::Label>) | Tabela translacji ładunków |
| getparameter(<parameter>, [<shiftmask>,] <block>) | Odczyt parametru newGRF |
| current_climate(<block>) | Current climate (1 == TEMPERATE, 2 == ARCTIC, 4 == TROPIC, 8 == TOYLAND) |
| date(<block>) | Bieżąca data (liczona jako dni od 1920 r.) |
| dayofmonth(<block>) | Dzień miesiąca (0 .. 30) |
| dayofyear(<block>) | Dzień roku (0… 364, 'odp.' 0… 365) |
| game_level(<block>) | Poziom trudności gry (0 == easy, 1 == medium, 2 == hard, 3 == custom) |
| game_mode(<block>) | Tryb gry (0 == title screen, 1 == in game, 2 == in editor) |
| leapyear(<block>) | Rok przestępny (1 == YES, 0 == NO) |
| month(<block>) | Obecny miesiąc (jan == 1 .. dec == 12) |
| railtypetranslationtable(<List::Label>) | Tabela translacji typu szyny |
| snowline(<block>) | Wysokość linii śniegu, 0xFF, jeśli śniegu w ogóle nie ma |
| call(<reference>, <registers>, <block>) | Funkcje, procedury, podprogramy |
| proc(<reference>, <head>, <block>) | |
| setregbase(<register>) | |
| subroutine(, ) | |
| trafficside(<block>) | Strona ruchu drogowego (1 == right, 0 == left) |
| year(<block>) | Bieżący rok liczony od 1920 roku |
Ta funkcja pozwala na ocenę wyrażeń złożonych z funkcji wydajnościowych, liczb zwykłych i operatorów. Służy do łączenia kilku wyników funkcji przed podjęciem decyzji.
| calculate(<expression>, <block>) <expression> ::= "{" <term> <operator> <term> {<operator> <term>} "}" <term> ::= <function> | <number> |
<operator> może mieć następujące wartości:
| Operator | Opis |
|---|---|
| + | Dodanie a[*] + b |
| - | Odejmowanie a - b |
| MIN | Minimum (a, b), 'bez znaku' |
| MAX | Maximum (a, b), unsigned |
| SMIN | Minimum (a, b), 'ze znakiem' |
| SMAX | Maximum (a, b), signed |
| / | Dzielenie a / b, unsigned |
| MOD | Modulo a % b, unsigned |
| S/ | Division as above, signed |
| SMOD | Modulo jak wyżej, sygn |
|
|
Mnożenie a * b, wynik zostanie obcięty do Byte/Word/Dword |
| AND | Bitowo a AND b |
| OR | Bitowo a OR b |
| XOR | Bitowo a XOR b |
| CMP | Porównanie; wynik jest "0" if a < b, "1" if a == b and "2" if a > b, obie wartości bez znaku |
| SCMP | Jak wyżej, ale obie wartości są 'signed' |
| ROR | Rotuj pozycje a na b w prawo, zawsze 32-bitowa rotacja |
| << | Przesuń a o b pozycje w lewo, b powinno być w zakresie 0 .. 31 |
| >> | Przesuń a o b pozycje w prawo, bez znaku; b powinno mieścić się w zakresie 0 .. 31 |
| S>> | Przesuń a na b pozycje w prawo, ze znakiem; b powinno mieścić się w zakresie 0 .. 31 |
<function> może być dowolną niestandardową[*] funkcją wydajnościową, funkcjami globalnymi subroutine() i getparameter() lub następującymi funkcjami specjalnymi:
| Funkcja | Opis |
|---|---|
| store(<Byte>) | przechowywać wartość w rejestrze tymczasowym |
| register(<Byte>) | wartość dostępu z rejestru tymczasowego |
[*] Na przykład, zobacz tutaj dla trains
Przykład 1 (vehicle aging):
def(0x20) calculate({date() - lastmaintenance() * 100 / servint()},
engine(
ref(16) if(word(0) .. 12) // light: 00 .. 12%
ref(17) if(13 .. 25) // normal: 13 .. 25%
ref(18) if(26 .. 50) // dark: 26 .. 50%
ref(19) else // very dark: > 50%
)
)
Przykład 2 (push/pull: checking foreign vehicles):
def(11) calculate({idcount(_A80D,) + idcount(_MR,) - veh_num()},
engine(
ref(8) if(1) // no foreign vehicles except trailer
cbr(0) else // foreign vehicles
)
)
Przykład 3 (automatic change of light):
def(LIGHTS) calculate({veh_posabs(BACK,) SMIN 1 * 4 store(0)
veh_posabs(FRONT,) SMIN 1 * 2 OR register(0) store(0)
veh_num() SMIN 1 OR register(0)},
ref(5) if(0) // single forward/backward
ref(6) if(5) // head forward/backward
ref(7) if(3) // tail forward/backward
ref(LI_OFF) else // no lights at all
)
Przykład 4 (setting callback result from newGRF parameter 1):
// LVST, BDMT, FICR := 150/300/450/600
def(0x74, __newcapacity) calculate({getparameter(1,) * 150},
cbfail() else
)
...
// livestock, building materials, fibre crops
def(5) callback(
ref(__newcapacity) if(CB_RCAP)
cbr(15) if(CB_LOAD)
ref(0) else
)
Należy odnotować, <expression> musi być zawsze cytowane, a funkcjom wydajnościowym należy nadać poprawną liczbę parametrów (z wyłączeniem parametru <block>), aby uniknąć niepotrzebnych komunikatów o błędach m4nfo. Zobacz przykład 2.
getparameter(<parameter>, [<shiftmask>,] <block>)Ta funkcja odczytuje parametr aktualnego newGRF (jeśli jest podany). Wynikiem może być wartość Byte lub Word i można nim manipulować za pomocą funkcji pomocniczej shiftmask() . Jest również dostępny na liście zakupów. Zobacz przykład 4 powyżej.
Ta funkcja odczytuje parametr bieżącego newGRF (jeśli został podany). Wynikiem może być wartość Byte lub Word i może być manipulowana przez funkcję pomocniczą shiftmask(). Jest również dostępny na liście zakupów. Patrz przykład 4 powyżej.
subroutine(<reference>, <block>)Ta funkcja stanowi wywołanie podprogramu, przy czym pierwszy podany parametr jest używany jako odniesienie do podprogramu.
Sam podprogram (który może składać się z normalnego łańcucha lub funkcji specjalnej) musi dostarczyć swój wynik (y) jako wynik (y) wywołania zwrotnego, które mogą być użyte jako normalne wartości z bloku funkcyjnego wywołującego podprogram, patrz przykłady.
Korzystanie z podprogramów jest najbardziej przydatne wewnątrz funkcji calculate() , ale może być również używane w opłacalny sposób z dowolnego punktu w łańcuchu kontroli.
Przykład (using subroutines): define(SLOPE_WATER,200) // using a very high c-ID // return values: // 0 - flat, no slope // 1 - slope NW, no water in front // 2 - slope SE, no water in front // 3 - slope NW, water in front // 4 - slope SE, water in front def(10) tinfo_waterclass(position(0,1), cbr(1) if(WC_LAND) // no water in front cbr(3) else // water ) def(11) tinfo_waterclass(position(0,-1), cbr(2) if(WC_LAND) // no water in back cbr(4) else // water ) def(SLOPE_WATER) tinfo_slope(position(0,0),shiftmask(0,NORTH+WEST+SOUTH+EAST), ref(10) if(NORTH+WEST) // slope, check water tile front ref(11) if(SOUTH+EAST) // slope, check water tile back cbr(0) else // flat ) ... def(1) subroutine(SLOPE_WATER, cbr(0) if(4) // access to water cbr(58) else // no water access, fence )call(<reference>, <registers>, <block>)
W m4nfo sparametryzowane funkcje/procedury są zbudowane na funkcji calculate() m4nfo i wykorzystaniu rejestrów. W rzeczywistości wszystkie używane parametry są mapowane na rejestry, które muszą być wcześniej określone za pomocą funkcji setregbase(), definiującej pierwszy rejestr zakresu rejestrów, który ma być używany.
Tylko funkcje wydajności z "rzeczywistymi" parametrami (z REGISTER jako alternatywnym parametrem; opartym na nfo 60+x vars) mogą być używane w ten sposób w rozsądny sposób, patrz tabela poniżej. Używając funkcji wydajności bez parametrów, funkcja proc() powróci do swojej podstawowej funkcjonalności calculate().
| TTD Feature | nfo var | Functions |
|---|---|---|
| vehicles | 60 | idcount() |
| 62 | veh_straight() | |
| stations | 60 | cargowaiting() |
| 66 | anim_frame() | |
| 67 | tinfo_flatwater(), ~grfid(), ~height(), ~lclass(), ~slope(), ~terrain(), ~water(), ~waterclass() | |
| 68 | tinfo_statid() | |
| 69 | cargohist() | |
| houses | 61 | typecount(), classcount() |
| 62 | houseinfo_height(), ~lclass(), ~slope(), ~terrain(), ~water(), ~waterclass() | |
| 63 | anim_frame() | |
| 64 | cargohist() | |
| 65 | findhouse() | |
| 66 | houseinfo_id(), houseinfo_class() | |
| 67 | houseinfo_grfid() | |
| objects | 60 | objinfo_view(), ~type(), ~typeview() |
| 61 | objinfo_randombits() | |
| 62 | objinfo_height(), ~lclass(), ~slope(), ~terrain(), ~water(), ~waterclass() |
Każda parametryzowana funkcja/procedura jest definiowana przez funkcję proc(), która jest po prostu specjalnym opakowaniem dla metody calculate() i przyjmuje jako swój pierwszy parametr rejestr, który ma być użyty dla parametru funkcji/procedury. Drugi parametr proc() implementuje funkcję/procedurę, tj. cytowany zestaw instrukcji do wykonania, w taki sam sposób jak w przypadku funkcji calculate(). Zobacz przykłady poniżej. Trzeci parametr proc() jest zwykłym blokiem funkcjonalnym.
Teraz sparametryzowane funkcje/procedury mogą być wywoływane w późniejszym czasie przez function call(), którego pierwszym parametrem jest odwołanie/nazwa funkcji/procedur, które mogą być połączone w zwykły sposób. Drugi parametr call() jest listą wartości parametrów, które mają być odwzorowane na danym parametrze (parametrach) w sposób sekwencyjny, patrz przykłady. Trzecim parametrem call() jest zwykły blok funkcyjny.
Podobnie w przypadku podprogramów, sparametryzowane funkcje/procedury muszą zwracać swoje ostateczne wyniki jako wywołania zwrotne, używając funkcji cbr().
setregbase(<register>)Ta funkcja definiuje pierwszy z rejestrów, który ma być użyty w kombinacji funkcji proc()/call(). Jeśli ma być użyty więcej niż jeden parametr (zdefiniowany przez wywołanie funkcji call()), rejestry będą definiowane jako kolejny zakres, zaczynając od tego właśnie parametru.
Przykład (użycie 1 parametru):
setregbase(7) // Rejestry do użycia: 7
def(1) proc(7, {tinfo_statid(REGISTER,) AND 0x800},
cbr(2) if(0x800)
cbr(1) else
)
def(2) proc(7, {tinfo_statid(REGISTER,) AND 0xFF},
ref(1) if(MODULAR_LOW .. MODULAR_HIGH)
cbr(0) else
)
def(3, building_nearby) proc(7, {tinfo_grfid(REGISTER,) AND 0xFF},
ref(2) if(label(GRFID_PART1))
cbr(0) else
)
def(4) call(building_nearby, 0xFF,
cbr(7) if(1, 2)
cbr(8) else
)
Przykład (użycie 2 parametrów):
setregbase(7) // rejestry do wykorzystania: 7, 8
def(8) proc(7, {anim_frame(REGISTER,)},
cbr(0) if(0)
cbr(1) else
)
def(9, FRAME) proc(8, {tinfo_tracktype() AND tinfo_terrain(REGISTER,)},
ref(8) if0)
cbr(1) else
)
def(10) call(FRAME, {pos(-1,1), SNOW},
ref(1) if(0)
ref(2) if(1)
ref(3) else
)
