Skip to content

flowOfControl

extrazi edited this page Jul 1, 2023 · 17 revisions
original    original
EN     PL

Manual użytkownika m4nfo i Raport Techniczny

Flow of control

Przebieg kontroli parametrów i obsługi parametrów

Content

Introduction
Ten rozdział dotyczy "przepływu kontroli" w newGRF. Ogólnie rzecz biorąc, istnieje jeden "łańcuch" dla każdego ID funkcji TTD (pojazdy, stacje, domy, ...), łączący funkcję aktywacji ID (makevehicle(), makestation(), ...) z jego graficznymi ikonkami i/lub wartości właściwości. Zobacz także tutaj, aby zobaczyć przykład . W m4nfo łańcuchy te składają się z "bloków" funkcyjnych, które w zwykłym nfo odpowiadają wartościowaniu tak zwanego "pseudosprite" . Takie łańcuchy mogą być dość długie i zawierać wiele decyzji pośrednich, opartych na danych lub generowanych losowo, a także mogą zawierać "wywołania zwrotne", specjalne funkcje, które są "wywoływane" w celu modyfikacji różnych właściwości, na przykład wpływ pojazdów kolejowych.

Na przykład, rysunek po lewej stronie przedstawia łańcuch sterowania z jego różnorodnymi blokami funkcyjnymi (callback(), cargo(), getubits(), year(), yearbuilt() ) dla silnika wysokoprężnego DB Set V200. Jak widać, przepływ kontroli rozgałęzia się również wzdłuż łańcucha, wyświetlając "drzewo" ('do góry nogami'), z każdym jego liściem kończącym się "wynikiem wywołania zwrotnego" (cbr) lub 'real sprite' (grafika).

Functions for flow of control

Funkcja Opis
def( [,]) Zdefiniuj odniesienie
ref(<Byte> | <Label>) Odniesienie do funkcji
deflabel() Zdefiniuj etykietę gałęzi
placelabel() Umieść etykietę 'gałęzi'
getothergrfparameter(<target-param>, <grf-ID>, <grf-param> | VERSION) Odczytaj parametr innego newGRF
pcalc(<expression>) Przypisz nowe parametry GRF i oblicz wyniki
setparameter(, ) / setparameterbits(, ) Ustaw wartość parametru / bity dla tego nowego GRF
skip(<Byte>) Bezwarunkowo pomiń tę liczbę sprite'ów
skipif(, , , ) Zmień przepływ kontroli
getowngrfparameter() Pobierz parametr dla tego newGRF
patchvar() Użyj flagi TTDPatch jako zmiennej dla skipif()
reflabel() Odniesienie do etykiety oddziału
setbit() Ustaw bit w parametrze
Opis

def(<Byte> [,<Label>]) / ref(<Byte> | <Label>)

Funkcje def() i ref() są implementacją 'łańcuchowania' zwykłego nfo w m4nfo. Funkcja def() definiuje odniesienie do funkcji m4nfo, która ma być połączona w 'łańcuch', a funkcja ref() odwołuje się do funkcji m4nfo. Obie funkcje są specjalnymi funkcjami m4nfo (nie zawierają bloku funkcyjnego), ale po prostu śledzą łańcuchowe odniesienia, stanowiące 'przepływ kontroli' w nowym kodzie GRF. Zobacz tutaj, aby uzyskać dogłębną dyskusję .

Prośba odnotowania, że referencje mogą być 'etykietowane', a nawet 'szablonowane' przez funkcje makr m4nfo.
 Przykład (etykietowane referencje):
 def(0xB0, FP_RHEIN) callback(
 	ref(6) if(CB_LOAD) // ilość załadunku
 	ref(3) if(CB_RCAP) // pojemność
 	ref(4) if(CB_TSFX) // text suffix
 	ref(5) else        // graphics
 )
 
 ...
 
 // mail
 def(3) yearbuilt(
 	ref(FP_RHEIN) if(1928 .. 1940) // Rheingold refit
 	ref(FP_) else          	       // generic
 )
Należy pamiętać, że nadmierne etykietowanie może spowodować, że źródło będzie nieczytelne i nie będzie działać poza granicami plików. Ponadto ze względów bezpieczeństwa etykiety są 'jednorazowe', a w rzadkich przypadkach, gdy zachodzi potrzeba przedefiniowania etykiety, należy ją cytować w zwykłych nawiasach klamrowych.

deflabel(<String>)

