Roblox Wiki
Advertisement

Artykuł ten nie wymaga żadnej znajomości jakiegokolwiek języka skryptowego/programowania. Jest on skierowany głównie do osób, które chciałyby, aby ich model w ROBLOX'ie zaczął działać logicznie, a nie wiedzą kompletnie nic na ten temat. Oczywiście doświadczenie w programowaniu nie przeszkodzi w uczeniu się z poradnika.

Zanim zaczniesz, mam kilka porad;

  • nie kopiuj kodu, który zobaczysz w tym artykule i w następnych(o ile się ukażą). Przepisując nauczysz się więcej niż duplikując moją pracę;
  • przepisując kod stosuj swoje własne nazwy(dla zmiennych, plików etc.);
  • jeżeli poczujesz się na tyle zmęczony, że przestaniesz rozumieć kod/treść artykułu, odpocznij, wyjdź na zewnątrz, napij się kawy, lub cokolwiek, co spowoduje u  Ciebie powrót do logicznego myślenia. Czytanie artykułu i kodu bez rozumienia go może sprawić jedynie to, że zaczniesz mieć zaległości i nic nie wyniesiesz z artykułu.

Chyba czas już zacząć.


Teoria, dużo teorii

Zacznijmy od tego czym są skrypty. Skrypt to zbiór procedur, które wykonuje gra w trakcie działania. Chyba to zdanie nie każdy mógł zrozumieć, bądź nie oddałem w nim całej istoty skryptu. Istnieje jednak coś takiego jak pseudokod. Jest to po prostu tekst, który mówi człowiekowi w jaki sposób skrypt ma działać i to za jego pomocą wyjaśnię jego istotę. Poniżej znajduje się przykładowy pseudokod mogący poinstruować człowieka jak zaparzyć herbatę:

czy jest herbata?

jeśl nie ma: kup herbatę

jeśli jest: 

czy jest w czajniku woda?

jeśli nie ma: wlej 500ml

jeśli jest:

gotuj

czekaj 1min

włóż torebkę do szklanki

wlej do szklanki 200ml wody

Rozumiesz już na jakiej zasadzie działają te całe skrypty? Po prostu jako autor skryptu rozkazujesz coś zrobić grze tak, jak pseudokod wydawał polecenia osobie gotującej herbatę. Mam nadzieję, że to jest już jasne.

Analizując pseudokod można zaobserwować pewne jego części.

Funkcje:

kup herbatę
wlej
gotuj
czekaj

Powyżej można zaobserwować funkcje. Ich celem jest wykonanie pewnej czynności.

Więcej powiem o nich trochę później. Zanim jednak przejdziesz dalej, domyśl się które fragmenty kodu przedstawiają funkcje, a nie wypisałem ich powyżej.

Wartości:

500ml
1min

Funkcje czasem potrzebują pewnych wartości do działania. Wartości przyjmowane przez funkcję nazywają się argumentami i w zależności od funkcji mogą przyjmować inny typ wartości. Na przykład funkcja "czekaj" z przyjętą jako argument wartością "500ml" nie miałaby sensu.

Mam nadzieję, że odszukanie w pseudokodzie niewymienionej wartości nie jest trudne.

Warunki:

czy jest herbata?

jeśl nie ma:

jeśli jest: 

Dzięki tej części kodu nasz skrypt staje bardziej otwarty na możliwe do zaistnienia okoliczności. Gdy warunek zostaje spełniony, wykonywana zostaje część kodu wewnątrz "jeśli jest:", a jeżeli warunek nie zostaje spełniony wykonywany jest kod wewnątrz "jeśli nie ma:".

Istnieje możliwość, że warunek "jeśli nie ma:" nie będzie konieczny. W razie jego braku i niespełnienia warunku, ten zostaje po prostu pominięty.

Tutaj postąpiłem trochę inaczej, niż w lua. W lua jako pierwsze powinno był "jeśli jest", a "jeśli nie ma" powinno być drugie. Zrobiłem to jednak dla przejrzystości kodu.

(mam nadzieję, że odszukanie niewymienionego warunku nie jest trudne)

Wnioski

  • Kod wykonywany jest od góry do dołu
  • Nieodpowiedni typ wartości jako argument funkcji może spowodować błąd
  • Niespełniony warunek bez ścieżki alternatywnej("jeśli nie ma:") zostanie pominięty

