Poprzedni temat «» Następny temat
[TUTORIAL] Tworzenie skryptu dialogowego
Autor Wiadomość
L`f 
Uczeń Gonda


Wiek: 26
Posty: 1381
Podziękowania: 290/154
Wysłany: 2008-10-05, 22:17   [TUTORIAL] Tworzenie skryptu dialogowego

TWORZENIE SKRYPTU DIALOGU W GRZE BALDUR’S GATE II

Opracowanie: L`f


Jeśli zamierzasz właśnie stworzyć mod dodający nowe misje do gry, nowe postacie rozwijające linię fabularną, czy przyłączalnego bohatera, trafiłeś(aś) pod dobry adres.
Tworzenie dialogów wymaga umiejętności planowania i na pierwszy rzut oka może wydawać się trudne. Jednak gdy tylko poznamy podstawowe zasady pisania plików .d wyda nam się to bardzo proste i większym problemem będzie wymyślenie tekstu, niż oskryptowanie go.
Pliki .d, które nauczymy się tworzyć, zawierają nieskompilowany skrypt dialogu oraz treść wypowiedzi. Podczas instalacji aplikacja WeiDU skompiluje je do odpowiednich plików i umieści w grze. Jednak tym zajmiemy się dopiero w punkcie piątym tutorialu, a teraz naszym głównym zmartwieniem będzie napisanie dobrego skryptu dialogu, który gra odczyta. No cóż, dość gadania, zabierajmy się do roboty.


SPIS TREŚCI:

1. Zanim zaczniesz pisać skrypt
1.1. Programy do ściągnięcia
1.2. Pojęcia podstawowe

2. Podstawy tworzenia bloku dialogu
2.1. Prosty blok dialogowy
2.2. Zastosowanie tokenów w dialogach
2.3. Akcja zakończenia i linki między blokami w jednym pliku .dlg
2.4. Rozbudowane bloki dialogowe i ich elementy
2.4.1. REPLY
2.4.2. DO
2.4.3. JOURNAL i podkomendy

3. Linki zewnętrzne:
3.1. Istota komendy EXTERN
3.2. Struktura i skrypt dialogu łańcuchowego
3.3. Aktualizacje istniejących plików .dlg, czyli komenda APPEND

4. Komendy zaawansowane
4.1. EXTEND_BOTTOM i EXTEND_TOP
4.2. COPY_TRANS – kopiowanie przejść
4.3. INTERJECT, czyli wtrącenia
4.4. INTERJECT_COPY_TRANS
4.5. Dodawanie nowych warunków do bloków w istniejących plikach .dlg

5. Kompilacja i implementacja dialogu w grze



1. Zanim zaczniesz pisać skrypt


1.1. Programy do ściągnięcia

Do pisania dialogów nie potrzebujemy skomplikowanych programów, wystarczy nam Notatnik. Warto jeszcze ściągnąć WeiDU, dzięki któremu będziemy mogli zainstalować dialog.
Poleciłbym także Infinity Explorer (do ściągnięcia z załącznika), jest to przeglądarka silnika Infinity (na silniku Infinity pracuje m. in. Baldur’s Gate II). Dzięki temu programowi możemy poznać konstrukcję oryginalnych dialogów, a także innych elementów gry.
Aby mieć informacje potrzebne do modyfikacji istniejących plików .dlg, przyda nam się również program DLTCEP (również do ściągnięci z załącznika). Ma on wiele funkcji, nam jednak przyda się tylko jedna.

1.2. Pojęcia podstawowe

Plik dialog.tlk
Jest to zbiór wszystkich stringów (o teksty chodzi, erotomani ;P) występujących w grze, z których każdemu przypisany jest numer. W ‘czystym’ Baldur’s Gate II + Tron Bhaala w tym pliku znajduje się około 70000 stringów.
Pliczku tego nie można zmieniać ręcznie (spowodowałoby to niekompatybilność z niemal wszystkimi modami), ale jego bezinwazyjna modyfikacja jest możliwa za pomocą aplikacji WeiDU.
String
String to tekst przypisany do jednego numeru w pliku dialog.tlk. Może mieć dowolną ilość znaków, tak więc stringiem może być imię ‘Anomen’, albo długi wpis w dzienniku bohatera. W dialogach również je wykorzystujemy, a każdy string pojawia się w okienku dialogowym jako pojedyncza wypowiedź. Więcej o zapisywaniu stringów w dialogach dowiemy się w punkcie 2.1.
Blok dialogowy
Jest to podstawowa jednostka dialogu składająca się z jednego oskryptowanego stringu. Do stringu w dialogu można opcjonalnie przypisać wykonywaną akcję (np. odebranie przedmiotu, zaatakowanie postaci gracza, ucieczkę z obszaru), odpowiedź rozmówcy z naszej drużyny, czy dodanie wpisu do dziennika. W blokach rozpoczynających możemy dodać również warunek, kiedy ten blok ma zostać wypowiedziany.
Blok musi również mieć połączenie z innym blokiem dialogowym, lub akcję zakończenia dialogu. Wszystkie bloki dialogowe w danym pliku .dlg tworzą tak zwane drzewko dialogowe, które możemy obejrzeć, rozwijając pierwszy lepszy dialog otwarty dzięki Infinity Explorerowi.
Plik .dlg
Jest to plik dialogowy, który odczytuje gra. Zawiera on strukturę dialogu (połączenia między blokami, odpowiedzi bohatera, akcje, warunki), ale nie zawiera samego tekstu – tylko odnośniki do konkretnych stringów z pliku dialog.tlk Zawartość takiego pliku można przypisać jednemu lub wielu stworzeniom w grze.



2. Podstawy tworzenia bloku dialogowego


//tak będę zapisywał uwagi na temat danego fragmentu kodu

2.1. Elementy prostego bloku dialogowego


Nadszedł czas na skryptowanie – otwieramy Notatnik i zapisujemy pusty plik nie jako *.txt, tylko jako *.d. .d to format pliku, który aplikacja WeiDU potrafi skompilować.
Poznajmy więc podstawową komendę tworzącą pusty, surowy plik .dlg:

Kod:
BEGIN ~NAZWA_PLIKU_.DLG~


Komenda BEGIN ~~ tworzy plik .dlg o nazwie takiej, jak zawarta między tyldami. Na przykład, chcąc stworzyć plik dialogowy gienek.dlg wpisujemy w naszym pliku .d komendę:

Kod:
BEGIN ~GIENEK~


Proste. Plik .dlg o danej nazwie zostanie dodany do zasobów gry przy instalacji modu. Nazwa może być dowolna, byleby nie zawierała tyld i miała najwyżej osiem znaków.

Teraz zajmiemy się blokiem dialogowym. Schemat prostego bloku dialogowego przedstawia się tak:

Kod:
IF ~(warunki, przy których blok ma być użyty, tylko dla bloków rozpoczynających)~ THEN BEGIN (nazwa bloku)
SAY ~(wypowiedź)~
IF ~(warunki, dla których przejście nr 1 ma zostać wykonane)~ THEN (komendy przejścia nr 1)
END


W tyldach pomiędzy IF i THEN umieszczamy warunki, korzystając z oznaczeń skryptowych warunków, które gra może odczytać. Pełny ich spis znajduje się w pliku trigger.ids, który możemy otworzyć Infinity Explorerem. Zwykle po nazwach łatwo się zorientować, co warunkują.

Nazwa bloku może być dowolna. Ważne jest tylko, żeby nazwy bloków w połączeniach się zgadzały. Bloki w oryginalnych plikach .dlg są nazwane numerami od 0 wzwyż. W danym pliku .dlg danej nazwy bloku można użyć tylko raz.

W polu wypowiedź wpisujemy tekst naszej wypowiedzi. Tekst ten przy instalacji modu zostanie zapisany jako nowy string w dialog.tlk. W rodzaju znaków, które może zawierać wypowiedź, są tylko drobne ograniczenia. Tekst zapisany w tyldach, który zawiera tyldę, zostanie źle odczytany, dlatego teksty zawierające tyldy powinno się pisać w taki sposób:

Kod:
SAY %Kopytko~!!%


Albo:

Kod:
SAY "Kopytko~!!"


Jednak w zapisie stringu z wykorzystaniem procentów nie możemy użyć procentu w treści stringu, analogicznie rzecz się ma z cudzysłowami. Najlepiej więc korzystać z tyld.

Jeśli jednak chcemy zastosować w wypowiedzi procent, tyldę i cudzysłów (pogratuluję temu, kto wpadnie na taki pomysł), możemy zapisać taki string w jeszcze inny sposób:

Kod:
SAY ~~~~~"Kopytko~!!", zawartość 74%~~~~~


Czyli zapisujemy string pomiędzy dwoma zestawami pięciu tyld. Jedynym ograniczeniem do stosowania takiego sposobu jest to, że nie wolno umieścić w stringu pięciu tyld w jednym ciągu, jednak kto, u diabła, robiłby coś takiego!? ;)

Komendy przejść dostarczają grze informacji o akcji, jaką ma wykonać, kiedy dane warunki są spełnione. Na przykład osoba postronna nie nawiąże dialogu z Minsciem, kiedy ten jest martwy, potrzebna jest alternatywna ścieżka dialogu. Takich przejść w jednym bloku dialogowym możemy stworzyć wiele, ale tymi kwestiami zajmiemy się w punkcie 2.3, gdzie omówię tworzenie skomplikowanych bloków dialogowych.

Komend przejść jest kilka, wśród nich wyróżniamy najważniejsze:

Komendy linków:
GOTO (nazwa bloku) – linki wewnętrzne, czyli połączenia wewnątrz danego pliku .dlg
EXIT – zakończenie dialogu
EXTERN (nazwa pliku .dlg) (nazwa bloku w danym pliku .dlg) – linki zewnętrzne, czyli połączenia z innymi plikami .dlg

Komendy zdarzeń:
REPLY ~(treść odpowiedzi)~ - odpowiedzi, które możemy wybierać jako rozmówca
DO ~(komendy akcji)~ - akcje, które w danej chwili mają zostać wykonane, pisane w języku skryptów Infinity
JOURNAL i jej podkomendy – wpisy w różnych kategoriach dziennika.