Ta funkcja definiuje rozgałęzioną etykietę w newGRF, tj. Normalny przepływ sterowania jest modyfikowany przez funkcję reflabel() wewnątrz funkcji skipif(), aby kontynuować w miejscu, w którym ta sama etykieta zostanie umieszczona . Zobacz przykład poniżej.

Parametr tej funkcji, a także parametrów placelabel() i reflabel() jest ciągiem tekstowym, który można dowolnie wybrać. Jest wewnętrznie tłumaczony na unikalny identyfikator o rozmiarze bajtu, stąd tylko 255 różnych etykiet jest dozwolonych w nowym pliku GRF.

Używanie etykiet skoku to jedyny sposób na pominięcie więcej niż 255 'sprites' naraz. Parametr <num-skip> skipif() pozwala tylko na ustawienie 255 elementów.

W rzadkich przypadkach, gdy chcesz użyć etykiet skoku w rozproszonych plikach źródłowych, jest to możliwe w ograniczony sposób. Zobacz przykład w sekcji dotyczącej obsługi tekstu.

placelabel(<String>)

Ta funkcja umieszcza etykietę rozgałęzienia w określonym miejscu w newGRF. Zobacz przykład poniżej .

getothergrfparameter(<target-param>, <grf-ID>, <grf-param> | VERSION)

Ta funkcja odczytuje podany parametr innego newGRF i zapisuje go do podanego parametru docelowego. W przypadku podania VERSION jako innego parametru newGRF, zwracane jest version newGRF, podane w funkcji grfinit() . W przypadku, gdy numer wersji nie został ustawiony dla tego newGRF, zwracane jest 0 (tylko OpenTTD).

pcalc(<expression>)

Funkcja ta pozwala na ustawienie wartości parametrów newGRF (tj. Tych zwykle ustawianych jako opcje w pliku newgrf(w).cfg ), a także na wykonywanie na nich operacji matematycznych. </p>

Format
pcalc(<target> := <source1> [<operator> <source2>])
Dane wyglądają następująco:
<target> - parametr docelowy
<operator> - obliczenia do wykonania
<source1> - pierwszy argument
<source2> - drugi argument

Opis

<target, source1, source2>

Te argumenty określają parametry docelowe i źródłowe. Mogą to być parametry newGRF, zdefiniowane przez funkcję pomocniczą grfparameter() lub specjalne zmienne używane w funkcji skipif() , patrz opis tam. Ponadto argumenty <source> mogą być prostymi wartościami liczbowymi.

<operator>

Operacja do wykonania na argumentach źródłowych. Wynik tego obliczenia zostanie zapisany w parametrze docelowym.
Operator Operacja Wynik
:= Przypisanie target := source1
+ Dodanie target := source1 + source2
- Odejmowanie target := source1 - source2
* Mnożenie bez znaku target := source1 * source2
S* Mnożenie 'ze znakiem'
<< Przesunięcie bitu 'bez znaku' target := source1 << source2 if source2>0, or target = source1 >> abs(source2) if source2 < 0. source1 jest uważane za bez znaku
S<< Przesunięcie bitu ze znakiem tak samo jak 05, ale source1 jest uważane za 'ze znakiem
AND Bitowo AND target := source1 AND source2
NOT Bitowo NOT target := NOT source1
OR Bitowo OR target := source1 OR source2
/ Dzielenie bez znaku target := source1 / source2
S/ Signed division
MOD Unsigned modulo target := source1 % source2
SMOD Signed modulo

param(<Byte>)

Ta funkcja pomocnicza jest potrzebna do zdefiniowania parametrów, które mają być używane w pcalc() . Zobacz przykłady.

Notes
Parametr jest traktowany jako zdefiniowany, jeśli zachodzi którakolwiek z poniższych sytuacji: nadano mu dowolną wartość w liście parametrów newgrf(w).cfg; lub parametr o wyższym numerze został ustawiony na dowolną wartość przez wcześniejsze wywołanie funkcji pcalc().

Jeśli na przykład parametr(0) i parametr(1) są ustawione w pliku newgrf(w).cfg, a pcalc() ustawia parametr(4), to parametr(2) i parametr(3) zostaną automatycznie zdefiniowane i uzyskać wartość zero.

Przykłady
Przykład: ustawienie parametrów, które mają być używane w obliczeniach linii śniegu:
 define(SLOW,2) // min snowline
 define(SHI,8)  // max snowline 
    // define named parameters
