Komentarze

# 10 naprawdę denerwujących rzeczy
  1. do momentu aż mu ktoś heada nie sprzeda :D...


Witamy w pierwszej odsłonie poradnika, który ma na celu zaznajomić was z naszym silnikiem skryptowym. Nasze rady pomogł nauczyć się pisać w języku LUA używając, również naszych, funkcji. Krok po kroku będziemy analizować małe fragmenty kodu wyjaśniając wszystko. Będziemy również załączać materiały dodatkowe, w postaci krótkich filmów instruktażowych oraz zrzutów ekranu.

Zacznijmy więc od: Własnych teleportów

Napiszemy skrypt, który pozwoli ustawiać I zapamiętywać własne punkty teleportacyjne, dla każdego z graczy osobne. Dokładniej pozwolimy graczom tworzyć punkty docelowe, oraz punkty startowe. Gracze będą mogli przemieszczać się między nimi, jeżeli tylko są poprawne.

Film instruktażowy: scriptvideo1.wmv – Windows Media Video 9 (640×480, 30fps)
Gotowy scrypt: script1.lua

Dodawanie naszego skryptu do gry oraz uruchamianie go
Skrypty w MTA są całkowicie bazowane na zdarzeniach. Zdarzenia są dynamiczne, zmienne I można wprowadzać oraz tworzyć własne, ale w tym przykładzie posłużymy się wbudowanymi funkcjami, których MTA ma około czterdziestu. Zdarzenia są wykonywane podczas całej gry. Gdy jemy lecząc się, to jest zdarzenie Każde zdarzenie składa się z funkcji powiązanych między sobą (odwołując się do funkcji addEventHandler).
Stworzymy pierwszą własną funkcją Script_onResourceLoad, która automatycznie załaduje się, gdy serwer będzie się odwoływać do danych, które znajdują się na mapie używając zdarzenia onResourceLoad. W dalszej części pokażemy, jak to ładowania danych przebiega.

Potem utworzymy globalne zdarzenie, które będzie włączało lub wyłączało nasz skrypt. Odwołamy się do funkcji bindKey żeby przypisać klawiszowi ‘I’ funkcję ‘modeIO‘, którą również utworzymy.
Oczywiście, funkcja powinna być dostępna dla wszystkich graczy, więc trzeba utworzyć pętlę dla…-wykonaj…, z języka programowania pętlą for-loop;:

addEventHandler ( ‘onResourceLoad’, getRootElement(), ‘Script_onResourceLoad‘ )

function Script_onResourceLoad ( resource )

if ( resource == getThisResource() ) then

– dla każdego gracza na serwerze

for index, player in getElementsByType ( ‘player‘ ) do

– przypisuje klawiszowi r0;Ir1; funkcję ‘modeIO’

bindKey ( player, ‘i’, ‘down’, ‘modeIO’ )

end

end

end

Zauważcie, że funkcja kończy się słówkiem end z angielska koniec;.

Ale o czymś zapomnieliśmy: powyższa funkcja przypisze klawisz I tylko raz dla obecnych graczy. Co zrobić z dopiero co dołączonymi? Możemy użyć zdarzenia onPlayerJoin, które zwraca wszystkich graczy, którzy się dołączają do gry:

addEventHandler ( ‘onPlayerJoin‘, getRootElement(), ‘Script_onPlayerJoin‘ )

function Script_onPlayerJoin ()

– przypisuje klawiszowi ‘i’ funkcję ‘modeIO’

bindKey ( source, ‘i’, ‘down’, ‘modeIO’ )

end

Pamiętajmy, że oryginalne funkcje klawiszy nadal będą aktywne! Nie wolno nam przypisać tej funkcji do lewego przycisku myszy. Po co stawiać teleport, gdy się strzela?
Następny krok
Ustawianie punktu docelowego może być trudne do zrobienia za pomocą klawiatury. Właściwie POTRZEBUJEMY kursora myszy, by to zrobić. Na szczęście, MTA ma kilka wbudowanych funkcji przeznaczonych do pracy z myszą, włączając showCursor (pokaż kursor), którą zastosujemy.
Ale najpierw napiszmy funkcję ‘modeIO’, o której było wcześniej.
function modeIO ( source, key, keyState )
– funkcja pokazuje kursor

if isCursorShowing ( source ) then
– jeżeli być już widoczny

showCursor ( source, false )
– chowamy go

else
– jeżeli jednak nie być:

showCursor ( source, true )
– pokaż

end

end

Teraz, gdy mamy większość pracy za sobą, przypiszemy każdą funkcję klawiszom myszy (gdy kursor będzie widoczny).
MTA posiada wbudowane zdarzenie onPlayerClick które pozwala uzyskać dokładne współrzędne miejsca położenia kursora w momencie kliknięcia.
Napiszmy więc główną funkcję Script_onPlayerClick, którą przypiszemy do zdarzenia onPlayerClick podczas gdy kursor jest widoczny:

addEventHandler ( ‘onPlayerClick‘, getRootElement(), ‘Script_onPlayerClick‘ )

function Script_onPlayerClick ( key, keyState, element, x, y, z )

if keyState == ‘up‘ then