Na razie zajmiemy się komendami GOTO i EXIT, komendy REPLY, DO i JOURNAL poznamy w punkcie 2.4, a komendą EXTERN zajmiemy się dopiero w punkcie 3.1.

END oznacza koniec danego bloku skryptowego w pliku .dlg.

2.2. Zastosowanie tokenów w dialogach


Warto o tym wspomnieć, zanim przejdzie się do pisania dialogu. Tokeny dialogowe to specjalne wyrażenia, które można zapisać w wypowiedzi bohatera, a które w zależności od pewnych warunków wyświetlają w okienku dialogowym gry różny tekst.

Pełna lista w polskiej wersji Baldur’s Gate II i przykład ich zastosowania – opracowane przez Shaggiego – znajdują się w tym temacie na forum.

2.3. Akcja zakończenia i linki między blokami w jednym pliku .d


Każdy blok dialogowy musi zawierać link do innego bloku dialogowego, chyba, że jest to blok kończący dialog (w grze wywołuje on przycisk ‘koniec rozmowy’). Istnieją dialogi jednoblokowe, w których pierwszy blok jest tym kończącym. Tak skonstruowane dialogi ma np. większość statystów w miastach.

Jeżeli dla naszego Gienka będziemy chcieli stworzyć taki blok, będzie to wyglądało na przykład tak:

Kod:
IF ~True()~ THEN BEGIN 0 //True() jest zawsze spełnione, wpisuje się je tam, gdzie musi być warunek, a żadnych warunków nie chcemy umieszczać
SAY ~Hej! Którędy na Wrocław?~ //wypowiedź Gienka
IF ~~ THEN EXIT //komenda powodująca zakończenie dialogu
END //zakończenie bloku dialogowego


Tak wygląda możliwie najprostszy blok dialogowy.

Jednak gra wyglądałaby średnio, gdyby dialogi składały się z pojedynczych bloków. Dialogi są rozbudowane, składają się z wielu połączonych bloków, a do łączenia dwóch takich jednostek służy komenda GOTO.

Oto przykład połączenia trzech bloków dialogowych Gienka:

Kod:
IF ~NumTimesTalkedTo(0)~ THEN BEGIN powitanie //NumTimesTalkedTo(X) to warunek określający, ile razy rozmawialiśmy z daną osobą; wartość X=0 to pierwsza rozmowa
SAY ~Cześć! Jestem Gienek i nie mam tchawicy.~
IF ~~ THEN GOTO tchawica //link do bloku o nazwie 'tchawica'
END

IF ~~ THEN BEGIN tchawica //jako że nie jest to blok rozpoczynający dialog, nie ma warunków dla rozpoczęcia tego bloku
SAY ~Urwała mi się, kiedy podrapałem się w nogę.~
IF ~~ THEN GOTO koniec //link do bloku o nazwie 'koniec'
END

IF ~~ THEN BEGIN koniec
SAY ~Dobra, no nie gap się tak, <GIRLBOY>. Już sobie idę.~ //<GIRLBOY> to token, po szczegóły odsyłam do punktu 2.2
IF ~~ THEN EXIT //zakończenie dialogu
END

Można to zapisać tak. Zadziała. Jednak zdecydowanie prościej jest zastosować skróconą formę skryptu. Ten sam dialog w skróconej formie wygląda tak:

Kod:
IF ~NumTimesTalkedTo(0)~ THEN BEGIN powitanie
SAY ~Cześć! Jestem Gienek i nie mam tchawicy.~
= //znak równości działa jak komenda GOTO do następnej wypowiedzi
~Urwała mi się, kiedy podrapałem się w nogę.~ //pomijamy komendę SAY, która już raz została użyta w tym bloku
=
~ Dobra, no nie gap się tak, <GIRLBOY>. Już sobie idę.~
IF ~~ THEN EXIT
END


Jasne, że prościej. Na trzy bloki dialogowe piszemy jeden blok skryptowy, w dodatku używamy jednej, a nie trzech nazw (pozostałe dwie dopowiada sobie WeiDU, ale to już nie nasz problem).

Komenda GOTO jednak jest używana, lecz w sytuacjach bardziej skomplikowanych, kiedy w zależności od warunków może wystąpić kilka przejść z jednego bloku dialogowego.

Dzięki temu można tworzyć nie linie, a drzewka dialogowe. Oto przykład skryptu dialogu o dwóch różnych liniach. Bohaterem jest wciąż Gienek.

Kod:
IF ~NumTimesTalkedTo(1)~ THEN BEGIN powrót //wartość 1 dla tego warunku oznacza, że drugi raz zaczynamy rozmowę z daną osobą
SAY ~O, wracacie, <LADYLORD>. Gienkowi miło was znowu widzieć.~
=
~Wiecie, hm, chciałbym cię zapytać...~
IF ~Gender(LastTalkedToBy,MALE)~ THEN GOTO facet //przejście nr 1, opis poniżej
IF ~Gender(LastTalkedToBy,FEMALE)~ THEN GOTO dziewczyna //przejście nr 2
END

IF ~~ THEN BEGIN facet
SAY ~... widzisz pan tego tam kretyna? To jest brat mój, Zenek. Ta szuja ukradła mi mięso. Mógłbyś mu dać po pysku?~
=
~No dobra, rozumiem. Nic za darmo. Dam dwa miedziaki i racicę kozła.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN dziewczyna
SAY ~Masz śliczną krtań, paniusiu. Zechciałabyś mi towarzyszyć w przechadzce po parku rządowym?~
=
~Ee... Nie musisz tak patrzeć. To może... ja już pójdę, co?~
IF ~~ THEN EXIT
END


Ten dialog ma dwie ścieżki w zależności od płci bohatera, który rozmawia z Gienkiem – wybór ścieżki dialogu określa warunek Gender(obiekt,wartość), gdzie obiektem jest LastTalkedToBy, czyli bohater rozmawiający z Gienkiem.
Jeśli rozmawia z nim mężczyzna (wartość warunku – MALE), Gienek będzie próbował wynająć bohatera na Zenka, a gdy porozmawiamy z Gienkiem kobietą (wartość – FEMALE), ten będzie usiłował ją poderwać. Z mizernym skutkiem.

Takich rozwidleń w dialogach są setki, dlatego aby dobrze pisać dialogi, należy zapoznać się z charakterystyką warunków. A tych najlepiej się uczyć, przeglądając oryginalne skrypty i dialogi z gry.

Oczywiście, jeśli sytuacja jest bardziej skomplikowana, warunków do danego przejścia może być więcej, niż jeden. Przejście zostanie wykonane tylko wtedy, kiedy wszystkie będą spełnione. Jednak, aby nie doszło do sytuacji bez wyjścia, należy uwzględniać wszystkie alternatywy. Oto, jak nie warunkować przejść:

Kod:
IF ~True()~ THEN BEGIN criticalerror
SAY ~Cośtam~
IF ~Gender(LastTalkedToBy,MALE)~ THEN EXIT
END


Taki blok dla rozmówcy-mężczyzny spowoduje wywołanie przejścia (w tym wypadku zakończy dialog), natomiast dla rozmówcy-kobiety nie przewidziano wykonania żadnej akcji. Dyskryminacja! Jeśli rozmówca jest kobietą – gra się posypie. Należy uwzględniać wszystkie alternatywy i warunkować ostrożnie, aby nie było sytuacji bez wyjścia.

2.4. Rozbudowany blok dialogowy i jego elementy


Rozbudowane bloki zawierają tylko kilka elementów więcej, niż te prostsze. Podstawowe bloki dialogowe nie obędą się bez komend przejść GOTO i EXIT, bez innych mogą. I będą działać.

Jednak bez komendy REPLY dialog to właściwie monolog, a bez DO rozmówca nie może wywoływać prostych czynności typu ustalenie zmiennej, albo danie drużynie pięciuset sztuk złota. JOURNAL i jej podkomendy mają znaczenie bardziej marginalne, jednak przy tworzeniu misji się przydają.

Generalnie nie ma znaczenia, w jakiej kolejności ustawimy te trzy komendy (kiedy skorzystamy z więcej niż jednej z nich), ważne jest tylko, aby GOTO, albo EXIT, czyli komenda linku było ostatnią komendą przejścia.

Zaczniemy po kolei…

2.4.1. Komenda REPLY

Komenda REPLY (a właściwie REPLY ~tekst~) powoduje, że aby wykonać dane przejście, należy w okienku dialogowym wybrać jedną z możliwych odpowiedzi, które wypowiada nasz drużynowy rozmówca. Mówiąc prościej – pozwala ona na wybór odpowiedzi na daną wypowiedź.

Schemat bloku z odpowiedziami wygląda następująco:

Kod:
IF ~(ewentualne warunki)~ THEN BEGIN (nazwa_bloku)
SAY ~(wypowiedź)~
IF ~(ew. warunki)~ THEN REPLY ~(tekst odpowiedzi nr 1)~ (dalsze komendy przejścia nr 1)
IF ~(ew. warunki)~ THEN REPLY ~(tekst odpowiedzi nr 2)~ (dalsze komendy przejścia nr 2)
IF ~(ew. warunki)~ THEN REPLY ~(tekst odpowiedzi nr n)~ (dalsze komendy przejścia nr n) //nie ma ograniczonej liczby odpowiedzi, podobnie jak nie ma ograniczonej liczby przejść w jednym bloku
END


Odpowiedzi pozwalają graczowi na wybór ścieżki dialogu. Mogą być uwarunkowane, jednak nie muszą. Ważne jest, aby możliwe do wyboru nie znalazły się jednocześnie przejście z odpowiedzią i przejście bez odpowiedzi – gra nie będzie wtedy wiedziała, co zrobić.

Jednak odkąd ukazały się nowsze wersje WeiDU, możemy zamiast długiego ‘IF ~warunek~ THEN REPLY ~tekst~ GOTO x’ użyć do zapisania przejścia z odpowiedzią prostej komendy trzech plusów. Wygląda to tak:

