Wstęp
Oto jest. Poradnik dla niecierpliwych, opornych, albo po prostu lubiących konkret. Po co przedłużać? Jedziemy!
Przygotowanie
Musisz znaleźć folder, w którym będziesz pracować.
Windows Documents\My Games\Wesnoth<version>
W przypadku Windowsa, do tworzenia dodatków potrzebujesz czegoś lepszego niż ten marny notatnik, który masz już w systemie. Oczywiście, da się w nim tworzyć dodatki, ale musiałbyś być niezłym masochistą by wytrzymać pracę w czymś takim. Zaopatrz się w Notepad++ z https://notepad-p....
Mac OS X ~/Library/Application Support/Wesnoth_<version>
Linux ~/.local/share/wesnoth/<version>
Teraz wchodzimy w data\add-ons. Znalazłeś? Świetnie. Zapamiętaj gdzie jest, zrób sobie skrót, czy co tam chcesz.
Tworzymy podstawowy dodatek
Jesteś w folderze add-ons? Jeśli pobrałeś jakieś dodatki to tutaj znajdują się ich foldery. Wesnoth działa tak, że podczas uruchamiania gry przeszukuje wszystkie te foldery i czyta wszystkie pliki _main.cfg jakie znajdzie.
Stwórz nowy folder. To będzie folder twojego dodatku. Nazwij go jak chcesz. Radzę jednak unikać używania polskich znaków i spacji. Mogą one powodować błędy. Zamiast tego, możesz go nazwać np. moj_dodatek albo MojDodatek. Nazwa folderu nie ma wielkiego znaczenia, ale ważne była unikalna, bo jak dodasz jakiś inny dodatek, używający folderu o takiej samej nazwie, to może on nadpisać (czytaj: zepsuć) twój dodatek.
Wejdź do swojego folderu (w moim przypadku będzie to MojDodatek). Stwórz pusty plik tekstowy o nazwie _main (np. za pomocą jakiegoś edytora tekstu). Jeśli nie widzisz .txt za nazwą, to wyłącz ukrywanie rozszerzeń plików w systemie (nie będę tłumaczył jak to zrobić, nie o tym jest poradnik, poszukaj sobie). Zmień rozszerzenie z .txt na .cfg.
Masz już folder dodatku z plikiem _main.cfg w środku. Gratulacje, masz już działający dodatek do Wesnoth! Nic tylko świętować... ale chwila! Twój dodatek jest pusty. To znaczy, że nic nie dodaje do gry. Co komu po takim dodatku? Zmienimy to w następnej części kursu.
Edytowane przez Smok dnia 10-11-2016 22:47
Jak już wspomniałem, Wesnoth wymaga tylko pliku _main.cfg. Co prawda istnieją też inne pliki np. _server.pbl, których szuka, ale nie są one obowiązkowe, ani nie będą ci na razie do niczego potrzebne. A co z tym całym śmietnikiem, to jest masą folderów i plików jakie zawierają inne dodatki? Zapomnij o nich! Nie są do niczego potrzebne. Jedyne czego potrzebujesz do szczęścia to _main.cfg.
Otwieramy _main.cfg w edytorze tekstu. W Wesnoth używamy głównie języka WML (ale w pewnych przypadkach można korzystać też z lua). WML opiera się gównie na tak zwanych znacznikach (ang. tag), dzięki którym gra będzie wiedzieć czego od niej chcemy. Znaczniki najpierw otwieramy [znacznik], a potem zamykamy [/znacznik]. Między znacznikami możemy, a często wręcz musimy sprecyzować czego dokładnie chcemy. Dokonamy tego ustawiając wartości kluczy (ang. key, czym jest klucz wyjaśnię dalej).
W swoim kodzie (tekście), możesz używać do woli spacji, tabulatora i entera, byle tylko nie dzielić wyrazów, a ustawianie wartości klucza powinno odbywać się w jednej linijce.
Czas użyć znaczników [era].
Kod źródłowy
[era]
[/era]
W ten oto sposób dodaliśmy do gry nową erę. By nasza era działała poprawnie, brakuje jeszcze kilku rzeczy, które musimy wpisać między znacznikami. Przyda się dokumentacja: https://wiki.wesn...org/EraWML. Niezbędne będą klucze id oraz name. Wpisujemy między znacznikami nazwę klucza, potem =, na końcu wartość jaką chcemy mu ustawić.
Dla większego porządku, między każdymi znacznikami warto robić wcięcia tabulatorem.
id będzie nazwą ery niewidoczną dla gracza (musi być unikalne).
Dzięki id możemy odwoływać się do naszej ery w kodzie. Jeśli znacznik posiada klucz id, to ustawienie go jest niemal zawsze obowiązkowe, nawet jeśli go potem nie użyjemy, bowiem często używa go sama gra.
name to nazwa naszej ery wyświetlana w grze.
Kod źródłowy
[era]
id = MojaEra
name = "Moja Era"
[/era]
Zwróć uwagę, że każda wartość dla klucza, która nie jest id (albo liczbą), powinna być w cudzysłowach ””. W większości przypadków, stosowanie cudzysłowów nie jest obowiązkowe, bo gra i tak domyśli się, o co nam chodzi, jednak czasami pominięcie cudzysłowów może powodować błędy.
Dodajmy teraz do naszej ery dwie strony konfliktu: Elfy i Nieumarłych. Makro {RANDOM_SIDE} pozwoli na wybranie losowej frakcji.
Makro to nic innego jak gotowy kawałek kodu spakowany do postaci jednego wyrazu pomiędzy znakami {}. Zamiast pisać całą serię znaczników i kluczy, możemy skorzystać właśnie z makr, żeby zaoszczędzić czas i skorcić kod. Krótszy kod łatwiej jest ogarnąć. Tutaj znajduje się spis wszystkich makr w Wesnoth: https://www.wesno...ence.xhtml, jak by co. Na razie jednak nie ma potrzeby do niego zaglądać.
Nową stronę konfliktu dodamy znacznikiem [multiplayer_side]. Niezbędne nam będą klucze id i name, działające podobnie jak w przypadku ery.
Kod źródłowy
[era]
id = MojaEra
name = "Moja Era"
{RANDOM_SIDE}
[multiplayer_side]
id = Elfy
name = "Elfy"
[/multiplayer_side]
[multiplayer_side]
id = Nieumarli
name = "Nieumarli"
[/multiplayer_side]
[/era]
leader to id jednostki przywódcy. Id jednostek możemy znaleźć pod tym adresem: https://units.wes.... Można dodać więcej jednostek oddzielając je przecinkiem. recruit to lista dostępnych do rekrutacji jednostek.
Kod źródłowy
[era]
id = MojaEra
name = "Moja Era"
{RANDOM_SIDE}
[multiplayer_side]
id = Elfy
name = "Elfy"
leader = Elvish Lord
recruit = Elvish Archer
[/multiplayer_side]
[multiplayer_side]
id = Nieumarli
name = "Nieumarli"
leader = Dark Sorcerer, Skeleton
recruit = Walking Corpse
[/multiplayer_side]
[/era]
Teraz możesz już uruchomić grę i zobaczysz, że twoja era działa.
Brakuje jeszcze tylko obrazków reprezentujących frakcje. Dodamy je za pomocą kluczy image. Obrazki znajdziemy w folderze z zainstalowaną grą w folderze data/core/images. Jako wartość klucza image podajemy brakującą ścieżkę do obrazka, czyli np. "units/orcs/archer.png".
Kod źródłowy
[era]
id = MojaEra
name = "Moja Era"
{RANDOM_SIDE}
[multiplayer_side]
id = Elfy
name = "Elfy"
leader = Elvish Lord
recruit = Elvish Archer
image = "units/elves-wood/avenger+female-sword-1.png"
[/multiplayer_side]
[multiplayer_side]
id = Nieumarli
name = "Nieumarli"
leader = Dark Sorcerer, Skeleton
recruit = Walking Corpse
image = "units/undead/shadow-s-attack-4.png"
[/multiplayer_side]
[/era]
Na koniec, dobrym zwyczajem było by objąć naszą erę za pomocą warunku preprocesora. Kod preprocesora to kod wykonywany PRZED kodem WML. Są to specjalne wyrazy użyte po znaku #. Jeśli po znaku # nie użyjesz jednego z wyrazów specjalnych, gra nie zgłosi błędu a reszta linijki zostanie po prostu pominięta. Dla tego znak # również służy do zostawiania komentarzy w kodzie. Dodajmy #ifdef MULTIPLAYER na początku naszego kodu i #ednif na końcu. Po co? Ten kod mówi grze, że ma załadować wszystko co jest pomiędzy #ifdef i #endif (czyli naszą erę) jeśli rozpoczynamy grę w trybie wielu graczy. Takie warunki pozwalają uniknąć ładowania elementów naszego dodatku, kiedy nie są potrzebne.
Kod źródłowy
#ifdef MULTIPLAYER
[era]
id = MojaEra
name = "Moja Era"
{RANDOM_SIDE}
#Pierwszy komentarz. Pod spodem frakcja elfów.
[multiplayer_side]
id = Elfy
name = "Elfy"
leader = Elvish Lord
recruit = Elvish Archer
image = "units/elves-wood/avenger+female-sword-1.png"
[/multiplayer_side]
#Drugi komentarz. Poniżej mamy frakcję nieumarłych.
[multiplayer_side]
id = Nieumarli
name = "Nieumarli"
leader = Dark Sorcerer, Skeleton
recruit = Walking Corpse
image = "units/undead/shadow-s-attack-4.png"
[/multiplayer_side]
[/era]
#endif
Solidny materiał, w artykułach bardzo się przyda, biorąc pod uwagę że obecna dokumentacja jest już trochę przestarzała.
Następny poradnik będzie o jednostkach? Jeśli tak to będzie już trochę więcej informacji do zawarcia. Ale czekam z niecierpliwością.
Edytowane przez Piko dnia 09-11-2016 20:35
Tu cię zaskoczę. Następny poradnik, będzie o publikacji dodatku na serwerze. Jednostki to dość obszerny temat. Mam go zamiar poruszyć trochę później. Na początku chciałbym omówić wszystko, co powinna wiedzieć osoba, która chce robić tylko ery. Są to dosyć łatwe tematy. Na trudniejsze rzeczy przyjdzie czas.
Edytowane przez Smok dnia 09-11-2016 22:26
W poprzednim poradniku ukończyliśmy nasz dodatek dodający erę. Czas podzielić się nim ze światem. Do dzieła!
Nie publikuj niedokończonych/nieprzetestowanych dodatków. Zaśmiecanie serwera wątpliwej jakości dodatkami to ciężki grzech dla wesnothczyka. Dlatego polecam skończyć ten poradnik przy jednym posiedzeniu, by nie trzymać naszego „testowego” dodatku zbyt długo na serwerze.
Przygotowanie pliku _server.pbl
Nieprzypadkowo w poprzednim kursie wspomniałem o pliku _server.pbl. Będzie potrzebny, jeśli chcesz opublikować swój dodatek na serwerze dodatków. Taki plik tworzymy podobnie jak _main.cfg.
Tu znajdziesz dokładne informacje na temat tego, jak powinna wyglądać zawartość tego pliku: https://wiki.wesn...org/PBLWML. Na pierwszy ogień pójdą klucze title, czyli nazwa oraz description, czyli opis twojego dodatku. Następne author, czyli twój nick. Najlepiej by był zgodny nickiem na oficjalnym forum. email to e-mail kontaktowy do autora.
Kod źródłowy
title="My Test Addon"
description="Just doing tutorial about how to upload addons. Ignore. I will delete this very soon."
author="Me, artwork by myself"
email="name@example.com"
icon to ikonka reprezentująca dodatek. Wskazujesz ją podobnie jak image w poprzednim poradniku. type to kategoria (listę wszystkich znajdziesz w linku). version, czyli numer wersji dodatku (przykłady również znajdziesz w linku).
Kod źródłowy
icon="misc/red-x.png"
type="era"
version="0.0.1"
Świetnie, uzupełniliśmy już najważniejsze informacje o dodatku. Teraz przyszła kolej na passphrase, czyli niewidoczne dla innych hasło. Nie jest ono wymagane do pobrania dodatku, ale zarządzania nim. Jeśli chcesz przesłać nową wersję dodatku, musi ona zawierać plik _server.pbl z identycznym kluczem passphrase. Chroni on przed trollami próbującymi podmienić lub usunąć twój dodatek z serwera.
Nie używaj haseł, których używasz gdziekolwiek indziej. Hasła do dodatków nie są nawet szyfrowane i mogą zostać łatwo wykradzione przez hakerów.
Kod źródłowy
passphrase="qwerty123"
Znacznik [feedback] umożliwia umieszczenie w opisie dodatku linku do poświęconemu dodatkowi wątkowi na oficjalnym forum. Wewnątrz tego znacznika używamy klucza topic_id. Jego wartość odpowiada końcówce adresu do twojego wątku. Dla adresu https://forums.wesnoth.org/viewtopic.php?t=43318 będzie to 43318.
Kod źródłowy
[feedback]
topic_id=12345
[/feedback]
Wszystko już gotowe. Oto ostateczny wygląd pliku:
Kod źródłowy
title="My Test Addon"
description="Just doing course about how to upload addons. Ignore. I will delete this very soon."
author="Me, artwork by myself"
email="name@example.com"
icon="misc/red-x.png"
type="era"
version="0.0.1"
passphrase="qwerty123"
[feedback]
topic_id=12345
[/feedback]
Publikacja i zarządzanie dodatkiem
Uruchom Wesnoth i otwórz menu pobierania dodatków. Na samym dole listy dodatków powinna pojawić się pozycja Opublikuj dodatek: <nazwa_dodatku>.
Zaznaczamy ją i nasikamy OK. Musimy zaakceptować warunek korzystania z serwera dodatków.
To wszystko. Już możesz znaleźć swój dodatek pośród innych.
Będzie miał opis zgodny z tym co zamieściłeś w pliku _server.pbl.
Wyczyść pole filtru i ponownie zjedź na sam dół listy. Pojawi się tam pozycja usunięcia dodatku.
Możesz teraz ponownie użyć pozycji publikacji do zaktualizowania dodatku. Jeśli wersja podana w pliku _server.pbl nie jest większa od tej na serwerze, pojawi się stosowne ostrzeżenie. Edytowane przez Smok dnia 16-12-2016 17:48
Jedyne czego brakuje do pełni szczęścia naszej erze, to tłumaczeń na inne języki. Aby przygotować tłumaczenie, będziemy potrzebowali specjalnego pliku z końcówką .po oraz edytor takich plików. Tutaj masz listę proponowanych edytorów: https://wiki.wesn...tors#Tools. Ja będę korzystał z multiplatformowego poEdit.
Przygotowanie dodatku do przetłumaczenia
Zanim zdobędziemy plik .po, musimy odpowiednio przygotować dodatek. Otwórz plik _main.cfg. Na początek potrzebujemy domeny tłumaczeń. Stworzymy ją znacznikiem [textdomain]. Dwa niezbędne klucze to name oraz path. name to nazwa naszego tłumaczenia. Powinno się je nazywać wesnoth-<nazwa_folderu_dodatku>. path to ścieżka do naszego folderu z tłumaczeniami, zaczynająca się od folderu data. Powinna wyglądać tak: data/add-ons/<nazwa_folderu_dodatku>/<folder_z_tłumaczeniami>.
Ponieważ nasz dodatek nie ma jeszcze folderu na tłumaczenia, stwórzmy go sobie. Ja nazwałem go translations. Dodajmy jeszcze #textdomain <nazwa_tłumaczenia> na początek pliku. Wszystkie pliki, które mają być przetłumaczone, muszą się tak zaczynać.
Teraz przerobimy trochę kod naszej ery. Zmienimy nazwy widoczne w grze z polskich na angielskie. Dzięki temu, jeśli ktoś gra w języku, na który nasz dodatek nie jest przetłumaczony, będzie miał wszystko po angielsku. Dodatkowo, przed każdym tekstem, który ma zostać przetłumaczony stawiamy znak _. Pozwoli to później na automatyczne wygenerowanie pliku .po.
Kod źródłowy
#ifdef MULTIPLAYER
[era]
id = MojaEra
name = _"My Era"
{RANDOM_SIDE}
#Pierwszy komentarz. Pod spodem frakcja elfów.
[multiplayer_side]
id = Elfy
name = _"Elves"
leader = Elvish Lord
recruit = Elvish Archer
image = _"units/elves-wood/avenger+female-sword-1.png"
[/multiplayer_side]
#Drugi komentarz. Poniżej mamy frakcję nieumarłych.
[multiplayer_side]
id = Nieumarli
name = _"Undead"
leader = Dark Sorcerer, Skeleton
recruit = Walking Corpse
image = "units/undead/shadow-s-attack-4.png"
[/multiplayer_side]
[/era]
#endif
Jeśli przyjrzysz się powyższemu kodowi, zauważysz że postawiłem znak _ również przed ścieżką do obrazka. Jakkolwiek dziwnie to nie zabrzmi, ścieżki też można tłumaczyć. Pozwoli to np. na podmianę obrazka zawierającego angielski tekst, na jego spolszczoną wersję.
Wszystko gotowe. Oto ostateczna wersja pliku _main.cfg:
#ifdef MULTIPLAYER
[era]
id = MojaEra
name = _"My Era"
{RANDOM_SIDE}
#Pierwszy komentarz. Pod spodem frakcja elfów.
[multiplayer_side]
id = Elfy
name = _"Elves"
leader = Elvish Lord
recruit = Elvish Archer
image = _"units/elves-wood/avenger+female-sword-1.png"
[/multiplayer_side]
#Drugi komentarz. Poniżej mamy frakcję nieumarłych.
[multiplayer_side]
id = Nieumarli
name = _"Undead"
leader = Dark Sorcerer, Skeleton
recruit = Walking Corpse
image = "units/undead/shadow-s-attack-4.png"
[/multiplayer_side]
[/era]
#endif
W końcu możemy zająć się sprawą pliku .po.
Pozyskiwanie pliku .po
Istnieją trzy sposoby pozyskania pliku .po.
WesCamp
Aby pozyskać plik .po z WesCamp należy ustawić w naszym pliku _server.pbl klucz translate na true
Kod źródłowy
translate=true
Następnie nasz dodatek musi zostać opublikowany na serwerze (i dlatego na razie nie polecam tego sposobu), a my za jakiś czas będziemy mogli znaleźć nasz plik .po na stronie https://www.wesno...g/gettext/.
Użycie programu, który potrafi generować pliki .po dla Wesnoth
Takim programem jest WesPo. Można go pozyskać z tąd: http://wespo.sour.... Uruchamiamy WesPo i wskazujemy folder naszego dodatku. Możemy też zaznaczyć opcję Fuzzy.
Fuzzy oznaczy wszystkie teksty w pliku .po jako niepewne. To czy zaznaczysz tę opcję, nie ma tak na prawdę znaczenia. Niektóre edytory .po specjalnie wyróżniają tak oznaczone teksty. Może to poprawić komfort pracy tłumaczowi, który łatwiej odróżni teksty przetłumaczone od tych, którymi jeszcze się nie zajął.
Klikamy na Create skele.po. W folderze dodatku pojawi się plik skele.po.
Ręczne stworzenie pliku .po
To wcale nie jest trudne! Stwórz w dodatku nowy plik tekstowy. Nazwij go nazwą swojego tłumaczenia i zmień końcówkę na .po (wesnoth-MojDodatek.po). Na początku naszego nowego pliku dodajemy dwie linijki: msgid "" i msgstr "".
Kod źródłowy
msgid ""
msgstr ""
Zostawiamy linijkę przerwy i ponowne dodajemy msgid "" i msgstr "". Tym razem uzupełnimy sobie cudzysłowy. Po msgid będzie tekst oryginalny, jaki ma zostać przetłumaczony. Po msgstr będzie jego przetłumaczona wersja.
Kod źródłowy
msgid ""
msgstr ""
msgid "My Era"
msgstr "Moja Era"
Dodajmy jeszcze wszystkie pozostałe teksty, które chcemy przetłumaczyć. Nie musimy od razu tłumaczyć naszych tekstów. Wygodniej będzie dokończyć tłumaczenie w edytorze .po.
Co zrobić z gotowym plikem .po
Mamy już plik .po. Posłuży on do wygenerowania pliku .mo, z którego kożysta gra. Ponieważ .mo musi się nazywać <nazwa_tłumaczenia>.mo, dla wygody upewnij się twój plik .po nazywa się <nazwa_tłumaczenia>.po (wesnoth-MojDodatek.po). Przenieś go folderu tłumaczeń (translations).
W folderze tłumaczeń konieczne będzie utworzenie właściwie nazwanego folderu dla języka, na jaki tłumaczymy. Podpowiedź co do nazwy, możesz znaleźć w <folder_z_zainstalowanym_Wesnoth>/translations. Dla polskiego języka będzie to pl. W folderze pl utwórz folder o nazwie LC_MESSAGES (to w nim Wesnoth będzie szukać pliku tłumaczenia). Do niego przenieś plik .po. Możesz zostawić również kopię pliku .po w folderze translations, jako bazę dla innych tłumaczeń.
Tłumaczenie dodatku i generowanie pliku .mo
Otwórz plik .po w pl/LC_MESSAGES za pomocą edytora .po.
Teraz wybierając teksty z listy możesz dopisywać do nich tłumaczenia. My era przetłumaczyłem na Moja Era, Elves na Elfy, Undead na Nieumarli, a ścieżkę do obrazka podmieniłem na units/elves-wood/shyde.png.
Nawet jeśli edytor każe ci uzupełnić jakieś informacje o twoim tłumaczeniu, nie musisz tego robić. Po prostu przetłumacz teksty, a resztą się nie przejmuj.
Na koniec zapisz. Jeśli twój edytor nie skompiluje pliku .po na plik .mo automatyczne przy zapisie, powinien posiadać gdzieś opcję kompilacji. W folderze LC_MESSAGES powinien pojawić się plik .mo.
Pliki .po są grze niepotrzebne i teraz możesz je bezpiecznie usunąć. Radzę je jednak zachować. Ułatwi to nanoszenie poprawek, albo tworzenie nowych tłumaczeń. Oczywiście, gdy dodatek się rozrośnie, trzeba będzie przygotować nowy plik .po.
Przetestuj swoje tłumaczenie w grze. Edytowane przez Smok dnia 16-12-2016 17:50
Tym razem umieścimy w naszym dodatku nową mapę, w którą będzie można zagrać w trybie wielu graczy.
Nie będę tłumaczył obsługi edytora map, bo jest on bardzo prosty. Kiedy stworzysz już swoją mapę (na potrzeby poradnika możesz użyć dowolnej mapy, nawet takiej z samą trawą), nie zapomnij umieścić pozycji startowych i zapisać (swoją nazwałem mapa).
Umieszczamy mapę w naszym dodatku
W folderze dodatku stwórz folder na mapy (u mnie to będzie maps) i umieść w nim swoją mapę. Oczywiście, mapę możesz równie dobrze umieścić bezpośrednio w folderze dodatku, ale żeby uniknąć bałaganu zalecam segregować rzeczy w odpowiednich folderach. Samo umieszczenie mapy w dodatku jednak nie wystarczy. Musisz stworzyć scenariusz, by gra wiedziała co z tą mapą zrobić. Istnieją dwa typy scenariuszy. Tworzymy je znacznikami [scenario] oraz [multiplayer]. Scenariusze typu [scenario] są nie widoczne w grze i mogą posłużyć do stworzenia kampanii. My jednak zajmiemy się drugim typem. Dzięki użyciu [multiplayer] zamiast [scenario], nasz scenariusz pojawi się na liście dostępnych map. Dodaj znaczniki [multiplayer] między #ifdef i #enddef, gdzieś obok naszej ery. Musimy podać kilka niezbędnych informacji o naszej mapie. Dokumentację znajdziesz tutaj: https://wiki.wesn...cenarioWML. Użyj kluczy id i name, które już wiesz co oznaczają. W kluczu description podamy opis naszej mapy. map_data to ścieżka do mapy wyglądająca tak: {~add-ons/<reszta_ścieżki>}.
Kod źródłowy
[multiplayer]
id = MojaMapa
name = _ "2p - MojaMapa"
description = _ "Opis"
map_data = "{~add-ons/MojDodatek/maps/mapa.map}"
[multiplayer]
Mapę już można uruchomić, ale nie będzie na niej muzyki ale ani pór dnia. Dodamy je makrami {DEFAULT_SCHEDULE} i {DEFAULT_MUSIC_PLAYLIST}. Aby nasza mapa nie zaczynała się zawsze o świcie, dodamy random_start_time=yes.
Kod źródłowy
[multiplayer]
id = MojaMapa
name = _ "2p - MojaMapa"
description = _ "Opis"
map_data = "{~add-ons/MojDodatek/maps/mapa.map}"
Zrobił się trochę długi. Jak tak dalej pójdzie, będziesz musiał scrollować pół dnia, żeby coś w nim znaleźć. Podzielimy sobie kod naszego dodatku na więcej plików. Stwórz folder multiplayer. W nim plik MojaMapa.cfg. To tu umieścimy sobie nasz scenariusz. Wytnij znaczniki [multiplayer] razem z zawartością i wklej do MojaMapa.cfg. Możesz dodać też #textdomain wesnoth-MojDodatek na początek.
Dodanie #textdomain wesnoth-MojDodatek w pliku _main.cfg zwalnia z konieczności umieszczania go w innych plikach. Jeśli zdecydowałeś się korzystać akurat z WesPo, musisz zawsze dodawać #textdomain wesnoth-MojDodatek na początek pliku, by program go nie pomiął.
Żeby gra wiedziała gdzie szukać naszego kodu należy użyć {~add-ons/MojDodatek/multiplayer} w miejscu gdzie wcześniej był kod. Dzięki temu przeszuka folder multiplayer i wykona WSZYSTKIE pliki .cfg jakie w nim znajdzie. Oto co teraz mamy:
Teraz, kiedy masz już niezbędne podstawy, przyszedł czas na naukę tworzenia jednostek.
Tworzymy jednostkę od zera
Otwórz _main.cfg. Pomiędzy #ifdef i #endif dodaj znacznik [units]. W tym znaczniku możesz użyć kilku rodzajów znaczników (spis tutaj: https://wiki.wesn...g/UnitsWML), by dodawać różne rzeczy związane z jednostkami, np. nowy typ jednostki, znacznikiem [unit_type]. Stworzymy sobie absolutnie minimalistyczną jednostkę używając znacznika [unit_type] i ustawiając jedyny niezbędny klucz, czyli id na GoblinHunter. Nasza jednostka będzie goblińskim łowcą.
Kod źródłowy
[units]
[unit_type]
id = GoblinHunter
[/unit_type]
[/units]
Stwórz folder na jednostki units. Znacznik [unit_type] przenieś do pliku GoblinHunter.cfg w tym folderze. [units] zostanie w pliku _main.cfg, żeby nie trzeba było go powtarzać w każdym pliku z jednostką, tworząc za każdym razem coś takiego:
By móc łatwo testować naszą jednostkę w grze, dodajmy ją listy rekrutacji elfów, w naszej erze.
Kod źródłowy
recruit = Elvish Archer, GoblinHunter
Przetestuj jednostkę w grze. Zobaczysz pustą jednostkę, bez nazwy, wyglądu, na poziomie 0, o koszcie 1, z punktami życia i ruchu także równymi 1. Będzie miała 0% obrony na każdym terenie i nie będzie mogła się ruszać, ponieważ wszystkie typy terenu będą dla niej oznaczone jako niedostępne. Twoja jednostka także pojawiła się także w spisie jednostek (możesz szybko podejrzeć jej opis klikając na nią prawym przyciskiem myszy i wybierając opcję Opis Jednostki).
Nadajmy jej nazwę i obrazek kluczami name i image (jeśli chcesz użyć własnego obrazka zobacz ostatni rozdział tego poradnika). Użyj klucza movement aby ustawić ilość punktów ruchu oraz movement_type aby rozwiązać problem z obroną terenową i kosztami ruchu. Jako wartość klucza movement_type, wybierz jeden z typów ruchu dostępnych w grze, jako bazę. Później będzie można go nieco przerobić. Spis dostępnych typów znajdziesz w data/core/units.cfg na samym końcu pliku. Łatwiejszą metodą może się jednak okazać podejrzenie pliku jednostki w data/core/units, której typu ruchu chcesz użyć.
Kod źródłowy
#textdomain wesnoth-MojDodatek
[unit_type]
id = GoblinHunter
name = _ "Goblin hunter"
image = "units/goblins/rouser.png"
movement = 5
movement_type = orcishfoot
[/unit_type]
Przetestuj jednostkę.
Teraz ma już nazwę, obrazek... coś jest nie tak. Nasza jednostka jest różowa (a dokładniej mówiąc w kolorze magenta) zamiast w kolorze gracza. Co zrobić żeby zmieniła kolor? Użyj klucza flag_rgb i ustaw go na magenta. To samo możesz zrobić używając makra {MAGENTA_IS_THE_TEAM_COLOR}. Jak już wspomniałem możemy zmodyfikować nieco nasz typ ruchu. Oto kod:
Zmniejszyliśmy koszt ruchu przez las do 1. Ustawiliśmy obronę w lesie na 60% (wartość to tak naprawdę szansa w % na bycie trafionym, na danym terenie). Dodaliśmy także 40% odporności na obrażenia sieczne (wartość to tak na prawdę % obrażeń otrzymywanych od danego typu ataków).
Jeśli chcesz wprowadzić więcej zmian, podejrzyj typy ruchu na końcu pliku data/core/units.cfg. Zobacz jak tam to jest zrobione.
Czas ulepszyć naszą jednostkę dodając jeszcze kilka kluczy. level określa poziom jednostki, cost jej koszt w złocie, hitpoints punkty życia, alignment określa czy jednostka jest chaotyczna/neutralna itp. (gra rozpoznaje tylko angielskie nazwy, dla tego wartości zawsze piszemy po angielsku), race to rasa. gender określa płeć jednostki (male/female, domyślnie male). Można też użyć listy gender = male, female, jeśli chcemy aby jednostka posiadała zarówno wariant męski, jak i żeński. Ostatnie 2 klucze mogą nie wydawać się aż takie ważne, ale warto o nich nie zapominać. usage podpowie AI, jak ma używać naszej jednostki (możliwe wartości spisane są w dokumentacji). die_sound to dźwięk, jaki będzie wydawać jednostka umierając (podejrzyj u jednostek goblinów).
Trochę tego było. Sprawdź efekt w grze. Dzięki określeniu rasy nasz goblin zyskał imię i cechy typowe dla goblina. Pojawia się też losowo, jako goblin lub goblinka. Poza inną odmianą wyrazów, nie różnią się niczym od siebie. Naprawimy to przy okazji omawiania wariacji.
Teraz zajmiemy się sprawami związanymi z doświadczeniem. Użyj klucza experience by określić ilość punktów doświadczenia potrzebnych do awansu. Goblin nie awansuje, dopóki nie określimy w jaki sposób ma awansować. Jeśli chcesz by jednostka awansowała na inną, użyj klucza advances_to, a jako wartość podaj listę id jednostek, na które może awansować (podobnie jak w przypadku listy liderów, czy rekrutacji). Jeśli jednostka nie będzie awansować na inną, musisz określić, jak ma przebiegać After max level advancement, czyli awans dla jednostek z maksymalnym poziomem. Możesz stworzyć własny sposób znacznikiem [advancement], lub użyć standardowego sposobu awansowania makrem {AMLA_DEFAULT}.
Możesz użyć znacznika [abilities], aby dodać jednostce specjalne umiejętności (zdecydowałem się na zasadzkę i harcownika). Umiejętności możesz dodawać za pomocą odpowiednich makr. Ich spis znajdziesz w pliku data/core/macros/abilities.cfg. Aby informacje o jednostce były kompletne, dodajmy jeszcze portret profile (będzie on używany również w dialogach) oraz opis description. Jeśli dodajesz jakieś specjalne umiejętności, nie zapomnij na końcu opisu dodać +{SPECIAL_NOTES}+{<makro_z_opisem_umiejętności>}. {SPECIAL_NOTES} zawiera tekst "Uwagi specjalne:". Znaki + mówią grze, że ma połączyć dwa teksty w jeden, dzięki czemu możemy dodać kolejne kawałki tekstu do opisu. Makra związane z opisami umiejętności znajdziesz w pliku data/core/macros/special-notes.cfg.
Nasz goblin jest już w pełni funkcjonalny, jednak nie posiada żadnych ataków. Dodajmy jeden znacznikiem [attack]. name to nazwa ataku (nie można jej przetłumaczyć, to coś w rodzaju id). description to również nazwa, wyświetlana w grze (można przetłumaczyć). type to rodzaj ataku (np. ognisty, sieczny, astralny itp., oczywiście, w kodzie używamy angielskiej nazwy). range określa czy to atak wręcz czy dystansowy (melee/range). damage i number to ilość obrażeń od ataku oraz liczba ataków. icon to obrazek ataku. W znaczku [specials] dokładnie tak samo, jak w przypadku umiejętności, można dodać specjalne właściwości ataku (makra znajdziesz w tych samych plikach). Nie zapomnij dodać też odpowiednich makr, do opisu jednostki.
[attack]
name = spear
description =_"spear"
type = pierce
range = melee
damage = 10
number = 2
icon= "attacks/spear-orcish.png"
[specials]
{WEAPON_SPECIAL_FIRSTSTRIKE}
[/specials]
[/attack]
[attack]
name = net
description =_"net"
type = impact
range = ranged
damage = 8
number = 1
icon = "attacks/net.png"
[specials]
{WEAPON_SPECIAL_SLOW}
{WEAPON_SPECIAL_MARKSMAN}
[/specials]
[/attack]
[/unit_type]
Jednostce do perfekcji brakuje już tylko większego zróżnicowania płci oraz animacji.
Wariacje
Najbardziej oczywistymi wariacjami są męska i żeńska. Używając znaczników [male] i [female] możemy nadpisywać klucze i znaczniki dla danej wariacji. Chcę by obecny wygląd i statystyki należały do wariacji męskiej, dla tego skorzystamy ze znacznika [female], aby zmienić kilka rzeczy goblinkom.
Wewnątrz znacznika wariacji możemy skorzystać z klucza inherit (po polsku oznacza dziedziczenie). Wartość yes powoduje, że wariacja będzie kożystać z naszej jednostki, jako bazy. To czego nie ustawimy będzie takie samo, jak u jednostki bazowej. Dla [male] i [female] ma on domyślnie wartość yes.
Kod źródłowy
[female]
name = _ "Goblin huntress"
image = "units/goblins/impaler.png"
profile= "portraits/goblins/impaler.png"
movement = 6
hitpoints = 30
[/female]
Goblinki będą miały teraz inny wygląd i bardziej adekwatną nazwę. Będą też nieco szybsze, ale mniej wytrzymałe od goblinów. W informacjach o jednostce pojawi się również alternatywny wygląd i portret.
Zajmijmy się teraz specjalnym typem wariacji. Tworzy się go znacznikiem [variation].
W przeciwieństwie do płci, ten typ nie pojawia się losowo i można go przywołać jedynie za pomocą skryptu. Zombie (Chodzący trup) są przykładem jednostki, która korzysta ze znacznika [variation], a wariacje przywoływane są dzięki umiejętności.
Trzeba nadać mu variation_id. variation_name to nazwa wariacji wyświetlana w opisie. UWAGA! Tutaj klucz inherit ma domyślnie wartość no. Aby łatwo przetestować wariację, można użyć klucza variation z wartością utawioną na id wariacji. Wówczas wszystkie rekrutowane jednostki, będą pojawiać się jako wariacje.
Jedna wariacja może się jednak różnić, w zależności od płci jednostki. Jeśli użyjesz znacznika [variation] wewnątrz [female], gra podmieni podane wartości, w odpowiadającym znaczniku [variation] bazowej jednostki.
To znaczy, jeśli np. chcesz podmienić klucze tylko 2-giego z kolei znacznika attack, po prostu wstaw wcześniej pusty znacznik: [attack][/attack].
Kod źródłowy
variation = slow
[variation]
variation_id = slow
variation_name = _ "Slow"
name = _ "Slow goblin hunter"
movement = 2
inherit = yes
[/variation]
[female]
name = _ "Goblin huntress"
image = "units/goblins/impaler.png"
profile= "portraits/goblins/impaler.png"
movement = 6
hitpoints = 30
[variation]
name = _ "Slow goblin huntress"
[/variation]
[/female]
Na wszelki wypadek, wstawiam pełen kod jednostki (już bez klucza variation):
[attack]
name = spear
description =_"spear"
type = pierce
range = melee
damage = 10
number = 2
icon= "attacks/spear-orcish.png"
[specials]
{WEAPON_SPECIAL_FIRSTSTRIKE}
[/specials]
[/attack]
[attack]
name = net
description =_"net"
type = impact
range = ranged
damage = 8
number = 1
icon = "attacks/net.png"
[specials]
{WEAPON_SPECIAL_SLOW}
{WEAPON_SPECIAL_MARKSMAN}
[/specials]
[/attack]
[variation]
variation_id = slow
variation_name = _ "Slow"
name = _ "Slow goblin hunter"
movement = 2
inherit = yes
[/variation]
[female]
name = _ "Goblin huntress"
image = "units/goblins/impaler.png"
profile= "portraits/goblins/impaler.png"
movement = 6
hitpoints = 30
[variation]
name = _ "Slow goblin huntress"
[/variation]
[/female]
[/unit_type]
Animacje
Animacje to jednocześnie bardzo prosty, jak i obszerny temat. Potężna dokuentacja znajduje się tutaj: https://wiki.wesn...imationWML. Niech cię to jednak nie przestraszy. Wystarczy zrozumieć kilka podstaw, a reszta będzie już bardzo prosta.
Animacja to zbiór klatek, czyli obrazków, które wyświetlane są jeden po drugim przez określony czas. Szybko zmieniające się obrazki dają wrażenie ruchu. Kto wie czym jest film, ten doskonale rozumie o czym mówię.
Pojedyncza animacja (zwana też blokiem) tworzona jest znacznikiem [animation]. Najważniejszym kluczem tutaj jest apply_to, ponieważ określa on wydarzenia, jakie spowodują wyświetlenie animacji (spis znajdziesz w dokumentacji: https://wiki.wesn...animations). Pod każdym wydarzeniem znajdziesz dodatkowe informacje, odnośnie domyślnych wartości innych kluczy itp. Jeśli nie jesteś pewien, czy te informacje będą ci potrzebne, znaczy że nie będą.
Stwórzmy sobie animację, która wyświetli się podczas obrony, lub podczas wybrania jednostki (takie połączenie, może i nie ma sensu, ale chcę pokazać, że jest jak najbardziej możliwe).
Teraz wstawimy sobie klatkę znacznikiem [frame]. Klatka posiada tylko dwa istotne klucze: image i duration. image to obrazek, wyświetlany w danej klatce. duration to czas trwania tej klatki w milisekundach (ms). Klucz duration można pominąć, podając wartość klucza image w formacie <ścieżka_do_obrazka>:<wartość_dla_klucza_duration>.
Gotowe. Animacja już działa. Możesz dodać więcej klatek, jeśli chcesz. Zostaną wyświetlone, jedna po drugiej.
Omówimy sobie jeszcze dwa często używane w [animation] klucze: start_time i offset.
start_time określa milisekundę, w której rozpocznie się animacja (domyślnie 0). Ma to znaczenie w przypadku ataku i obrony. Wtedy wszystko liczone jest względem 0 - momentu zadania obrażeń. Ustawienie start_time = -200 naszej jednostce sprawi, że zacznie się bronić 200ms przed otrzymaniem ciosu i opuści gardę 200ms po nim.
offset to przesunięcie animacji, względem pola, na którym stoi jednostka. Wartość 1 oznacza pole przed jednostką, wartość -1 to pole za nią. offset jest parametrem progresywnym (wyjaśnienie znajdziesz tutaj: https://wiki.wesn...parameters). offset = 0~-0.3,-0.3~0 sprawi, że jednostka w pierwszej połowie animacji cofnie się nieznacznie do tyłu, a w drugiej wróci na miejsce.
Stworzymy sobie jeszcze animację dla ataku siecią. Użyjemy uproszczonego znacznika [attack_anim]. Według dokumentacji, ustawi on za nas klucz apply_to na attack. Musimy upewnić się, że broń, którą atakuje goblin to sieć. W tym celu użyjemy filtru:
Kod źródłowy
[filter_attack]
name = net
[/filter_attack]
Sprawi on, że blok zostanie wykonany tylko w przypadku, gdy klucz name ataku będzie ustawiony na net.
Zamiast tworzyć kilka znaczników [frame], można zapis uprościć, stosując - tak jak w przypadku offset - progresję. W poniższym kodzie pierwsza klatka wykorzysta obrazek rouser-lead-1.png o czasie trwania 250ms. Druga rouser-lead-2.png o czasie trwania 500ms. Trzecia będzie taka sama jak pierwsza.
Kod źródłowy
[attack_anim]
[filter_attack]
name = net
[/filter_attack]
start_time = -750
[frame]
image = units/goblins/rouser-lead-[1~2,1].png:[250,500,250]
[/frame]
[/attack_anim]
Znacznik [frame] może posiadać prefiks [<cokolwiek>_frame]. Klatki z danym prefiksem będą wyświetlane niezależnie od klatek z innym prefiksem, lub bez niego. Ta wiedza pozwoli ci zaanimować nie tylko goblina ale również sieć. Znacznik [attack_anim] ustawił już missile_offset dla znacznika [missile_frame], którego użyjemy dla sieci.
Animacja jest gotowa. Klucze start_time zostały ustawione tak, by sieć pojawiła się w odpowiedniej klatce animacji goblina, a następnie trafiła w cel w momencie zadania obrażeń.
W tym miejscu zakończę. Znasz już podstawy. Korzystaj z dokumentacji i poeksperymentuj, a będziesz stanie stworzyć animację, jaka tylko ci się spodoba. Jeśli wciąż czujesz się niepewnie, możesz zajrzeć jeszcze do tego artykułu: http://www.wesnot...icle_id=69, lub podejrzeć animacje u innych jednostek.
Droga na skróty, czyli tworzenie jednostek z innych jednostek
Jednostki można tworzyć szybciej, używając jako bazy już istniejącej jednostki. Wówczas możemy ograniczyć się do ustawienia tylko paru kluczy. To czego nie ustawimy będzie takie samo, jak u jednostki bazowej. Aby skorzystać z jednostki bazowej, należy w kodzie użyć znacznika [base_unit] z kluczem id równym id bazowej jednostki, np.:
Kod źródłowy
[unit_type]
id = MojaJednostka
[base_unit]
id = Mage
[/base_unit]
cost = 15
health = 20
[attack]
[/attack]
[attack]
number = 10
[/attack]
[/unit_type]
W ten sposób dostaniemy maga, który kosztuje 15 złota, ma 20 hp, a jego drugi atak uderza teraz 10 razy.
UWAGA! Nie polecam tej metody, gdyż nie daje nam ona pełnej kontroli nad nową jednostką. Np. nie pozwoli usunąć już istniejącego ataku. Najlepiej jest po prostu skopiować sobie plik jakiejś jednostki, po czym podmienić id i inne rzeczy.
Używanie własnych obrazków
Jeśli chcesz używać własnych obrazków w swoim dodatku, będzie ci potrzebny znacznik [binary_path], z kluczem path = data/add-ons/<nazwa_dodatku>.
Musisz stworzyć folder images (koniecznie o tej nazwie) i do niego wrzucić swoje obrazki. Teraz możesz się odwoływać do nich identycznie jak do obrazków z data/core/images.
images to nie jedyny folder obsługiwany przez [binary_path]. Są jeszcze music i sound, poświęcone plikom dźwiękowym.