PDA

Zobacz pełną wersję : [PORADNIK] Zaawansowana obsługa języka skryptowego Rom'y



kwinto93
18-08-2010, 08:16
Witam,

Po bardzo uważnej lekturze anglojęzycznych tutoriali i zrobieniu paru użytecznych skryptów, postanowiłem napisać zaawansowany poradnik ich tworzenia. Przed zapoznaniem się z tym tutorialem, powinieneś najpierw przeczytać ten: http://forum.totalwar.org.pl/viewtopic.php?f=248&t=5948.

Źródła:
http://www.twcenter.net/forums/showthread.php?t=259487
http://www.twcenter.net/forums/showthread.php?t=169689

Spis treści:

1. Tworzymy główny skrypt i osadzamy w nim, nasz poprzedni - kasa.txt
2. Tworzymy skrypt na spawn armii Hannibala
3. Uruchamiamy obydwa skrypty
4. Zakończenie i podsumowanie

1.

Tworzymy główny skrypt, czyli szkielet całego skrypt – moda.

Przerobimy teraz skrypt, który napisaliśmy ostatnim razem. Tak więc otwieramy nasz plik kasa.txt i kasujemy z niego następujące zapisy:


monitor_event FactionTurnStart FactionIsLocal
and I_TurnNumber = 3

terminate_monitor

end_monitor

while I_TurnNumber < 9999
suspend_unscripted_advice true
end_while

Natomiast bezpośrednio pod script, dopisujemy:



select_ui_element advisor_dismiss_button
simulate_mouse_click lclick_up

while I_AdvisorVisible
end_while

Uniemożliwi to wyświetlanie dymka z informacjami. Jeżeli chcemy aby pozostał to wystarczy nie wklejać powyższego kodu.

Ostatecznie zostaniem nam coś takiego:


script


select_ui_element advisor_dismiss_button
simulate_mouse_click lclick_up

while I_AdvisorVisible
end_while

console_command add_money 10000

end_script

Teraz tworzymy nowy plik o nazwie main.txt w folderze: DATA \ SCRIPTS \ moj_mod
Otwieramy go notepad'em ++ i wklejamy do niego poniższy kod


script ; początek skryptu

; Teraz usuwamy dymek z informacją o uruchomieniu skryptu
select_ui_element advisor_dismiss_button
simulate_mouse_click lclick_up

; Czekamy aż dymek zniknie
while I_AdvisorVisible
end_while

suspend_unscripted_advice true

; Deklarujemy obsługę „show_me”
declare_show_me

; Wymuszamy wyłączenie skryptu po wyjściu z kampanii, aby uniknąć ewentualnych błędów
monitor_event ScrollAdviceRequested ScrollAdviceRequested end_game_scroll
terminate_script
end_monitor

; Potrzebne źródło [?] Z tego co mi się wydaje poniższy zapis umożliwia ponowne uruchomienie skryptu po wczytaniu zapisanej gry
monitor_event GameReloaded TrueCondition
terminate_script
end_monitor

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Tutaj będziesz uaktywniał swoje skrypty za pomocą kolejnych monitor_event ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

monitor_event FactionTurnStart FactionIsLocal
and I_TurnNumber = 3

advance_advice_thread kasa ;; Ten zapis powinien Wam być znajomy ze skrypt_kampanii.txt, z poprzedniego poradnika :]

end_monitor

;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Koniec twoich kodów ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Zabezpieczamy skrypt przed zapętleniem się w nieskończoność
while I_TurnNumber < 9999
suspend_unscripted_advice true
end_while

end_script


To jest nasz główny skrypt, za pomocą którego będziemy mogli uruchamiać pozostałe podskrypty :]

A teraz czas na jeszcze dokładniejsze omówienie.
Najważniejszą częścią main.txt i zarazem tym segmentem skryptu, który będziemy często edytować (resztę możesz po prostu skopiować do każdego swojego projektu) są linijki między: „ Tutaj będziesz uaktywniał swoje skrypty za pomocą kolejnych monitor_event”, a „ Koniec twoich kodów”. To tutaj będziemy uruchamiać kolejne skrypty za pomocą monitor_event.

Na początku skasowaliśmy pewne linijki kodu z pliku kasa.txt. Przecież mówiliśmy sobie ostatnio, że są bardzo ważne? To gdzie one się podziały? Odpowiedź jest prosta, zostały przeniesione do skryptu main.txt (dokładnie przejrzyj kod main.txt, a na pewno je dostrzeżesz :]). Nasz skrypt uruchamia taki sam monitor_event jak w ostatnim poradniku:

monitor_event FactionTurnStart FactionIsLocal
and I_TurnNumber = 3
tak więc skoro i tak skrypt kasa.txt zostanie uruchomiony dopiero w trzeciej (a właściwie to czwartej, bo rundy są liczone od zera!!) rundzie to nie ma już potrzeby, dodatkowo, w jego wnętrzu, dokładać takiego samego warunku. To nie ma sensu.