Kod:
IF ~(ewentualne warunki)~ THEN BEGIN (nazwa_bloku)
SAY ~(wypowiedź)~
+ ~(ew. warunki)~ + ~(tekst odpowiedzi nr 1)~ + x
+ ~(ew. warunki)~ + ~(tekst odpowiedzi nr 2)~ + y
END


Pierwszy plus oznacza tutaj IF, drugi – THEN REPLY, a trzeci – GOTO.
Jeśli odpowiedź jest niczym nieuwarunkowana, dwa pierwsze plusy zapisujemy obok siebie – ++, co oznacza ‘IF ~~ THEN REPLY’. Jeżeli natomiast nie chcemy stosować komendy GOTO, zamiast trzeciego plusa podstawiamy właściwą komendę. Komenda plusowa jest zdecydowanie łatwiejsza i przyjemniejsza, a jej zastosowanie przedstawię na przykładzie.

Po raz kolejny za przykład posłuży nam Gienek.

Kod:
IF ~NumTimesTalkedTo(2)~ THEN BEGIN prosba //warunek do bloku - rozmowa zaczynana trzeci raz
SAY ~Hm, <LADYLORD>... Czy mógłbym...~
++ ~No?~ + prosba1
++ ~Dobrze, tylko się streszczaj.~ + prosba2
END

IF ~~ THEN BEGIN prosba1
SAY ~Yy... no to... co ja też chciałem...~
++ ~Błagam, myśl szybciej.~ + prosba3
++ ~(nic nie mów)~ + prosba3
END

IF ~~ THEN BEGIN prosba2
SAY ~Dobrze! No to... ee...~
IF ~~ THEN GOTO prosba3
END

IF ~~ THEN BEGIN prosba3
SAY ~Chciałem podwyższyć stawkę. Pięć złociszy, racica osioła i moja dozgonna wdzięczność za przestawienie gęby Zenkowi. Co ty na to?~
++ ~Daj mi się chwilę zastanowić.~ + wait
++ ~Nie zgadzam się. Nie znam człowieka.~ + refuse
+ ~Alignment(LastTalkedToBy,MASK_EVIL)~ + ~Dość! Znikaj stąd, albo dam ci takiego kopa, że wylądujesz w Młynku Nieświńskim!~ + runrunaway //co znaczy warunek do tego przejścia - objaśnię poniżej
END

IF ~~ THEN BEGIN wait
SAY ~Dobra. Przyjdź do mnie jak się zdecydujesz.~
=
~A mam nadzieję, że się zdecydujesz, no.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN refuse
SAY ~Ej, nie bądźcie źli dla mnie! Jak zmienicie decyzję to wróćcie.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN runrunaway
SAY ~Ee... przecież my jesteśmy w Młynku Nieświńskim, no nie?~
++ ~Czepiasz się szczegółów.~ EXIT //zamiast trzeciego plusa stosujemy EXIT, który kończy dialog
END


Nie takie trudne, prawda? Pozwala to stworzyć drzewko dialogowe, w którym sami wybieramy, co chcemy powiedzieć. To chyba wszystko związane z odpowiedziami gracza.

A warunek Alignment(obiekt,wartość) sprawdza charakter danej osoby, w tym wypadku LastTalkedToBy – gracza rozmawiającego z Gienkiem.
Warunek ten przy wartości MASK_EVIL jest spełniony, gdy charakter rozmówcy Gienka jest zły. Podobnie przy wartości MASK_GOOD jest spełniony, gdy charakter rozmówcy jest dobry. Jest jeszcze kilka innych wartości, które określają ten warunek.

2.4.2. Komenda DO

Ta komenda (właściwie DO ~akcja~) wywołuje określoną inną czynność po wyborze odpowiedzi w dialogu lub kliknięciu przycisku ‘dalej’, czy ‘koniec rozmowy’. Akcję tą określa się poprzez komendy akcji skryptów silnika Infinity. Spis wszystkich komend akcji znajduje się w pliku action.ids – również do otwarcia przez Infinity Explorer.

Schemat wygląda tak:

Kod:
IF ~(ewentualne warunki)~ THEN BEGIN (nazwa_bloku)
SAY ~(wypowiedź)~
IF ~(ew. warunki)~ THEN DO ~(akcje przejścia nr 1)~ (dalsze komendy przejścia nr 1)
IF ~(ew. warunki)~ THEN DO ~(akcje przejścia nr 2)~ (dalsze komendy przejścia nr 2)
END


Komenda DO wywołuje akcje niezwiązane z dialogiem, jak na przykład ustawienie zmiennej, stworzenie przedmiotu w ekwipunku, rzucenie czaru, stanie się wrogiem itp. Jej zastosowanie pokażę na przykładzie czwartej rozmowy z Gienkiem:

Kod:
IF ~NumTimesTalkedTo(3)~ THEN BEGIN decyzja
SAY ~I jak? Namyśliliście się już?~
++ ~Tak. Zenek nic mi nie zrobił. Jak chcesz, sam go zlej. Chyba się go nie boisz?~ DO ~SetGlobal("GieneksJobRefused","LOCALS",1)~ + refuse1 //komendę SetGlobal() objaśnię poniżej
++ ~Pomogę, ale musisz zapłacić więcej.~ + more
++ ~Dobra. Załatwię to szybko. I liczę na umówioną zapłatę. Gdzie znajdę tego Zenka?~ DO ~SetGlobal("GieneksJob","LOCALS",1)~ + place
END

IF ~~ THEN BEGIN refuse1
SAY ~N-nie. To znaczy... e, kurczę, dajcie mi spokój.~
IF ~~ THEN EXIT
END

IF ~~ THEN BEGIN more
SAY ~Zdzieracie z Gienka ile się da! Niech stracę, dziesięć złociszy, kij i mój kaszkiet. Tylko przetrzepcie go porządnie!~
++ ~Za mało. Nie zrobię tego. Sam mu dokop, chyba że się go boisz.~ DO ~SetGlobal("GieneksJobRefused","LOCALS",1)~ + refuse1
++ ~Dobra. Pożałuje, że ukradł ci mięso i je *zwróci*, zapewniam cię. Gdzie on jest?~ DO ~SetGlobal("GieneksJob","LOCALS",2)~ + place
END

IF ~~ THEN BEGIN place
SAY ~Świetnie! Ten kretyn siedzi tam, pod ścianą i żre moje mięso. Idźcie mu dokopać, a później wróćcie do mnie.~
IF ~~ THEN EXIT
END


No i jest. Zastosowanie DO ~akcja~ nie jest szczególnie trudne i poza warunkami nie ma praktycznie żadnych ograniczeń. A co do komend akcji zastosowanych w DO…

Komenda SetGlobal("X","Y",Z) ustawia zmienną na określoną wartość. Zmienne służą jako niestandardowe warunki, oznaczane jako Global("X","Y",Z). X w tym wypadku to nazwa zmiennej (może być dowolna), Y to charakter zmiennej – globalna (dla całej gry), lokalna (dla jednej osoby), obszarowa (dla jednego obszaru). Z to wartość liczbowa zmiennej.

Tak więc SetGlobal("GieneksJob","LOCALS",2) ustawia zmienną lokalną GieneksJob na wartość 2.

Jeśli jednak odmówiliśmy i zmienna GieneksJobRefused jest ustawiona na 1, możemy w dalszym ciągu przyjąć zadanie Gienka. Piszemy mu specjalny dialog, który uaktywni się przy kolejnej rozmowie z nim:

Kod:
IF ~Global("GieneksJobRefused","LOCALS",1)~ THEN BEGIN refused2
SAY ~Hej, ludzie! Zmieniliście może zdanie? Pomożecie mi z tym czymś? On mi już zeżarł prawie całe mięso!~
++ ~Chyba nie mówisz poważnie.~ + refuse1 //omijamy akcję DO - po co drugi raz tak samo ustawiać zmienną? Linki prowadzą do bloków z poprzedniego przykładu
++ ~Zapłać więcej, to pomogę.~ DO ~SetGlobal("GieneksJobRefused","LOCALS",0)~ + more //neutralizujemy zmienną GieneksJobRefused - jeśli odmówimy mu w bloku 'more', ustawi się ona ponownie
++ ~Dobra. Gdzie znajdę tego Zenka?~ DO ~SetGlobal("GieneksJob","LOCALS",1)
SetGlobal("GieneksJobRefused","LOCALS",0)~ + place //tutaj dwie akcje następują po sobie
END


To wszystko, co związane z komendą DO. Po resztę odsyłam do action.ids, warto też poczytać sobie pliki skryptów (.bcs), żeby przyswoić co bardziej skomplikowane komendy akcji.

2.4.3. Komendy wpisów do dziennika

Komendy dodające wpisy do dziennika są trzy, ale wszystkie mają taki sam sposób działania. Różnią się tylko tym, że dodają wpisy do różnych zakładek.

Są to JOURNAL, UNSOLVED_JOURNAL i SOLVED_JOURNAL. Stosujemy je tak samo, jak DO i REPLY, czyli:

Kod:
IF ~(ewentualne warunki)~ THEN BEGIN (nazwa_bloku)
SAY ~(wypowiedź)~
IF ~(ew. warunki)~ THEN JOURNAL ~wpis~ (dalsze komendy przejścia nr 1)
END


Komenda JOURNAL dodaje wpis do głównej zakładki dziennika, czyli tam, gdzie pojawiają się wpisy o postępie głównego wątku fabuły. UNSOLVED_JOURNAL dodaje do zakładki z nierozwiązanymi misjami, a SOLVED_JOURNAL – do zakładki, gdzie są wpisy z ukończenia misji.

Schemat takiego wpisu wygląda następująco:

Kod:
JOURNAL ~Nagłówek wpisu (najlepiej krótki)

Treść wpisu~


Przykład podam na bloku ‘place’ z poprzedniego podpunktu:

Kod:
IF ~~ THEN BEGIN place
SAY ~Świetnie! Ten kretyn siedzi tam, pod ścianą i żre moje mięso. Idźcie mu dokopać, a później wróćcie do mnie.~
IF ~~ THEN UNSOLVED_JOURNAL ~Skopać mięsokrada

