• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

[Lua] Understanding Storages

Evan

A splendid one to behold
Senator
Premium User
Joined
May 6, 2009
Messages
7,019
Solutions
1
Reaction score
1,029
Location
United States
This will be a very simple and well-described tutorial on using the storage system in OpenTibia

Descriptive Introduction

What does storage mean?
It is the control of retrievable data on a computer or other electronic system; in other words, memory.

In OpenTibia, we use storage to hold numeric values (StorageValues), which we would later use to control things in-game.
When it comes to managing storage, we will mostly worry about two things: StorageID and StorageValues.

qOMs1X5.png


What are these two things?
  • StorageID is a space in memory that holds a numeric value (Storage Value). It is named with a pre-defined ID number.
  • StorageValue is a number that will be stored in a space in memory (StorageID)
The default storage value for any storage is -1.

There are two different kinds of storage:
Player storage - a StorageValue can be stored in a StorageID that is specific to a player
Global storage - a StorageValue can be stored in a StorageID that is used globally in the game (pretty much applies to every player)

How do we manage storage in Lua?
To get the storage value:
kFM9ulm.png

PFWXDZC.png

These functions return the StorageValue of the specified StorageID

To set the storage value:
7G45zLo.png

YaIeBDW.png

These functions store the StorageValue in StorageID

Examples

Scenario 1: Let's say we want to give a player a storage with an ID 4200 and give it a storage value of 3.

Initial: The player has nothing (default storage value: -1)
u82bhUy.png


We set storageID 4200 to have storage value of 3:
w3vfbUu.png


Final: The player now has a storage with an ID 4200 and it has a storage value of 3
Vt6GSNW.png


Scenario 2: Let's have a player click on a statue and have it print "Bazinga!" IF AND ONLY IF the player's storage value in 5400 is -1 or less, else print "Aww shucks!". If the statue says "Bazinga!", we set the player's storage value in 5400 to 1.

The understanding to this scenario is that we want the player to use something only once.
In order to do that, we will use a storageID to hold a value that will help us determine if a player has used the statue or not.
If the storage value is -1 or less, the statue will say "Bazinga!", else it will say "Aww shucks!".

Initial: The player has nothing (default storage value: -1)
FPUk2D9.png


When we use the statue, we want to know which message to print ("Bazinga!" or "Aww shucks!").
We said if the storage value of 5400 is -1 or less, then print "Bazinga!", else print "Aww shucks!".

In order to check if a player has storage value of -1 or less in storage 5400, we will do something like this:
Then if it is true, we will print "Bazinga!" and then give the player a storage value of 1 in storage 5400.
Lua:
	if (getCreatureStorage(cid, 5400) < 0) then
	-- print "Bazinga!"
	doCreatureSetStorage(cid, 5400, 1)
J8whxmF.png


If the player has a storage value in 5400 that is anything other than 0, we need to print "Aww shucks!", we will use this:
Lua:
if (getCreatureStorage(cid, 5400) < 0) then
	-- print "Bazinga!"
	doCreatureSetStorage(cid, 5400, 1)
else
	-- print "Aww shucks!"
end
74PVDZY.png


This happened because when we used the statue with storage value 0 in storage 5400, it will print "Bazinga!" and change the storage value in 5400 to 1. Since 1 does not equal any number less than 0, it fails the initial condition and moves to the else, which then would print "Aww shucks!".

Scenario 3: Let's create something where a player can only do something once per day.

Something like this would be ideal for tasks where you want players to complete only once per day (like the Rottin Wood quest).
It's fairly simple to do with storage and storage values. We just need the quest to check if it has been 24 hours since the last use.
And we will be doing that using storage values and the operating system time!

Things to know:
  • There are 60 seconds in a minute
  • There are 3600 seconds in an hour
  • There are 86400 seconds in a day

Here is the full Lua script for something like this scenario:
Lua:
local dayStorage = getCreatureStorage(cid, 7300)
local secondsInADay = 86400
if (os.time() > dayStorage + secondsInADay) then
        -- do something
        doCreatureSetStorage(cid, 7300, os.time())
else
        -- print "You must wait 24 hours before doing it again"
end
The variable dayStorage will hold the storage value of storage 7300.
The variable secondsInADay will hold the value 86400, which is the number of seconds in a day
os.time() returns the number of seconds since 00:00:00 UTC, January 1, 1970. This will help use keep track of time.