Teraz, tak jak ostatnio edytujemy:
DATA \ export_descr_advice.txt
DATA \ text \ export_advice.txt
DATA \ world \ maps \ campaign \ moja_kampania \ skrypt_kampanii.txt

export_descr_advice.txt

Wklejamy na górze pliku wg. ostatnio poznanego wzoru, tylko jak nie trudno się domyślić zmieniamy odpowiednie zapisy z kasa na main :] (Uwaga!! Stary wpis ds. kasy zostawiamy, ponieważ nadal będzie nam potrzebny.), następujący fragment kodu:


;-----------------------------------------------------------MAIN
AdviceThread main
GameArea Campaign

Item mainItem1
Uninhibitable
Verbosity 0
Threshold 1
MaxRepeats 0
RepeatInterval 1
Attitude Normal
Presentation Default
Title mainTitle
On_display scripts\moj_mod\main.txt
Text mainText

Triggery

Tym razem musimy użyć triggerów. Triggery pozwolą uruchomić główny skrypt po wczytaniu zapisanej gry. Aby tego dokonać gracz musi nacisnąć na przycisk frakcji, konstrukcji, rekrutacji lub po prostu kliknąć na dowolne, swoje miasto, czyli wykonać jedną z rutynowych czynności w Rom'ie (prawda, że sprytnie? :]). Oczywiście należałoby nadmienić w dokumentacji naszego mod'a, że aby zrestartować skrypty, trzeba wykonać jedną z powyższych czynności.

Na końcu export_descr_advice.txt wklejamy następujący kod:


;--------------------------------------------------------------TRIGGERY_MÓJ_MOD
Trigger background_script_trigger_1
WhenToTest ButtonPressed ; sprawdza czy klawisz naciśnięty

Condition ButtonPressed faction_button ; jeśli naciśnięty klawisz frakcji...

AdviceThread main 1 ; … to aktywuje skrypt main

;------------------------------------------
Trigger background_script_trigger_2
WhenToTest ButtonPressed

Condition ButtonPressed construction_button

AdviceThread main 1

;------------------------------------------
Trigger background_script_trigger_3
WhenToTest ButtonPressed

Condition ButtonPressed recruitment_button

AdviceThread main 1

;------------------------------------------
Trigger background_script_trigger_4
WhenToTest SettlementSelected

AdviceThread main 1

export_advice.txt

Tak jak poprzednio (Uwaga!! Stary wpis ds. kasy zostawiamy, ponieważ nadal będzie nam potrzebny.):


{mainTitle}Skrypty
{mainText}Załadowane pomyślnie

skrypt_kampanii.txt

kasa
zamieniamy na:
main

Dobrze, teraz po uruchomieniu kampanii powinniśmy, tak jak ostatnio, w 4 rundzie (numery rund liczymy od zera) otrzymać 10000 premii do naszego stanu konta. Ponadto, chciałbym zauważyć, że dzięki niezastosowaniu terminate_monitor, gdybyśmy zamiast „and I_TurnNumber = 3” wstawili „and I_TurnNumber > 3” to od trzeciej rundy, aż do prawie nieskończoności (prawie, ponieważ zakończenie w 9998 turze gwarantuje nam pętla while na końcu main.txt), dostawalibyśmy naszą kasiorkę :]

2.

Tworzymy skrypt na spawn armii Hannibala, czyli modelujemy świat

Najpierw kod:


script ;; początek skryptu

select_ui_element advisor_dismiss_button ;; zamykamy dymek
simulate_mouse_click lclick_up

while I_AdvisorVisible
end_while

spawn_army ;; początek funkcji spawn'ującej armię
faction carthage ;; nazwa frakcji
character Hannibal, named character, age 25, x 89, y 80 ;; Członek rodziny + współrzędne
unit carthaginian general's cavalry early, 30 exp 3 armour 2 weapon_lvl 3 ;; jednostki
unit carthaginian medium cavalry, 30 exp 3 armour 2 weapon_lvl 3
unit carthaginian medium cavalry, 30 exp 3 armour 2 weapon_lvl 3
unit carthaginian royal cavalry, 30 exp 3 armour 2 weapon_lvl 3
unit carthaginian elephant forest, 6 exp 0 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
unit carthaginian heavy infantry, 40 exp 2 armour 2 weapon_lvl 0
end

console_command diplomatic_stance carthage romans_julii war ;; wojna między Kartaginą., a Juliuszami

if not I_LocalFaction gauls
and no I_LocalFaction carthage ;; jeśli nie gramy Galią lub Kartaginą...
console_command diplomatic_stance carthage gauls allied ;;... to zostanie podpisany sojusz Kartagina - Galia
end_if

end_script ;; koniec skryptu

Ogólny zapis skryptu spawn'ującego wojsko:


spawn_army
faction <nazwa frakcji>
character <Imię z descr_names dla danej frakcji>, <typ: general, named character itp.>, age <wiek>, , x <współ. X>, y <współ. Y>; Lista 18 jednostek
unit <typ jednostki (jak w export_descr_unit)>, <liczba żołnierzy> [doświadczenie] [poziom uzbrojenia] [poziom broni]
end