Pewien facet imieniem Gienek zlecił mi zmianę kształtu nosa jego brata Zenka, który ukradł mu mięso. Obiecał w zamian nieprzebrane bogactwa, dlatego zdecydowałem się podjąć tej świętej misji. Zenek jest niedaleko ode mnie, chyba tylko kretyn nie zdoła go znaleźć. Mam nadzieję, że nie jestem kretynem.~ EXIT
END


Taka komenda spowoduje dodanie tego wpisu do zakładki niewykonanych zadań. Pozostałe komendy działają tak samo. I to wszystko na temat wpisów.

Ponadto poznaliśmy już podstawowe funkcje działań w zakresie jednego pliku .dlg – możecie już pisać dialogi pomiędzy jednym bohaterem niezależnym i graczem należącym do drużyny.



3. Linki zewnętrzne i dialogi na kilka postaci


3.1. Komenda EXTERN


Każdej postaci może być przypisany tylko jeden plik .dlg. W takim razie, aby kolejna postać włączyła się do rozmowy, musimy stworzyć link pomiędzy plikiem .dlg pierwszej i drugiej postaci.

Ta komenda (jej właściwa nazwa to EXTERN nazwa_pliku.dlg nazwa_bloku) pozwala na tworzenie połączenia z innym plikiem dialogowym. Samo EXTERN to skrót od ‘external link’, czyli ‘link zewnętrzny’ Zastosowanie tej komendy przejścia pozwala na tworzenie dialogów z więcej niż jedną postacią, a także np. wtrąceń członków drużyny.

Schemat bloku z wykorzystaniem EXTERN wygląda tak:

Kod:
IF ~(ewentualne warunki)~ THEN BEGIN (nazwa_bloku)
SAY ~(wypowiedź)~
IF ~(ew. warunki)~ THEN (ew. komendy typu REPLY/DO przejścia nr n) EXTERN NAZWA_PLIKU_.DLG nazwa_docelowego_bloku
END


Wyobraźmy sobie sytuację, że Gienek nawiązuje dialog z Zenkiem. Obaj są bohaterami niezależnymi, a więc zastosowanie EXTERN będzie potrzebne.

Kod:
IF ~See("Zenek")
!Dead("Zenek")~ THEN BEGIN zenek
SAY ~Ej, ty! Złodzieju!~
IF ~~ THEN EXTERN ZENEK zenek1
END


Jednak taki link jest linkiem ślepym, bo nie mamy stworzonego pliku zenek.dlg. Jednak nie jest to dla nas problemem, znamy już komendę BEGIN. Zapisujemy:

Kod:
BEGIN ~ZENEK~

IF ~~ THEN BEGIN zenek1
SAY ~No? Czegoś chciał?~
IF ~~ THEN EXTERN GIENEK zenek2
END


Teraz piszemy blok dla Gienka, jednak robimy to po komendzie BEGIN ~GIENEK~, a przed BEGIN ~ZENEK~ - czyli w obszarze pliku .dlg Gienka. Zapisujemy go pod blokiem ‘zenek’.

Kod:
IF ~~ THEN BEGIN zenek2
SAY ~Oddaj mi to, co ukradłeś! Słyszysz? Przyprowadziłem przyjaciół!~
IF ~~ THEN EXTERN ZENEK zenek3
END


I piszemy kolejny blok dla Zenka w obszarze zenek.dlg

Cały skrypt tego dialogu będzie wyglądał następująco:

Kod:
BEGIN ~GIENEK~

(... - inne bloki dialogowe)

IF ~See("Zenek")
!Dead("Zenek")~ THEN BEGIN zenek
SAY ~Ej, ty! Złodzieju!~
IF ~~ THEN EXTERN ZENEK zenek1
END

IF ~~ THEN BEGIN zenek2
SAY ~Oddaj mi to, co ukradłeś! Słyszysz? Przyprowadziłem przyjaciół!~
IF ~~ THEN EXTERN ZENEK zenek3
END

(...)
END //zakończenie ostatniego bloku na obszarze pliku gienek.dlg

BEGIN ~ZENEK~

(...)

IF ~~ THEN BEGIN zenek1
SAY ~No? Czegoś chciał?~
IF ~~ THEN EXTERN GIENEK zenek2
END

IF ~~ THEN BEGIN zenek3
SAY ~(wypowiedź)~
IF ~~ THEN EXTERN GIENEK zenek4
END

(....)
END //zakończenie ostatniego bloku na obszarze pliku zenek.dlg


Jest to klasyczny przykład dialogu łańcuchowego – po jednej wypowiedzi bezwarunkowo następuje inna.

Jeżeli takie dialogi ciągną się łańcuchowo, istnieje znacznie prostszy sposób zapisania ich. Zaraz objaśnię to w punkcie 3.2.

Komenda EXTERN działa podobnie, jak komenda GOTO i stosujemy ją w taki sam sposób, jeśli tylko chcemy stworzyć link zewnętrzny.

3.2. Skrypt bloku łańcuchowego


Dialogi łańcuchowe, jak ten z przykładu w 3.1, można zapisać w pliku .d w prostszy sposób za pomocą bloku łańcuchowego. Taki blok należy umieścić poza obszarami plików .dlg.

Bloki łańcuchowe rządzą się nieco innymi prawami, niż zwykłe zespoły bloków dialogowych typu:

Kod:
IF ~~ THEN BEGIN x
SAY ~(wypowiedź)~
=
~(dalsza część wypowiedzi)~
=
~(ostatnia część wypowiedzi)~
IF ~~ THEN (komendy przejścia)
END


Choć mimo to są do nich podobne. Oto przykład prostego bloku łańcuchowego – rozmowa między Lianevą i Raldonionem, dwoma postaciami z Pieśni Władającej. CRGOR02 to nazwa pliku .dlg Lianevy, a CRGOR04 to plik Raldoniona:

Kod:
CHAIN CRGOR02 eastnothcalm //komenda CHAIN rozpoczyna blok łańcuchowy, a nazwa pliku dialogowego informuje, kto rozpoczyna dialog; 'eastnothcalm' to nazwa bloku dialogowego
~Przyjrzyj się uważnie, <GABBER>. Ani jednego zaplutego potworka, poza tym w zielonym, która przy mnie stoi.~ //nawet w pierwszej wypowiedzi pominięte zostaje SAY
== CRGOR04 //przełączenie rozmawiającego na Raldoniona, '==' działa jak komenda EXTERN; po znakach równości piszemy nazwę pliku .dlg
~Och, niech cię szlag trafi... Czuję się, jakby w mojej głowie trwało powstanie zbrojne elfów.~ //wypowiedź Raldoniona
== CRGOR02 //przełączenie na Lianevę
~Nie użalaj się nad sobą. To nie wygląda szczególnie reprezentatywnie.~ //wypowiedź Lianevy
== CRGOR04 //przełączenie na Raldoniona
~...~
== CRGOR02
~Hah, to mi się nawet podoba, Raldonion. Z taką migreną możesz co najwyżej strzelić we mnie magicznym pociskiem.~
= //pojedynczy znak równości działa jak GOTO - link w zakresie pliku .dlg Lianevy
~Choć bardziej prawdopodobne, że próbując, podpalisz sobie szatę na tyłku.~
== CRGOR04
~(ugh...) Zaprawdę, jesteś złą kobietą, Lianeva...~
EXIT //koniec rozmowy; pomijamy IF ~~ THEN, oraz końcowy END


Struktura dość przejrzysta. Na końcu bloku łańcuchowego możemy umieścić komendy przejścia:
EXIT;
• komendę GOTO x (jeśli blok x należy do tego samego pliku .dlg, co ostatnia wypowiedź w bloku łańcuchowym);
EXTERN nazwa_pliku_.dlg x (jeżeli blok x nie należy do tego samego pliku .dlg, co ostatnia wypowiedź w bloku łańcuchowym)
END nazwa_pliku_.dlg x (działa tak samo, jak EXTERN)
COPY_TRANS (zastosowanie tej komendy opisane jest w punkcie 4.2.)

W bloku łańcuchowym nie możemy stosować REPLY ani JOURNAL (można jednak na końcu stworzyć przejście do zwykłego bloku dialogowego, w którym zostanie zastosowana odpowiedź, albo wpis).

Możemy jednak zastosować komendę DO i to przed każdym z linków w bloku łańcuchowym, np.:

Kod:
CHAIN GIENEK blok_x
~(wypowiedź)~
DO ~(akcja nr 1)~
== ZENEK
~(odpowiedź)~
(...)
== GIENEK
~(ostatni tekst)~
DO ~Attack("Zenek")~ //po zakończeniu dialogu Gienek atakuje Zenka
EXIT


Jednak powyższy blok łańcuchowy był uruchamiany z przejścia i nie był on uwarunkowany. Jeśli jednak pierwsza wypowiedź bloku łańcuchowego ma zawierać warunek rozpoczęcia, początek będzie wyglądał na przykład tak:

Kod:
CHAIN
IF ~NumTimesTalkedTo(0)~ THEN ILLANITH beginning
~(wypowiedź)~
(...)
EXIT


Aktorów może być oczywiście więcej niż dwóch, jednak cały dialog musi być tak uwarunkowany, aby wszyscy żyli i mogli rozmawiać (tj. nie byli nieprzytomni itp.). I wszyscy muszą być na tym samym obszarze. W innym wypadku gra się posypie.

A oto prostszy zapis dialogu między Zenkiem i Gienkiem z punktu 3.1:

Kod:
CHAIN
IF ~ See("Zenek")
!Dead("Zenek")~ THEN GIENEK zenek
~Ej, ty! Złodzieju!~
== ZENEK
~No? Czegoś chciał?~
== GIENEK
~Oddaj mi to, co ukradłeś! Słyszysz? Przyprowadziłem przyjaciół!~
(...)


3.3. APPEND – aktualizacje istniejących plików .dlg


