Ja będe opierał się na tych Tfs'owskich gdyż wydaje mi się, że jest to teraz najpopoularniejszy silnik.
Podstawowymi funkcjami o które opiera się każdy skrypt są:
Actions:
Kod :
function onUse(cid, item, fromPosition, itemEx, toPosition)
cid - użytkownik
item - przedmiot używany
formPosition - pozycja na której znajduje sie użytkownik przedmiotu
itemEx - przedmiot na którym został użyty przedmiot (item)
toPosition - pozycja na której znajduje się przedmiot
Wywoływana gdy używamy przedmiotu.
Deklaracja w actions.xml:
<action itemid="itemid" script="sciezka.lua" />
<action uniqueid="uniqueid" script="sciezka.lua"/>
<action actionid="actionid" script="sciezka.lua"/>
Kod :
function onAddItem(moveitem, tileitem, position):
moveitem - przedmiot na którym 'wrzucamy' przedmiot
tileitem - kratka na którą 'wrzucamy' przedmiot
position - pozycja
Wywoływana gdy 'rzucimy' jakiś przedmiot na drugim.
Szczerze się przyznam, że onAddItem raz wychodzą raz nie więc ekspertem w nich nie jestem.
Deklaracja w movements.xml:
<movevent event="AddItem" tileitem="1" itemid="itemid" script="dough.lua"/>
function onStepIn(cid, item, position, fromPosition)
cid - użytkownik
item - przedmiot
position - pozycja
formPosition - z pozycji
Wywoływana gdy po wejściu na daną pozycje.
Deklaracja w movements.xml:
<movevent event="StepIn" itemid="itemid" script="sciezka.lua""/>
<movevent event="StepIn" uniqueid="uniqueid" script="sciezka.lua"/>
<movevent event="StepIn" actionid="actionid" script="sciezka.lua"/>
function onStepOut(cid, item, position, fromPosition)
Argumenty funkcji jak wyzej.
Wywołana po zejściu z danej pozycji.
Deklaracja w movements.xml:
<movevent event="StepOut" itemid="itemid" script="sciezka.lua""/>
<movevent event="StepOut" uniqueid="uniqueid" script="sciezka.lua"/>
<movevent event="StepOut" actionid="actionid" script="sciezka.lua"/>
function onEquip(cid, item, slot)
cid - użytkownok
item - przedmiot
slot - miejsce na które wkładamy przedmiot
Wywoływana po założeniu jakiegoś Eq
Deklaracja w movements.xml:
<movevent event="Equip" itemid="itemid" slot="slot" function="sciezka.lua"/>
function onDeEquip(cid, item, slot)
Odwrotność funckji onEquip. Argumenty te same.
Deklaracja w movements.xml:
<movevent event="DeEquip" itemid="itemid" slot="slot" function="sciezka.lua""/>
Kod :
function onSay(cid, words, param)
cid - użytkownik
words - słowo kluczowe(stałe)
param - parametr(w odróżnieniu od words jest zmienne)
Funkcja wywoływana mową
Deklaracja w talkactions.xml:
<talkaction words="słowo_kluczowe" script="sciezka.lua"/>
od talkactions ,a reszta sama przyjdzie, lecz na pewno potem rozwine o Creaturescripts ten artykuł.
Tak jak powiedziałem, mój artykuł opierać się będzie o TFS, lecz nie chciałbym zupełnie wprowadzić jedynie funkcje TFS'owskie, więc wkleje
funkcje które były dostępne w TFS 0.2. <a href = "http://rafb.net/p/a6IwIa68.html">Funkcje</a>
Podstawy jakiegokolwiek działania już mamy, więc teraz możnaby przejść do samego programowania w lua.
I.Typy zmiennych
W lua zmienne nie są tak rygorystycznie potraktowane jak w np c++, gdzie każda deklaracja poprzedzona jest typem zmiennej.
Są dwa rodzaje zmiennych:
lokalne - 'local'
globalne - najczęściej zapisywane w global.lua lub w lib/constant.lua
Zmienne mogą przyjmować takie wartości jak:
boolen - wartość logiczna zwracana wartość to true/false
integer - wartość liczbowa zwraca poprostu liczbe
tablicowa - zbiór elementów, niekoniecznie jednej maści
Jak deklarujemy zmienne:
Kod :
local logiczna = false ---boolen
local liczba = 15 -- integer
local tablica = {15, 20, 16, 50} -- tablicowa
local str = "String"
local str2 = 'String'
-- laczenie (konkatenacja) lancuchow - nie mozna uzywac +!
local osoba = "Tato"
local str3 = "Witaj" .. osoba .. "!"
-- str3 => "Witaj Tato!"
Kod :
type(nazwa_zmiennej)
Kod :
local n = 12
local s = 't'
local t = { 1, 2, 3 }
local x = true
doPlayerSendTextMessage( cid, MSG_INFO_DESCR,
type( n ) .. ' ' .. type( s ) .. ' ' .. type( t ) .. ' ' .. type( x ) )
-- wypisze graczowi => number string table boolean
Operatory arytmetyczne to nic prosteszego tylko znane Nam z matematyki znaki. Nie będe się tutaj rozwodził na ich temat bo znacie na pewno je doskonale
ze szkoły. Przejdź od razu do ich działania w lua.
Kod :
== Znak przyrównania
= Znak równości, nadaje wartość zmiennej
+ Znak dodawania
- Znak odejmowania
~= Znak oznaczający że coś jest różne od
> Znak większości
< Znak mniejszości
<= Znak mniejszy lub równy
>= Znak większy lub równy
programowania.
III.Instrukcje warunkowe
Instrukcje warunkowe to bardzo proste instrukcje sprawdzające najczęściej czy lewa strona spełnia nierówność z prawą stroną. To tego będą potrzebne
nam operatory arytmetyczne omówione z poprzednim rozdziale. Wygląda ona tak:
Kod :
if cos operator_aryt cos2 then
--kod
elseif cos operator_aryt cos2 then
--kod
else
--kod
end
Kod :
Czyli np.:
if 4 == 5 then
--Warunek nie spełniony przechodzimy dalej.
elseif 4 == 4 then
--Warunek spełniony, tutaj będzie pracować nasz skrypt
else
--Jeżeli oba powyższe warunki nie byłyby spełnione wykonałoby sie to
end -- Każda instrukcje kończymy end'em.
Kod :
if 4 ~= 5 then
if 8 == 8 then
--kod
else
--kod
end
else
--kod
end
W instrukcjach warunkowych moga rowniez wystapic zmienne np.:
Kod :
local cos = 10
local cos1 = 15
if cos == cos1 then
elseif cos > cos1 then
else
end
wartości logicznych.
IV.Troche wiecej o tablicach
[code]
local tablica = {15, 20, 16, 50}
[code]
Jest to znany Nam przyklad z poprzedniego paragrafu. Jest to tablica 4-elementowa. W lua nietypowym jest numerowanie elementów tablicy.
Przebiega ona od numeru 1, a nie jak większośći języków programowania od 0.
Chcą 'wyciągnąć' wartość 20 z naszej tablicy odnosimy sie poprostu w ten sposób
Kod :
tablica[2]
Istnieje również typ tablic w których sami możemy decydować o ich indeksowaniu.
Teraz prawdopodobnie wydaje Ci się 'Ledwo co rozumiem zwykłe tablice, a teraz te o jeszcze innych zasadach panujących'.
Spokojnie, wrócisz do tego na pewno gdy zwykłe tablice będą Ci ciążyły ;)
Nazwa tych tablic, to tablice asocjacyjne.
Zacznijmy od przykładu:
Kod :
local tab = { 1, 2, 3, foo = 'bar' }
-- tab[1] == 1
-- tab[2] == 2
-- tab[3] == 3
-- tab.foo == 'bar'
W tym wypadku indeksem tablicy jest nie liczba [4], ale 'foo'.
To nie wszystko, bo możemy również stworzyć tablicę w tablicy:
Kod :
local tab =
[2134] = {4, 8, 3, 5}
[2135] = {4, 8, 3, 5}
[2136] = {4, 8, 3, 5]
Kod :
tab[2134][4]
Pętle są to swoiste funkcje które powtarzają kod w określonej liczbie razy. Właście w pętli możemy skorzystać z dobrodziejstw niesionych przez
tablica. No to zacznijmy od kodu, to rozjaśni sytuacje.
Mamy dwa kody, pierwszy jest bez użycia pętli:
Kod :
function onUse(cid, item, fromPosition, itemEx, toPosition)
if item.uid == 1234 then
doPlayerAddItem(cid, 4567, 1)
doPlayerAddItem(cid, 4568, 1)
doPlayerAddItem(cid, 4569, 1)
doPlayerAddItem(cid, 4570, 1)
doPlayerAddItem(cid, 4571, 1)
doPlayerAddItem(cid, 4572, 1)
doPlayerAddItem(cid, 4576, 1)
doPlayerAddItem(cid, 4574, 1)
doPlayerAddItem(cid, 4579, 1)
end
end
Spójrzmy teraz na kod z użyciem pętli:
Kod :
function onUse(cid, item, fromPosition, itemEx, toPosition)
local tablica = {4567, 4568, 4569, 4570, 4571, 4572, 4576, 4574, 4579}
if item.uid == 1234 then
for i = 1, #tablica do
doPlayerAddItem(cid, tablica[i], 1)
end
end
end
Teraz przejdźmy do samej budowy pętli:
Kod :
for (wartosc liczbowa(bardzo czesto i = 1), do jakiej wartości liczbowej i ma zapętlać) do
ciało_pętli
end
pokazanej wyżej tablicy to 9.
Ciekawie tez wyglada sama funkcja:
Kod :
doPlayerAddItem(cid, tablica[i], 1)
Istnieją również pętle które wspomagają użycie tablic asocjacyjnych podanych jak przykład pierwszy, wróć proszę do nich
czytając tą część poradnika o pętlach ;)
Pierwszy rodzaj pętli:
Kod :
for element in tablica do
-- w tej petli przy kazdej iteracji (obiegu) zmienna element bedzie ustawiana na nastepny element tablicy.
end
Kod :
for klucz, element in pairs( tablica ) do
-- druga wersja - w tym wypadku zmienna klucz bedzie ustawiona na klucz do wartosci, a element na wartość. Przykladowo dla tablicy:
-- tab = { 12, 23, 36, x = 'y' }
-- zmienne beda przyjmowaly nastepujace wartosci:
-- klucz = 1, element = 12
-- klucz = 2, element = 23
-- klucz = 3, element = 36
-- klucz = 'x', element = 'y'
end
Kod :
local itemArr =
{
item.itemid,
item.actionid,
item.uid,
pos.x,
pos.y,
pos.z
}
local itemArrNames = { "ID", "AID", "UID", "X", "Y", "Z" }
for i, v in pairs(itemArr) do
if type(v) ~= "table" then
if v ~= 0 and v < 70000 then
msg = msg .. "[" .. itemArrNames[i] .. ": " .. v .. "]"
end
else
msg = msg .. "[" .. itemArrNames[i] .. ": " .. implode(v, "/") .. "]"
end
end
Pisząc ten artykuł, użyłem w nim pare razy funkcji, nie informując Cię Drogi Czytelniku o tym, za co serdecznie przepraszam.
Teraz poświęce ten podrozdział tylko funckjom, co myślę zrekompensuje moje wcześniejsze niedbalstwo.
Zacznijmy od prostego przykładu, funkcji:
Kod :
doPlayerAddItem(cid, item_id, ilosc)
Kod :
doPlayerAddItem(cid, 4567, 1)
na przykład funkcja wyżej podana ma dać nam item.Abyśmy mogli decydować jaki to item i ile tych itemów potrzebne nam
są argumenty funkcji.
Kod :
doPlayerAddItem(cid, item_id, ilosc)
Kod :
function onDoQuest(cid, storage_value, reward, reward_number)
Cid tutaj oznacza osobę wykonująca tzn gracza.
Musimy się zastanowić, co zrobić, aby nasza funkcja była jak najbardziej uniwersalną, aby podczas używania jej w skrypcie
nie trzebaby dodawać za dużo instrukcji.
1. Na pewno musimy sprawdzić czy gracz już czasem nie zrobił danego questa
2. Musimy sprawdzić czy gracz ma tyle wolnego capa.
3. Jeżeli spełnia te warunki no to musimy mu dać item.
4. Miło też by było gdyby wiedział co dostaje, więc wyświetlamy nazwę itemu.
5. Trzeba również się zabezpieczyć przed kolejnym wykonaniem tego quest'a.
6. Jeżeli nie spełnił dwóch pierwszych warunków, trzeba go o tym poinformować.
Jeżeli już wszystko obmyśliliśmy i mamy pewność, jak nasza funkcja ma działać, to bierzemy się za jej pisanie.
W moim wypadku wygląda to tak:
Kod :
function onDoQuest(cid, storage_value, reward, reward_number)
local freeCap = getItemWeight(reward, reward_number)
local itemName = getItemNameById(reward)
if getPlayerStorageValue(cid, storage_value) < 1 then
if getPlayerFreeCap(cid) >= freeCap then
doPlayerAddItem(cid, reward, reward_number)
setPlayerStorageValue(cid, storage_value, 1)
doPlayerSendTextMessage(cid, MESSAGE_EVENT_ADVANCE, "You have found "..reward_number..""..itemName..".")
else
doPlayerSendCancel(cid, "You don/'t have enough capacity.")
end
else
doPlayerSendCancel(cid, "It is empty.")
end
return TRUE
end
Może również zwracać:
Kod :
return 10
local zmienna = 40
return zmienna
return FALSE --return 0
local table = {}
return table
Ostatnim rozdziałem będą eventy. Są to funkcje wywołujące funkcje po określonym czasie.
Na przykład mamy funkcję zabierzGraczowiPunktyŻycia(ilość_pkt_życia).
Chcemy żeby ta funkcja zadziałała no, ale np po 10 sekundach. Nic prostszego!
Z pomocą przychodzą nam właście Eventy.
Wyglądają one tak:
Kod :
ciekawyEvent = addEvent(funkcja_uzywana, czas_w_milisekundach, argumenty_funkc_używanej)
Wyglądałoby to tak:
Kod :
stopEvent(ciekawyEvent)
Kod :
addEvent(zabierzGraczowiPunktyŻycia, 10 * 1000, {10})
Dziękuje bardzo Killavusowi za wzbogacenie tego artykułu paroma cennymi informacjami(pętle, zmienna string, motywacja do napisania o tablicach asocjacyjnych, jak i rozpoczęcie tego wątku.)
Artykuł pogłębiłem o pare informacji jak i dodałem dział o Funkcjach oraz o Eventach.
Jeżeli widzicie jakieś błędy lub macie jakieś uwagi proszę zgłaszać, proszę również o informacje o czym jeszcze
chcielibyście poczytać.
Pozdrawiam,
Tairens
Zakładki