ArmA 2 - Briefing

Każdy użytkownik ArmA 2, zarówno missionmaker jak i zwykły gracz, z pewnością zauważył po odpaleniu pierwszej misji zmiany, jakie zaszły w sekcji briefingu. Stary, wysłużony notesik definitywnie odszedł w zapomnienie ustępując miejsca o wiele bardziej nowoczesnej strukturze odprawy.

Niestety, dla missionmakerów, stary sposób tworzenia briefingów także odszedł już do historii. Koniec z HTML-em - przenosimy się na skrypty. Nowa metoda nie jest szczególnie trudna do nauczenia się, ale może sprawiać z początku problemy. Ponadto wymaga podstawowej wiedzy skryptowej, którą nie wszyscy posiadają. Jest jeszcze jeden problem - by zachować odpowiednie działanie funkcji Join-in-Progress w trybie multiplayer, briefingi do singleplayer i multi robi się zupełnie inaczej. Mam jednak nadzieję, że po przeczytaniu niniejszego poradnika wszystko stanie się jasne.





Briefing SP



No to jedziemy :) Na początek warto sobie uświadomić, że wszelkie zmiany w briefingu, czyli tworzenie wpisów, celów misji, zmiana ich statusu i inne rzeczy, będziemy wprowadzać poleceniami w skrypcie, a następnie odpalać taki gotowy zestaw poleceń w odpowiednim momencie podczas misji. Zacznijmy od tego, co będzie widoczne już na odprawie przed rozpoczęciem rozgrywki. W tym celu potrzebne są nam dwa pliczki - init.sqf i briefing.sqf. Nazwa tego drugiego może być oczywiście dowolna, tu jest najbardziej oczywista. Opis ich tworzenia znajduje się w wielu poradnikach i jest dość prosty, nie będę się nim więc zajmował.

Mając oba pliki, musimy się zabrać za wypełnianie ich tekstem. Pamiętamy, że jest to format .sqf, który ma składnię o wiele bardziej skomplikowaną od przestarzałego .sqs - trzeba stawiać średnik ( ; ) na końcu każdej linii. Otwieramy więc na początek init.sqf. Prawdę mówiąc, moglibyśmy tu umieścić polecenia odpowiadające za briefing i wszystko by grało, ale by nie robić śmietnika wstawimy tylko polecenie odpalenia briefing.sqf.

[] execVM "briefing.sqf";

Zamykamy init.sqf i zapominamy o nim - nie będzie już potrzebny do stworzenia briefingu. Otwieramy briefing.sqf. Teraz zaczynają się schody :) Załóżmy, że chcemy stworzyć 3 cele misji i jeden wpis w sekcji "Uwagi". Zacznijmy więc od tych pierwszych.

tsk1 = player createSimpleTask["Capture Gorka"]; - tworzy cel misji tsk1 (nazwa celu, do której będziemy się później odwoływać) o nazwie "Capture Gorka". Piszę po angielsku, ponieważ briefing tworzony w ten sposób nie może zawierać polskich literek - angielski po prostu lepiej wygląda. Jak zrobić briefing z polfontami napiszę później.
tsk1 setSimpleTaskDescription["Elliminate every American occupying our beautiful village and fortify yourselves in Gorka.","Capture Gorka","Capture Gorka"]; - tutaj ustalamy bardziej szczegółowy opis celu misji. Jak widać, w nawiasach kwadratowych mamy trzy pola do wypełnienia. Pierwsze pole odpowiada za zazwyczaj dłuższy tekst w dużym polu po prawej stronie briefingu. W dwóch pozostałych radzę wpisać to, co umieściliśmy w poleceniu "createSimpleTask".
tsk1 setSimpleTaskDestination (getMarkerPos "wiocha"); - w miejscu markera "wiocha" tworzy zaznaczone na mapie i pokazuje jako waypoint w grze pozycję celu misji. Przydatne, lecz nieobowiązkowe. Pozwala jednak kompletnie zrezygnować z waypointów dla gracza.
player setCurrentTask tsk1; - ustala ten cel jako zaznaczony "obecnie do wykonania", tak samo, jakbyśmy kliknęli odpowiednią opcję w briefingu w grze.