Jeśli chcemy nie tylko dodawać, ale również modyfikować istniejące już pliki .dlg, komenda APPEND będzie niezastąpiona. Nie jest to komenda przejścia, ogranicza ona w pliku .d bloki dodawane do danego pliku .dlg.

Można ją zastosować do pisania wtrąceń bohaterów z drużyny.

W grze istnieje plik keldorj.dlg i jest on przypisany Keldornowi, kiedy ten jest w naszej drużynie. Załóżmy, że w piszemy plik illanith.dlg. Jeśli w pisanym przez nas nowym dialogu umieścimy taki blok:

Kod:
IF ~~ THEN BEGIN illamove
SAY ~Słyszałem, że w tym mieście jest stowarzyszenie paladynów... jakieś Promienne Serce, czy coś takiego. Może słyszeli o mojej organizacji... Będę czekał na ciebie w ich kwaterze.~
IF ~IsValidForPartyDialog("Keldorn")~ THEN EXTERN KELDORJ illakeldpaladins //warunek sprawdza, czy Keldorn jest w drużynie i czy może rozmawiać
IF ~!IsValidForPartyDialog("Keldorn")~ THEN GOTO illamove1 //wykrzyknik przed warunkiem to negacja danego warunku, czyli jeśli Keldorna nie ma w drużynie lub nie może on rozmawiać, rozmowa przejdzie do bloku 'illamove1'
END


Musimy dodać blok ‘illakeldpaladins’ w pliku keldorj.dlg. Możemy zrobić to za pomocą komendy APPEND. W tym samym pliku dialogowym poza obszarem illanith.dlg wpisujemy:

Kod:
APPEND KELDORJ //komenda aktualizacji danego pliku .dlg
IF ~~ THEN BEGIN illakeldpaladins
SAY ~Z pewnością ciepło cię przyjmą, elfie. Gościmy każdego, kto ma w cenie honor i służy dobru.~
=
~A tobie nie można odmówić żadnej z tych dwóch rzeczy.~
IF ~~ THEN EXTERN ILLANITH illakeldpaladins1 //link do bloku w pliku illanith.dlg
END //zakończenie danego bloku dialogowego
END //drugie END to zakończenie bloku APPEND


W ten sposób Keldorn komentuje wypowiedź Illanitha.

Tak budowane są wtrącenia do nowych dialogów. W zakresie jednego bloku APPEND możemy umieścić dowolną liczbę bloków dialogowych.

APPEND jest wykorzystywane również w blokach łańcuchowych, lecz jest ono ukryte w znaku przełączenia, czyli ‘==’.
Dzięki temu pliki .dlg poszczególnych aktorów bloku łańcuchowego mogą już być w grze, a przez skrypt dialogu łańcuchowego zostaną zmodyfikowane.

Teraz wiesz już wszystko, co potrzebne jest do pisania nowych dialogów. Warto jednak nauczyć się też bardziej szczegółowej modyfikacji istniejących.




4. Zaawansowane komendy i bloki


Komendy te, takie jak COPY_TRANS, EXTEND_TOP, czy INTERJECT są przydatne do modyfikacji plików dialogowych istniejących już w grze. Przydadzą się one, gdy będziemy chcieli tworzyć moda NPC z wtrąceniami czy komentarzami pojawiającymi się w różnych dialogach, lecz nie tylko.

O ile INTERJECT lub COPY_TRANS nie przydają się zbyt często w pisaniu dialogów (chyba, że tworzymy wtrącenia nowemu przyłączalnemu NPCowi), to komendy EXTEND_BOTTOM lub EXTEND_TOP warto znać, aby dodać niezależne przejście w istniejącym bloku dialogowym. Właśnie nimi zajmiemy się najpierw:

4.1. Dodawanie nowych przejść w blokach dialogowych, czyli EXTEND_TOP i EXTEND_BOTTOM


Te dwie komendy mają podobne zastosowanie – dodają one całkiem nowe przejścia w blokach dialogowych plików .dlg, które istnieją już w grze. Jednak aby określić blok, w którym zechcemy umieścić nowe przejście, trzeba użyć edytora DLTCEP.

Otwieramy zainstalowany DLTCEP i ustawiamy w nim setup, klikając na przycisk ‘Setup’ w lewym dolnym rogu okna (wystarczy podać ścieżkę pliku chitin.key, czyli rejestru całej gry BG II, do tego zaznaczyć typ gry i podać nazwę ustawień – obojętnie jaką, może być BG2. Zapisujemy i wychodzimy).

Następnie na pasku menu wybieramy Edit/Dialog (DLG), a gdy pokaże się okienko przeglądania pliku .dlg, klikamy ‘Load Dialog’ i wybieramy interesujący nas plik. Podczas rozwijania poszczególnych gałęzi drzewka dialogowego odnajdziemy oznaczenie interesującego nas bloku.

Bloki dialogowe plików .dlg mają nazwy od 0 wzwyż.

Komendy EXTEND_TOP i EXTEND_BOTTOM mają podobny schemat, a wygląda on tak:

Kod:
EXTEND_BOTTOM (nazwa modyfikowanego pliku .dlg) (nazwa modyfikowanego bloku)
IF ~(ew. warunki przejścia nr 1)~ THEN (komendy zdarzeń) (komenda linku)
IF ~(ew. warunki przejścia nr 2)~ THEN (komendy zdarzeń) (komenda linku)
END //zakończenie bloku EXTEND_BOTTOM


Zastosowania tej komendy są różne, od budowy wtrąceń NPCów po dodawanie nowej linii dialogu. Jednego z zastosowań nauczymy się na przykładzie dialogu Księgarza – opowiadacza z gospody na Wzgórzach Umar. Nazwa jego pliku .dlg to imnbook1.dlg. Oryginalny skrypt jego bloku dialogowego o nazwie 0 wygląda tak:

Kod:
IF ~True()~ THEN BEGIN 0
SAY ~ Przykro mi, ostatnimi czasy nie mam zbyt wiele ksiąg. Interes marnie się kręcił, więc przeniosłem większość towaru do Athkatli. Właściwie to nie rozmawiałem z nikim od tygodni.~
++ ~Nie powodziło ci się w handlu przez te wszystkie nieprzyjemne wydarzenia w okolicy?~ + 2
++ ~Przepraszam za kłopot.~ + 1
+ ~(oryginalne warunki)~ + ~Szukam informacji o księdze opisującej szczegóły leczenia wampiryzmu.~ + 4
END


W tym bloku są tylko trzy przejścia. Jeśli chcemy dodać czwarte, w pliku .d piszemy taką komendę:

Kod:
EXTEND_BOTTOM IMNBOOK1 0
+ ~Global("KaatjeIavScroll","GLOBAL",1)~ + ~Szukamy potężnego zwoju magicznego. Handlujesz też zaklęciami?~ + bookscrolls
END //zakończenie bloku

APPEND IMNBOOK1 //komenda APPEND dodaje do modyfikowanego pliku blok, do którego prowadzi link z nowego przejścia
IF ~~ THEN BEGIN bookscrolls
SAY ~Rzeczywiście, mogę coś takiego mieć. Jakie konkretnie zwoje was interesują?~
IF ~~ THEN REPLY ~Szukamy zwoju zaklęcia przeciwnego do zaklęcia Uwięzienie. Masz coś takiego?~ GOTO bookscrolls1 //link do kolejnego bloku
END
(...) //blok bookscrolls1 i inne
END //zakończenie bloku APPEND


Tak do bloku 0 dodaliśmy kolejne przejście, do którego stworzyliśmy kolejny blok i kolejny wątek rozmowy. Skrypt bloku 0 w pliku imnbook1.dlg po instalacji takiego dialogu wygląda następująco:

Kod:
IF ~True()~ THEN BEGIN 0
SAY ~ Przykro mi, ostatnimi czasy nie mam zbyt wiele ksiąg. Interes marnie się kręcił, więc przeniosłem większość towaru do Athkatli. Właściwie to nie rozmawiałem z nikim od tygodni.~
++ ~Nie powodziło ci się w handlu przez te wszystkie nieprzyjemne wydarzenia w okolicy?~ + 2
++ ~Przepraszam za kłopot.~ + 1
+ ~(oryginalne warunki)~ + ~Szukam informacji o księdze opisującej szczegóły leczenia wampiryzmu.~ + 4
+ ~Global("KaatjeIavScroll","GLOBAL",1)~ + ~Szukamy potężnego zwoju magicznego. Handlujesz też zaklęciami?~ + bookscrolls
END


I jako przejście numer cztery pojawia się to dodane przez EXTEND_BOTTOM. Jeśli zmienna globalna KaatjeIavScroll jest ustawiona na wartość 1, podczas rozmowy będziemy mogli wybrać tą odpowiedź.
Dzięki temu uzyskamy u Księgarza informacje na temat kupna zaklęcia Uwolnienie.

Komenda EXTEND_TOP różni się od EXTEND_BOTTOM tylko nieznacznie, ponieważ dodaje dane przejście nie jako ostatnie z przejść w danym bloku, tylko jako pierwsze.

Kolejne podpunkty punktu 4. polecam modderom, którzy mają już doświadczenie w pisaniu dialogów i ogólnie w modowaniu. Tych zaś, którzy znajdują się na początku drogi pisania skryptów dialogów zapraszam do przeczytania punktu 5., z którego dowiedzą się, jak zainstalować napisany dialog.

4.2. Kopiowanie listy przejść – komenda COPY_TRANS


Tej komendy używa się przy tworzeniu wtrąceń w ważnych momentach gry przy tworzeniu własnego przyłączalnego NPCa. Kopiuje ona całą listę przejść danego bloku w danym pliku dialogowym do bloku dialogowego, w którym COPY_TRANS użyjemy. Pokażę to na przykładzie dialogu przy zdradzie Yoshimo.

Kod:
EXTEND_BOTTOM YOSHJ 113 //tekst Yoshimo, po którym następują komentarze członków drużyny
IF ~IsValidForPartyDialogue("ILLANITH")~ THEN EXTERN ILLANIJ yoshibetrayilla //jeśli w drużynie jest Illanith, wypowie on swoje zdanie na temat Yoshimo
END