define(max_height, param(0)) define(min_height, param(1))
 define(diff, param(2))
 define(step, param(3))
    pcalc(min_height := eval(SLOW * 8)) // snowline is multiple of 8
    pcalc(max_height := eval(SHI * 8))    // ditto


    pcalc(diff := max_height - min_height)
    pcalc(step := diff / 12)
 ...

setparameter(<Byte>, <Dword>) / setparameterbits(<Byte>, <Dword>)

Ta funkcja ustawia dany parametr newGRF na wartość odpowiednio do wzorca bitowego podanego przez drugi parametr. Jest najbardziej przydatny do zarządzania parametrami zdefiniowanymi-przez-użytkownika , ale także do sprawdzania dostępności określonego nowego GRF, lub innych rzeczy związanych z parametrami:
Przykład: ustawianie i odczytywanie bitów parametrów:

skipif(6,CLIMATE,==,TEMPERATE) // skip if temperate

// not temp, now check for AlpineClimate active?
skipif(2,GRFACTIVE,+,GRF_ALPINESET)


// not temp, check for AlpineClimate inactive but will be activated? 
skipif(1,GRFACTIVE,-+,GRF_ALPINESET)


skip(EXIT) // neither temp nor alpineclimate 



setparameterbits(2,_ALPINE) // mark it

 skipif(1,getowngrfparameter(2),BITSET,_ALPINE)
skip(EXIT) // Parameter not set


...

 skipif(1,getowngrfparameter(2),BITSET,_ALPINE)
definevehicle(_SELF2, {""},
 	cargotype(COAL)
 ) 
Odnotacja , że funkcja setparameterbits() ustawia tylko określone bity w parametrze docelowym. Nie modyfikuje nieokreślonych bitów. W takich przypadkach będziesz musiał użyć funkcji setparameter() , tj. Ustawić parametr z wartością/liczbą.

skipif(<Byte>, <variable>, <condition>, <Word> [, <Word>])

Ta funkcja pozwala na pominięcie określonej liczby elementów w łańcuchu kontroli (zwykle funkcji) w pliku newGRF. Można to wykorzystać na przykład do wyświetlania grafiki specyficznej dla klimatu, sprawdzania wersji TTDPatch i komunikatów o błędach lub dezaktywacji w obecności innych aktywnych plików newGRF.

Parametry są następujące:
Parametr Opis
<num-skip> Liczba elementów do pominięcia
<variable> Na której zmiennej należy podjąć decyzję
<condition> Jaki stan sprawdzić
<value> Wartość do porównania
<mask> Maska bitowa używana podczas porównywania wartości

num-skip

Ten parametr określa, ile elementów zostanie pominiętych, jeśli <condition> jest prawdziwy. Jeśli <num-skip> jest ustawione na EXIT, cała reszta pliku newGRF zostanie pominięta, w przeciwnym razie dokładnie tyle elementów zostanie pominiętych. Jeśli to spowoduje pominięcie grf_init() , plik newGRF zostanie uznany za nieaktywny.

Jeśli <condition> ma wartość false, przetwarzanie jest kontynuowane w następnym elemencie.

Począwszy od TTDPatch 2.0.1 alpha 49, można przeskoczyć do określonej pozycji w pliku newGRF poprzez zdefiniowanie "etykiet" za pomocą funkcji deflabel() . Jeśli parametr <num-skip> jest ustawiony na etykietę przez funkcję reflabel() , znajdującą się gdzieś w pliku newGRF, to przetwarzanie pliku newGRF zostaje wznowione z elementem następującym po tej etykiecie, zamiast pomijania tylu elementów. Tylko w ten sposób można pominąć więcej niż 255 elementów naraz.

Od wersji 2.0.1 alfa 70 zduplikowane etykiety są w pełni obsługiwane. Skok będzie zawsze do pierwszej pasującej etykiety, która następuje. Jeśli nie nastąpi żadna pasująca etykieta, zamiast niej zostanie użyta pierwsza pasująca etykieta w pliku newGRF.
Note:

Zwykle nie jest bezpieczne przeskakiwanie do tyłu, tj. Do wcześniejszej pozycji w pliku newGRF. Chociaż TTDPatch z radością to zrobi, otrzymasz dziwne wyniki, jeśli pewne funkcje zostaną powtórzone przez taki skok.

zmienna