No i to wszystko. Gdybyśmy teraz włączyli grę, mielibyśmy ten cel w briefingu. Ale, o ile dobrze pamiętam, miało być tego trochę więcej. Więc tworzymy kolejne cele w ten sam sposób. Powinniśmy otrzymać mniej więcej coś takiego:

tsk1 = player createSimpleTask["Capture Gorka"];
tsk1 setSimpleTaskDescription["Elliminate every American occupying our beautiful village and fortify yourselves in Gorka.","Capture Gorka","Capture Gorka"];
tsk1 setSimpleTaskDestination (getMarkerPos "wiocha");
player setCurrentTask tsk1;
tsk2 = player createSimpleTask["Destroy ammo depot"];
tsk2 setSimpleTaskDescription["Americans have organized there some kinda ammo depot. We don't need their ammunition 'cos we have Russian guns. So destroy it. Simple.","Destroy ammo depot","Destroy ammo depot"];
tsk2 setSimpleTaskDestination (getMarkerPos "ammo");
tsk3 = player createSimpleTask["Kill col. Strathmore"];
tsk3 setSimpleTaskDescription["He's responsible for the mass killings of the civillian people supporting us and the radical change of the situation on the front. He's now somewhere in this area. Find him and kill him.","Kill col. Strathmore","Kill col. Strathmore"];


Mamy więc cele misji. Nic trudnego, prawda? Teraz pozostało nam jeszcze tylko zrobić wpis w sekcji odpowiadającej za raporty sytuacyjne, pamiętniki, etc. Zastosować należy troszkę inne polecenie.

player createDiaryRecord["Diary", ["Situation on the frontline","We've won all battles so far, except those which we've lost."]];

Jak widać mamy tu także trzy pola do wypełnienia. W pierwszym musi być "Diary". Drugie odpowiada za tytuł wpisu, a trzecie za sam tekst.

Tak więc skończyliśmy tworzyć plik briefingu, który będziemy mieli przed sobą w momencie odpalenia misji. Zapisujemy init.sqf i idziemy testować już in-game.
Teraz przejdziemy do modyfikacji briefingu w czasie misji, na przykład (a raczej zazwyczaj) po wypełnieniu jednego z zadań. Należy pamiętać, że nie ma tu, tak jak było w OFP, celów ukrytych, które aktywujemy. Kiedy chcemy dodać cel po prostu go tworzymy w sposób opisany powyżej. Status zadania modyfikujemy komendą:

tskx SetTaskState "STATUS";

Gdzie za tskx wstawiamy nazwę odpowiedniego celu (na przykład tsk1) a w miejscu "STATUS" wpisujemy odpowiedni status:

"SUCCEEDED" - wykonany
"FAILED" - nieudany
"CANCELED" - anulowany
"CREATED" - w stanie "nienaruszonym"

Jak zapewne zauważyliśmy, w misjach "fabrycznych" po zmianie statusu celu pojawia się odpowiednie okienko u góry ekranu z informacją. Jak coś takiego zrobić? Jest to sprawa dość trudna, więc odsyłam was
na OFPEC, skąd ściągniecie odpowiedni pliczek (mk_fTaskHint) autorstwa mikeya i przeczytacie, jak go użyć. Jeśli nie chce Wam się z tym męczyć, można po prostu wstawić komendę "Hint" zaraz po poleceniu zmiany statusu. Na przykład:

Hint "TASK SUCCEEDED:\n'Capture Gorka'";

Należy także poznać tagi i polecenia odpowiadające za formatowanie tekstu w briefingu. Co ciekawe, są to pozostałości po HTML-u. Postaram się przytoczyć większość z nich.

<br/> - przejście do nowej linii.
<marker name='gorka'>Capture this town</marker> - tekst wpisany pomiędzy tagami będzie linkiem do markera o nazwie "gorka".
<img image='heniek.paa'/> - wstawia obrazek heniek.paa, który musi się znajdować w folderze głównym misji.
<img image='zdzisiek.paa' witdh='200' height='200'/> - J/W, tylko tu ustalamy wymiary obrazka.

Jeśli chcemy w innym skrypcie uzyskać aktualne dane o celach briefingu używamy komend taskState tskx i taskDescription tskx. Pierwsza zwraca wartość statusu celu, a druga - tytuł celu w formacie tekstu, oczywiście.



Briefing MP - TaskMaster