APPEND ILLANIJ //aktualizacja pliku .dlg Illanitha będącego w drużynie
IF ~~ THEN BEGIN yoshibetrayilla
SAY ~Zatem, "przyjacielu", zamierzasz poznać tajemnice śmierci? Niech tak się stanie, jeśli to jest twym życzeniem.~
COPY_TRANS YOSHJ 113 //skopiowanie oryginalnej listy przejść bloku 113 pliku yoshj.dlg
END
END


Oznacza to, że blok dialogowy, w którym Illanith grozi złodziejowi śmiercią będzie miał takie same przejścia, jak te zawarte w oryginalnym bloku 113 pliku yoshj.dlg.

Dokładnie aż 15 różnych przejść. Zainteresowani mogą przyjrzeć się danemu blokowi w DLTCEP, a następnie zaimplementować dany skrypt w grze (patrz punkt 5.) i zaobserwować zmianę.

4.3. Budowa wtrąceń – INTERJECT


Wtrącenia można budować przez zastosowanie EXTEND_BOTTOM i APPEND, tak jak to poniższe:

Kod:
EXTEND_BOTTOM C6ELHAN2 28
IF ~IsValidForPartyDialog("Illanith")~ THEN EXTERN ILLANIJ illasuld
END

APPEND ILLANIJ
IF ~~ THEN BEGIN illasuld
SAY ~Zniszczył całe elfie miasto? Będę pierwszym, który nabije tego mordercę na klingę.~
IF ~~ THEN EXTERN C6ELHAN 29
END
END


W tym wypadku Illanith komentuje wypowiedź Elhana zniszczeniach w Suldanessenarze. Między blokami 28 i 29 w pliku dialogowym Elhana nie występują żadne skomplikowane przejścia, dlatego obywamy się bez COPY_TRANS.

Taki sposób działa, jednak jest bardziej pracochłonny, a musimy się oszczędzać na następne dialogi, prawda? Lepiej zastosować blok INTERJECT. To samo wtrącenie zapisane za jej pomocą wygląda tak:

Kod:
INTERJECT C6ELHAN2 28 illasuld //oznaczenie podobne jak w EXTEND_TOP/BOTTOM
== ILLANIJ IF ~IsValidForPartyDialog("Illanith")~ THEN //konstrukcja tego dialogu przypomina blok łańcuchowy, jednak po przełączeniu aktora dodajemy IF ~(warunek)~ THEN
~Zniszczył całe elfie miasto? Auessie... Pozwól mi być pierwszym, który nabije tego mordercę na klingę.~ //wtrącenie Illanitha, pomijamy SAY
EXTERN C6ELHAN 29 //zakończenie charakterystyczne dla bloku CHAIN


Bloki INTERJECT są skonstruowane podobnie, jak bloki CHAIN i mogą być zakończone tak jak one, czyli przez komendę EXTERN (używaną zamiennie z END), GOTO lub EXIT. Po szczegóły odsyłam do punktu 3.2.

Możemy też rozbudować wtrącenie Illanitha, dodając do tego komentarz Elhana:

Kod:
INTERJECT C6ELHAN2 28 illasuld
== ILLANIJ IF ~IsValidForPartyDialog("Illanith")~ THEN
~Zniszczył całe elfie miasto? Auessie... Pozwól mi być pierwszym, który nabije tego mordercę na klingę.~
== C6ELHAN IF ~IsValidForPartyDialog("Illanith")~ THEN //powtarzamy warunek dla każdej kolejnej wypowiedzi tego wątku
~Mam nadzieję, że miasto nie zostało jeszcze zniszczone, elfie. Na razie mamy tylko doniesienia o atakach.~
GOTO 29 //ostatnią wypowiedź słyszymy od Elhana, dlatego stosujemy link wewnętrzny zamiast zewnętrznego


Całkiem, jak w CHAIN.

Jednak bloki INTERJECT tworzymy wtedy, kiedy wtrącenie danego NPCa będzie jedynym, albo kiedy chcemy pominąć pozostałe wtrącenia innych bohaterów. Tak, jak w przypadku pochlebstw wobec Adalon:

Kod:
INTERJECT UDSILVER 9 illaadalon //wtrącenie przy bloku 9 pliku dialogowego Adalon
== ILLANIJ IF ~IsValidForPartyDialog("Illanith")~ THEN
~Teraz już wiem, czemu srebrne smoczyce uznaje się za najpiękniejsze istoty. Twój urok przewyższa wszystko, co dotąd widziałem.~
EXTERN UDSILVER 58


Pomimo tego, że na temat urody smoczycy mogą wypowiedzieć się również jeden z czworga innych bohaterów, chcemy, aby wypowiedź Illanitha była jedyną. Jednak gdyby Illanitha nie było w drużynie, tylko jeden z pozostałych czworga mógłby zacząć kadzić Adalon, a następnie, z pominięciem trzech innych, dialog przeskoczyłby do bloku 58.

4.4. Połączenie komend INTERJECT i COPY_TRANS


To połączenie było tak popularne w modach, że do WeiDU dodano obsługę nowego sposobu dodawania bloków wtrącenia – bloku INTERJECT_COPY_TRANS.

Jej zapis jest taki sam, jak INTERJECT, tylko, że podczas gdy INTERJECT wywoływał akcję EXTERN, GOTO, EXITINTERJECT_COPY_TRANS zawsze wywołuje akcję COPY_TRANS.

Taki sposób pisania dialogu przydaje się, gdy dodajemy wtrącenie w to samo miejsce, gdzie mogą mówić inni bohaterowie. Na przykład w przypadku dialogu, gdy bohaterowie zauważają, że są w Piekle. Tam wypowiadają się *wszyscy*. W takim wypadku można zastosować ten blok. Będzie to wyglądało tak:

Kod:
INTERJECT_COPY_TRANS PLAYER1 25 helilla //blok o Piekle, po którym wszyscy się wypowiadają to właśnie blok nr 25 pliku player1.dlg
== ILLANIJ IF ~IsValidForPartyDialog("Illanith")~ THEN //warunek
~Nie sposób się z tobą nudzić, <CHARNAME>...~
END //zamiast GOTO, EXTERN lub EXIT, kończymy blok samym END - przecież wykonywaną akcją i tak jest COPY_TRANS, nie?


W ten sposób po Illanithu wypowiedzą się inni członkowie naszej drużyny, którzy spadli do Piekła za nami.

Podobnie rozpiszemy sprzeciw Illanitha po zawarciu układu z Firkraagiem:

Kod:
INTERJECT_COPY_TRANS FIRKRA02 32 illaattack //blok 32 pliku firkra02.dlg to ten, w którym podpisaniu układu sprzeciwia się 'dobra' część naszej drużyny
== ILLANIJ IF ~IsValidForPartyDialog("Illanith")~ THEN
~Nie tym razem, <CHARNAME>. Nie pozwolę, aby to doszło do skutku. Stawaj, a kiedy cię zabiję, sam obronię dziecko Garrena!~
DO ~LeaveParty()
Enemy()
Attack(Player1)~ //akcja - Illanith opuszcza drużynę, staje się wrogiem i atakuje głównego bohatera; pomijamy 'IF ~~ THEN', jak w blokach CHAIN
END


Gdybyśmy zastosowali zwykłe INTERJECT, inni członkowie drużyny nie mogliby się wypowiedzieć. Stosując INTERJECT_COPY_TRANS – mogą wszyscy.

4.5. Dodawanie nowych warunków do bloków w istniejących plikach .dlg


Ten punkt, w odróżnieniu od trzech poprzednich, ma niewiele wspólnego z wtrąceniami. Jednak przy tworzeniu modu sam miałem problem z tym, jak dodać warunek do istniejącego już bloku bez nadgrywania zmodyfikowanego pliku .dlg.

Do dodawania warunków dla całego bloku służy komenda ADD_STATE_TRIGGER. Przydaje się ona do dodawania zaprzeczeń jakiegoś warunku, by (gdy dany warunek jest spełniony) rozmowa rozpoczęła się w określony sposób.

Komenda dodająca nowy warunek jest prosta:

Kod:
ADD_STATE_TRIGGER (nazwa modyfikowanego pliku .dlg) (nazwa modyfikowanego bloku) ~(dodawany warunek lub warunki)~


Czyli jeśli do dialogu z Solarem w finale gry zechcemy dodać alternatywną linię dialogową, warunkowaną jakąś zmienną, do istniejącej linii dialogowej musimy wstawić zaprzeczenie takiego warunku.
Załóżmy, że zmienną sprawdza warunek Global("SolarAlternativeBranch","GLOBAL",1) – skrypt dodania zaprzeczenia tego warunku w istniejącej linii będzie wyglądał tak:

Kod:
ADD_STATE_TRIGGER FINSOL01 4 //blok zaczynający rozmowę po 'upadku' Melissany ~!Global("SolarAlternativeBranch","GLOBAL",1)~


Dzięki temu, jeśli SolarAlternativeBranch ma wartość 1, rozmowa przebiegnie alternatywnym torem, jeśli jednak ta zmienna ma wartość 0 – pozostanie po staremu.

5. Kompilacja i implementacja dialogu w grze


Kiedy skończymy pisać nasz dialog, będziemy chcieli go umieścić w grze. Przyjmijmy, że nazwa tego pliku .d to ‘dialog.d’.

Przygotowujemy zestaw instalacyjny naszego modu-dialogu. Składa się on z trzech elementów, czyli folderu o nazwie ‘dialog’, który zawiera w sobie pusty folder ‘backup’ i plik ‘dialog.d’. Poza tym folderem musimy mieć jeszcze pliki setup-dialog.exe (czyli aplikację WeiDU.exe o zmienionej nazwie), oraz plik setup-dialog.tp2.

Aby zaimplementować nasz dialog w plikach gry będziemy potrzebowali WeiDU (najlepiej najnowszej wersji). Zmieniamy jego nazwę na setup-dialog.exe. Ta aplikacja zajmie się kompilacją pliku lub plików .d.

