-
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 )