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:

Kod:
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

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:
Kod:
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:

Kod:
;-----------------------------------------------------------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:

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.):

Kod:
{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:

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:

Kod:
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:

Kod:
 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).

Kod:
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:

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:

Kod:
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/showt...77#post5147477
Przypominam, że pełny zbiór komend jest w paczce na dole pierwszego poradnika.

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