Jednak musimy utworzyć plik z instrukcjami dla WeiDU. Plik ten nazwiemy setup-nazwa_folderu_z_modem.tp2, w tym wypadku setup-dialog.tp2. Plik .tp2 to zwykły plik tekstowy o zmienionym rozszerzeniu.

Otwieramy Notatnik i wpisujemy trzy linie, które zakwalifikują nasz dialog jako oddzielny mod, a następnie instrukcję skompilowania go:

Kod:
BACKUP ~dialog\backup~
AUTHOR ~(tu podaj swój nick i adres e-mail)~
BEGIN ~Mój dialog~ //ta nazwa będzie oficjalną nazwą danego komponentu modu

COMPILE ~dialog\dialog.d~
USING ~~ //ta komenda służy do używania plików .tra, ale w tym tutorialu tym się nie zajmujemy; pozostaje pusta


Plik zapisujemy jako setup-dialog.tp2.

Nasz zestaw instalacyjny powinien wyglądać tak:
- dialog //folder
-- backup //folder
-- dialog.d
- setup-dialog.exe
- setup-dialog.tp2


Następnie przenosimy folder dialog i pliki setup-dialog.exe i setup-dialog.tp2, po czym włączamy aplikację setup-dialog.exe i klikamy ‘y’, kiedy program zapyta nas, czy instalować mod.

Jeżeli program wskaże błędy, spójrz na dane przez WeiDU linie i sprawdź, gdzie w kodzie dialogu jest błąd. Popraw go, zapisz plik dialog.d i spróbuj zainstalować mod jeszcze raz.

Jeśli aplikacja nie znajdzie błędów w kodzie (bo ich nie będzie ;)) i wszystko dobrze zinterpretuje, instalacja przebiegnie pomyślnie. Gratuluję, właśnie dodałeś(aś) do gry całkiem nowy dialog!


Jednak aby dialog mógł funkcjonować w grze, musi być on przypisany do jakiejś osoby. Można to zrobić, edytując plik .cre za pomocą DLTCEP. Ale to już inna historia…

Wszystkie działy modowania są ze sobą powiązane. Jednak można się nauczyć każdego z osobna. Umiejętność pisania kodu dialogu leży nie w znajomości samego kodu, a w zrozumieniu całego logicznego mechanizmu dialogu. Należy umieć planować, co pozwoli stworzyć całe drzewko dialogowe.

Przy pisaniu kodu trzeba myśleć jak maszyna. Przy pisaniu samych wypowiedzi dialogowych – jak pisarz. Przy pisaniu kodu dialogu – jak jedno i drugie jednocześnie. I to chyba wszystko na ten temat.


W razie pytania dotyczącego któregoś punktu proszę zgłosić je na moje PW.

Źródła, z których korzystałem, pisząc ten tutorial:
- Oryginalne pliki BG II + ToB
- ReadMe WeiDU
- skrypty modów 'Er'vonyrah: Pieśń Władającej' i 'Historia pewnego Kronikarza'
- skrypty mojego porzuconego projektu o nazwie 'Illanith NPC Mod'
- moja własna wiedza i wyobraźnia...
I nic więcej. - L`f


dltcep71.zip
DLTCEP
Pobierz Plik ściągnięto 1230 raz(y) 973,01 KB

InfExp-0.85.zip
Infinity Explorer v0.85
Pobierz Plik ściągnięto 996 raz(y) 614,68 KB

_________________
AshfncaeicaliuheangfkacgakfgegcalgfcalhfcamhlhKi~.!
Ostatnio zmieniony przez L`f 2014-04-27, 18:07, w całości zmieniany 1 raz  
Podziękuj autorowi tego posta
 
 
 
Więcej szczegółów
Za tę wypowiedź podziękowali:
Gawith, Lava Del'Vortel, Wszelak, Marcin, Vinci, Kallen, morgan, Zed Nocear, Vel`Dan, Yochloll, madla, chisette, Alvarez, Jvegi, Kirara, Tuldor88
Tuldor88 
Uczeń Gonda
Dziki kurczak zagłady


Wiek: 29
Posty: 1742
Podziękowania: 129/135
Wysłany: 2014-04-04, 22:14   

Mam nadzieję ze L'f mnie nie złaja, acz widzę, że w punkciku 4 zabrakło jeszcze przydatnej komendy tedy pozwolę sobie dobrego Gondowego avatara zacytować :smile:

4.6. Dodawanie akcji do bloków w istniejących plikach .dlg [ADD_TRANS_ACTION]
L'f napisał/a:
Cytat:
Skoro można dodać odpowiedni warunek do danej wypowiedzi z klasycznego, oryginalnego baldura przez ADD_STATE_TRIGGER to czy mogę dodac do danej wypowiedzi tylko same akcje DO bez koniecznosci pisania kolejnego przejscia?
Da radę - na ratunek przybywa nam ADD_TRANS_ACTION. Komenda ta działa podobnie jak REPLACE_TRANS_TRIGGER i odrobinę tylko się różni strukturalnie od ADD_TRANS_TRIGGER. Konstrukcja wygląda następująco:
Kod:
ADD_TRANS_ACTION nazwa_pliku_dialogowego BEGIN numer_bloku END BEGIN numer_przejścia END ~dodawane_akcje~