Wskazówka: aby odczytać współrzędne punktu bezpośrednio z mapy kampanii, należy najechać myszką na dany punkt, wcisnąć ~ i wpisać show_cursorstat.

A teraz kilka uwag. Dodałem dwa nowe elementy:


console_command diplomatic_stance carthage romans_julii war

Jak nietrudno się domyślić komenda diplomatic_stance służy do zmiany dyplomacji. Skoro stworzyliśmy Hannibala to wypadało by jeszcze wypowiedzieć wojnę Rzymowi ;] po to właśnie użyłem tą komendę. Po więcej informacji zapraszam do dokumentacji (console_commands).


if not I_LocalFaction gauls
and no I_LocalFaction carthage ;; jeśli nie gramy Galią lub Kartaginą...
console_command diplomatic_stance carthage gauls allied
end_if

To jest pętla if, czyli jeśli. Powiecie, że przecież to to samo co monitor_event. No w pewnym sensie tak, bo w poprzednim poradniku Was do tego przekonywałem :] Różnica jest bardzo mała. Po prostu w kodzie przyjęło się używać pętli if. Poza tym wewnątrz monitor_event także powinniśmy użyć pętli if, a nie kolejnych monitor_event.


Nie muszę chyba teraz powtarzać, że skoro mamy jakiś nowy skrypt, to trzeba go zapisać w DATA \ SCRIPTS \ moj_mod \ spawn, nadając mu nazwę, powiedzmy hannibal.txt, i dodając odpowiednie wpisy w export_descr_advice.txt i export_advice (najlepiej z nazwami hannibal)?

3.

Teraz uruchomimy obydwa skrypty. Czy mogą one zostać uruchomione (nie działać, tylko uruchomione) jednocześnie? Nie. A z opóźnieniem? Tak. To może dodamy do monitor_event komendę wait 1 (czekaj 1) pomiędzy obydwoma advance_advice_thread? No właśnie, nie. A dlaczego, a dlatego, że taka komenda nie będzie działać w monitor_event. Nie zadziałają także:
wait, campaign_wait, battle_wait, while. A dlaczego? Bo panowie z Activision sobie tak wymyślili.
Więc co zrobić? Jest oczywiście sposób. Można przecież bardzo sprytnie uruchomić w main.txt skrypt kasa.txt, a w skrypcie kasa.txt dodać tuż przed end_script - advance_advice_thread hannibal :]
Prześledźmy co się stanie:


Start → main.txt → monitor_event → kasa.txt → kod kasy → advance_advice_thread hannibal → kod spawn Hannibal'a

W przykładzie, który zaraz przedstawię nie ma takiego problemu, gdyż kasa.txt zadziała w 4 rundzie, a spawn Hannibala w 3.

Otwieramy main.txt i przechodzimy do monitor_event z naszą kasą. Pod end_monitor, wklejamy poniższy kod:


monitor_event FactionTurnStart FactionIsLocal
and I_TurnNumber = 2 ;; w turze 104 (218 r.p.n.e.) licząc od 270 r.p.n.e. - to możecie wstawić po przetestowaniu :]
and not I_LocalFaction carthage ;; kiedy nie grasz Kartaginą
and I_SettlementOwner Carthage = carthage ;; i Kartagina posiada miasto Kartagina

advance_advice_thread hannibal ;; nastąpi uruchomienie skryptu na spawn Hannibal'a

end_monitor

Dodatkowo w monitor_event zabezpieczyliśmy się przed wykonaniem kodu, gdy gracz, gra Kartaginą, i gdy Kartagina utraci swoją stolicę (czyli nie będzie miała funduszy na wielką armię - dzięki temu dajemy szansę Rzymowi, na nie dopuszczenie do inwazji Hannibal'a – musi do 218 r.p.n.e. zdobyć stolicę Kartaginy :]). Ostatecznie fragment kodu odpowiadające za uruchamianie skryptów w main.txt, powinien wyglądać tak:


monitor_event FactionTurnStart FactionIsLocal
and I_TurnNumber = 3

advance_advice_thread kasa

end_monitor

monitor_event FactionTurnStart FactionIsLocal
and I_TurnNumber = 2
and not I_LocalFaction carthage
and I_SettlementOwner Carthage = carthage

advance_advice_thread hannibal

end_monitor

4.

Dzisiaj nauczyliśmy się robić tzw. background script (skrypt tła – czyt. działający w tle) – nasz main.txt, który czuwa nad uruchamianiem w odpowiednich momentach naszych podskryptów. Poznaliśmy też nową komendę konsoli i nowy event. Wiemy też jak uruchomić dwa skrypty w czasie jednej tury i w różnych turach. Jednak to nie wszystko. Istnieje jeszcze coś takiego jak counter'y, ich opis znajdziecie tu: http://www.twcenter.net/forums/showthread.php?p=5147477#post5147477
Przypominam, że pełny zbiór komend jest w paczce na dole pierwszego poradnika.

Życzę owocnej pracy i wielu udanych skrypt – paków :]