Sentil
Ten Typ
- Joined
- May 11, 2008
- Messages
- 211
- Reaction score
- 82
"Systemy Storage i Global Storage"
- czyli jak dzia?aj? questy
- czyli jak dzia?aj? questy
Spis tre?ci:
I: Prolog
1. Od autora.
II: Storage i Global Storage
2. Storage - czym jest?
2a. Storage w silnikach XML.
2b. Storage w silnikach SQL.
3. Global Storage.
III: Epilog
4. Prawa autorskie.
5. Zako?czenie.
Inne moje artyku?y:
Prolog
1. Od autora.
1. Od autora.
Cze??. Poradnik, kt?ry czytasz, traktuje o systemach Storage i Global Storage, kt?re s? nieod??cznym i bardzo wa?nym elementem ?wiata Open Tibii. Zapraszam do lektury.
II: Storage i Global Storage
2. Storage - czym jest?
2. Storage - czym jest?
Na pocz?tek elementarne pytanie: czym jest storage?
Storage - (z ang. przechowywanie, magazynowanie) - system "kluczy" (storageID) i ich warto?ci (storage_value), dzi?ki kt?rym silnik mo?e czyta?, interpretowa? i zmienia? osi?gni?cia gracza w grze. Wykorzystywany g??wnie tam, gdzie posta? mo?e wykona? dan? czynno?? jednokrotnie (np. wyci?gni?cie nagrody ze skrzynki), przy rozbudowanych questach wymagaj?cych przej?cia jednej misji do odblokowania kolejnej, lub przy czynno?ciach wykonywanych z ograniczeniem czasowym (np. znany wszystkim exhaused).
Najpopularniejszym przyk?adem u?ywania storage s? skrzynki questowe, czyli takie skrzynie, z kt?rych mo?emy wyci?gn?? jaki? przedmiot jeden raz. Za drugim klikni?ciem pojemnik oka?e si? pusty. Wyobra?my sobie gracza i skrzyni? z Demon Armorem. Typ nigdy nie klika? na skrzynk?, wi?c mo?e wyci?gn?? nagrod?. W zabawie z systemem storage bardzo wa?ne jest stwierdzenie, ?e:
Je?li klucz nie zosta? jeszcze nadany graczowi, to domy?lnie posiada warto?? -1.
Co to znaczy? Przedstawi? to na obrazku. Tak wygl?da sytuacja napalonego na Demon Armor gracza przed klikni?ciem na skrzyni?:

Typ nigdy nie klika? na skrzyni?, wi?c klucz 2494 narysowa?em przerywanymi krechami - jeszcze nie istnieje, a skoro nie istnieje, ma warto?? -1. Dlaczego StorageID 2494? To jest ID Demon Armoru. Kiedy? kogo? ol?ni?o i ten kto? stwierdzi?, ?e nie warto pisa? osobnych skrypt?w dla ka?dej skrzynki questowej. Napisa? uniwersalny skrypt, kt?ry dzia?a? tak, ?e gdy jednej ze skrzynek questowych nadamy UID r?wny ID itemu, to ten item nam z niej zleci i utowrzy si? klucz o numerze takim, jak ID itemu.
Teraz gracz podchodzi do skrzyni i ci?nie Use. Skrypt na skrzynk? daje mu Demon Armor i jednocze?nie tworzy klucz 2494, nadaj?c mu warto?? 1:

