-
Notifications
You must be signed in to change notification settings - Fork 0
callbacksTut
EN PL |
- Introduction
- Jak to działa
- Jak zdefiniować callbacki
- Przykłady
- Przykład 1: używanie wywołań zwrotnych dźwięku (CB_SOUND)
- Przykład 2: używanie wywołań zwrotnych dla ilości obciążenia, pojemności i dodatkowych sufiksów tekstowych
- Przykład 3: używanie wywołań zwrotnych dotyczących długości wagonu i pojazdów przegubowych
- Przykład 4: używanie 'callbacks' dotyczących zasilania, pojazdów przegubowych, 'dołączania' i dodatkowy tekst w menu zakupu
- Przykład 5: użycie ogólnego wywołania zwrotnego, aby umożliwić sztucznej inteligencji zbudowanie odpowiednich stacji
Introduction |
Od TTDPatch 2.0.1 alpha 11, możliwe jest użycie 'callbacków', w których newGRF mogą wpływać na działanie funkcji TTDPatch. Jest to o wiele bardziej wyrafinowane niż zwykłe używanie 'funkcji właściwości' do wybierania różnych ustawień, ponieważ wywołania zwrotne mogą wykorzystywać pełne możliwości różnych funkcji wydajnościowych , w tym randomizacji.
Jak to działa |
- TTDPatch ustawia bieżący identyfikator wywołania zwrotnego, zgodnie z tym, jaki to jest callback
- Następnie TTDPatch rozpoczyna się od funkcji makevehicle() pojazdu i znajduje początkową funkcję wydajności do użycia
- TTDPatch podąża następnie za łańcuchem funkcji wykonawczych
- Wartość zwracana przez końcową funkcję wydajności jest używana jako wynik dla wywołania zwrotnego
Jak zdefiniować callbacki |
- W razie potrzeby włącz oddzwanianie. W przypadku pojazdów ustaw wywołanie zwrotne w funkcji właściwości pojazdu, który powinien używać wywołań zwrotnych
- Ustaw wartość domyślną dla wartości, którą modyfikuje callback, np. użyj funkcji właściwości loadamount() podczas korzystania z funkcji zwrotnej kwoty obciążenia CB_LOAD
- Zdefiniuj funkcję makevehicle() dla pojazdu, jeśli jeszcze jej nie ma
- Dodaj funkcję callback() , która sprawdza typ wywołania zwrotnego. Zobacz listę callbacks pociągów, aby zobaczyć dostępne typy oddzwonień
- Ostatnia funkcja wydajności w łańcuchu musi zwrócić wynik wywołania zwrotnego w wywołaniu zwrotnym lub zwykły set-id, gdy nie jest w wywołaniu zwrotnym
- Upewnij się, że sprawdzenie "default" bloku funkcyjnego callback() (odpowiadającego nieznanym wywołaniom zwrotnym) wskazuje na zwykłą graficzną ikonkę zamiast funkcji, która zwraca wyniki wywołania zwrotnego, najlepiej używając tej samej funkcji lub sprite'a, co w przypadku nie wywołania zwrotnego . W ten sposób nieznane wywołania zwrotne nie będą zwracać prawidłowych, ale błędnych wyników.
Przykłady |
Przykład 1: używanie wywołań zwrotnych dźwięku (CB_SOUND) |
Przykład (używanie wywołań zwrotnych dźwięku):
setfeature(_TRAIN) grf_init(GRF_TUT1, ...) // ustaw silnik (veh-ID 0), aby używał nowych 'sprites' i włączał dźwięku callback definevehicle(0,{}, newgraphics() callbacks(CB_SOUND) ) // zdefiniować pliki dźwiękowe soundtable( defsnd(_DEPART, br38s.wav) defsnd(_TUNNEL, br38t.wav) ) // idą tutaj sprite'y silnika spriteblock( set( sprite( ... ) sprite( ... ) sprite( ... ) sprite( ... ) ) ) def(0) spriteset(move(0),load(0)) // lokomotywa // funkcje wydajności silnika def(1) soundevent( refsnd(_DEPART) if(SND_START) // whistle: departure refsnd(_TUNNEL) if(SND_TUNNEL) // whistle: in tunnel cbfail() else // else CB fail ) // przełączać się między callback i grafiką def(2) callback( ref(1) if(CB_SOUND) // to dźwięku callback, ustaw dźwięk ref(0) // grafiki ) makevehicle(0, default(ref(2)) ) |
Przykład 2: używanie wywołań zwrotnych dla ilości obciążenia, pojemności i dodatkowych sufiksów tekstowych |
Przykład (używanie 'callbacks' dla ilości ładunku, 'refitted' pojemności i sufiksów tekstowych): setfeature(_TRAIN) grf_init(GRF_TUT2, ... ) // zdefiniować dodatkowe sufiksy tekstowe defgrftext(0,ALL, " (1st class)" " (2nd class)" ) // ustawić <span title=""wagon"">'coach'</span> (veh-ID 27) na używanie nowych 'sprites', // i włącz wywołania zwrotne CB_LOAD, CB_RCAP, CB_TSFX definevehicle(27,{}, newgraphics() callbacks(CB_LOAD, CB_RCAP, CB_TSFX) ) // idą tutaj sprite'y <span title="coach">'wagonu'</span> spriteblock( set( // 4 sprites for 1st class coach sprite(...) sprite(...) sprite(...) sprite(...) ) set( // 4 sprites for 2nd class coach sprite(...) sprite(...) sprite(...) sprite(...) ) ) def(0) spriteset(move(0),load(0)) // 1st class def(1) spriteset(move(1),load(1)) // 2nd class // funkcje wydajności silnika // kolejne 4 funkcje sprawdzają możliwości 'refitting'u': // [1] i // [2] // ustawić wielkość obciążenia def(2) refitted( cbr(6) if(0) // 1st class = 6/tick cbr(8) else // 2nd class = 8/tick ) // ustawić 'refitted' pojemność def(3) refitted( cbr(48) if(0) // 1st class = 48 pass cbr(56) else // 2nd class = 56 pass ) // ustaw sufiksy tekstu def(4) refitted( grftext(0) if(0) // "1-sza klasa" grftext(1) else // "2 klasa" ) // zestaw barw def(5) refitted( ref(0) if(0) // 1-sza klasa ref(1) else // 2 klasa ) // przełączać się między callbackami a gałęzią grafiki def(6) callback( ref(2) if(CB_LOAD) // set load amount ref(3) if(CB_RCAP) // set refitted capacity ref(4) if(CB_TSFX) // set text suffix ref(5) else // graphics ) makevehicle(27, default(ref(6)) ) |
Przykład 3: użycie wywołań zwrotnych 11 (długość wagonu) i 16 (silnik przegubowy) |
Ten przykład pokaże, jak używać CB_ARTI do projektowania "pojazdów przegubowych", np. lokomotywy z przetargami. Skonfigurujemy dwie lokomotywy przy użyciu dwóch różnych ofert: <engine1> użyje standardowej krótkiej <tender1>, a <engine2> użyje jeszcze krótszej <tender2> poprzez zastosowanie CB_WLEN .
Przykład (używanie callbacks w przypadku pojazdów przegubowych i długości pojazdu): |
setfeature(_TRAIN) |
grf_init(GRF_TUT3, ... ) |
// ustaw przetarg ogólny (veh-ID 45) na używanie nowych 'sprites', |
// włącz callback CB_WLEN
def(240) spriteset(move(0),load(0)) // tender1 (0xF0) def(0) spriteset(move(1),load(1)) // tender2 // tender2 (0xF1) is shorter def(241) callback( cbr(3) if(CB_WLEN) // skrócić o 37,5% ref(0) else // graphics ) makevehicle(45, default(ref(240)) // standard tender ) |
// ustawić dwa silniki (00 i 01) na używanie nowych 'sprites', |
// włącz callback CB_ARTI |
definevehicle(0,{}, |
// engine sprites go here spriteblock( set( ... // 8 sprites dla silnika 1 ) set( ... // 8 sprites dla engine2 ) ) def(0) spriteset(move(0),load(0)) // engine1 def(1) spriteset(move(1),load(1)) // engine2 |
// <engine1> używa standardowego <tender1> |
def(3) articulated( |
addveh(45) if(1) // dodanie tender (veh-ID 45) |
// Przełączanie się między callback a grafiką def(4) callback( |
ref(3) if(CB_ARTI) // przegubowe wywołanie zwrotne |
ref(2) else // graphics
) |
// <engine2> używa krótszego <tender2> |
// silnik jest przegubowy, więc pokaż silnik (1) lub tender (241)
// przełączać się między callback i grafiką def(4) callback( |
|
ref(2) else // graphics ) makevehicle(1, default(ref(4)) // engine2 override(45,ref(241)) // zastąp z tender2 )
|}
<p>
<a id='example4' title="Example4: using callbacks for powered wagons, articulated vehicles, engine attach, and additional menu text"> {| |Przykład 4: używanie wywołań zwrotnych dla wagonów z napędem, pojazdów przegubowych, mocowania silnika i dodatkowego tekstu menu |} </a>
Ten przykład wyjaśnia, jak używać [http://www.ttdpatch.de/grfspecs/m4nfoManual/TrainCallbacks.html#CB_POWR CB_POWR ] (wagon z napędem), [http://www.ttdpatch.de/grfspecs/m4nfoManual/TrainCallbacks.html#CB_ARTI CB_ARTI ] (pojazd przegubowy), [http://www.ttdpatch.de/grfspecs/m4nfoManual/TrainCallbacks.html#CB_ATAC CB_ATAC ] (mocowanie silnika) i [http://www.ttdpatch.de/grfspecs/m4nfoManual/TrainCallbacks.html#CB_TEXT CB_TEXT ] (dodatkowy tekst w menu) do budowy czteroczęściowego EMU.
EMU składa się z tego samego bloku konstrukcyjnego, elektrycznego wagonu szynowego (<span title=veh-ID>poj-ID</span> = 62). Ponadto należy zezwolić na połączenie trzech z tych czteroczęściowych EZT, tj. Pełny skład może zawierać łącznie 12 wagonów.
Ze względu na realizm, żadne „zagraniczne” pojazdy nie powinny być przyłączane do UGW. Uzyskuje się to poprzez sprawdzenie <span title="identyfikatora pojazdu">veh-ID</span> przez [http://www.ttdpatch.de/grfspecs/m4nfoManual/TrainFunctions.html#veh_id veh_id() ] . Odpowiednie komunikaty o błędach zostaną wygenerowane, jeśli coś jest nie tak z liczbą lub typem dodanych pojazdów.
Prośba odnotowania, że CB_ATAC i CB_TEXT nie potrzebują być wprowadzane w właściwości funkcji [http://www.ttdpatch.de/grfspecs/m4nfoManual/TrainProperties.html#callbacks callbacks() ] .
Ponadto pokazano, jak utworzyć wyraźną pozycję menu dla takiej UGW. Aby to zadziałało, potrzebujemy dodatkowego sprite'a przedstawiającego nie pojedynczy wagon, ale całą czteroczęściową EMU. Ponieważ ten 'sprite' będzie używany tylko w menu kupowania, odpowiedni blok 'sprites' potrzebuje tylko tego pojedynczego 'sprite' dla kierunku poziomego. Wszystkie inne kierunki nie są potrzebne, dlatego nie musimy uwzględniać dla nich sprite'ów.
Ponadto łańcuch funkcji dla pozycji menu wymaga odniesień do wywołań zwrotnych CB_ARTI i CB_TEXT. Ten ostatni służy do umieszczania tekstu dodatkowych informacji we wpisie menu, a CB_ARTI jest potrzebne, aby pojemność czteroczęściowej EMU była poprawnie wyświetlana w menu zakupów.
{| | Przykład (używanie callbacks dla wagonów z napędem, pojazdów przegubowych, <span title=attach>'mocowania'</span> silnika |} {| | i dodatkowego tekstu menu): |} {| |
setfeature(_TRAIN) grf_init(GRF_TUT4, ... )
|} {| |// komunikaty o błędach 'załączenie silnika' |} {| |
define(ATT_CARBADNUM,0x00) define(ATT_CARBADTYPE,0x01) defgrftext(ATT_CARBADNUM,ALL,
|} {| |" (wrong number of cars)", " (wrong type of car)"
|} {| |
|} {| | // ustawić wagon (veh-ID 98) na używanie nowych 'sprites', |} {| |
//---------------------------------------------------------- // "train" //---------------------------------------------------------- // wszystkie sprite'y wagonów są tutaj spriteblock( set( sprite( ... ) // 8 sprites dla 1-y wagon ) set( sprite( ... ) // 8 sprites 2nd -"- ) set( sprite( ... ) // 8 sprites 3rd -"- ) set( sprite( ... ) // 8 sprites 4th -"- ) ) // użyj powyższych zestawów sprites def(0) spriteset(move(0),load(0)) // 1 wagon def(1) spriteset(move(1),load(1)) // 2 -"- def(2) spriteset(move(2),load(2)) // 3 -"- def(3) spriteset(move(3),load(3)) // 4 -"- // określić, w jakim samochodzie się znajdujemy. Możemy połączyć maksymalnie cztery // EMU w składzie, więc użyj funkcji modulo-4. def(2) veh_posrel(MOD4, ref(3) if(3) // 4th car ref(2) if(2) // 3rd car ref(1) if(1) // 2nd car ref(0) else // 1st car ) // ustawić callback dla pojazdu przegubowego def(5) articulated( addveh(_BR425) if(1 .. 3) // 3 dodatkowe części tego ID pojazdu ENDLIST else // koniec pojazdu przegubowego ) // ustawić oddzwanianie do podłączenia silnika // zezwalaj tylko na 3 * EMU (= 12 wagonów) def(6) veh_num( engine( attach(ATT_OK) if(0 .. 9) // pozwalają na dodanie dodatkowych 8 wagonów attach(ATT_CARBADNUM) else // błąd: "zła liczba wagonów" ) ) // pozwolić tylko UGW na przyłączenie się, nic więcej def(7) veh_id( ref(6) if(_BR425) // pozwól, sprawdź całkowitą liczbę samochodów attach(ATT_CARBADTYPE) else // błąd: "zły typ wagonu" ) // tylko wagon 1 i jeśli istnieją, 5 i 9 powinny świecić def(8) veh_posabs(FRONT, effect(electric(4)) if(1,5,9) // iskra ref(0) else // brak iskier ) // przełączać się między callback i grafiką def(9) callback( ref(5) if(CB_ARTI) // pojazd przegubowy ref(7) if(CB_ATAC) // silnik podłączyć ref(8) if(CB_POWR) // moc i efekty ref(4) else // graphics ) //---------------------------------------------------------- // pozycja menu //---------------------------------------------------------- spriteblock( set( sprite(emu.pcx 226 120 01 15 91 -27 -11) ) ) def(0) spriteset(move(0),load(0)) // menu pic // przełączać się między callback i grafiką def(1) callback( ref(5) if(CB_ARTI) // (do obliczenia pojemności) grftext() if (CB_TEXT) // show additional text in menu ref(0) else // graphics ) makevehicle(_BR425, link(ref(1),MENU) // menu entry default(ref(9)) // vehicle )
|}
<p>
<a id='example5' title="Example5: using the generic callback to allow the AI to build suitable stations"> {| |Przykład 5: użycie ogólnego wywołania zwrotnego, aby umożliwić AI zbudowanie odpowiednich stacji |} </a>
W oryginalnym TTD AI była zakodowana na stałe. W przypadku pojazdów miał stałą listę dla każdego rodzaju ładunku, a dla stacji używał po prostu jednego z 4 możliwych typów stacji TTD.
Po raz pierwszy TTDPatch zaimplementował interfejs między AI i newGRF, wprowadzając ogólne wywołanie zwrotne ("Wybór budowy/zakupu AI"). Jest to wymagane do podejmowania różnych decyzji, gdy sztuczna inteligencja konstruuje nową trasę. Dzięki temu wywołaniu zwrotnemu stało się możliwe uzależnienie wyboru AI od branży źródłowej i docelowej, a także odległości usług.
W tym przykładzie pokazano, jak nauczyć sztuczną inteligencję budowania stacji z 1 lub 2 platformami w zależności od przewożonego ładunku, bieżącego roku i liczby mieszkańców miasta, w którym stacja ma zostać zbudowana.
W m4nfo, ogólne wywołanie zwrotne nazywa się CB_AISELECT , zwraca ID-stacji, która ma być zbudowana (przez funkcję cbr() ), najprawdopodobniej opracowaną po ocenie pewnych zmiennych, patrz przykładowy kod.
Prośba odnotowania na specjalną postać funkcji makestation() , która w ogóle nie określa żadnego identyfikatora stacji. Tworzy to ogólną definicję specyficzną dla funkcji, niezwiązaną z żadną konkretną funkcją, która jest używana na potrzeby ogólnego wywołania zwrotnego.
Prośba odnotowania również , że ten przykład kodu jest częścią zestawu [http://www.ttdpatch.de/download.html NewStations] i jako taki odnosi się do typów stacji (<span title=ROOFS>'DACHY'</span>, ŁAWKI, <span title=FLATROOF>'PŁASKIE'</span>, ...) zdefiniowane w tym zestawie.
Również prośba odnotowania, że w OpenTTD SI jest implementowana przez niezależne moduły, więc potrzebujesz takiego, który implementuje również stacje budowlane, a nie tylko pojazdy.
{| | Przykład (niech SI buduje stacje): |} {| |
//------------------------------------------------------------------ // AI platforms //------------------------------------------------------------------ // Losuj za pomocą tick silnika anim_counter(): // trzeba przesunąć w prawo o 3 bity, ponieważ jeden gracz jest przetwarzany // każdy tik, więc mod 8 będzie zawsze taki sam dla każdego gracza
|}
// Pick n*1 station, <1950
// Wybierz stację n&#42;1 w zależności od roku def(3) year( |
ref(1) if(<1950)
def(1) townpopulation( |
cbr(FLATROOF) if(<800) // budował "płaskie dachy" w małych miejscowościach
// Pick n&#42;2 station depending on year def(4) year( |
cbr(ROOFS) if(<1960) // build "roofs"
// Check callback typ&#58; // zwraca nieprawidłowy wynik dla braku wywołania zwrotnego lub wywołania zwrotnego innego niż 18 def(7) callback( ref(6) if(CB_AISELECT) // AI construction cbfail(0) if(1 .. 0xFF) // nieprawidłowy CB NOTAVAILABLE else // no callback ) // zdefiniować ogólne wywołanie zwrotne stacji makestation(default(ref(7))) |