Initial: The player has nothing in storage 7300
df4LWnC.png


When you use the script, it will check if os.time() is greater than dayStorage + secondsInADay.
  • Current os.time() in this moment is: 1368219623.
  • dayStorage is the storage value in 7300, which is 0.
  • secondsInADay is defined as the number of seconds in a day, which is 86400.
Since 1368219623 is greater than (0 + 86400), the initial condition is passed.
Therefore we will -- do something and set the player's storage 7300 value to os.time().

Ce7MlGM.png


Now, let's say the player uses this script again after 12 hours (which is before 1 day has passed).
When you use the script, it will check if os.time() is greater than dayStorage + secondsInADay.
  • The os.time() after 12 hours is: 1368262823.
  • dayStorage is the storage value in 7300, which is 1368219623.
  • secondsInADay is defined as the number of seconds in a day, which is 86400.
Since 1368262823 is less than (1368219623 + 86400, which is 1368306023), the initial condition has failed.
Therefore it will skip the initial condition and move to the else will -- print "You must wait 24 hours before doing it again"
It will continue to do this until os.time() is greater than the storage value in storage 7300.




I think that is all that I should share.
If you have any questions, comments, concerns, or spot any mistakes in this thread (hope not), PLEASE POST!
 
Last edited:
Absolute necessity for proper scripting these days. I found it quite awkward that no one made such a tutorial before. You deserve respect my friend.

Salute,
Zum~
 
Awesome job Evan!
This is hands down the most complete and clear tutorial of storages I've ever seen.
 
Great structure.
Should help beginners for sure.
 
Useful to store strings too, not only numbers
 
Useful to store strings too, not only numbers

Oh yes! How could I forget, will update it when I get the chance today. Thanks man

Cool thread:D. You could also write something about packing many values into single storage. Here is link to my thread.
http://otland.net/f163/lib-serializing-deserializing-many-values-into-single-storage-value-177284/
I belive it might be helpfull since, this structure allows you to handle storages similary to packets handling :D

I did not see this, it looks really awesome
 
I am not the best at LUA scripting but i am trying :p

I've seen a lot of scripts like this:
if (getCreatureStorage(cid, 5400) ~= -1) then

or if it is:

if (getCreatureStorage(cid, 5400) == -1) then


Dont remember.
Could you explain what -1 in a getCreatureStorage means?
 
I am not the best at LUA scripting but i am trying :p

I've seen a lot of scripts like this:
if (getCreatureStorage(cid, 5400) ~= -1) then

or if it is:

if (getCreatureStorage(cid, 5400) == -1) then


Dont remember.
Could you explain what -1 in a getCreatureStorage means?

The storage id which has a storage value that equals -1 is a storage id that has never had it's value changed, unless it got set to -1.
 
The storage id which has a storage value that equals -1 is a storage id that has never had it's value changed, unless it got set to -1.

Ah so if you want to check if someone never had that ID example beginning of a quest (first setStorage) you use -1 :p?
 
Ugh dammit, made a booboo, I forgot the default storage value is -1, not 0.
Yes, that is correct. A storage that has never been touched or used will have a default value of -1.
 
Ugh dammit, made a booboo, I forgot the default storage value is -1, not 0.
Yes, that is correct. A storage that has never been touched or used will have a default value of -1.

Now i get why some of my scripts gets fucked up :)

btw does Global and player storage work the same with -1? i'm trying to make a first advance script :)
 
Now i get why some of my scripts gets fucked up :)

btw does Global and player storage work the same with -1? i'm trying to make a first advance script :)

Yes, the default value is -1 for both.

PS: Updated first post with changes to examples and information regarding -1.
 
doing :
Lua:
if getCreatureStorage(cid, 1234) == -1 then

or

if getCreatureStorage(cid, 1234 == nil then
is the same in general -1 is the same as nil(nothing)
 
I´ve read the article but what I'm asking now... how can make that when a player gets into a teleport, it gets a storage value? I've tried just adding the line to a function o a teleport that appears when a determinated monster is killed but the player doesn't receive the storage value :/
 
I would do this:

When the teleport is created, give it an actionid. Then create a movement script (onStepIn) to check if the actionid is equal to the actionid of the teleport.
If it's equal, then give player a storage value.
 
Back
Top