Ćwiczenie

Zanim przejdziesz do następnej części artykułu, napisz pseudokod robienia kanapki. I przy okazji odpocznij przed wchłonięciem kolejnej porcji wiedzy. Na przykład zrób kanapkę.

Witaj Świecie!

Nadszedł czas, by zacząć pracę z prawdziwym skryptem. W tym celu otwórz ROBLOX Studio, utwórz nowy place(w zakładce TEMPLATES wybierz Baseplate). Gdy nowa mapa zostanie utworzona dodaj okno "Advanced Objects"(jeżeli je posiadasz, pomiń ten akapit). W tym celu w górnej zakładce "Insert" wybierz "Advanced Objects". Powinno Ci się pojawić małe okno. Umieść je w wygodne dla siebie miejsce.

Okna

Bardzo wygodny i praktyczny układ okien

Następnie utwórz nowy skrypt klikając dwukrotnie na "Script" w nowo otwartym oknie "Advanced Objects". Powinien Ci się otworzyć edytor skryptu z napisem:

print 'Hello world!'

Jest to działający skrypt, ale wyczyść tę linijkę w zamian za nią wpisz:

print("Moj pierwszy skrypt w lua!");

Jak możesz się domyślić "print" jest funkcją. W lua argumenty funkcji umieszcza się w nawiasach po nazwie funkcji. Argumentem jest tutaj tekst, który także jest wartością.

Aby jednak cieszyć się z wyników naszego kodu musimy dodać nowe okno - "Output"(pomiń, jeżeli je już masz). Aby to zrobić w górnej zakładce View wybieramy "Output" i umieszczamy naszą konsolę w wygodnym miejscu(ja wybrałem dolną krawędź).

Po tym należy zaktualizować nasz skrypt. W tym celu w zakładce Explorer znajdź utworzony przez Ciebie obiekt "script"(jeżeli nic nie zmieniałeś, znajduje się w "Workspace"). Naciśnij na niego i oknie "Properiets"(jeśli go nie posiadasz, to go utwórz) dwukrotnie kliknij na kwadrat obok parametru "Disabled". To działanie restartuje skrypt, który zostanie wykonany z nową zawartością.

Teraz naciśnij zielony przycisk "Run" na górnej zakładce "Home".

W oknie "Output" powinien się wyświetlić tekst "Moj pierwszy skrypt w lua!". Możesz przez to zauważyć, że funkcja "print" powoduje wypisanie argumentu w konsoli. Funkcja ta jednak przyjmuje nie tylko tekst jako argument. W miejsce tego tekstu wpisz jakąś liczbę. Jednak bez cudzysłowu, ponieważ ten stosuje się wyłącznie do wartości tekstowych. Zaktualizuj kod. Powinna zostać wypisana liczba, którą wpisałeś.


Zmienne, warunki i pętle

Wszystkie wartości, które dotychczas widziałeś w tym artykule zarówno w pseudokodzie, jak i w pierwszym skrypcie były wartościami stałymi*. To znaczy, że los skryptu był z góry przewidziany.

Przeciwieństwem stałych są zmienne. Przechowują one wartość, którą w każdej chwili można zmienić. Ich cechą pozytywną jest duża podatność na modyfikowanie, ponieważ można nadać zmiennej wartość zmienną lub stałą, wyniki działań matematycznych mogą być przypisane do zmiennej i wiele innych. Krótko mówiąć - zmienne są bardzo przydatne.


*Wiem, że to nie są stałe, tylko literały, ale nie chcę kursantom mieszać w głowach.

Typy zmiennych

