T
Tairens
Guest
Zaczynaj?c artyku? chcia?bym stwierdzi?, ?e w silnikach nast?pi?o do?? du?e rozr??nienie w posiadanych funkcjach.
Ja b?de opiera? si? na tych Tfs'owskich gdy? wydaje mi si?, ?e jest to teraz najpopularniejszy silnik.
Podstawowymi funkcjami o kt?re opiera si? ka?dy skrypt s?:
Actions:
Movements:
Talkactions
Uwa?am, ?e s? to informacje podstawowe. Nie chce narazie wdra?a? si? w tematyke Creaturescripts gdy? wydaje mi si?, ?e i tak ka?dy zacznie
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:
boolean - 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:
Mo?liwe jest r?wnie? sprawdzenie typu zmiennej. W tym wypadku u?ywamy funkcji:
II.Operatory arytmetyczne
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.
Uwa?am, ?e to s? to najwa?niejsze operatory arytmetyczne. Niech nie zwiedzie Was to ?e to matematyka itd, bo dobre ich opanowanie to klucz do dobrego
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:
S? te? zagnie?d?one instrukcje warunkowe kt?re w lua s? do?? cz?sto spotykane tzn.:
W takim wypadku else zawsze nalezy do najblizszego if'a.
W instrukcjach warunkowych moga rowniez wystapic zmienne np.:
W tym wypadku porownujemy dwie zmienne.Do ktorych przypisane s? warto?ci. W przypadku zmiennych logicznych sprawdzana jest zgodno??
warto?ci logicznych.
IV.Troche wiecej o tablicach
Tablice u?ywane s? najcz??ciej do optymalizacji kodu, w czym pomagaj? p?tle, o kt?rych zaraz powiemy.
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:
Jak widzisz w pierwszych trzech elemenetach indeksowanie jest standardowe, ale element numer 4.
W tym wypadku indeksem tablicy jest nie liczba [4], ale 'foo'.
To nie wszystko, bo mo?emy r?wnie? stworzy? tablic? w tablicy:
Chc? wyci?gn?? warto?? 5, z tablicy o indeksie [2134], stosuje co? takiego:
V.P?tle
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:
Co? du?o takich samych instrukcji wysz?o, co nie?
Sp?jrzmy teraz na kod z u?yciem p?tli:
Czy nie wygl?da to estetyczniej i czytelniej?
Teraz przejd?my do samej budowy p?tli:
Ja w swojej p?tli u?y?em znaczka '#' jest on niczym innym jak operatorem pobieraj?cym najwi?kszy element tablicy co w wypadku
pokazanej wy?ej tablicy to 9.
Ciekawie tez wyglada sama funkcja:
W tym wypadku poprostu pobiera element tablicy, poniewa? zmienna jaka jest i, przyjmuje dla kazdego zapetlenie wartosc wieksza o 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:
Drugi rodzaj p?tli:
No i oczywi?cie przyda si? przyk?ad, kt?ry jest zaczerpni?ty z silnika DeadTouch:
VI.Funkcje
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:
Tak wygl?da bez 'dopasowania' do danej sytuacji argument?w, a tak gdy mamy konkretny przyk?ad:
Zacznijmy od tego, ?e funkcja to zbite w jakie? konkretne informacje, dzia?anie kt?ry ma okre?lony cel, czyli
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.
To teraz spr?bujmy napisa? w?asn? funkcj?:
Widzicie zapewne w przed ostatniej linijce 'return TRUE', to jest tzw zwracanie warto?ci, w tej funckji akurat zwraca prawd?.
Mo?e r?wnie? zwraca?:
VII.Eventy
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:
Umie?ci?em go w zmiennej ciekawyEvent, poniewa? przyda nam si? to aby mo?na zastopowa? Event w razie jakiej? ewentualno?ci.
Wygl?da?oby to tak:
Wywo?uj?c nasz konkretny Event b?dzie to wygl?da?o tak:
-------------------------------------------------------------------------------------------------------------------------------
Dzi?kuje bardzo Killavusowi za wzbogacenie tego artyku?u paroma cennymi informacjami.
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
Ja b?de opiera? si? na tych Tfs'owskich gdy? wydaje mi si?, ?e jest to teraz najpopularniejszy silnik.
Podstawowymi funkcjami o kt?re opiera si? ka?dy skrypt s?:
Actions:
Code:
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" event="script" script="sciezka.lua" />
<action uniqueid="uniqueid" event="script" script="sciezka.lua"/>
<action actionid="actionid" event="script" script="sciezka.lua"/>
Code:
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""/>
Code:
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:
boolean - 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:
Code:
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!"
Code:
type(nazwa_zmiennej)
Code:
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.
Code:
== 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:
Code:
if cos operator_aryt cos2 then
--kod
elseif cos operator_aryt cos2 then
--kod
else
--kod
end
Code:
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.
Code:
if 4 ~= 5 then
if 8 == 8 then
--kod
else
--kod
end
else
--kod
end
W instrukcjach warunkowych moga rowniez wystapic zmienne np.:
Code:
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
[code]
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:
Code:
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:
Code:
local tab =
[2134] = {4, 8, 3, 5}
[2135] = {4, 8, 3, 5}
[2136] = {4, 8, 3, 5]
Code:
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:
Code:
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:
Code:
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:
Code:
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:
Code:
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:
Code:
for element in tablica do
-- w tej petli przy kazdej iteracji (obiegu) zmienna element bedzie ustawiana na nastepny element tablicy.
end
Code:
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
Code:
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:
Code:
doPlayerAddItem(cid, item_id, ilosc)
Code:
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.
Code:
doPlayerAddItem([b]cid, item_id, ilosc[/b])
Code:
function onDoQuest(cid, storage_value, reward, reward_number)
[code]
Chcemy, aby ta funkcja dawa?a graczowi item o id = reward , o ilosc = reward_number oraz zmienia?a storage value = storage_value
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:
[code]
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?:
Code:
return 10
local zmienna = 40
return zmienna
return false
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:
Code:
ciekawyEvent = addEvent(funkcja_uzywana, czas_w_milisekundach, argumenty_funkc_u?ywanej)
Wygl?da?oby to tak:
Code:
stopEvent(ciekawyEvent)
Code:
addEvent(zabierzGraczowiPunkty?ycia, 10 * 1000, {10})
Dzi?kuje bardzo Killavusowi za wzbogacenie tego artyku?u paroma cennymi informacjami.
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