Ten parametr ustawia zmienną, na której będzie opierać się decyzja. Może to być jeden z parametrów newGRF, za pomocą funkcji getowngrfparameter() lub wbudowanej zmiennej TTDPatch, patrz tabela poniżej. Jeśli jest to parametr newGRF, który nie został określony w pliku newgrf(w).cfg, lub zmienna GRFACTIVE z nowymGRF-ID, który nie istnieje, skok jest ignorowany i żadne elementy nie są pomijane, jedynym wyjątkiem jest typ warunku "--" , który pominie elementy, jeśli newGRF-ID również nie istnieje.
Zmienna Opis
CLIMATE Obecny klimat
WINDOS TTD version, "DOS" lub "WIN"
PLATFORM TTDPatch ("TTDPATCH") lub OpenTTD ("OTTD")
TTDPATCHVERSION TTDPatch version
OTTDVERSION OpenTTD version
FLAGS flagi TTDPatch (lub TTDPatchFlags)
MULTIHEAD
STARTYEAR
NEWTRAINS
NEWRVS
NEWSHIPS
SIGNALSONTRAFFICSIDE
ELECTRIFIEDRAILWAY
BUILDONSLOPES
NEWSTATIONS
BUILDONCOASTS
CANALS
FREIGHTTRAINS
NEWHOUSES
SPEEDLIMIT
PBSIGNALLING
NEWINDUSTRIES
TEMPSNOWLINE
NEWCARGOS
NEWSOUNDS
TRAMS
SHORTRVS
ARTICULATEDRVS
DYNAMIC
VARRUNNINGCOST
GRFACTIVE Sprawdza, czy nowyGRF-ID jest aktywny, czy nie
CARGO Sprawdza, czy typy ładunku jest dostępny, czy nie
RAILTYPE Sprawdza, czy typ szyny jest dostępny, czy nie

condition

Ten parametr definiuje warunek, który ma być używany do oceny skipif() . Do wyboru jest kilka warunków (patrz przykłady zastosowania poniżej):
'Warunek' Opis
BITSET Sprawdź bit podany przez ustawianą wartość
BITCLR Sprawdź, czy bit podany przez wartość jest czysty
== Parametr jest równy wartości
!= Parametr nie jest równy wartości
< Parametr jest mniejszy niż wartość
> Parametr jest większy niż wartość
+ GRF-ID jest aktywny (tylko dla zmiennej GRFACTIVE)
- GRF-ID nie jest aktywny (tylko dla zmiennej GRFACTIVE)
-+ GRF-ID nie jest jeszcze aktywny, ale zostanie aktywowany (tylko dla zmiennej GRFACTIVE)
++ GRF-ID jest lub będzie aktywne (tylko dla zmiennej GRFACTIVE)
-- GRF-ID nie jest i nie będzie aktywne (tylko dla zmiennej GRFACTIVE)
+ Typ ładunku jest dostępny (zmienna jest ignorowana; wartością jest etykieta)
- Typ ładunku jest niedostępny (zmienna jest ignorowana; wartością jest etykieta)
+ Zdefiniowano etykietę typu szyny (zmienna jest ignorowana; wartością jest etykieta)*
- Etykieta typu szyny nie jest zdefiniowana (zmienna jest ignorowana; wartością jest etykieta)*
  • Dostępne tylko w OpenTTD

value

Z tym parametrem porównuje się zmienną. Jego rozmiar zależy od typu <variable>:

W przypadku testów bitowych (BITSET, BITCLR) zawsze musi to być pojedynczy bajt z zakresu 0 .. 7, określający bit do przetestowania.

Na potrzeby testowania dostępności typów ładunku i kolei wartość musi określać etykietę ładunku / rodzaju kolei. Aby to zadziałało, etykieta musi być "zacytowana" w ten sposób: {WATER} , w przeciwnym razie byłaby traktowana jako indeks tabeli tłumaczeń.

Jeśli w przypadku warunku "+" nie jest zdefiniowany ładunek ani typ szyny z tą etykietą, podana liczba elementów jest pomijana. Dla warunku "-", elementy są pomijane, jeśli została zdefiniowana etykieta typu ładunku lub szyny. Oba testy działają niezależnie od kolejności plików newGRF w newgrf(w).cfg; ładunek jest uważany za dostępny, nawet jeśli jest zdefiniowany w późniejszym pliku newGRF. Aby to działało poprawnie, nie wolno pomijać definicji ładunku z warunkami "+" lub "-". To samo dotyczy typów szyn.