return – przestań podawać pozycję, gdy przycisk jest puszczony

end
Tworzenie markera
Zanim to zrobimy musisz zrozumieć jak działa hierarchia wydarzeń w grze (podobnie jak w innych, podobnie zbudowanych, grach).
MTA używa elementów do wszystkiego. Pól, obiektów, pojazdów, graczy itd. To są elementy gry;. To dobrze, bo można łatwo je powiązać I używać i nie trzeba sprawdzać typu objektu, który zostanie ‘oskryptowany’. Na przykład: Jeżeli chcesz usunąć albo ustawić pozycję pola, pojazdu lub obiektu, po prostu odwołujesz się do destroyElement albo setElementPosition.
My chcemy stworzyć tylko dwa pola (oddzielne dla każdego gracza, własne),’pole początkowe’ i ‘docelowe’. Skrypt będzie prosty, ale o ogromnej funkcjonalności. Dla każdego id gracza będziemy przechowywać dwa pola, używając setElementData.
Jeżeli gracz naciśnie lewy przycisk (I będzie widoczny kursor), stworzymy miejsce ’startu’, które będzie naszym portalem. Jeżeli gracz naciśnie prawy przycisk, stworzymy pole ‘docelowe’.

Więc zaczynamy pisać:
if key == ‘left‘ then – jeżeli jest naciśnięty lewy przycisk

– zniszcz poprzedni start

destroyElement ( getElementData ( source, ‘teleport‘ ) )

– stwórz nowe, zwykłe pole

local marker = createMarker ( x, y, z, ‘cylinder‘, 2, 0, 255, 0, 50 )

– zmień jego typ na teleport

setElementData ( marker, ‘type’, ‘teleport’ )

– lzapisz wszystko, aby gracz mógł się do tego odwoływać

setElementData ( source, ‘teleport‘, marker )

setElementData ( marker, ‘owner‘, source )
elseif key == ‘right‘ then – jeżeli naciśnie prawy przycisk

– zniszcz poprzednie miejsce ‘docelowe’

destroyElement ( getElementData ( source, ‘destination‘ ) )

– stwórz świecące pole

local marker = createMarker ( x, y, z+1, ‘corona‘, 1, 0, 255, 255, 50 )

– zmień typ na ‘docelowy’ dla teleportu

setElementData ( marker, ‘type’, ‘destination’ )

– zapisz wszystko, aby gracz mógł tego używać

setElementData ( source, ‘destination‘, marker )

setElementData ( marker, ‘owner‘, source )

Użyliśmy setElementData żeby zapisać dane każdego pola. W dalszej częćci pokażemy jak łatwo się do tych danych odwołać.
setElementData oraz jej bliźniacza funkcja pobierająca dane getElementData pracują na elementach. Przypisują każdy typ danych danemu elementowi (graczowi, pojazdowi). Można te dane zmieniać używając setElementData oraz odwoływać się do nich przez getElementData.

Musimy też stworzyć możliwość stawiania teleportów wszędzie, gdzie gracz chce.
elseif key == ‘middle‘ then – jeżeli naciśniemy środkowy przycisk myszy — teleportować gracza tam, gdzie kursor pokazuje

setElementPosition ( source, x, y, z+1 )

end
Teleportacja
Wszystkie pola są już oskryptowane. Czas wykryć kiedy gracz wejdzie w obszar danego pola możemy użyć wbudowanego zdarzenia onMarkerHit. Zwróci pole, które jest wywoływane:
addEventHandler ( ‘onMarkerHit‘, getRootElement(), ‘Script_onMarkerHit‘ )

function Script_onMarkerHit ( player )
Teraz posłużymy się danymi uzyskanymi przez wcześniej napisaną funkcję Script_onPlayerClick Sprawdzimy, jaki to typ pola (startowe, czy docelowe)..

Gdy gracz znajdzie się w obrębie danego pola:
– Sprawdzamy, czy jest to pole startowe

if getElementData ( source, ‘type‘ ) == ‘teleport‘ then

– sprawdzamy który to gracz I porównujemy z właścicielem

local owner = getElementData ( source, ‘owner‘ )

– pobieramy pole docelowe

local destination = getElementData ( owner, ‘destination‘ )

– jeżeli istnieje, następuje teleportacja

if destination then

– pobieramy pozycję miejsca docelowego

local x, y, z = getElementPosition ( destination )

– wreszcie gracz się teleportuje

setElementPosition ( player, x, y, z )

end

end

end
Czyszczenie niepotrzebnych już danych po procesie teleportacji
Należy pamiętać o usunięciu wszystkich danych, jeżeli gracz opuści serwer. Wcześniej używaliśmy zdarzenia onPlayerJoin żeby wykryć, czy gracz dołączył się od gry. Jest również wbudowanie zdarzenie o przeciwnym zadaniu: onPlayerQuit:
addEventHandler ( ‘onPlayerQuit‘, getRootElement(), ‘Script_onPlayerQuit‘ )

function Script_onPlayerQuit ( reason )

–destroy his teleport point, if any

destroyElement ( getElementData ( source, ‘teleport‘ ) )

– destroy his destination point, if any

destroyElement ( getElementData ( source, ‘destination‘ ) )

end