Thread Rating:
  • 1 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PL]1.Skryptuj z Danielem - DeatchMatch
#1
Siema. Trochę was przetrzymałem, ale mogę wam przysiąc, że nie próżnowałem ze skryptowaniem. Dzięki temu moja wiedza którą chcę wam przekazać, będzie większa i dokładniejsza. Chociaż miałem mały problem z wymyśleniem, co jeszcze mam opisać. Nie wiedziałem jak i co mam opisać, żeby się nie powtarzać. Tutaj wpadłem na pomysł napisania kilku poradników "tematycznych". Powoli zbliżam się do wyczerpania tematów, chyba, że nie dam rady opisać wszystkich dostępnych modułów, albo dojdą nam jakieś nowe.
Wszelkie formy wyświetlania tekstu i tekstur, aktywacji funkcji, timery, pobieranie pozycji i operowanie kursorem. Zmienne, tabele oraz konwersja pomiędzy typami. Naginaliśmy gothicową czasoprzestrzeń naszymi skryptami Big Grin
Od teraz nastąpi wzrost poziomu trudności. Co to dla was oznacza? Że będziemy mieli więcej treści na jeden temat, mniej powtarzania kodu i więcej będę od was wymagał. Jak to mówi mój znajomy "skończyły się tłuste lata".
Zaczniemy od skryptu DM. DM jest najprostszą do zorganizowania formą zabawy w Gothicu. OCZYWIŚCIE, że można napisać skrypt DM którzy przewyższa skrypt RP (pozdrowienia dla Zmorry) , ale zdecydowanie mniej się od niego wymaga. Zapoznamy się tutaj z komunikacją klient-serwer, serwer-klient(extremalnie przydatne) jak i samą konsolą, która stanie się od teraz naszym najlepszym przyjacielem. Zrobimy trochę inny wybór klasy który powinien być już standardem! A na koniec wstawimy naszą muzykę na serwer za pomocą biblioteki BASS.

1. Wybór klasy.

Quote:WAŻNE! NIE PODAJĘ TUTAJ JAK NAPISAĆ SKRYPTU WYBORU KLASY. Taki paradoks. Zastanawiałem się nad tym długo. Robię to dlatego, że skrypt wyboru klasy jest takim "kamieniem milowym" w życiu skryptera, wymaga już dużo LOGICZNEGO myślenia. Drugi powód jest taki, że skryptów na wybór klasy może być tyle, ile samych skrypterów. Więc ważnym jest, żeby rozwiązać ten problem samemu.
Jeśli będzie z tym jakiś wielkie problem, to może zrobię to jako Quest