Od TTDPatch r1384 możliwe jest użycie maski bitowej, nadanej przez dodatkowy parametr, podczas dostępu do zmiennej. Jest to przydatne podczas sprawdzania szeregu nowych identyfikatorów GRF. Należy pamiętać, że parametr podany jako maska ​​musi być uporządkowany w taki sam sposób, jak podana wartość, patrz przykłady.

Przykłady
Parametr Opis
skip(5) pomiń 5
skip(EXIT) Zakończ nowy plik GRF
skipif(1, FLAGS, BITSET, NEWTRAINS) pomiń 1, jeśli ustawiony jest bit dla „nowych pociągów”
skipif(1, patchvar(MULTIHEAD), ==, 0) pomiń 1, jeśli TTDPatch var "multihead" jest ustawione na zero
skipif(6, CLIMATE, ==, TEMPERATE) pomiń 6, jeśli aktywny jest klimat umiarkowany
skipif(1, TTDPATCHVERSION, >, 2359) pomiń 1, jeśli wersja TTDPatch jest wyższa niż r2359
skipif(1, OTTDVERSION, <, 0x14080000) pomiń 1, jeśli wersja OpenTTD jest niższa niż stabilna 1.4.0
skipif(reflabel(noDBrails), PLATFORM, ==, TTDPATCH) pomiń do etykiety "noDBrails", jeśli TTDPatch
skipif(2, GRFACTIVE, +, GRF_ALPINESET) pomiń 2, jeśli AlpineSet jest aktywny
skipif(2, GRFACTIVE, +, 6d 62 04 00, FF FF 00 00) pomiń 2, jeśli jakikolwiek newGRF z ID "6d 62 xx xx" jest aktywny
skipif(1, GRFACTIVE, -+, GRF_ALPINESET) pomiń 1, jeśli AlpineSet jest nieaktywny, ale zostanie aktywowany później
skipif(1, getowngrfparameter(0), BITSET, _ALPINE) pomiń 1, jeśli ustawiony jest specjalny bit w newGRF parametr 0
skipif(reflabel(noDBrails), getowngrfparameter(1), BITCLR, _DBRAILS) pomiń do etykiety "noDBrails", jeśli specjalny bit ("_DBRAILS") w newGRF parametr 1 nie jest ustawiony
skipif(reflabel(WINJMP), WINDOS, ==, WIN) pomiń do etykiety WINJMP, jeśli gra działa w systemie Windows (nie DOS)
skipif(33, CARGO, -, {BRCK}) pomiń 33, jeśli typ ładunku "BRCK" jest nieznany
skipif(EXIT, TRAFFICSIDE, ==, LEFT) wznowić nowyGRF, jeśli "jazda po stronie ruchu" jest ustawiona na "lewo"
Przykład: obsługa etykiet skoku:
 deflabel(noDBrails)
 
 // not for TTDPatch!
 skipif(reflabel(noDBrails),PLATFORM,==,TTDPATCH)
 
 skipif(2,GRFACTIVE,+,GRF_DBRAILS)
 skipif(1,GRFACTIVE,-+,GRF_DBRAILS)
 skip(reflabel(noDBrails)) // no DBrails
 
 skipif(reflabel(noDBrails),getowngrfparameter(0),BITSET,_DBRAILS)
 // parameter set to "no DBrails"
 
 // branch line
 setproperties(_BR92 .. _BR38,
 	tracktype(SABN)
 )
 
 ...
 
 setproperties(_BR111,
 	tracktype(SACE)
 )
 
 placelabel(noDBrails)

Auxiliary functions

Te funkcje pomocnicze są używane w kontekście funkcji skipif () do oceny niektórych jej parametrów. Powinny być używane tylko w tym kontekście.

getowngrfparameter(<Byte>)

Ta funkcja uzyskuje dostęp do podanego parametru newGRF i udostępnia go jako drugi parametr funkcji skipif() . Zobacz przykład powyżej .

patchvar(<Byte>)

Ta funkcja pobiera flagę TTDPatch ( lub link TTDPatchFlags ) i udostępnia ją do użycia przez skipif(). Zobacz tabelę powyżej dla użytecznych flag TTDPatch.

reflabel(<String>)

Ta funkcja odwołuje się do wstępnie zdefiniowanej etykiety. Musi być użyty jako pierwszy parametr w funkcji skipif().

setbit(<Byte>)

Ta funkcja ustawia określony bit w danym parametrze swojej funkcji nadrzędnej. Musi być używany jako drugi parametr w funkcji setparameter() .