Komentarze

# The Lost and Damned Tips: Chopper vs. Chopper
  1. gra wygląda ciekawie, chciałem w nia pograć, ale nikt nie dołącza do mojego serwera...

Witamy w pierwszej odsłonie poradnika, który ma na celu zaznajomić Was z naszym silnikiem skryptowym. Nasze rady pomogą nauczyć Cię pisać w języku LUA używając różnych 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.

Własne teleporty

Napiszemy skrypt, który pozwoli ustawiać i zapamiętywać własne punkty teleportacyjne, dla każdego z graczy osobno. Dokładniej pozwolimy graczom tworzyć punkty docelowe, oraz punkty startowe. Gracze będą mogli przemieszczać się między nimi tzw. portale.

MTA teleport

Dodawanie skryptu do gry oraz uruchamianie go

Skrypty w MTA całkowicie opierają się na tzw. zdarzeniach. Zdarzenia są dynamiczne, zmienne. Możemy wprowadzać oraz tworzyć własne zdarzenia, 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;:

Kod
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 „I” 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:

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

Funkcja modeIO

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. Najpierw jednak napiszmy funkcję ‘modeIO’, o której było wcześniej.

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

Kod
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 obiektu, 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”.

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

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

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

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

Kod
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