Za???my, ?e klikamy na skrzynk? ponownie. Silnik nie pami?ta naszej "twarzy" (=d) albo pr?dzej nicku, ale czyta, ?e posiadamy StorageID (klucz) 2494 o storage_value (warto?ci) 1, wi?c z drugiego Demon Armoru nici. Tak to mniej wi?cej dzia?a.
W silniku za system storage odpowiadaj? dwie funkcje:
getPlayerStorageValue(cid, storageID) - pobiera od gracza warto?? klucza o danym numerze (storageID). Jak ju? wiemy, je?li klucz jeszcze nie zosta? utworzony, to posiada warto?? domy?ln? -1.
setPlayerStorageValue(cid, storageID, storage_value) - zmienia graczowi warto?? storage_value na inn? dla danego klucza storage_ID. Za pomoc? tej funkcji mo?emy zrobi? dwie rzeczy: albo utworzy? nowy klucz o jakiej? warto?ci, albo zmieni? warto?? istniej?cego.
Przyk?ad pierwszy
Teraz pos?u?? si? skryptem. Wida? na nim, w jaki spos?b mo?emy bawi? si? w zmian? warto?ci dla danego klucza. Dzia?a tak:
Kiedy gracz kliknie Use na przedmiot o jakim? UID po raz pierwszy, dostanie sworda i pojawi si? tekst. Kiedy kliknie drugi raz, dostanie bright sworda + tekst. Kiedy kliknie trzeci raz - magic sworda i standardowo wiadomo??. Czwartego miecza za czwartym klikni?ciem nie b?dzie, w zamian za to graczowi uka?e si? sam tekst.
Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)
[COLOR="green"]if getPlayerStorageValue(cid, 1000) == -1 then[/COLOR]
doPlayerAddItem(cid, 2376, 1)
doPlayerSendTextMessage(cid, 25, "Kliknales na skrzynie pierwszy raz i dostales miecz!")
[COLOR="royalblue"]setPlayerStorageValue(cid, 1000, 1)[/COLOR]
[COLOR="red"]elseif getPlayerStorageValue(cid, 1000) == 1 then[/COLOR]
doPlayerAddItem(cid, 2407, 1)
doPlayerSendTextMessage(cid, 25, "Kliknales na skrzynie drugi raz i dostales lepszy miecz!")
[COLOR="darkorange"]setPlayerStorageValue(cid, 1000, 2)[/COLOR]
[COLOR="Magenta"]elseif getPlayerStorageValue(cid, 1000) == 2 then[/COLOR]
doPlayerAddItem(cid, 2400, 1)
doPlayerSendTextMessage(cid, 25, "Kliknales na skrzynie trzeci raz i dostales najlepszy miecz!")
[COLOR="slategray"]setPlayerStorageValue(cid, 1000, 3)[/COLOR]
[COLOR="blue"]elseif getPlayerStorageValue(cid, 1000) == 3 then[/COLOR]
doPlayerSendCancel(cid, "Skrzynia nie ma w sobie wiecej mieczy!")
end
return TRUE
end
if getPlayerStorageValue(cid, 1000) == -1 then - ta linijka sprawdza, czy gracz nie posiada jeszcze StorageID 1000. Je?li nie (storage_value = -1), wykonuje dalsz? cz??? skryptu.
setPlayerStorageValue(cid, 1000, 1) - ta linijka tworzy klucz i nadaje mu warto?? 1. Dzi?ki temu silnik odr??nia sytuacj? przed klikni?ciem (brak klucza) od sytuacji po klikni?ciu (klucz 1000 o warto?ci 1).
elseif getPlayerStorageValue(cid, 1000) == 1 then - sprawdzenie, czy istnieje klucz 1000 o warto?ci 1. Istnieje, wi?c kod zawarty pod instrukcj? wykonuje si?.
setPlayerStorageValue(cid, 1000, 2) - tutaj nast?puje zmiana warto?ci dla klucza 1000. Wcze?niej mia? 1, a ta funkcja powoduje, ?e ma 2.
elseif getPlayerStorageValue(cid, 1000) == 2 then - sprawdzenie, czy gracz ma klucz 1000 o warto?ci 2. Ma, poniewa? StorageID zmieni? warto?? z 1 na 2 po drugim klikni?ciu.
setPlayerStorageValue(cid, 1000, 3) - zmiana storage_value na 3 dla storageID 1000.
elseif getPlayerStorageValue(cid, 1000) == 3 then - tak jak wcze?niej, sprawdzenie, czy gracz ma klucz 1000 o warto?ci 3.
To ju? wszystkie u?ycia storage w skrypcie. Tak zmienia?a si? sytuacja gracza w formie graficznej:

Uwaga! Mo?na ca?kowicie odebra? dany klucz postaci. Robi si? to zmieniaj?c warto?? klucza z powrotem na -1:
Code:
setPlayerStorageValue(cid, storageID, [COLOR="red"]-1[/COLOR])
Przyk?ad drugi
Ten skrypt dzia?a tak:Mamy trzy skrzynie: o UniqueID 3005, 3006 i 3007. Z pierwszej leci sword, z drugiej bright sword a z trzeciej magic sword. Gracz mo?e wyci?gn?? tylko jeden miecz.
Typowy skrypt na wyb?r jednej nagrody z questa (wiem, ?e kiepsko napisany, ale tablica i p?tla niepotrzebnie pogmatwa?yby spraw? - musicie mi wybaczy? ; d). Kod:
Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)
local nagroda1, nagroda2, nagroda3 = 2376, 2407, 2400
[COLOR="green"]local quest_status = getPlayerStorageValue(cid, 1001)[/COLOR]
if item.uid == [COLOR="darkorange"]3005[/COLOR] then
[COLOR="royalblue"]if quest_status == -1 then[/COLOR]
doPlayerAddItem(cid, [COLOR="darkorange"]nagroda1[/COLOR], 1)
doPlayerSendTextMessage(cid, 25, "Oto twoja nagroda!")
[COLOR="red"]setPlayerStorageValue(cid, 1001, 1)[/COLOR]
else
doPlayerSendCancel(cid, "Brales juz nagrode z tego questa!")
end
elseif item.uid == [COLOR="magneta"]3006[/COLOR] then
[COLOR="royalblue"]if quest_status == -1 then[/COLOR]
doPlayerAddItem(cid, [COLOR="magneta"]nagroda2[/COLOR], 1)
doPlayerSendTextMessage(cid, 25, "Oto twoja nagroda!")
[COLOR="red"]setPlayerStorageValue(cid, 1001, 1)[/COLOR]
else
doPlayerSendCancel(cid, "Brales juz nagrode z tego questa!")
end
elseif item.uid == [COLOR="deepskyblue"]3007[/COLOR] then
[COLOR="royalblue"]if quest_status == -1 then[/COLOR]
doPlayerAddItem(cid, [COLOR="blue"]nagroda3[/COLOR], 1)
doPlayerSendTextMessage(cid, 25, "Oto twoja nagroda!")
[COLOR="red"]setPlayerStorageValue(cid, 1001, 1)[/COLOR]
else
doPlayerSendCancel(cid, "Brales juz nagrode z tego questa!")
end
end
return TRUE
end
local quest_status = getPlayerStorageValue(cid, 1001) - funkcja sprawdzaj?ca klucz 1001 zosta?a wci?ni?ta do zmiennej quest_status (dla wi?kszej przejrzysto?ci kodu).
if quest_status == -1 then - je?li klucz nie istnieje, to...
setPlayerStorageValue(cid, 1001, 1) - zmie? warto?? klucza na 1.
3005, nagroda1 - skrzynia o UID 3005 (pierwsza) to nagroda1 (sword).
3006, nagroda2 - skrzynia o UID 3006 (druga) to nagroda2 (bright sword).
3007, nagroda3 - skrzynia o UID 3007 (trzecia) to nagroda3 (magic sword).
Obrazkowo:

2a. Storage w silnikach XML.
W silnikach XML i SQL mamy te same funkcje obs?uguj?ce system storage, lecz r??ni si? spos?b przechowywania kluczy i ich warto?ci. W SQLach, jak ?atwo si? domy?li?, klucze trzymane s? w bazie danych (o tym za chwil?), natomiast w XMLach StorageID maj? swoje miejsce w plikach ".xml" poszczeg?lnych graczy. Wchodzimy w data/players/nazwa_gracza.xml. Teraz odszukujemy <storage>. Pomi?dzy <storage> a </storage> znajduj? si? wszystkie klucze i ich warto?ci, jakie posiada player:

Key to klucz, a value - jego warto??. Kiedy gracz otrzyma jaki? StorageID w grze, w jego pliku automatycznie dopisywana jest kolejna linijka z kluczem i warto?ci?.
2b. Storage w silnikach SQL.
Wy?ej nadmieni?em ju?, ?e klucze i warto?ci w silniku SQL znajduj? si? w bazie danych. Wejd?my w swoj? baz? (o ile takow? posiadacie) przez phpMyAdmina. Po lewej stronie szukamy zak?adki player_storage:

Klikamy j? i widzimy takie co?:

Player_id to numer ID gracza, do kt?rego nale?y dany klucz. ?eby edytowa?/usun?? klucze odpowiedniemu graczowi, najpierw musimy zna? jego ID (nie nick). Mo?na go sprawdzi? w zak?adce players. Key i value - wiadomo. Klikamy o??wek przy kluczu 1001 (krzy?yk usuwa klucz):

Player_id raczej nie zmieniamy, chyba, ?e ten sam klucz o danej warto?ci chcemy zdj?? z jednej postaci i wrzuci? na inn?. Edytuj?c key zmieniamy numer klucza (warto?? zostaje), a edytuj?c value, zmieniamy sam? warto??. Wszystkie zmiany zatwierdzamy guzikiem "Wykonaj".
3. Global Storage.
System global storage dzia?a podobnie jak storage, z t? r??nic?, ?e klucze StorageID dotyczy?y konkretnych graczy, a klucze Global_StorageID odnosz? si? do wszystkich jednocze?nie (mo?na powiedzie?, ?e klucz globalny otrzymuje nie gracz, a silnik). Za global storage odpowiadaj? dwie funkcje:
getGlobalStorageValue(global_storageID) - pobiera z silnika warto?? dla klucza global_storageID. Je?li silnik nie posiada klucza, zwracana jest warto?? -1.
setGlobalStorageValue(global_storageID, global_storage_value) - zmienia silnikowi star? warto?? na warto?? global_storage_value dla klucza global_storageID, lub tworzy silnikowi nowy klucz.
Mo?e to troch? dziwne, ale wszystko wyja?ni si? w przyk?adzie.
Przyk?ad
Skrypt dzia?a tak:
Je?li nikt na serwerze nigdy nie klikn?? danego przedmiotu, to graczowi wy?wietli si? informacja, ?e zrobi? to pierwszy. Je?li kto? kiedykolwiek klikn?? Use, playerowi poka?e si? inny tekst.
Kod:
Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)
[COLOR="green"]if getGlobalStorageValue(cid, 2000) == -1 then[/COLOR]
doPlayerSendTextMessage(cid, 25, "Jako pierwszy na serwerze dotknales ten przedmiot.")
[COLOR="royalblue"]setGlobalStorageValue(cid, 2000, 1)[/COLOR]
else
doPlayerSendCancel(cid, "Jakis gracz z tego swiata juz to kiedys dotknal.")
end
return TRUE
end
if getGlobalStorageValue(cid, 2000) == -1 then - sprawdzenie, czy silnik ma globalny klucz 2000.
setGlobalStorageValue(cid, 2000, 1) - utw?rz w bazie danych globalny klucz 2000 o warto?ci 1 (kt?ry b?dzie dotyczy? ka?dego gracza na serwerze).
Obrazek sobie podarowa?em ; ).