Przygotowanie odprawy dla misji multiplayer (nawet dla prostego coopa), różni się nieco od tworzenia tej do single - istotne jest choćby przystosowanie briefingów do wymogów funkcji Join-In-Progress, czy systemu zmiany ról. W każdym z przypadków (a także innych, wliczając w to misje PvP) najlepiej wykorzystać narzędzie zwane TaskMaster, stworzone przez członka community o ksywce Schuko.

Można go pobrać
tutaj, wraz z naszymi przykładami.

    "INSTALACJA" TASKMASTERA W NASZEJ MISJI

Po rozpakowaniu powyższej paczki Twoim oczom powinny ukazać się (oprócz folderu Przykłady") pliki:
- Briefing.sqf
- Init.sqf

Oba pliki .sqf należy wrzucić do folderu swojej misji. Od tego momentu briefing.sqf nie tykamy, koncentrując wszystkie swoje talenty psuja na pliku init.sqf.

Istotne uwagi:
- Nie używaj Polskich znaków.
- Briefingu nie widać w podglądzie edytora (SP). Musisz przekopiować misję z folderu Missions do MPMissions w katalogu użytkownika, po czym założyć serwer MP (może być prywatny, na LANie) i tam sprawdzić.
- Teksty w briefingu (opisy zadań itp) możemy formatować lub wbogacać tymi samymi komendami co w briefingu SP (np. odstępy, obrazki, etc - to tu działa tak samo)

    INIT.SQF

W tym pliku tworzymy cały briefing, wg wzorców podanych niżej.

PODSTAWA FORMY BRIEFINGU:

 
[[[A],[b]],[[C],[D]]] execvm "briefing.sqf";


A, B - Opis zadań (1 i 2)
C, D - Sekcje odprawy (1 i 2)

OPIS ZADANIA TWORZYMY WG. PONIŻSZEJ FORMUŁKI:

 
[X,"Y", ["E", "F", "G"]]


X - Komu ma być przydzielone (dla kogo będzie widoczne) zadanie (patrz niżej)
Y - Nazwa zadania (NIE STOSOWAĆ SPACJI ANI POLSKICH ZNAKÓW)
E - Opis zadania (ten główny, właściwy)
F - Opis zadania na pasku (powinien być krótki, jak najprostszy)
G - Opis waypointa na HUDzie w grze

alternatywnie, z przypisaniem zadania do markera

 
nul = [X,"Y",["E","F","G"],"M"] call TASKMASTER_add;


M - nazwa markera do którego ma być przypisany obj (jeżeli ma być)

SEKCJE ODPRAWY TWORZYMY WG. PONIŻSZEJ FORMUŁKI:

 
[X,["Y","E"]]


X - Komu ma być przydzielone (dla kogo będzie widoczne) zadanie (patrz niżej)
Y - Nazwa sekcji
E - Zawartość danej sekcji odprawy

PRZYDZIAŁ ZADANIA:
 
"true"
- wszyscy (jeśli jest tylko 1 drużyna graczy to tylko to stosować)
 
WEST
- siły Zachodu
 
EAST
- siły Wschodu
 
GUER
- siły Niezależne
 
FireTeam1
- grupa graczy opisana jako FireTeam1 (patrz pkt: nazwanie grupy)
 
banan1
- jednostka nazwana banan1

Oprócz tego dostępne są również wariacje, np. przydziały łączone:

 
"((group _x == FireTeam1) OR (_x == banan1))"


w ten sposób zadanie wyświetlone zostanie jedynie dla grupy FireTeam1 i jednostki Banan1. Można też przydzielić zadanie kilku grupom:

 
"((group _x == FireTeam1) OR (group _x == FireTeam2) OR (group _x == FireTeam3))"


Wpis będzie widoczny dla grup FireTeam1, FireTeam2, FireTeam3. Można też przydzielić samym wybranym jednostkom:

 
"((_x == banan1) OR (_x == banan2) OR (_x == banan3))"


W tym wypadku wpis będzie widoczny dla jednostek banan1, banan2 i banan3.


Ilość zadań i sekcji może być dowolna (taskmaster ma jakiś tam limit z tego co pamiętam, ale raczej nierealny do osiągnięcia w typowej misji Coop\PvP), mniejsza lub większa w zależności od Twoich zapotrzebowań. Pamiętaj tylko, by zgadzała się ilość otwieranych i zamykanych nawiasów oraz składnia. Np.

 
[[[A]],[[C],[D]]] execvm "briefing.sqf";
1 zadanie 2 sekcje odprawy

 
[[[A]],[[C]]] execvm "briefing.sqf";
1 zadanie 1 sekcja odprawy

 
[[[A],[b],[C]],[[D],[E],[F]]] execvm "briefing.sqf";
3 zadania 3 sekcje odprawy

    EDYTOR (bądź skrypty zewnętrzne)

Init.sqf załatwia wszystko to co dostajemy "na dzień dobry". A co z całą resztą, czyli zaliczaniem zadań i tworzeniem nowych?

STWORZENIE NOWEGO ZADANIA W TRAKCIE MISJI
Elementy składowe komendy jak w briefingu przed misją tj.

 
nul = [X,"Y",["E","F","G"]] call TASKMASTER_add;


X - Komu ma być przydzielone (dla kogo będzie widoczne) zadanie (patrz wyżej)
Y - Nazwa zadania (NIE STOSOWAĆ SPACJI ANI POLSKICH ZNAKÓW)
E - Opis zadania (ten główny, właściwy)
F - Opis zadania na pasku (powinien być krótki, jak najprostszy)
G - Opis waypointa na HUDzie w grze

alternatywnie, z przypisaniem zadania do markera

 
nul = [X,"Y",["E","F","G"],"M"] call TASKMASTER_add;


M - nazwa markera do którego ma być przypisany obj (jeżeli ma być)

ZMIANA STATUSU ZADANIA

Wykonane (zielone wypełnienie):
 
nul = ["nazwa_zadania","succeeded"] call TASKMASTER_upd;


Zakończone niepowodzeniem (czerwony krzyżyk):
 
nul = ["nazwa_zadania","failed"] call TASKMASTER_upd;


Odwołane (szara kreska):
 
nul = ["nazwa_zadania","canceled"] call TASKMASTER_upd;


Aktualne (szare wypełnienie):
 
nul = ["nazwa_zadania","current"] call TASKMASTER_upd;


I to w gruncie rzeczy wszystko. Na wypadek gdyby coś było niejasne - polecam zajrzeć do zamieszczonych w naszej paczce przykładów, zarówno tych oryginalnych jak i naszego.




Debriefing



Uważni czytelnicy zapewne spostrzegli, że brakuje nam jeszcze jednej rzeczy. Oczywiście chodzi mi o debriefing, czyli podsumowanie misji po jej zakończeniu. Niestety, wyjdzie teraz na jaw, iż skłamałem na początku poradnika - debriefing jest jedną jedyną pozostałością po HTML-owskiej formie odprawy. Starzy wyjadacze z OFP i znający się na HTML-u nie będą mieli najmniejszych problemów ze stworzeniem go. Debriefing w A2 jest w formie pliku briefing.html, tyle że pozbawiony całej sekcji odprawy. Tworzymy go w sposób podobny, jak skrypty i inne tego typu pliki, z tym, że dodajemy rozszerzenie .html. Dla tych, którzy nie wiedzą, jak powinna wyglądać jego zawartość, umieszczam przykład:


<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1250">

<title>Title</title>
</head>

<body bgcolor="#FFFFFF">
<! -----DEBRIEFING----->
<hr>
<br>
<h2><a name="Debriefing:End1">Zwycięstwo.</a></h2>
<br>
<p>
<! ------victory------>
Dowiedziałeś się, co się stało z konwojem i pokonałeś NAPA. Dobra robota, Kuzniecow.
</p>
<br>

<hr>
<br>
<h2><a name="Debriefing:Loser">Misja wykonana.</a></h2>
<br>
<p>
<! ------KIA------>
Misja została wykonana, ale NAPA udało się uciec. Mimo to - dobra robota.
</p>
<br>

<! -----DEBRIEFING END----->

</body>
</html>


<h2><a name="Debriefing:End1">Zwycięstwo.</a></h2> - fragmenty, które modyfikujemy dla własnych potrzeb są dwa, zaznaczyłem je kursywą (zresztą jest to dość oczywiste). Pierwszy odpowiada za przypisanie danego debriefingu do odpowiedniego zakończenia, które wywołujemy wyzwalaczem - w tym przypadku ujrzymy ten debriefing gdy aktywujemy wyzwalacz z zaznaczonym Typ -> Koniec #1. Drugi fragment to oczywiście nagłówek debriefingu.
Następnym polem do edycji jest miejsce pod komentarzem "victory". Tam wpisujemy właściwy tekst zakończenia. Uwaga! Jeśli chcemy mieć polskie znaki, modyfikujemy kodowanie pliku w sposób podany na końcu poradnika (ale nie bawimy się w żadne stringtable! - tu to nie działa). Jeżeli chcemy mieć wiele zakończeń, po prostu kopiujemy daną sekcję debriefingu i zmieniamy tylko numerek przy End, bądź wpisujemy tam Loser.




Polskie znaki - Stringtable



W tym miejscu powinniście już wiedzieć, jak stworzyć porządny briefing ze wszystkim, co powinien takowy posiadać. Jednak pozostała jeszcze jedna sprawa - polskie znaki. Problem wynika z kodowania pliku. Notatnik domyślnie zapisuje wszystko w ANSI. ArmA 2 odczytuje polfonty tylko w UTF-8, jednak jeśli zapiszemy skrypt w tym kodowaniu, mogą pojawić się problemy. Dlatego właśnie w tym miejscu do gry wchodzi Stringtable. Jest to plik, w którym umieścimy wszystkie teksty i odnośniki do każdego z nich, a później zamiast tekstu w skrypcie briefingu wstawimy te odnośniki. Stringtable jest w formacie .csv (Excellowskim) i tworzymy je oraz edytujemy Notatnikiem (nie próbujcie MS Excellem) tak samo, jak inne pliczki, z tym jednak, że w polu "Kodowanie" zaznaczamy "UTF-8". Wpisów w stringtable dokonujemy w następujący sposób:

LANGUAGE,"Polish"
STR_O1,"Znajdź zniszczony konwój",
STR_O2,"Wyeliminuj partyzantów",
STR_O3a,"Zniszcz obóz NAPA",
STR_O3b,"Odbij bazę Moroz",
STR_O1desc,"Musicie podążyć szlakiem konwoju. Z pewnością został zniszczony lub przejęty przez wroga, więc miejcie oczy otwarte. Bądźcie przygotowani na eliminację ewentualnego zagrożenia. Zacznijcie poszukiwania <marker name='unknown'>w tym obszarze</marker>, który jest częścią trasy konwoju.",
STR_O2desc,"NAPA zniszczyła konwój! Zabij każdego partyzanta w okolicy!",
STR_O3adesc,"Niedaleko od miejsca ataku na konwój, NAPA posiada obóz. Ruszaj tam i zniszcz go, zanim zostanie przeniesiony.",
STR_O3bdesc,"Baza Moroz została zajęta przez NAPA. Musicie zostawić bieżące zadania, wrócić się i odbić ją z rąk partyzantów.",


Wpis składa się z dwóch części. Pierwszy - STR_o1 na przykład - to oczywiście odnośnik. Ważne by zawierał na początku litery STR. Dalsza część w cudzysłowie to... wiadomo co :) Na początku dokumentu znajduje się deklaracja języka. LANGUAGE - musi być. Po przecinku wpisujemy w cudzysłowie, w jakim języku jest dany wpis. Możemy umieścić kilka języków, np.:

LANGUAGE,"ENGLISH","POLISH"

Wtedy trzeba zadbać o odpowiednią strukturę wpisów, która powinna wyglądać następująco:

STR_o1,"Secure the Altar hill","Zabezpiecz wzgórze Altar"

Można się domyślić, że polecenia w skrypcie briefingu będą się troszkę różnić w tym przypadku. Chodzi mianowicie o to, że nie wystarczy pomiędzy cudzysłowami wpisać STR_o1, gdyż wtedy oczywiście wyświetli nam właśnie te litery. Należy PRZED cudzysłowem umieścić wyraz localize, a następnie dopiero, już w cudzysłowie, wpisać STR_o1. Czyli:

tsk1 = player createSimpleTask[localize "STR_o1"];
tsk1 setSimpleTaskDescription[localize "STR_o1desc",localize "STR_o1",localize "STR_o1"];


Po odpaleniu gry powinniśmy móc oglądać swój tekst z polskimi znakami bez żadnych problemów. UWAGA - metody z "localize" można używać także we wszystkich przypadkach, gdzie mamy pole do wpisania tekstu, np. TitleText, Hint, i tak dalej.