Komendy BEGIN i END muszą być obecne, nawet jeśli nie dajesz numeru przejścia (wtedy akcje zostaną dodane do każdego z przejść bloku.
_________________
Heinrich Heine napisał/a:
Sen jest dobrą rzeczą, śmierć jeszcze lepszą, ale najlepiej byłoby wcale się nie narodzić.
Alvarez o modowaniu napisał/a:
Może przytoczę twierdzenie Liberty'ego, które jakoś tak idzie: planujesz jakiś projekt, wyznacz sobie termin, pomnóż potrzebny czas przez 2 a i tak nie zdążysz.

Wybrane fragmenty banterów:
Edwin napisał/a:
-Phi! Porównywać mnie do jakiegoś podrzędnego nekromanty! (Stanowczo na zbyt wiele sobie pozwala, muszę pokazać mu gdzie jego miejsce.) Prawdopodobnie przemawia przez ciebie zwykła zazdrość. Wy, maluczcy macie tendencje do zawiści wobec tych, którzy was przerastają. Ja zaś czynię to nie tylko talentem ale i wzrostem, karzełku.
-*Posłał Edwinowi szeroki uśmiech przemawiając serdecznym tonem* Jeszcze raz nazwiesz mnie „karzełkiem” a utnę ci na dole coś niezwykle małego, co może jednak mimo wszystko być ci drogie. Gdy zaś chodzi o te dyrdymały o talencie... znów przypominasz mojego żałosnego, byłego towarzysza...
Minsc napisał/a:
-Niebywałe, że ten chomik jeszcze oddycha. Znajdując się nieco bliżej ciebie wielkoludzie na pewno zaniechałbym tej czynności, powiedz, uważasz że pranie onuc urąga twej męskości, czy po prostu lubisz informować wrogów zapaszkiem o tym, iż się do nich zbliżasz?
-Boo być może jest niewielki Montaronie, ale jest też o wiele silniejszy niż się zdaje. A to, co czujesz to zapach prawdziwego mężczyzny, który przykryje każdy odór zła, na jaki trafi, co nie, Boo?.
Viconia napisał/a:
-Mmm... wciąż robisz wrażenie Viconio, moja ty hebanoskóra kusicielko. Zdajesz sobie sprawę jak działasz na otoczenie, prawda?
-Oczywiście samcze, dzięki temu jalukul, mężczyźni tacy jak ty – myślący kroczem zamiast głową – stają się łatwiejsi w kontrolowaniu

-cała prawda o Imoen :P
Podziękuj autorowi tego posta
 
 
 
Tuldor88 
Uczeń Gonda
Dziki kurczak zagłady


Wiek: 29
Posty: 1742
Podziękowania: 129/135
Wysłany: 2014-12-15, 20:36   

I kolejne malutkie uzupełnienie (póki pamiętam :P).

4.6. Dodawanie/podmienianie warunków i/lub akcji w blokach istniejących plików .dlg:
ADD_STATE_TIGGER, REPLACE_STATE_TRIGGER,
ADD_TRANS_TRIGGER, REPLACE_TRANS_TRIGGER
ADD_TRANS_ACTION, REPLACE_TRANS_ACTION

L'f pisał już o ADD_STATE_TIGGER, acz jest to tylko jedna z 6 bardzo przyjemnych komend. Poniżej zebrałem je razem dla Waszej wygody.

Opiszę ww na przykładzie najprostszego bloku dialogowego
Plik AAA.dlg napisał/a:
BEGIN AAA
IF ~WARUNEK_WYPOWIEDZI~ THEN BEGIN XYZ
SAY~WYPOWIEDŹ~
IF ~WARUNEK ODPOWIEDZI~ THEN REPLY ~ODPOWIEDŹ~ DO~EFEKTY~ EXIT
END
END

ADD_STATE_TRIGGER – do istniejących warunków wypowiedzi dodaje kolejne:
ADD_STATE_TRIGGER ~AAA(nazwa_pliku)~ ~XYZ(nazwa_bloku)~ ~dodawany_warunek~

REPLACE_STATE_TRIGGER – usuwa stary warunek wypowiedzi i wstawia nowy na jego miejsce:
REPLACE_STATE_TRIGGER ~AAA(nazwa_pliku)~ ~XYZ(nazwa_bloku)~ ~nowy_warunek~

ADD_TRANS_TRIGGER – dodaje dodatkowy warunek odpowiedzi:
ADD_TRANS_TRIGGER ~AAA(nazwa_pliku)~ ~XYZ(nazwa_bloku)~ ~dodawany_warunek~ ~nr_odpowiedzi~

REPLACE_TRANS_TRIGGER – podmienia istniejace warunki odpowiedzi na takie jakie podamy:
REPLACE_TRANS_TRIGGER ~AAA(nazwa_pliku)~ BEGIN ~XYZ(nazwa_bloku)~ END BEGIN ~nr_odpowiedzi~ END ~stary_warunek~ ~nowy_warunek~

ADD_TRANS_ACTION – dodaje kolejne akcje do tych już istniejących:
ADD_TRANS_ACTION ~AAA(nazwa_pliku)~ BEGIN ~XYZ(nazwa_bloku)~ END BEGIN ~nr_odpowiedzi~ END ~dodawane_akcje~

REPLACE_TRANS_ACTION – usuwa stare akcje w danej odpowiedzi i podmienia je na nowe:
REPLACE_TRANS_ACTION ~AAA(nazwa_pliku)~ BEGIN ~XYZ(nazwa_bloku)~ END BEGIN ~nr_odpowiedzi~ END ~stare_akcje~ ~nowe_akcje~


W przypadku, gdy musimy wstawić gdzieś numer odpowiedzi musimy pamiętać, że zawsze zaczyna się od 0, więc w przypadku jednej jedynej opcji do wyboru będzie to właśnie 0. Gdyby w bloku były dwie odpowiedzi to druga miałaby wartość 1, trzecia 2 itd

Powyższe 6 komend umożliwia sporą ingerencję w istniejące w grze dialogi (zauważmy, że jedyne czego nie mogliśmy przy ich pomocy zmienić to sama treść wypowiedzi danej istoty, czyli to co sie mieści w SAY~~). Jak widać mozemy całkowicie zmienić w nich warunki wypowiedzi BN/NPC, warunki odpowiedzi postaci, oraz akcje które dana opcja wywoła. Przy odpowiednim wprowadzeniu zmian możemy w prosty sposób nawet całkowicie zablokować starą ścieżkę dialogową i wprowadzić nasze własne poprawki.
_________________
Heinrich Heine napisał/a:
Sen jest dobrą rzeczą, śmierć jeszcze lepszą, ale najlepiej byłoby wcale się nie narodzić.
Alvarez o modowaniu napisał/a:
Może przytoczę twierdzenie Liberty'ego, które jakoś tak idzie: planujesz jakiś projekt, wyznacz sobie termin, pomnóż potrzebny czas przez 2 a i tak nie zdążysz.

Wybrane fragmenty banterów:
Edwin napisał/a:
-Phi! Porównywać mnie do jakiegoś podrzędnego nekromanty! (Stanowczo na zbyt wiele sobie pozwala, muszę pokazać mu gdzie jego miejsce.) Prawdopodobnie przemawia przez ciebie zwykła zazdrość. Wy, maluczcy macie tendencje do zawiści wobec tych, którzy was przerastają. Ja zaś czynię to nie tylko talentem ale i wzrostem, karzełku.
-*Posłał Edwinowi szeroki uśmiech przemawiając serdecznym tonem* Jeszcze raz nazwiesz mnie „karzełkiem” a utnę ci na dole coś niezwykle małego, co może jednak mimo wszystko być ci drogie. Gdy zaś chodzi o te dyrdymały o talencie... znów przypominasz mojego żałosnego, byłego towarzysza...
Minsc napisał/a:
-Niebywałe, że ten chomik jeszcze oddycha. Znajdując się nieco bliżej ciebie wielkoludzie na pewno zaniechałbym tej czynności, powiedz, uważasz że pranie onuc urąga twej męskości, czy po prostu lubisz informować wrogów zapaszkiem o tym, iż się do nich zbliżasz?
-Boo być może jest niewielki Montaronie, ale jest też o wiele silniejszy niż się zdaje. A to, co czujesz to zapach prawdziwego mężczyzny, który przykryje każdy odór zła, na jaki trafi, co nie, Boo?.
Viconia napisał/a:
-Mmm... wciąż robisz wrażenie Viconio, moja ty hebanoskóra kusicielko. Zdajesz sobie sprawę jak działasz na otoczenie, prawda?
-Oczywiście samcze, dzięki temu jalukul, mężczyźni tacy jak ty – myślący kroczem zamiast głową – stają się łatwiejsi w kontrolowaniu

-cała prawda o Imoen :P
  
Podziękuj autorowi tego posta
 
 
 
Tuldor88 
Uczeń Gonda
Dziki kurczak zagłady


Wiek: 29
Posty: 1742
Podziękowania: 129/135
Wysłany: 2015-03-28, 10:52   

4.7. Uproszczona podmiena opcji tekstowych w blokach istniejących plików .dlg: ALTER_TRANS i REPLACE_SAY

W poprzednim poście pisałem o akcjach REPLACE_TRANS_TRIGGER i REPLACE_TRANS_ACTION. Nie są one złe gdy chcemy podmienić jedną określoną rzecz w danej wypowiedzi ale z chwilą gdy wprowadzamy więcej zmian i konieczne jest uzycie obu (i czegoś jeszcze) w kodzie robi się bałagan.
Na pomoc przychodzi komenda jaką możemy jednocześnie podmienić kilka rzeczy w danym dialogu: ALTER_TRANS.

Zapis jest bardzo prosty:
ALTER_TRANS ~AAA(nazwa_pliku)~ BEGIN ~XYZ(nazwa_bloku)~ END BEGIN ~nr_odpowiedzi~ END
BEGIN ~Akcje~
END

W akcjach jakie można podjąć znajdują się:
Kod:
TRIGGER: - podmienia triggery odpowiedzi (IF~~)
ACTION: - podmienia akcje w odpowiedzi (DO~~)
REPLY: - podmienia treść w odpowiedzi (REPLY ~~)
JOURNAL / SOLVED_JOURNAL: UNSOLVED_JOURNAL - podmienia treść dodawana do dziennika
EPILOGUE: - podmienia epilog
FLAGS: - zmiana pozycji flag


Innymi słowy w bloku tekstowym AAA:
Cytat:
BEGIN AAA
IF ~True()~ THEN BEGIN 1
SAY~Cześć, jestem Zenek!~
IF ~~ THEN REPLY ~Won!~ EXIT
IF ~~ THEN REPLY ~A ja Jacek!~ EXIT
END
END


możemy zapisać coś takiego:

ALTER_TRANS AAA BEGIN 1 END BEGIN 1 (pierwsza odpowiedź ma numer 0, ta jaką edytujemy kolejny czyli 1) END
BEGIN "TRIGGER" ~InParty("Placek")~
"ACTION" ~AddexperienceParty(50)~
"REPLY" ~A ja Jacek, to zaś Placek!~
"SOLVED_JOURNAL" ~Spotkanie

Razem z Plackiem spotkaliśmy Zenka.~
END

i nasz przykładowy blok tekstowy zmienia się dzięki jednej prostej komendzie nie do poznania:
Cytat:
BEGIN AAA
IF ~True()~ THEN BEGIN 1
SAY~Cześć, jestem Zenek!~
IF ~~ THEN REPLY ~Won!~ EXIT
IF ~InParty("Placek")~ THEN REPLY ~A ja Jacek, to zaś Placek!~ SOLVED_JOURNAL ~Spotkanie

Razem z Plackiem spotkaliśmy Zenka.~ DO~AddexperienceParty(50)~ EXIT
END
END
Prawda ze przydatne? Jedyne czego nie zrobiliśmy (bo ALTER_TRANS tego nie potrafi) to podmienienie wypowiedzi Zenka na jakąś inną... i tu pojawia się kolejna komenda: REPLACE_SAY która podmienia treść wypowiedzi danego NPC a konstrukcję ma tak banalną jak to tylko możliwe:
REPLACE_SAY ~AAA(nazwa_pliku)~ ~XYZ(nazwa_bloku)~ ~nowy_tekst~

REPLACE_SAY AAA 1 ~Jestem Zenek, a wy coście za jedni?~
i wuala - zmieniliśmy calusieńki blok przy pomocy dwóch banalnych komend. Teraz zastanówcie się ile trzeba by sie rozpisywać by zrobic to samo inaczej :)
_________________
Heinrich Heine napisał/a:
Sen jest dobrą rzeczą, śmierć jeszcze lepszą, ale najlepiej byłoby wcale się nie narodzić.
Alvarez o modowaniu napisał/a:
Może przytoczę twierdzenie Liberty'ego, które jakoś tak idzie: planujesz jakiś projekt, wyznacz sobie termin, pomnóż potrzebny czas przez 2 a i tak nie zdążysz.

Wybrane fragmenty banterów:
Edwin napisał/a:
-Phi! Porównywać mnie do jakiegoś podrzędnego nekromanty! (Stanowczo na zbyt wiele sobie pozwala, muszę pokazać mu gdzie jego miejsce.) Prawdopodobnie przemawia przez ciebie zwykła zazdrość. Wy, maluczcy macie tendencje do zawiści wobec tych, którzy was przerastają. Ja zaś czynię to nie tylko talentem ale i wzrostem, karzełku.
-*Posłał Edwinowi szeroki uśmiech przemawiając serdecznym tonem* Jeszcze raz nazwiesz mnie „karzełkiem” a utnę ci na dole coś niezwykle małego, co może jednak mimo wszystko być ci drogie. Gdy zaś chodzi o te dyrdymały o talencie... znów przypominasz mojego żałosnego, byłego towarzysza...
Minsc napisał/a:
-Niebywałe, że ten chomik jeszcze oddycha. Znajdując się nieco bliżej ciebie wielkoludzie na pewno zaniechałbym tej czynności, powiedz, uważasz że pranie onuc urąga twej męskości, czy po prostu lubisz informować wrogów zapaszkiem o tym, iż się do nich zbliżasz?
-Boo być może jest niewielki Montaronie, ale jest też o wiele silniejszy niż się zdaje. A to, co czujesz to zapach prawdziwego mężczyzny, który przykryje każdy odór zła, na jaki trafi, co nie, Boo?.
Viconia napisał/a:
-Mmm... wciąż robisz wrażenie Viconio, moja ty hebanoskóra kusicielko. Zdajesz sobie sprawę jak działasz na otoczenie, prawda?
-Oczywiście samcze, dzięki temu jalukul, mężczyźni tacy jak ty – myślący kroczem zamiast głową – stają się łatwiejsi w kontrolowaniu

-cała prawda o Imoen :P
  
Podziękuj autorowi tego posta
 
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Dodaj temat do Ulubionych
Wersja do druku

Skocz do:  
Powered by phpBB modified by Przemo © 2003 phpBB Group