W poprzednim poradniku wspominałem o funkcjach addMessage oraz print. Służyły one do wyświetlania pewnych informacji graczowi. Jest jeszcze jedna bardzo fajna funkcja, która bardzo nam się przyda, czyli Drawy.
Zacznijmy od początku. Potrzebowałem wstawić na serwer 30-sekundowe odliczanie. Wiedziałem już wcześniej co to jest Draw, ale myślałem, że Timer to tylko taki licznik-dodatek. Okazało się, że to bardzo przydatne narzędzie.
Timer wykonuje jakąś funkcję co jakiś czas. Może to być wyświetlanie czegoś na ekranie, a może być np. respawn Mobów.
Ale dlaczego użyłem Drawu? addMessage to wypisywanie czegoś na czacie. Bez sensu wypisywać co sekundę liczby od 0 do X ponieważ całkowicie uniemożliwiłoby to komunikację. Co do printa, sami zobaczcie, jak to wygląda. Ale to później.
1. Jak i gdzie.
Tym razem, dla odmiany, polecam utworzyć nowy plik .nut . Nie zapomnijcie dopisać go tam gdzie trzeba!
Jak już mówiłem, potrzebowałem WYŚWIETLIĆ na ekranie co JAKIŚ CZAS pewną informację. Użyłem Drawa.
Draw wyświetla nam informację na ekranie. Może to być godzina, może to być ilość zgonów/zabójstw. Różni się on od innych metod tym, że jest cały czas (póki go nie usuniemy) na swoim miejscu, zupełnie jak tekstura. I zupełnie jak przy jej wstawianiu, musimy podać jego pozycję. Drawy są bardzo często używane przy robieniu klikalnego menu np. animacji.
http://gothic-online.com.pl/wiki/index.p...CreateDraw
Pierwsze co zrobiłem to udałem się do wiki i zapoznałem z funkcją setTimer
http://gothic-online.com.pl/wiki/index.p...e=SetTimer
Wygląda to już dość skomplikowanie.
Myślę, że słowa local nie muszę już tłumaczyć.
counter będzie nam służyło do wypisywania odpowiedniej liczby co sekundę. Pomiędzy {} klamrami widzimy, poza printem ++counter. Dla nieobeznanych tłumaczę, że oznacza to zwiększenie liczy o 1.
Później mamy zmienną id, której jest przypisana funkcja setTimer(). Zmienna id będzie nam później potrzebna do zatrzymania Timera.
1000 i true. 1000 jest to wartość podana w milisekundach. 1000ms to sekunda, czyli nasza funkcja (ta w klamrze {} ) będzie się wykonywała co sekundę. True, to po prostu wywołanie powtarzania się Timera.
Dobrze, skoro mamy printa, to na początek użyjemy printa. A co do miejsca wpisania, to ja będę uruchamiał Timer od razu po wejściu na serwer, nie pod klawisz czy komendę.
Chcemy zrobić odliczanie od 1 do 30, a później zatrzymać timer.
counter zostawiamy jak jest. No tak, ale chcemy odliczać od 1? I od 1 zacznie się odliczanie, skoro przypisaliśmy counter = 0, to od razu za pierwszym "wykonaniem" Timera counter zwiększy nam się o 1.
Nadążacie? Teraz musimy ograniczyć czas wykonywanie Timera do 30. Posłuży nam do tego funkcja killTimer.
http://gothic-online.com.pl/wiki/index.p...=KillTimer
I tutaj mamy coś ciekawego, bo niby jest to druga funkcja, czyli wydawałoby się, na tym samym poziomie co setTimer, a jednak znajduje się wewnątrz niej. Oczywiście, nic nie szkodzi na przeszkodzie, żeby zatrzymać Timer z innego miejsca i po innym warunku, ale w tym przypadku nam się to nie przyda.
Jeśli zostawimy killTimer tak jak jest w przykładzie, to Timer zatrzyma się po pierwszym wykonaniu. My chcemy, żeby zatrzymał się wtedy gdy counter uzyska wartość równą 30. Posłużymy się do tego najważniejszym, najbardziej przydatnym i absolutnie niezbędnym w każdym języku programowania słowem if.
Czyli zapiszemy w języku programowania: Jeśli counter osiągnie wartość 0 (innaczej mówiąc, jeśli Timer wykona się 30 razy), to wyłącz Timer (o podanym ID).
Hmm...no dobra, to mała lekcja ogólnie z programowania, wyjątkowo.
Z matematyki każdy zna różne równania i nierówności. Mamy tam znaki równa się, większy, mniejszy równy. W językach programowania są to np. =, >, <=. Są to tak zwane operacje porównania. Tylko, że w tym wypadku nie możemy użyć jednego znaku równa się =, ponieważ wtedy PRZYPISALIBYŚMY do zmiennej daną wartość. Gdy napiszemy == to tylko PORÓWNAMY zmienną do liczby (w tym wypadku). Odsyłam was do bardziej rozbudowanych poradników.
A tutaj cały kod, porównaj go ze swoim:
I to by było na tyle. Koniecznie sprawdź ten kod. Podoba ci się efekt? Bo mi nie bardzo. Zaraz temu zaradzimy.
2. Nie takie Drawy straszne.
Jeśli na początku nie zrozumiałeś poco nam te drawy, to teraz na pewno widzisz zastosowanie dla "postawienia" w jednym miejscu takiego odliczania, a nie zasypywania całego ekranu liczbami. Zajrzyjmy do wiki.
http://gothic-online.com.pl/wiki/index.p...CreateDraw
Bez sensu jest mi przepisywać dobry artykuł z wiki. Co do fontu, to możemy tu dać swój, a możemy skorzystać z Gothicowych. Ich nazwy mamy podane w
...\_WORK\DATA\TEXTURES\FONTS\NOMIP
Oczywiście po wypakowaniu tekstur.
cursor- Determines whether the cursor will be under draw whether above draw.
Czyli możemy wybrać, czy przy "kontakcie" cursor ma być pod czy nad drawem.
Z RGB tworzy się kolor (Red, Green, Blue mówi wam to coś?). Oczywiście nikt nie strzela z wartościami, mamy odpowiednie listy np.
https://pl.wikipedia.org/wiki/Lista_kolor%C3%B3w
Ale równie dobrze, można pobrać kolor w programie graficznym.
W ARTYKULE ZABRAKŁO MAŁEGO SZCZEGÓŁU. Na początku przed Draw1, musimy wstawić local. I na początek polecam skopiować tylko ten kawałek i wkleić go do...
No właśnie, tutaj chwila zastanowienia. Osobiście wydaje mi się, że gdy wpiszemy Draw w timer, to za każdym wywołaniem będzie się on tworzył i tworzył od nowa. Nie wpłynie to zbyt dobrze na optymalizację skryptu, co jest równie ważne jak sam kod. Poco nam wypasiony kod, który zamula serwer? Jeśli moje rozumowanie jest poprawne. Całe szczęście, wracając do naszej listy funkcji, widzimy taki oto artykuł:
http://gothic-online.com.pl/wiki/index.p...etDrawText
Oznacza to, że możemy w gotowym drawie tylko zmienić tekst. W naszym przypadku, zamiast tekstu wstawimy zmienną z odliczaniem.
Ja zrobiłem tak, że zmienną draw1 utworzyłem przed Timerem, a w samym Timerze dałem tylko setDrawText, w którym zamiast tekstu podałem zmienną counter.
Co jest dziwniejsze? Ten akapit powyżej, czy to, że w pełni go rozumiesz? Nawet bez pokolorowania przeze mnie funkcji.
W chwili obecnej kod wygląda tak:
Czy nasz kod jest gotowy? Koniecznie go sprawdźcie. Osoby, które już potrafią pisać w Squirrelu pewnie śmieją się z nas w duchu, ale spokojnie, jeszcze im pokażemy. Najpierw sprawdź kod.
.
.
.
.
.
.
No ja też byłem zaskoczony i powiem, że długo mi zajęło rozwiązanie tego problemu. Nasz kod się nie wyświetla!
Co zrobić w takiej sytuacji? Wrócić do najbardziej "dziewiczej" wersji funkcji. Skoro timer wcześniej działał, to coś nie tak jest z Drawem. Zamiast zmiennej, wpiszmy tam jakiś tekst. W samej zmiennej jest już napis "Odliczanie". W takim razie, w serDrawText zamiast zmiennej, wpisz coś. Koniecznie pomiędzy "" cudzysłowem, o czym wspominałem wcześniej.
.
.
.
No dobra, wyświetla się. W czym problem? Dla osoby mniej obeznanej z jakimkolwiek językiem skryptowym mogłoby to praktycznie zatrzymać cały proces tworzenie serwera. No bo to nie ma sensu. Ja sam nie jestem jakimś wielkim programistą i nie od razu wiedziałem co robić. Dlatego ten tutorial napisałem dopiero dzisiaj.
Dobra, przejdźmy do sedna. Gdy wpiszemy.
setDrawText(draw1,counter);
To draw nie działa. Ale gdy wpiszemy
setDrawText(draw1,"Tekst1");
To wyświetli nam się Tekst1. Jaką mamy różnice pomiędzy tymi dwoma wartościami?
No dokładnie! Cudzysłów. Co to dla nas oznacza. Oznacza to, że Drawy akceptują tylko i wyłącznie zmienną tekstową (string). Żeby to sprawdzić, do setDrawText wpisz spowrotem counter, ale u góry, zrób tak:
local counter = "Tekst1";
Zawsze się zastanawiałem, poco w C++ trzeba definiować rodzaj zmiennej, skoro w takim PHP robi się to automatycznie. No i już wiem. Teraz, skoro Squirrel automatycznie przypisuje do counter = 0 zmienną liczbową, musimy to przekonwertować. Tego niestety nie ma na wiki (nie rozumiem działania sscanf, ale to chyba działa tylko dla tabel.) , więc musimy postawić się w sytuacji w której pisalibyśmy osobny program, a nie moduł do gry z gotowych funkcji. Czyli, musimy zajrzeć do dokumentacji języka Squirrel . Link jest na wiki.
http://squirrel-lang.org/doc/squirrel3.html
Długie, co nie? Spokojnie, wyręczę was, ale zapamiętajcie, że coś takiego istnieje, bo może wam się bardzo przydać.
Żeby zmienić typ zmiennej, musimy na pewno utworzyć drugą zmienną która nam tą pierwszą zmienną zmieni.
Tylko, gdy już przypiszemy po znaku = tą pierwszą zmienną, dodajemy na jej końcu .to[rodzaj zmiennej]. Ludzkim językiem pisząc:
local counter1 =0;
local counter2=counter1.tostring();
Zauważcie, że dodałem cyferki, żeby się odróżniało.
Teraz możecie przystąpić do napisania prawidłowego skryptu.
Parę uwag na koniec.
Użycie setDrawText w Timerze daje nam jeszcze jedną korzyść. Mianowicie, dzięki temu Drawy nie nakładają się na siebie. Gdybyśmy chcieli deklarować Drawa w Timerze, musielibyśmy pod jego koniec, albo na początku następnego(co by trochę ładniej wyglądało), usunąć stary i dopiero tworzyć nowy.
Wynika też z tego, że skrypty też mają swoją kolejność i nie możemy rozrzucać funkcji jak chcemy, tylko, żeby były w obrębie jednego bloku.
Na początku poradnika podałem:
local id = setTimer(function()
Ale gdy dodaliśmy killTimer, zamieniłem to na:
local id = -1;
id = setTimer(function()
Gdybym tego nie zrobił, killTimer by nie działał.
To koniec mojego kolejnego, przydługawego, ale myślę, że treściwego poradnika. Szykuje jeszcze coś ciekawego, ale muszę najpierw sam to wypróbować. Przygotujcie tylko ładne pakiety tekstur i DX11 do Gothica.
Zacznijmy od początku. Potrzebowałem wstawić na serwer 30-sekundowe odliczanie. Wiedziałem już wcześniej co to jest Draw, ale myślałem, że Timer to tylko taki licznik-dodatek. Okazało się, że to bardzo przydatne narzędzie.
Timer wykonuje jakąś funkcję co jakiś czas. Może to być wyświetlanie czegoś na ekranie, a może być np. respawn Mobów.
Ale dlaczego użyłem Drawu? addMessage to wypisywanie czegoś na czacie. Bez sensu wypisywać co sekundę liczby od 0 do X ponieważ całkowicie uniemożliwiłoby to komunikację. Co do printa, sami zobaczcie, jak to wygląda. Ale to później.
1. Jak i gdzie.
Tym razem, dla odmiany, polecam utworzyć nowy plik .nut . Nie zapomnijcie dopisać go tam gdzie trzeba!
Jak już mówiłem, potrzebowałem WYŚWIETLIĆ na ekranie co JAKIŚ CZAS pewną informację. Użyłem Drawa.
Draw wyświetla nam informację na ekranie. Może to być godzina, może to być ilość zgonów/zabójstw. Różni się on od innych metod tym, że jest cały czas (póki go nie usuniemy) na swoim miejscu, zupełnie jak tekstura. I zupełnie jak przy jej wstawianiu, musimy podać jego pozycję. Drawy są bardzo często używane przy robieniu klikalnego menu np. animacji.
http://gothic-online.com.pl/wiki/index.p...CreateDraw
Pierwsze co zrobiłem to udałem się do wiki i zapoznałem z funkcją setTimer
http://gothic-online.com.pl/wiki/index.p...e=SetTimer
Wygląda to już dość skomplikowanie.
Code:
local counter = 0;
local id = setTimer(function()
{
print(++counter);
}, 1000, true);
Myślę, że słowa local nie muszę już tłumaczyć.
counter będzie nam służyło do wypisywania odpowiedniej liczby co sekundę. Pomiędzy {} klamrami widzimy, poza printem ++counter. Dla nieobeznanych tłumaczę, że oznacza to zwiększenie liczy o 1.
Quote:counter to tylko takie słowo, można tu wpisać cokolwiek.
Później mamy zmienną id, której jest przypisana funkcja setTimer(). Zmienna id będzie nam później potrzebna do zatrzymania Timera.
1000 i true. 1000 jest to wartość podana w milisekundach. 1000ms to sekunda, czyli nasza funkcja (ta w klamrze {} ) będzie się wykonywała co sekundę. True, to po prostu wywołanie powtarzania się Timera.
Dobrze, skoro mamy printa, to na początek użyjemy printa. A co do miejsca wpisania, to ja będę uruchamiał Timer od razu po wejściu na serwer, nie pod klawisz czy komendę.
Chcemy zrobić odliczanie od 1 do 30, a później zatrzymać timer.
counter zostawiamy jak jest. No tak, ale chcemy odliczać od 1? I od 1 zacznie się odliczanie, skoro przypisaliśmy counter = 0, to od razu za pierwszym "wykonaniem" Timera counter zwiększy nam się o 1.
Quote:Jaki jest sens przypisywania zmiennej zera? A no jest i to ogromny. Zero to też wartość, brak wartości to null i też ma swoją reprezentację w językach programowania. Nie możemy zacząć odliczania od niczego, musimy zacząć od zera.
Nadążacie? Teraz musimy ograniczyć czas wykonywanie Timera do 30. Posłuży nam do tego funkcja killTimer.
http://gothic-online.com.pl/wiki/index.p...=KillTimer
I tutaj mamy coś ciekawego, bo niby jest to druga funkcja, czyli wydawałoby się, na tym samym poziomie co setTimer, a jednak znajduje się wewnątrz niej. Oczywiście, nic nie szkodzi na przeszkodzie, żeby zatrzymać Timer z innego miejsca i po innym warunku, ale w tym przypadku nam się to nie przyda.
Jeśli zostawimy killTimer tak jak jest w przykładzie, to Timer zatrzyma się po pierwszym wykonaniu. My chcemy, żeby zatrzymał się wtedy gdy counter uzyska wartość równą 30. Posłużymy się do tego najważniejszym, najbardziej przydatnym i absolutnie niezbędnym w każdym języku programowania słowem if.
Czyli zapiszemy w języku programowania: Jeśli counter osiągnie wartość 0 (innaczej mówiąc, jeśli Timer wykona się 30 razy), to wyłącz Timer (o podanym ID).
rozwiązanie
Z matematyki każdy zna różne równania i nierówności. Mamy tam znaki równa się, większy, mniejszy równy. W językach programowania są to np. =, >, <=. Są to tak zwane operacje porównania. Tylko, że w tym wypadku nie możemy użyć jednego znaku równa się =, ponieważ wtedy PRZYPISALIBYŚMY do zmiennej daną wartość. Gdy napiszemy == to tylko PORÓWNAMY zmienną do liczby (w tym wypadku). Odsyłam was do bardziej rozbudowanych poradników.
Quote:Niesamowicie przydatny jest też operator negacji
A tutaj cały kod, porównaj go ze swoim:
rozwiązanie
I to by było na tyle. Koniecznie sprawdź ten kod. Podoba ci się efekt? Bo mi nie bardzo. Zaraz temu zaradzimy.
2. Nie takie Drawy straszne.
Jeśli na początku nie zrozumiałeś poco nam te drawy, to teraz na pewno widzisz zastosowanie dla "postawienia" w jednym miejscu takiego odliczania, a nie zasypywania całego ekranu liczbami. Zajrzyjmy do wiki.
http://gothic-online.com.pl/wiki/index.p...CreateDraw
Bez sensu jest mi przepisywać dobry artykuł z wiki. Co do fontu, to możemy tu dać swój, a możemy skorzystać z Gothicowych. Ich nazwy mamy podane w
...\_WORK\DATA\TEXTURES\FONTS\NOMIP
Oczywiście po wypakowaniu tekstur.
cursor- Determines whether the cursor will be under draw whether above draw.
Czyli możemy wybrać, czy przy "kontakcie" cursor ma być pod czy nad drawem.
Z RGB tworzy się kolor (Red, Green, Blue mówi wam to coś?). Oczywiście nikt nie strzela z wartościami, mamy odpowiednie listy np.
https://pl.wikipedia.org/wiki/Lista_kolor%C3%B3w
Ale równie dobrze, można pobrać kolor w programie graficznym.
W ARTYKULE ZABRAKŁO MAŁEGO SZCZEGÓŁU. Na początku przed Draw1, musimy wstawić local. I na początek polecam skopiować tylko ten kawałek i wkleić go do...
No właśnie, tutaj chwila zastanowienia. Osobiście wydaje mi się, że gdy wpiszemy Draw w timer, to za każdym wywołaniem będzie się on tworzył i tworzył od nowa. Nie wpłynie to zbyt dobrze na optymalizację skryptu, co jest równie ważne jak sam kod. Poco nam wypasiony kod, który zamula serwer? Jeśli moje rozumowanie jest poprawne. Całe szczęście, wracając do naszej listy funkcji, widzimy taki oto artykuł:
http://gothic-online.com.pl/wiki/index.p...etDrawText
Oznacza to, że możemy w gotowym drawie tylko zmienić tekst. W naszym przypadku, zamiast tekstu wstawimy zmienną z odliczaniem.
Ja zrobiłem tak, że zmienną draw1 utworzyłem przed Timerem, a w samym Timerze dałem tylko setDrawText, w którym zamiast tekstu podałem zmienną counter.
Co jest dziwniejsze? Ten akapit powyżej, czy to, że w pełni go rozumiesz? Nawet bez pokolorowania przeze mnie funkcji.
W chwili obecnej kod wygląda tak:
rozwiązanie
Czy nasz kod jest gotowy? Koniecznie go sprawdźcie. Osoby, które już potrafią pisać w Squirrelu pewnie śmieją się z nas w duchu, ale spokojnie, jeszcze im pokażemy. Najpierw sprawdź kod.
.
.
.
.
.
.
No ja też byłem zaskoczony i powiem, że długo mi zajęło rozwiązanie tego problemu. Nasz kod się nie wyświetla!
Co zrobić w takiej sytuacji? Wrócić do najbardziej "dziewiczej" wersji funkcji. Skoro timer wcześniej działał, to coś nie tak jest z Drawem. Zamiast zmiennej, wpiszmy tam jakiś tekst. W samej zmiennej jest już napis "Odliczanie". W takim razie, w serDrawText zamiast zmiennej, wpisz coś. Koniecznie pomiędzy "" cudzysłowem, o czym wspominałem wcześniej.
.
.
.
No dobra, wyświetla się. W czym problem? Dla osoby mniej obeznanej z jakimkolwiek językiem skryptowym mogłoby to praktycznie zatrzymać cały proces tworzenie serwera. No bo to nie ma sensu. Ja sam nie jestem jakimś wielkim programistą i nie od razu wiedziałem co robić. Dlatego ten tutorial napisałem dopiero dzisiaj.
Dobra, przejdźmy do sedna. Gdy wpiszemy.
setDrawText(draw1,counter);
To draw nie działa. Ale gdy wpiszemy
setDrawText(draw1,"Tekst1");
To wyświetli nam się Tekst1. Jaką mamy różnice pomiędzy tymi dwoma wartościami?
No dokładnie! Cudzysłów. Co to dla nas oznacza. Oznacza to, że Drawy akceptują tylko i wyłącznie zmienną tekstową (string). Żeby to sprawdzić, do setDrawText wpisz spowrotem counter, ale u góry, zrób tak:
local counter = "Tekst1";
Zawsze się zastanawiałem, poco w C++ trzeba definiować rodzaj zmiennej, skoro w takim PHP robi się to automatycznie. No i już wiem. Teraz, skoro Squirrel automatycznie przypisuje do counter = 0 zmienną liczbową, musimy to przekonwertować. Tego niestety nie ma na wiki (nie rozumiem działania sscanf, ale to chyba działa tylko dla tabel.) , więc musimy postawić się w sytuacji w której pisalibyśmy osobny program, a nie moduł do gry z gotowych funkcji. Czyli, musimy zajrzeć do dokumentacji języka Squirrel . Link jest na wiki.
http://squirrel-lang.org/doc/squirrel3.html
Długie, co nie? Spokojnie, wyręczę was, ale zapamiętajcie, że coś takiego istnieje, bo może wam się bardzo przydać.
Żeby zmienić typ zmiennej, musimy na pewno utworzyć drugą zmienną która nam tą pierwszą zmienną zmieni.

local counter1 =0;
local counter2=counter1.tostring();
Zauważcie, że dodałem cyferki, żeby się odróżniało.
Quote:Gdybyśmy chcieli zmienną string, która by zawierała cyfrę (np liczba = "1"; ) zmienić na zmienną liczbową, zamiast .tostring() dodalibyśmy .tointeger() . Nazwy zmiennych pozostawiam do nauczania się przez was samemu.
Pamiętajcie też, że po zmiane typu na string, nie możemy zwiększać czy zmniejszać zmiennej o 1. Musimy to zrobić jeszcze przed konwersją.
Teraz możecie przystąpić do napisania prawidłowego skryptu.
rozwiązanie
Parę uwag na koniec.
Użycie setDrawText w Timerze daje nam jeszcze jedną korzyść. Mianowicie, dzięki temu Drawy nie nakładają się na siebie. Gdybyśmy chcieli deklarować Drawa w Timerze, musielibyśmy pod jego koniec, albo na początku następnego(co by trochę ładniej wyglądało), usunąć stary i dopiero tworzyć nowy.
Wynika też z tego, że skrypty też mają swoją kolejność i nie możemy rozrzucać funkcji jak chcemy, tylko, żeby były w obrębie jednego bloku.
Na początku poradnika podałem:
local id = setTimer(function()
Ale gdy dodaliśmy killTimer, zamieniłem to na:
local id = -1;
id = setTimer(function()
Gdybym tego nie zrobił, killTimer by nie działał.
To koniec mojego kolejnego, przydługawego, ale myślę, że treściwego poradnika. Szykuje jeszcze coś ciekawego, ale muszę najpierw sam to wypróbować. Przygotujcie tylko ładne pakiety tekstur i DX11 do Gothica.
Nie będzie mnie do sierpnia, jestem w Szkocji i zarabiam na studia. Do zobaczenia.