2. Edycja plikówJak już zostało pokazane w poprzedniej części, Twoja praca z Module Systemem wygląda w każdym wypadku tak:
1) Edytujesz wybrane pliki modułu (te zaczynające się na module_, o rozszerzeniu .py) i robisz jakie tylko chcesz zmiany.
2) Gdy skończysz i zapiszesz zmiany, uruchamiasz build_module.bat. To spowoduje utworzenie modyfikacji (uaktualnienie plików) oraz wykaże błędy, jeśli jakieś wystąpią.
3) Jeśli nie wystąpiły żadne błędy, możesz uruchomić Moun&Blade i sprawdzić zmiany, które zrobiłeś. Niekiedy będziesz zmuszony rozpocząć nową grę, żeby wszystko zadziałało.
2.1 Edycja plikówSystem używa list do zaprezentowania grup obiektów gry (lista rozpoczyna się od „[”, zawiera listę obiektów oddzielonych przecinkami i kończy się „]”). Przykładowo, plik module_map_icons.py zawiera:
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
]
Tutaj map_icons jest zadeklarowane jako lista, a każdy jej element dotyczy odpowiedniego obiektu na mapie. W tym przykładzie obiektem jest ("player",0,"player", 0.2, snd_footstep_grass). Będziemy nazywać te obiekty
krotkami (ang. tuples). Krotki, tak jak listy, zawierają elementy oddzielone przecinkami, ale rozpoczynają i kończą się zwykłym nawiasem. Struktura każdej krotki jest zapisana na początku pliku modyfikacji. Dla obiektów mapy, każda krotka zawiera:
1) nazwę obiektu,
2) oznakowanie obiektu,
3) nazwa mesha,
4) skala mesha,
5) id odpowiedniego dźwięku.
Tak więc, dla krotki ("player",0,"player", 0.2, snd_footstep_grass) wygląda to tak:
1) nazwa obiektu = "player"
2) oznaczenie = 0
3) nazwa mesha = "player"
4) skala mesha = 0.2
5) id dźwięku = snd_footstep_grass
W ten sam sposób można określić strukturę obiektów dla każdego pliku, czytając dokumentację na początku i łącząc to z jego zawartością.
2.2 Dodawanie nowych obiektówZnając strukturę krotek obiektów mapy, możemy teraz przystąpić do dodawania swoich własnych. Spójrzmy jeszcze raz na listę:
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
]
Obiekty muszą zostać oczywiście dodane wewnątrz listy, tak więc musisz przesunąć nawias o jedną linię w dół. Gdy to zrobisz, możesz dodać swój własny obiekt – najprościej poprzez skopiowanie innego istniejącego obiektu. Dla przykładu:
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
("new_icon",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
]
W tym przykładzie dodaliśmy nowy obiekt i nadaliśmy mu nazwę „new_icon”. Nowa ikona zawiera oznaczenie (flag), może być ono włączane lub wyłączane poprzez dołączenie go lub usunięcie ze swojego miejsca. Dla przykładu, oznaczenie mcn_no_shadow spowoduje, że ikona nie będzie dawała cienia na ziemi.
Usuniemy teraz mcn_no_shadow z naszego obiektu. By to zrobić, zamienimy mcn_no_shadow na 0, co system zrozumie jako brak jakiegokolwiek oznaczenia.
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
("new_icon",0,"City", 0.9,snd_footstep_grass),
]
Zarówno “town”, jak i “new_icon” używa mesha “City”, co oznacza, że na mapie oba obiekty będą reprezentowane jako ten sam model. Możemy zmienić to pole nazwę dowolnego innego modelu, który znajduje się w paczkach modeli w grze.
Spróbujmy teraz zmienić nieco wygląd naszego obiektu w grze.
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
("new_icon",0,"City", 5.0,snd_footstep_grass),
]
W tym przykładzie zmieniliśmy skalę naszej ikony z 0.9 na 5.0. Oznacza to, że będzie ona kilka razy większa niż normalnie. Powinno to pomóc nam odróżnić ją od „town”, gdy włożymy ją do gry.
Stworzymy teraz nowy oddział w module_parties.py, który będzie używał nowej ikony. By to zrobić, będziemy potrzebować odniesienia w postaci istniejącego już obiektu.
2.3 Odnośniki do objektówOtwórz module_parties.py. Znajdziesz tam listę “parties = [“. Jak widzisz, struktura krotek w tym pliku jest nieco inna niż wcześniej. Jest tak w przypadku wielu – jeśli nie wszystkich – plików modułu. Wykorzystamy tą sposobność, by bliżej przyjrzeć się strukturze oddziałów.
Przykładowy oddział:
("zendar","Zendar",icon_town|pf_is_static|pf_always_visible|pf_hide_defenders, "zendar", pt_none, fac_neutral,0,ai_bhvr_hold,0,(2,46),[(trp_swadian_knight,6,0)]),
Ta krotka umiejscawia miasto Zendar na mapie. Zmienne właściwości Zendaru są ustawione w odpowiednich miejscach – podobnie, jak było to w przypadku module_icons.py.
Rozłóżmy krotkę na czynniki pierwsze:
1) ID oddziału. Jest używany jako odnośnik do niego w innych plikach.
2) Nazwa oddziału. To nazwa, która wyświetlać się będzie w grze. Może całkowicie różnić się od ID.
3) Oznaczenia oddziału. Pierwszym z nich musi być ikona, jakiej ten oddział używać będzie w grze.
4) Menu. To pole wyszło z użycia i od wersji 0.730 nie ma żadnego zastosowania w grze.
5) Szablon oddziału. Określa, do kogo należy oddział. Wartość domyślna to pt_none.
6) Frakcja. Może być to jakakolwiek frakcja występująca w pliku module_factions.py.
7) Charakter oddziału. Najłatwiej zrozumiesz co to jest, jeśli zajrzysz do pliku header_parties.py.
8) Zachowanie AI. Określa, jak oddział sterowany przez komputer będzie zachowywał się na mapie strategicznej (świata).
9) Cel oddziału AI.
10) Współrzędne początkowe na mapie strategicznej (X, Y)
11) Lista, zawierająca grupy jednostek. Do każdej jednostki przypisane są trzy elementy:11.1 ) ID jednostki. Może być to dowolna regularna jednostka lub bohater z module_troops.py.
11.2 ) Liczba jednostek w grupie.
11.3 ) Oznaczenie członka oddziału. Opcjonalne. Przykładowo, pmf_is_prisoner oznacza, że ta jednostka/grupa jednostek jest więźniem.
Krotka Zendaru:
("zendar","Zendar",icon_town|pf_is_static|pf_always_visible|pf_hide_defenders, "zendar", pt_none, fac_neutral,0,ai_bhvr_hold,0,(2,46),[(trp_swadian_knight,6,0)]),
1) ID oddziału = "zendar"
2) Nazwa oddziału = "Zendar"
3) Oznaczenia oddziału = icon_town|pf_is_static|pf_always_visible|pf_hide_defenders
4) Menu = "zendar"
5) Szablon oddziału = pt_none
6) Frakcja = fac_neutral
7) Charakter oddziału = 0
8) Zachowanie AI = ai_bhvr_hold
9) Cel oddziału AI = 0
10) Współrzędne początkowe = (2,46)
11) Jednostki:11.1) Rodzaj jednostki (ID) = trp_swadian_knight
11.2) Ilość jednostek w grupie = 6
11.3) Oznaczenia jednostki = 0
Jeśli spojrzysz na trzecie pole, zauważysz, że Zendar używa icony „Town” z module_icons.py, dodając do tego przedrostek icon_. Nakierowuje on system na właściwy plik. W przypadku module_icons używamy prefiksu icon_, w przypadku module_factions używamy fac_, w przypadku modul_parties używamy p_. Każdy plik modułu posiada własny przedrostek. Ich listę znajdziesz poniżej.
Wiemy już, jak zbudowane są oddziały, więc możemy przejść do dodawania własnej. Jednak zanim to zrobisz, musisz wiedzieć jeszcze jedną rzecz: w przypadku module_parties.py i właściwie też wielu innych plików,
nie powinieneś dodawać żadnych nowych krotek na końcu listy. Może to spowodować wystąpienie błędów, tak więc zaleca się (w module_parties.py) dodawanie jakichkolwiek nowych wpisów pomiędzy „training_ground” a „castle_1” (uwaga: w nowszych wersjach może wyglądać to nieco inaczej).
Skopiuj teraz wpis „town_14” i wklej pomiędzy training_ground” a „castle_1”.
("training_ground","Training Ground", icon_town|pf_town|pf_disabled, "training_ground", pt_none, fac_vaegirs,0,ai_bhvr_hold,0,(-2,-3),[(trp_vaegir_knight,6,0)]),
("new_town","Mod_Town", icon_town|pf_town, "town", pt_none, fac_vaegirs,0,ai_bhvr_hold,0,(-4,-37),[(trp_vaegir_knight,6,0)]),
("castle_1","Culmarr_Castle",icon_town|pf_is_static|pf_always_visible, "castle", pt_none, fac_outlaws,0,ai_bhvr_hold,0,(-47,-51),[(trp_swadian_knight,5,0),(trp_swadian_crossbowman,25,0)]),
W tym przykładzie zmieniliśmy ID oddziału z „town_14” na „new_town”, a nazwę oddziału z „Halmar” na „Mod_Town”.
Możemy teraz ustalić parę rzeczy, patrząc na tą krotkę:
1) By odnieść się do tego oddziału w innym pliku, musimy użyć prefiksu „p_”, czyli w rezultacie będzie to wyglądać „p_new_town”.
2) W grze będziemy widzieć tylko „Mod Town”, nigdy ID.
3) Ten oddział używa icon_town i oznaczenie pf_town – oznaczenie, które zawiera wspólne właściwości miast. Z oznaczeniami spotkamy się także w następnych częściach.
4) "Mod Town" znajduje się obecnie pod władaniem Vaegirów.
5) Jeśli wstawiliśmy nasze nowe miasto w ten sposób, będzie miało ono identyczne współrzędne jak Halmar. To także będziemy zmieniać później.
("training_ground","Training Ground", icon_town|pf_town|pf_disabled, "training_ground", pt_none, fac_vaegirs,0,ai_bhvr_hold,0,(-2,-3),[(trp_vaegir_knight,6,0)]),
("new_town","Mod_Town", icon_new_icon|pf_town, "town", pt_none, fac_neutral,0,ai_bhvr_hold,0,(-1,-1),[(trp_vaegir_knight,6,0)]),
("castle_1","Culmarr_Castle",icon_town|pf_is_static|pf_always_visible, "castle", pt_none, fac_outlaws,0,ai_bhvr_hold,0,(-47,-51),[(trp_swadian_knight,5,0),(trp_swadian_crossbowman,25,0)]),
Tutaj zmieniliśmy ikonę naszego nowego miasta na „icon_new_icon”, a współrzędne na (-1,-1). Dodatkowo zmieliliśmy frakcję na neutralną.
Miasto jest teraz ustawione ze swoją własną ikoną i koordynatami, co powinno skutkować wyświetlaniem go bez żadnych problemów.
Zapisz zmiany i uruchom build_module.bat. Jeśli wszystko poszło dobrze, powinieneś teraz, po uruchomieniu swojej modyfikacji, zobaczyć nowe miasto w centrum mapy.
Jeśli nie wszystko poszło dobrze, sprawdź uważnie pisownię i składnię. Upewnij się, że wszystkie przecinki i nawiasy są w odpowiednich miejscach. Zła składnia jest głównym powodem błędów kompilacji w Module Systemie.
W grze wchodzenie do miasta będzie na razie skutkować uruchomieniem menu walki, ponieważ miasto nie ma na razie przypisanego do siebie żadnego menu i jest traktowane jako wrogi oddział. Przypisywanie menu jest nieco bardziej skomplikowanym zadaniem, więc opuścimy teraz nasze nowe miasto na chwilę i wrócimy do niego w późniejszym rozdziale tej dokumentacji.
Jak widzisz, wzajemne powiązania między różnymi plikami modułu mogą być naprawdę rozległe. Każdy element musi być dopracowany, by działać poprawnie. Na szczęście wiele zmian wymaga jedynie edytowania jednego lub dwóch plików.
Poznałeś już podstawy moddingu, a więc możemy zagłębić się bardziej w różne pliki modułu. Przejdź teraz do części trzeciej tej dokumentacji.
Lista przedrostków:
fac_ -- module_factions.py
icon_ -- module_map_icons.py
itm_ -- module_items.py
mnu_ -- module_game_menus.py
mno_ -- module_game_menus.py – odnosi się do indywidualnych opcji menu.
mt_ -- module_mission_templates.py
psys_ -- module_particle_systems.py
p_ -- module_parties.py
pt_ -- module_party_templates.py
qst_ -- module_quests.py
script_ -- module_scripts.py
scn_ -- module_scenes.py
spr_ -- module_scene_props.py
str_ -- module_strings.py
trp_ -- module_troops.py
Do pliku module_dialogs.py odnośniki nigdy nie występują, tak więc nie posiada on własnego prefixu.
----------
Tłumaczenie: Kyroman
Oryginał:
http://forums.taleworlds.net/index.php/topic,11422.0.htmlNastępna część pojawi się niebawem.
Dodam jeszcze tylko, żeby nie było niejasności: "tuples" przetłumaczyłem jako "krotki" (z czym chyba każdy się zgodzi), "references" jako "odnośniki". Wszystko powinno być zrozumiałe.