Skip to content

globalFunctions

extrazi edited this page Jun 25, 2023 · 6 revisions
original    original
EN     PL

Manual M4nfo

Funkcje globalne

Korzystanie z funkcji globalnych

Introduction

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

Opis

calculate

calculate(<expression>, <block>)
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.

Format

calculate(<expression>, <block>) <expression> ::= "{" <term> <operator> <term> {<operator> <term>} "}" <term> ::= <function> | <number>

Opis

<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
[*] a jest wartością wynikającą z bieżącego okresu, a b jest wartością wynikającą z następnego okresu.

<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
Nie ma pierwszeństwa operatora, wszystkie terminy w wyrażeniu są przetwarzane od lewej do prawej.

[*] Na przykład, zobacz tutaj dla trains

Examples

 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

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.

Funkcje, procedury, podprogramy

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

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

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

proc

proc(<register>, <head>, <block>)

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

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
 )
Clone this wiki locally