W lua typy zmiennych mają mały wpływ na kod w odróżnieniu do innych języków(C++, java, C# itd.). Czasami jednak znajomość tych typów może się przydać, szczególnie w praktycznym pisaniu skryptów, gdzie trzeba będzie nadać zmiennej lub argumentowi odpowiedni typ.

Nazwa typu Znaczenie Wartości / Przykłady
Boolean typ logiczny true(prawda) i false(fałsz)
Nil typ pusty nil
Number liczba zmiennoprzecinkowa 3.14159265
Integer liczba całkowita 123
String tekst "stringi", 'string'

Są to podstawowe typy danych w lua. Roblox udostępnia także kilka własnych typów. Jednak opiszę je w następnym artykule.

Boolean - typ logiczny, czyli taki, który może mieć tylko dwie wartości - true, albo false. Poznasz go lepiej w dalszej części artykułu.

Nil - typ pusty, ponieważ nie reprezentuje żadnej wartości. Wartość nil zmiennej może oznaczać, że ona nie istnieje.

Number - typ zmiennoprzecinkowy. Może zawierać liczby z ułamkiem dziesiętnym. Ułamek ten wpisuje się po kropce zaraz po cyfrze jedności.

Integer - typ całkowity. Tworzą go wszystkie liczby całkowite, czyli te bez ułamka.

String - typ reprezentujący tekst. Może zawierać znaki ASCII, a więc nie jest w stanie przechować polskich znaków. Wartości tekstowe należy zapisywać pomiędzy znakami cudzysłowia("), apostrofu(') lub w podwójnych nawiasach kwadratowych([[)

Operacje matematyczne i definicja zmiennych

Pierwszą operacją, którą przechodzi każda zmienna w skrypcie jest definicja. Służy ona do stworzenia zmiennej i nadania jej wartości. Oto skrypt przedstawiający definiowanie zmiennej tekstowej(nadanie jej wartości stałej):

nazwa_zmiennej = "wartosc zmiennej"

Zmienne tak jak stałe można użyć w tych samych funkcjach. Na przykład poniższy skrypt spowoduje wypisanie "wartosc zmiennej" w konsoli:

print(nazwa_zmiennej)



Za operacje matematyczne odpowiedzialne w lua są operatory matematyczne. Są to tak proste operacje, że znaczną większość będziesz pamiętał jeszcze z podstawówki. Oto one:

Znak Nazwa Przykład
+ dodawanie 5

 = 2 + 3

- odejmowanie 1 = 2 - 1
* mnożenie 6 = 2 * 3
/ dzielenie 4 = 16 / 4
^ potęga 9 = 3 ^ 2
% modulo(reszta z dzielenia) 4 = 10 % 6

(pogrubione zostały wartości wynikowe, czyli te które zostaną nadane zmiennej)

Operatorów używa się w taki sposób:

nazwa_zmiennej = wartosc_a <operator> wartosc_b

Efektem takiego działania jest nadanie zmiennej nazwa_zmiennej wartości pochodzącej z danej operacji.

Przykład A:

a = 12

b = a * 2

print(b)

efektem tego będzie wypisanie w konsoli "24".

Przykład B:

a = 12

print(a * 2)

Zamiast definiować zmienną, możesz użyć operacji matematycznej jako wartość dla argumentu funkcji.

Warunki, operatory porównawcze i logiczne

W lua tak samo jak w pseudokodzie istnieją warunki. Działają również na takiej samej zasadzie.

A.

if <warunek> then

<kod wykonywany, gdy warunek zostaje spełniony>

end

B.

if <warunek> then

<kod wykonywany, gdy warunek zostaje spełniony>

else

<kod wykonywany, gdy warunek nie zostaje spełniony>

end

C.

if <warunek1> then

<kod wykonywany, gdy warunek zostaje spełniony>

elseif <warunek2> then

<kod wykonywany, gdy warunek1 nie zostaje spełniony, a warunek2            zostaje>

end

Na razie nie będziemy pisać znaczących coś warunków, ponieważ potrzebujemy do tego wiedzy na temat operatorów logicznych i porównawczych. Jednak przed zapoznaniem z tym spróbuję pokazać kiedy warunek zostaje spełniony, a kiedy nie.

Warunek można porównać do funkcji. Tak jak ona przyjmuje pewną wartość. Jednak wartość ta musi mieć określony typ. Jest to typ bool, zwany także logicznym. Może on przyjąć jedynie dwie wartości - true(prawda) lub false(fałsz). W zależności od tego, czy warunek otrzymał wartość prawdziwą, czy fałszywą, wykonywana jest odpowiednia część kodu(warunek zostaje spełniony, gdy wartość jest prawdziwa). Aby zaprezentować to w bardziej praktyczny sposób zrobię eksperyment.

if true then
    print("prawda");
end
if false then
    print("falsz");
end

W konsoli zostanie wypisany tylko tekst "prawda", ponieważ warunek zostaje spełniony tylko wtedy, gdy jako argument otrzyma prawdę. Słowo "falsz" niezostanie wypisane, ponieważ warunek nie został spełniony.

Efektem operacji porównawczych i logicznych są wartości logiczne(prawda/fałsz), dlatego używa się ich w warunkach.

Operatory porównawcze

Operatory porównawcze służą do porównania dwóch wartości w celu otrzymania prawdy lub fałszu(wartości logicznej).

Znak Zwraca prawdę, gdy przykład z prawdą przykład z fałszem
== wartości są równe 12 == 12 3 == 10
~= wartości nie są równe 8 ~= 3 6 ~= 6
< lewa wartość jest mniejsza 3 < 4 2 < 1 oraz 2 < 2
> lewa wartość jest większa 10 > 1 1 > 2 oraz 1 > 1
<= lewa wartość jest mniejsza lub równa 4 <= 5 oraz 4 <= 4 6 <= 7
>= lewa wartość jest większa lub równa 7 >= 6 oraz 7 >= 7 4 >= 8

Dzięki tym operatorom można stworzyć już warunek, który spełnia swoją rolę:

if 10 > 5 then
    print("dziesiec jest wieksze od pieciu");
end

Operatory logiczne

Czasami będziesz chciał, by blok instrukcji wykonał się po spełnieniu kilku warunków, albo jednego z nich. Możesz zrobić jeden warunek wewnątrz drugiego, ale nie polepszy to czytelności kodu. A wręcz odwrotnie - pogorszy. Do tego celu służą operatory logiczne, które tak samo jak porównójące zwracają wartość logiczną. Jednak operatory logiczne w odróżnieniu od porównawczych jako argumeny przyjmują wyłącznie wartości logiczne.

Operator and

Operator and zwraca prawdę tylko gdy obie wartości są prawdziwe. Fachowo operację tą nazywa się koniunkcją. Oto zależności między przyjmowanymi, a zwracanymi wartościami:

and 1 0
1 1 0
0 0 0

Operator or

Operator or zwraca prawdę, gdy jedna lub druga wartość jest prawdziwa. Zwraca ją nawet wtedy, gdy obie są prawdziwe. Operacja ta nazywana jest alternatywą lub sumą logiczną.

or 1 0
1 1 1
0 1 0

Operator not

Operator or  jako jedyny operator logiczny przyjmuje jedną wartość. To dlatego, że zadaniem tego operatora jest ją odwrócić(z fałszu na prawdę i odwrotnie). Operacja ta nazywa się negacją.

1 0
not 0 1

Przykład A:

 if 1==1 and 5>1 then
    print("Oglaszam stan wojenny!!!");
end

Efekt: Wypisane zostanie w konsoli "Oglaszam stan wojenny!!!".


Przykład B:

if 4~=4 or 8<9 then
    print("Oglaszam stan wojenny!!!");
end

Efekt: Wypisane zostanie w konsoli "Oglaszam stan wojenny!!!".


Przykład C:

if not false then
    print("Oglaszam stan wojenny!!!");
end

Efekt: Wypisane zostanie w konsoli "Oglaszam stan wojenny!!!".


W języku lua we wszystkich operacjach(a więc także logicznych) można używać nawiasów. Działają one tak samo jak te znane z lekcji matematyki. Oto przykład ich zastosowania w warunku:

if not(4<3 and 9
==3) then
    print("Oglaszam koniec stanu wojennego!!!");
end

W efekcie tekst zostanie wypisany, ponieważ warunek zostanie spełniony. A to dlatego, że najpierw wykonywane są operacje porównawcze w nawiasie. Obie zwracają fałsz. Operacja and w nawiasie robi z dwóch fałszy jeden fałsz, który zamieniany jest na prawdę dzięki operatorowi not po za nawiasem.

Pętle i zasięg zmiennych

Czasem pojawia się potrzeba dodania samopowtarzalnej czynności. Pętlę tę potrzebę spełniają. Powodują one, że blok instrukcji wykonywany jest w kółko, aż do czasu gdy pętla zostanie zerwana. Istnieją trzy typy pętli. Oto one:

Pętla while

Pętla while wykonuje się dopóki jej argument ma wartość prawdziwą, co bardzo upodabnia ją do warunku. Schemat:

while <warunek wykonywania pętli> do
    <blok instrukcji>
end

Przykład:

i=0
while i < 5 do
    i = i+1;
    print(i);
end

Efekt: Do konsoli zostaną wypisane liczby od 1 do 5.


Pętla for

Pętla for bardzo różni się od pętli while. Nie potrzebuje ona logicznego warunku wykonywania, a posiada cztery elementy mówiące o warunku wykonywania. Są to: pierwszy indeks, ostatni indeks, indeks i wartość wzrostu. Pierwszy indeks to liczba całkowita od której odliczanie zaczyna indeks. Co każde wykonanie pętli powoduje dodanie do zmiennej indeksu wartości wzrostu i tak dalej, aż indeks przekroczy wartość ostatiego indeksu i pętla zostanie złamana.

Schemat:

for <indeks> = <pierwszy indeks>,<ostatni indeks>,<wartość wzrostu> do
    <blok instrukcji>
end

Przykład:

for i=0,5,1 do
    wait(0.1);
    print(i);
end

Pętla repeat

Pętla repeat działa odwrotnie do pętli while. To znaczy, że pętla jest przerywana wtedy, gdy wartość jest prawdziwa.

Schemat:

repeat
    <blok instrukcji>
until <warunek przerwania pętli>

Komenda Break

Z wcześniejszą wiedzą pętlę można złamać tylko poprzez zawartą w nich instrukcję. Za pomocą komendy break można złamać pętlę na jej końcu lub w dowolnym jej momencie za pomocą instrukcji warunkowej.

Zmienne lokalne i ich zasięg

Zmienna lokalne przydają się także w warunkach, które już poznałeś. Jednak ja umieszczam je tutaj, ponieważ w pętlach mogą być bardziej przydatne.

Jak dotąd w tym artykule mogłeś zaobserwować jedynie zmienne globalne, czyli dostępne w całym skrypcie. A więc czym są zmienne lokalne? Są to zmienne, które istnieją tylko w pewnej przestrzeni, zwaną wcześniej przeze mnie blokiem instrukcji. Warunki, pętle i definiowane funkcje(których jeszcze nie znasz) posiadają swój własny blok instrukcji zaczynający się od słowa kluczowego(np. then, do, repeat), a kończący się słowem end.

Jeżeli zdefiniujesz zmienną lokalną wewnątrz bloku instrukcji, to zmienna ta nie będzie istniała po zakończeniu jego wykonywania. Na przykład zmienna lokalna zdefiniowana wewnątrz pętli za każdym jej powtórzeniem będzie nową zmienną, a poza pętlą nie będziesz mógł uzyskać do niej dostępu i próba tego zakończy się błędem skryptu.

Zasięg zmiennych lokalnych ogranicza się także do instrukcji blokowych wewnątrz instrukcji blokowej, wewnątrz której została zdefiniowana. Na przykład będziesz mógł mieć dostęp do zmiennej lokalnej zdefiniowanej w pętli wewnątrz warunku znajdującego się w pętli i tak dalej.

Schemat:

 local nazwa_zmiennej = "wartosc zmiennej"

Przykład:

 if true then
    local zmienna = true
    
    if zmienna ~= nil then
        print("mam dostep wewnatrz!")
    else
        print("nie mam dostepu wewnatrz!")
    end
end

if zmienna ~= nil then
    print("mam dostep na zewnatrz!")
else
    print("nie mam dostepu na zewnatrz!")
end

Efekt: Zostanie wypisane "mam dostep wewnatrz!" oraz "nie mam dostepu na zewnatrz!"

Nil to stała wartość zmiennej, która oznacza, że zmienna nie ma wartości. Wartość nil zmiennej może oznaczać, że ta zmienna nie istnieje.


Tablice zmiennych

Czasem może zaistnieć potrzeba utworzenia grupy zmiennych. Możesz zrobić to manualnie, tzn. tworzyć zmienne o nazwach a1, a2, a3, a4 itd. Nie jest to jednak najpraktyczniejszy i najwygodniejszy sposób tworzenia grup zmiennych.

Tu z pomocą przychodzą tablice. Tablice także są zmiennymi, pomimo że zawierają w sobie zmienne. Mają bardzo podobny sposób definicji, z tą różnicą, że wszystkie wartości należy wpisać w nawiasach klamrowych i oddzielić je przecinkami.

Schemat:

 <nazwa tablicy> = {<wartości>}

Przykład:

tablica = {314, 3.14, "pi", true, nil}

Jak można zauważyć tablica może przechowywać dowolną ilość dowolnych wartości dowolnego typu(typy nawet mogą się mieszać).

W taki właśnie sposób definiuje się tablice. A jak uzyskać dostęp do ich elementów?

Wystarczy wpisać nazwę tablicy i obok niej w nawiasach kwadratowych numer elementu

Schemat:

<nazwa tablicy>[ <numer elementu> ]

Przykład:

tablica = {314, 3.14, "pi", true, nil}
print(tablica[1]);
print(tablica[3]);
print(tablica[5]);

W efekcie zostaną wypisane wartości: pierwsza(314), trzecia(pi) i piąta(nil).

Tablice pozwalają również na uzyskanie dostępu do ilości ich elementów. Aby to zrobić należy wpisać znak # oraz obok niego nazwę tablicy. W efekcie otrzymamy Integer, czyli liczbę całkowitą.

Schemat:

#<nazwa tablicy>

Przykład:

tablica = {123456}
print(#tablica)

W efekcie w konsoli zostanie wypisane 6, czyli liczba elementów tablicy.

Funkcje

Jak pamiętasz z początku rozdziału "Witaj Świecie!" w Lua istnieją funkcje. Ty jednak znasz jak na razie tylko jedną - print().

Oprócz tego istnieje także funkcja wait(), która jako argument bierze typ numeryczny i jej zadaniem jest po prostu opóźnienie wykonywania kolejnych procedur, czyli czekanie. Jest też wiele innych funkcji, ale te dwie uważam za podstawowe i to one aktualnie mogą Ci się przydać.

Jest jednak coś, czego nie poruszyłem na początku. Jest to definiowanie własnych funkcji. Pozwala to na umilenie sobie pracy ze skryptami i lepszą organizację skryptu. Przejdźmy jednak do konkretów.

Schemat:

function nazwa_funkcji(<argumenty>)
    <blok instrukcji>
end

Tam gdzie napisałem <argumenty> możesz zostawić wolną przestrzeń lub wpisać nazwy zmiennych, które posłużą jako argumenty i będziesz mógł ich użyć w bloku instrukcji.

Przykład:

 function nazwa_funkcji(liczba, potega)
    local a = liczba ^ potega % potega;
    print(a);
end

Funkcje te wywołuje się dokładnie tak samo jak print. Wystarczy napisać nazwę funkcji i wartości dla argumentów w nawiasach.

Przykład:

nazwa_funkcji(5, 8);

Wartości zwracane przez funkcję

Funkcje mogą zwracać pewne wartości, a więc możemy użyć funkcji jako argument innej funkcji, warunku, pętli, możemy też nadać zmiennej zwróconą przez funkcję wartość.

Za zwracanie wartości odpowiada słowo kluczowe return.

Przykład:

 function nazwa_funkcji(liczba, potega)
    local a = liczba ^ potega % potega;
    return a;
end
x = nazwa_funkcji(5, 8);
print(x);

Komentarze

Najmniej istotną części składni lua są komentarze. Nie mają one żadnego wpływu na działanie programu, a służą one opisywaniu danego skryptu.

Komentarze mogą być krótkie i długie.

Te krótkie, czyli jednoliniowe zaczynają się od --(dwa minusy) i sięgają do końca linii.

--nie mam zadnego wplywu na dzialanie skryptu


Te długie, czyli blokowe zaczynają się na --[[, a kończą na --]]

--[[
    nie mam zadnego wplywu na dzialanie skryptu
--]]

Zakończenie

By sprawdzić, czy przyswoiłeś wiedzę z tego artykułu, napisz pewien skrypt:

Napisz funkcję z jednym argumentem, którym będzie tablica. W tej funkcji utwórz pętlę, która będzie wypisywała wartości każdego elementu tablicy w kolejności od pierwszego do ostatniego i pomijała elementy o wartości nil. Niech funkcja zwraca prawdę, jeżeli ilość elementów będzie parzysta, a jeżeli nieparzysta - niech zwraca fałsz. Następnie utwórz dowolną tablicę i wywołaj funkcję jako argument funkcji print i jako argument funkcji ustaw tablicę.

Jeżeli udało Ci się napisać ten skrypt, to przejdź do następnego kursu -Lua w praktyce, w którym spróbuję nauczyć Cię pisania skryptów ingerujących w działanie gry.

Umieszczanie tego poradnika na innych stronach bez pozwolenia jest surowo zakazane.

Advertisement