Będziemy działali na atrapach (chyba, że ktoś zechce napisać sobie teraz skrypt wyboru klasy-to jak najbardziej możliwe!). Znowu uraczę was własnymi grafikami, na których będziemy pracowali. Tak, ja widzę, że są jeszcze takie kontury, ale nikogo nie oszukuję, że jestem grafikiem Big Grin Brać i wstawiać do gry według własnego uznania.
http://hostuje.net/file.php?id=0f7b2e869...e5dacab53a
No tak, ale co zrobić, żeby tekstury pobierały się tym którzy wchodzą na nasz serwer? Musimy je wrzucić do folderu download.
a) jako plik .vdf z odpowiednią ścieżką (czyli w data).
b) Bez pliku vdf, najlepiej w formacie .tex jako cała ścieżka (czy dla tekstur: ...\download\_Work\Data\Textures\_compiled

O co mi tu chodzi? Nic nie mam do wybierania klas strzałkami, ale gdy nam się ich trochę uzbiera, to musimy trochę poprzewijać. Nawet gdy jest ich mało, gdybyśmy mieli je wszystkie na ekranie wraz z opisami i musieli tylko jedną kliknąć, by wybrać, dużo szybciej i prościej moglibyśmy przejść do rozgrywki.
Mamy już wstawione te 3 obrazki? Podpiszmy je jeszcze Drawami i skupmy się na prawdziwym problemie. Zdarzeniu OnClick.


Code:
function onClick(button, x, y, wheel)
{
}

Pewnie ta część poradnika nie powstałaby, albo powstałaby później, gdyby nie pomoc Profesoresa.
Jest to taka sama funkcja jak onHit czy onInit. Czyli robi coś gdy coś się stanie, w zależności od warunków podanych w nawiasie. Tutaj możemy operować (nie tylko!), na:
button to instancja klawisza myszy. Obecnie są 4 instancje:
LEFT_UP - LPM puszczony
LEFT_DOWN - LPM wciśnięty
RIGHT_UP - PPM puszczony
RIGHT_DOWN
- PPM wciśnięty
x , y  to po prostu pozycja na ekranie. Jednak, nie będziemy jej konkretnie podawali, ponieważ oznaczałoby to konieczność kliknięcia w jeden konkretny punkcik na siatce o wielkości 8192X8192. Zamiast tego obliczymy dystans2d
wheel- nikt nie wie co to jest. Można się domyśleć, że dałoby się tym jakoś przesuwać np. listę, gdyby wartość rosła, tylko nie ma niczego co by tą wartość pobrało no i nie wiadomo, czy jest to liczone np. w stopniach (czyli 0-360) czy w jakichś innych radianach.
Obierzemy teraz jeden odpowiedni punkt i ustalimy odpowiednią reakcję w wypadku kliknięcia wybranym klawiszem w odpowiedniej odległości od tego punktu.
To teraz zadanie logiczno-geometryczne. Jeśli będziemy mieli punkcik i wyznaczymy w koło niego stałą odległość to czym będzie nasze pole?
Kołem. Może być to pewna niedogodność. Jednak nie ma rzeczy nierozwiązywalnych i może ja, a może wy wpadniecie na pomysł wyznaczenia innych figur. Ja na pewno w przyszłości spróbuję. Nam na potrzeby poradnika wystarczy koło. Zajrzyjmy do funkcji GetDistance2D
http://gothic-online.com.pl/wiki/index.p...Distance2D
Nic dodać, nic ująć. Serwer wszystko za nas policzy. My musimy tylko pobrać dobre koordynaty naszego punktu. Musimy mieć środek, a ponieważ mamy prostokąt, to jego środek oznaczają:
Dla X-punkt w połowie górnego/dolnego boku
Dla Y-punkt w połowie prawego-lewego boku.
Mamy ta wygodę, że sami podajemy i szerokość i miejsce na ekranie naszej tekstury. Mamy też stałą skalę, liczbę "punktów na ekranie" w grze. Więc nie problem odjąć co trzeba, szczególnie jeśli macie zamiar skryptować, gdzie nie jest potrzebna ani matematyka, ani (chyba, że piszecie silnik do np.gry) fizyka, tylko logika i sposób myślenia, którego uczą.
Wracamy do naszych klawiatur. Załóżmy że mamy klasę applyClass(idklasy). I to ona się wykonuje po kliknięciu. Nasza tekstura nazywa się klasatex, a draw klasadraw. Pozycje będą podawane w stylu posX1 i oznaczają wasze wyliczone pozycje.
Code:
function onClick(key, x, y, wheel)
{
local cur=getCursorPosition();

local dist = getDistance2D(cur.x,cur.y,posX1,posY1);    
local dist2 = getDistance2D(cur.x,cur.y,posX2,posY2);
local dist3 = getDistance2D(cur.x,cur.y,posX3,posY3);
    
    if(key == "LEFT_DOWN")
    {
        

        if(dist<=300 )
        {
        applyClass(1);
        destroyDraw(drawklasa1);
        destroyDraw(drawklasa2);
        destroyDraw(drawklasa3);
        destroyTexture(klasatex);
        }
            
        else if (dist2<=300)
        {
        applyClass(2);
        destroyDraw(drawklasa1);
        destroyDraw(drawklasa2);
        destroyDraw(drawklasa3);
        destroyTexture(klasatex);
        }
            
        else if (dist3<=300)
        {
        applyClass(3);
        destroyDraw(drawklasa1);
        destroyDraw(drawklasa2);
        destroyDraw(drawklasa3);
        destroyTexture(klasatex);
        }

    }        
}
Nie bierzcie tych skryptów na poważnie Big Grin  Przecież ja nie wiem, czy wy potrzebujecie odległości 300 czy 3000.
Oczywiście, one dalej przekazują wiedze, ale w innym formacie. Prawdziwy skrypt nie do końca będzie tak wyglądał, ale jak pisałem na początku, nie o to tu chodzi. Z podawaniem skryptów na talerzu musicie zerwać jak najszybciej, żeby tworzyć jak najmniej tematów w pomocy.
Co ważne, samo usunięcie drawów nie wystarczy. Nie możemy tak zostawić tej funkcji w powietrzu, musimy ją "jakoś" całkowicie wyłączyć, łącznie z warunkami. Ja rozwiązałem to stworzeniem zmiennej stan, która ma wartość 0 dla (umownego) trybu wyboru klasy, a przybiera wartość 1 gdy już ją wybierzemy. Dzięki temu kompilator całkowicie pomija nawet sprawdzanie tej funkcji, gdy już gramy.


2. "Zabiłeś gracza Ignisio"
Chcielibyście  Tongue Niemniej jednak, zabójstwa i zgony są dość częste w trybie DM. Wypadałoby to jakoś zaakcentować. Na przykład komunikatem na czacie, czy licznikiem gdzieś z boku. My zrobimy to pierwsze.
Wyobraźmy sobie tą sytuację. Mamy 10 graczy i jednym z nich jesteś ty. Zabiłeś kogoś. Logicznym jest, że ze strony plików serwerowych tego nie odnotujesz. Nie ma takiego zdarzenia "Onzabiłeśjakiegośgracza". Musimy mieć ID zabitego, ID zabijającego. Później musimy odpowiedniej osobie wysłać, że zginęła, a odpowiedniej, że zabiła. Pół biedy, jeśli chcemy wysłać tylko wiadomość na chacie, bo do tego mamy serwerową funkcję sendMessage. Ale gdybyśmy chcieli to gdzieś zapisywać, to jesteśmy zmuszeni wysłać pobrane na Serwerze dane do Klienta. I to właśnie zrobimy.
Teraz pamiętajcie o przełączeniu się do skryptów serwera!
Zacznijmy od samego "zauważenia sytuacji". Potrzebnego nam callbacka znajdziemy tutaj:
http://gothic-online.com.pl/wiki/index.p..._callbacks
Callback to tak funkcja, która pobiera dane w trakcie jakiegoś zdarzenia.
Code:
function onDie(pid, kid)
{
    print("Killer with ID: " + kid + " killed player with ID: " + pid + ".");
}
Jak już mówiłem, pid i kid pobierają się same przy zdarzeniu. Jak łatwo się domyśleć pid to skrót od playerID, kid to skrót od KillerID.
Drugą ważną informacją jest to, że w przypadku serwera print nie wykona się na środku ekranu tylko...w konsoli serwera. I to jest ta genialna funkcja, która pozwoli nam przez umieszczanie różnych funkcji w princie sprawdzić co one zwrócą. Jeśli macie jakiś dłuższy , "krokowy" skrypt z wieloma IFami, to możecie umieści print z jakąś cyfrą czy opisem i sprawdzić w konsoli, co się tak naprawdę wykona, albo jak daleko, zanim nastąpi błąd.
Quote:Mała przestroga. Gdy zauważyłem takie działanie funkcji, uznałem, że jak wrzucę skrypt klienta, to on też mi "się sprawdzi", a konsola zwróci mi błędy. Niestety, chociaż czasami to działa, to przy użyciu np. getTime() będziemy mieli zawsze błąd, ponieważ nie istnieje ona w skryptach serwera.


Wyślemy teraz 2 informacje. Do zabójcy, że kogoś zabił i do zabitego, że jest cieniasem.
http://gothic-online.com.pl/wiki/index.p...ClientFunc
Nie będę skromny i pochwalę się, że opis tej funkcji sam zaprojektowałem Smile Trzeba działać, a nie czekać na rozwój G2O panowie i panie. Nie po to wam tą wiedzę przekazuję, żebyście wy nie mieli dzielić się nią dalej.
Po stronie serwera mamy teraz dziecinnie prostą funkcję do wypełnienia. Używamy callClientFunc dwa razy, raz podstawiając w miejscu playerID pid, raz kid.
Code:
    callClientFunc(pid,"zgon",kid);
    callClientFunc(kid,"zabicie",pid);
Tutaj wysyłamy tylko potrzebne nam zmienne, nie podajemy żadnych instrukcji, poza nazwą funkcji w "" cudzysłowie. Przenosimy się teraz na stronę klienta i tam tworzymy odpowiednią, zadeklarowaną wyżej funkcję.
Code:
function zabicie(pid)
{
addMessage(255, 255, 0, "Zabiłeś gracza"+pid);
}
Jeśli ktoś jeszcze nie wiedział, może zauważyć jak się łączy tekst ze zmienną.
Ważne jest, żeby wpisać odbieraną zmienną w () nawiasie po nazwie funkcji.
Quote:Mała uwaga poza tematem. Jeśli będziecie odnotowywali śmierć gracza, to jeśli on sam się zabije, ID jego zabójcy jest oznaczony jako -1. Jeśli chcemy zliczać zgony, powinniśmy ustawić wykonywanie funkcji tylko wtedy, gdy kid jest większy od-1.
Teraz podajemy tylko ID. Dużo lepsze jest podanie nicku, którego bardzo łatwo można użyć, za pomocą funkcji którą sami sobie znajdziecie.

3. Kopiąc leżącego
Pewnie dla serwera DM bardzo przydatny może być po prostu stream danych stacji. Jednak, to już jest podane na tacy w plikach biblioteki BASS. My tutaj zrobimy coś, czego nie ma, ale jest w sumie bardzo podobne.

Żeby nasz skrypt był kompletny, musimy jeszcze wyśmiać gracza która został pokonany. Potrzebne nam będą:
http://gothic-online.com.pl/forum/showth...hp?tid=326
I proponowany przez mnie:
http://hostuje.net/file.php?id=d4bbb1ea4...d3ad62d2ef
Na początek skopiujmy pliki BASS.DLL oraz BASS_IMPL.nud do odpowiadających im folderów.
Jeśli już stworzyliśmy powyższe skrypty, na pewno mamy funkcje, która wyświetla graczowi kto go zabił. W tym samym miejscu musimy wstawić:
Code:
local smiech=BASS_StreamCreateFile("smiech.mp3", 0, 0);
BASS_ChannelPlay(smiech, false);


I to wszystko. Pamiętajcie, że nazwę pliku podajemy w "" cudzysłowie. Jest tylko jeden problem. W obecnej formie nie możemy ustawić od której do której minuty ma grać nasz utwór, chociaż są na to argumenty. Dlatego opisze teorię, która może kiedyś się przyda.
Nie możemy miejsca zer tak po prostu wstawić 0:02 czy 0.02. Musimy przeliczyć sekundę, od której chcemy zacząć/na której chcemy skończyć na liczbę bitową, która zależy też od kilku parametrów z naszego utworu. W tym celu użylibyśmy
BASS_ChannelSeconds2Bytes(smiech,0.02)
I wstawili to w odpowiednie miejsce. Cały skrypt wyglądałby tak:
Code:
local start=BASS_ChannelSeconds2Bytes(smiech,0.02);
local end=BASS_ChannelSeconds2Bytes(smiech,0.12)
local smiech=BASS_StreamCreateFile("smiech.mp3", start, end);
BASS_ChannelPlay(smiech, false);


Quote:Ważne! To tylko domysły. Po pierwsze, nie mogę tego sprawdzić, bo nie działa. Po drugie, funkcja BASS_StreamCreateFile wygląda u nas troszkę innaczej niż zazwyczaj. Mogłaby też być wymagana funkcja BASS_ChannelSetPosition


Patrzcie i uczcie się:
Nie będzie mnie do sierpnia, jestem w Szkocji i zarabiam na studia. Do zobaczenia.
Reply
#2
Mała aktualizacja Smile
Nie będzie mnie do sierpnia, jestem w Szkocji i zarabiam na studia. Do zobaczenia.
Reply
#3
Bez żadnej przypinki, pomagam koledze w skryptowaniu i czysta ciekawość mną kieruje - skrypty, które tutaj dałeś w przykładach, działają u Ciebie?
Quote:(report) Inariu - 22-12-06:39 -- Nie mam szacunku do człowieka który nie potrafi pisać twarzą w twarz

Reply
#4
Tu tak zbytnio nie ma co działać, bo to są takie wycinki, to już, jak pisałem, wyższy poziom, więc nie wstawiałem całych skryptów, tylko kawałki.
A jest jakiś problem?
Nie będzie mnie do sierpnia, jestem w Szkocji i zarabiam na studia. Do zobaczenia.
Reply
#5
Wszystko fajnie, ale nie dawaj funkcjom polskich nazw i dawaj jakieś normalne wcięcia w kodzie...
Reply
#6
Ej. Co wy wszyscy macie do moich wcięć? Big Grin Piszcie sobie z Nubziorem jak chcecie, dla mnie jest wszystko dczytelne Smile
Polskie nazwy dałem na potrzeby poradnika. Poradnik miał być przetłumaczony, ale coś nie wyszło.
Nie będzie mnie do sierpnia, jestem w Szkocji i zarabiam na studia. Do zobaczenia.
Reply
#7
Z tym, że kod powinien być czytelny dla każdego, a nie dla jednej osoby.
Reply
#8
Nie rozumiem do końca jak to możliwe, że działa u Ciebie ten patent z getDistance2D. Z dokumentacji na wiki wynika, że ta funkcja zwraca osi x i z, a jeśli dobrze rozumuje - liczy odległości w grze, tymczasem w przykładzie pierwszym bazujemy na wartościach dot. ekranu. Inaczej - to może faktycznie działać, jeśli ta funkcja traktuje to jako zwyczajne liczby i wylicza dystans między nimi, ale czy na pewno tak jest? Pytam się z czystej ciekawości, bo sam miałem kiedyś z takim czymś styczność, tylko że przy G1O (tworzyłem sobie crafting wtedy) i jeśli dobrze pamiętam, to kodziłem własne funkcję na obliczanie takich działań. Ew. to błąd dokumentacji, aczkolwiek ciekawi mnie jak to z tym jest.

Plus fakt, że przy wartościach w OnClick działamy na osiach x i y. Big Grin
Quote:(report) Inariu - 22-12-06:39 -- Nie mam szacunku do człowieka który nie potrafi pisać twarzą w twarz

Reply
#9
Pomyliłeś. Są 2 funkcje dla dystansu, także na wiki. getDistane2D i getDistance3D. 2D zwraca X i Y, 3D X, Y i Z. Tak samo jak w układach współrzędnych.
Nie będzie mnie do sierpnia, jestem w Szkocji i zarabiam na studia. Do zobaczenia.
Reply
#10
(15.03.2016, 17:51)Ignisio Wrote: Pomyliłeś. Są 2 funkcje dla dystansu, także na wiki. getDistane2D i getDistance3D. 2D zwraca X i Y, 3D X, Y i Z. Tak samo jak w układach współrzędnych.
Nie. Pojęcie zwracania wartości, a przyjmowanych argumentów to 2 różne rzeczy.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  [PL]2.Skryptuj z Danielem- Role-Play. Ignisio 0 3,640 15.02.2016, 19:06
Last Post: Ignisio
  [PL]2.Ucz się z Danielem - wyświetlanie i odliczanie. Ignisio 12 9,594 31.01.2016, 13:26
Last Post: Son Goku
  [PL]1. Ucz się z Danielem - pierwsze zmiany w skryptach serwera. Ignisio 4 6,840 21.01.2016, 15:58
Last Post: Ignisio
  [PL]1.Ucz się z Danielem - pierwsze zmiany w skryptach serwera. 2 Ignisio 5 4,812 19.01.2016, 20:48
Last Post: Quarchodron

Forum Jump:


Users browsing this thread: 1 Guest(s)