Action scripts tutorial

In this tutorial I will generally explain how to work with action scripts.

1 - Useful information (read when you are new with this)
2 - Commands
3 - Making useables
4 - Making quests

All item id’s used in 3 and 4 are 7.6 item ids!
--------------------------------------------------------------------

----1 Useful information

When editing the .lua / .xml files the best editor to use is simply Notepad. You could also use other editors like word. But notepad works best with me.

---1.1 Storing data

When scripting in ot action files you will have to understand what some thing mean. One of the important things are items in which you can store data. Here I will give an example:

Code:
number = 1now the storage item "number" contains "1". So each time we will call up the storage value "item", we will get the answer "1".
When you'd like to perform math calculations you can do it like this:

Code:
number = number + 1Now there will be added 1 to the storage value number. You can replace + with -, / and some more math signs (havn't tried them all).
If you want number to be an random number it would be like this:

Code:
number=math.random(1,10)1,10 is the min/max number that the random init should get.

It is also possible to store text inside these starage items. An example:

Code:
name = "hi, my name is Mindstorm"Now the storage item "name" will contain the text "hi, my name is Mindstorm".
In these two examples I used the storage items "number" and "name". However you can change them to whatever you like!

---1.2 If statements:
And if statement simply says that a piece of code between the "if" and the 'end' will only be carried out when the lines of code between the "if" and the 'then' is correct.
You always need to close an "If" statement with and "end".
Example:

Code:
if apple == 1 then
"piece of code"
endThis code will carry out the "piece of code" only if the storage value "apple" is 1. Look at the "==" part. When using an if statement and you want to compare two factors you must use the "=" signe twice instead of once!
If you want the "if" statement to compare multiple factors in one statement it will look like this:

Code:
if apple == 1 and pear == 2 then
"piece of code"
endNow the "piece of code" will only be carried out when the storage value "apple" is 1 and "pear" is 2. Of course you can put as many factors in one if statement, as long as you separate them with an "and".
If you'd like to carry out "piece of code" when the storage value "apple" is 1 OR when the storage value "pear" is 2 simply replace the "and" by an "or".

Let's say you want to execute "piece of code1" when the storage value "apple" is 1, and "piece of code2" when the storage value "apple" is not 1. It will have
to look like this:

Code:
if apple == 1 then
"piece of code"
else
"piece of code2"
endYou simply put an "else" between the "if ... then" and the "end". Everything which is between the "if .. then" and the "else" will be carried out if the storage value apple IS 1, everything which is between the "else" and "end" will be carried out when and store value apple is NOT 1

Now what if you want "piece of code1" to be carried out when the storage value "apple" is 1, and "piece of code2" when the storage value "apple" is 2. When apple is neither 1 nor 2 “piece of code3” will be carried out.

Code:
if apple == 1 then
"piece of code1"
elseif apple == 2 then
"piece of code2"
else
"piece of code3"
endNow if the storage value "apple" is 1 "piece of code1" will be carried out, but if the storage value "apple" is 2 ONLY "piece of code2" will be carried out!
When the apple is neither red nor green "piece of code 3" will be carried out.
You can put as many "elseif...then"'s between the "if...then" and the "else" as you want.
If you want nothing to happen when the apple is neither 1 or 2 simple remove the
else
"piece of code3"

When you are using "==" between apple and 1(if apple == 1 then) you are comparing. So you say, if the storage value of "apple is 1" then....
When you use the "==" sign, the part in front of the "==" (apple) most of the time represents a storage item.
But it would be nice if we could do other things then comparing factors! Therefore we can place a few different things between the storage value and then thing you want to compare (or something else) it to.
Examples:
- if apple > 1 then (will only be carried out if the storage value "apple" is bigger then 1)
- if apple < 1 then (will only be carried out if the storage value "apple" is smaller then 1)
- if apple ~= 1 then (will only be carried out if the storage value "apple" is not 1)
- if apple >= then (will only be carried out if the storage value "apple" is 1, or bigger then 1)
- if apple <= then (will only be carried out if the storage value "apple" is 1, or smaller then 1)

---1.3 For statements

For statements are completly different then if statements. Here is an example:

Code:
for apple 1,10 do
doPlayerSendTextMessage(cid,18,apple)
end"doPlayerSendTextMessage(cid,18,apple)" is an function (more about this later) which will send a message to the player with a text. Now the text which will be send is the contains of the storage item "apple". In this code the for statement will create a loop. It will repeat "doPlayerSendTextMessage(cid,18,apple)" until the storage value apple is 10.
[/i]for apple nr1,nr2 do[/i]. Here nr1 is the starting number, nr2 is the finishing number. The for loop will automatically increase the value of the storage item "apple" each time it repeats the loop.

---1.4 Repeat statements

Repeat statements will repeat a piece of code until something reaches a value. Example:

Code:
Repeat
“piece of code”
Until NumberOfApples > NumberOfPearsNow the “piece of code” wil be repeated unstill the storage value NumberOfApples is bigger then the storage value NumberOfPears. Ofcourse you can change NumberOfPears into a number.

----2 Commands
When scripting action files there are some commands which are useful to know. Here I will explain the once which you will use most.

“function onUse(cid, item, frompos, item2, topos)”:
This is what every action script starts with. The function onUse() just means that you are using something (a item or whatever). There are a few storage values you are given in the action script, which you don’t have to set! These storage values are:
-Cid: The person who uses the item (info about the person using).
-Item: Info on the item he is using. (so if you ctrl-click on a blue berry bush al lot information about that blue berry bush is stored inside the item storage value).
-frompos: From wich position he is going to use the item.
-item2: if he is using the item on something, item2 contains data of that item.
-topos: to wich position he is using to the item.
Keep in mind that fuction onUse() always ends with an “end”

--Do functions

“doPlayerSay(cid,”hi”,2)”:
This function will type a message for the player. Now the player would automatically say Hi.

“doPlayerSendTextMessage(cid,22,"Hi.")”:
If you type this in your action script it will send the message Hi to cid. Cid is the player who is using an object. 22 is the colour the message should be shown in. (1-22 work for sure, higher then those I do not know). numberFor example, if a player uses a lever this action script will be send.

Code:
Function onUse(cid, item, frompos ,item2, topos)
doPlayerSendTextMessage(cid,22,”hi”)
EndNow every time when a player uses a lever he will get a message saying “hi” inside his chat bar.

“doPlayerSendCancel(cid,"hi”)”:
This function looks a lot like the doPlayerSendTextMessage() function. The difference is that you can not use colours and the message will not be shown inside the chat bar, but on the bottom of the screen. (Normally the text “you are exhausted” or “you do not have enough mana” appear there).

“doCreateItem(id,number,topos)”:
This function will create an item on the title you use. Id is the item id which should be created, number is the amount of it, topos is the position where it should be created. Remember when you use an item topos Is already the coords

“doDecayItem(item.uid)”:
This function will decay an item. This means it will return to it’s original item.id. (For example shovel holes returning to piles of stone).

“doPlayerAddHealth(cid,100)”:
This will add 100 health to the player (cid). You can ofcourse replace 100 by any number you’d like! You can also make the 100 a negative number, this number will then be removed from the players health.

“doPlayerAddMana(cid,100)”:
This will add 100 mana to the player (cid). (Can also be negative numbers).

“doPlayerAddSkillTry(cid,6,1)”:
This function will add a skill. 6 means the type of skill 1 means the amount of skill to be added (not in %, or as a level, just as a number of tries).

“doPlayerSetMasterPos(cid,newpos)”:
This function will set the new master position of the player. The master position is the position where the player will go to if he dies.

“doPlayerSetVocation(cid,voc)”:
This function will set the players vocation. Voc is the vocation as a digit (0-4).

“doPlayerRemoveMoney(cid,100)”:
This function will remove an amount of money from the player’s backpack. (you can change 100 to whatever you want).

“doPlayerAddItem(cid ,itemid, amount)”:
This function will add an item to the players backpack. 2400 is the item number (you can find the item numbers in the item.xml. 1 represents the amount of these items to be given. When 2400 would be a item which you can get in amount (gold coins, platinum coins, runes) it will be the amount of it. So if you would send (cid,2152,100) you would add 100 gold coins inside the players backpack. When saying (cid,runeid,100) you would add a rune of the type runeid with 100 charges inside the players backpack.
When the id of the item you want to send is a bottle/mug/beer mug or something likewise the number will mean the contains of the bottle/mub/beer mug. (so what’s inside). For example: doPlayerAddItem(cid,bottleid,0) would give a bottle with blood inside it.

“doPlayerRemoveItem(cid, itemid, amount)”:
This function will remove an item from the players inventory.

“doRemoveItem(item.uid,item.type)”:
This function would remove the item you are using.

“doSetItemActionId(item.uid,newactionid)”:
This function will change the itemid from an item into a new itemid.

“doSetItemText(item.uid,”Hi”)”:
This function will set the text of an readable (books, letters…). Item.uid is the Unique item id. “hi” is the text you want to be set inside the readable. (I will give more explanation about this in the “4 – Making quests” part).

“doShowTextWindow(item.uid,0,0)”:
This function will show the text box on the screen from a readable (book, letters….). It can NOT put in the text which you will read! Item.uid is the item wich should be shown small on top. 0,0 is some general stuff (You shouldn’t use this function to much, most readable items are already set.

“doSendAnimatedText(position,”text”,180)”:
This function will send an animated text to the position (damage, monsters yelling). Position is the position. “text” is the text to be shown (can also be a digit). 180 is the colour. (180 is red, others you will have to experiment with).

“doTeleportThing(cid,position)”:
This function would teleport the player to a new position. Example

Code:
Function onUse(cid, item, frompos ,item2, topos)
position = {x=273, y=433, z=9}
doTeleportThing(cid,position)”:
EndThe position storage value has got multiply items stored. After you have set an position to for example “position = {x=273, y=433, z=9}” you can always change just the x coordinates like this:
Position.x = 272

“doSendMagicEffect(position,2)”:
This function simply sends a magic effect to a position. The values of position can be stored likewise as in the doTeleportThing() function. 2 means the magic effect. I think these can vary from 1-15 or something like that. I do not know what all of these magic effects do (2 = poof, 12 is teleport bubble).

“doTransformItem(item.uid, 1945)”:
With this function you can change an existing item into an other item. When using this function the item you clicked will change to the itemid 1945 (a lever pointing west in this case).

“doSummonCreature("orc warrior", position)”
This function will summon a creature on a position you set. (position is a storage value).

“doPlayerFeed(cid,food)”;
This function will feed the player a amount of food. I do not know the common amount for any kind of food though. You will have to experiment with it.

--Get functions

“getPlayerAcces(cid)”:
This function will get the access of the player. For example:
Access = getPlayerAcces(cid)
The storage value access will now contain the number of access of the player.

“getPlayerGuildId(cid)”:
This function will get the players guild id.

“getPlayerHealth(cid)”:
This function will get the players health.

“getPlayerLevel(cid)”:
This function will get the players current level.

“getPlayerMagLevel(cid)”:
This function will get the players current magic level.

“getPlayerMana(cid)”:
This function will get the players mana.

“getPlayerMasterPos(cid)”:
This function will get the players master position (most of the time the temple spawn position).

“getPlayerName(cid)”:
This function will get the players name.

“getPlayerPosition(cid)”:
This function will get the players position.

“getPlayerSkill(cid,6)”
This function will get the players skill level. 6 means the type of skill (0 = magic, 1 = sword, 2 = club, 3 = axe, 4 = distance, 5 = shielding, 6 = fishing. Atleast if I’m not mistaking ).
This is the level of the skill, not the number!

“getTilePzInfo(position)”:
This function will look if the title is a protection zone or not. If the result is 0 the title wont be a protection zone.

“getPlayerFood(cid)”:
This function gets the amount of food the player currently has eaten. (decreases every second he is online or in bed). A normal amount for a player to be “full” is 1200.

“getThingfromPos(position)”:
This function will get everything on a position. For example:

Code:
Function onUse(cid, item, frompos ,item2, topos)
position = {x=273, y=433, z=9, stackpos=0}
positioninfo = getThingfromPos(position)
EndPositioninfo now contains information about that position’s Title. (because stackpos is 0)
Positioninfo.itemid would be the item.id from the title from position {x=273, y=433, z=9}. More about the stackpos in “4 – Making Quests”.

“getPlayerStorageValue(cid,storage number)”:
This function would get a storage value from the playersname.xml. Storage values are a way to look if player for example already has done a quest. So if you would like to get a storage value it would probably look like this:
queststatus = getPlayerStorageValue(cid,2000)
Queststatus would now contain a number (most of the time this number is -1 if he hasn’t done the quest, and 1 if he has).

--Other functions

“setPlayerStorageValue(cid,storage number,1)”
With this function you would set an storage value. For example:
setPlayerStorageValue(cid,2000,1)

“print(“hi”,item)”:
A very simple function to print some text with a storage value inside the server box. So this will print hi 5 (or whatever value item contains).

----Making Usables
With making usable I mean scripting an action when you use an item.

The first thing you would have to do is edit the actions.xml. You can find this file inside the data/actions/ folder.
This file contains a lot of information. Most lines look a lot like this:

There are two different kinds of things you can add into this file.



When you insert an itemid=. The script.lua will be carried out when you use all item with this id! When using the uniqueid the script.lua will only be carried out when the item you use has the unique id “1000” (or an other id).
Script.lua is the script wich will be carried out when using the item. “script” can be anything you want. The location of where the script should be is data/actions/actions/.

Now let’s say we want to make a blueberry bush which you can actually use!
First we would have to insert a line inside the actions.xml. This line would look like this:

It doesn’t matter where this line stands as long as it stands between the

The script we are referring to is bush.lua. So go to the data/actions/actions folder and create a new file called bush.lua (when using notepad be carefull you don’t create a bush.txt).
The bush.lua would have to look like this:

Code:
function onUse(cid, item, frompos, item2, topos)
if item.itemid == 2785 then
doPlayerFeed(cid,5)
doCreateItem(2677,3,topos)
doTransformItem(item.uid, 2786)
doDecayItem(item.uid)
end
endThe if..end statement looks if the item.id is equal to the item id of a blue berry bush. (not actually necessarily because bush.lua only get’s carried out when using a blue berry bush.
doPlayerFeed(cid,5) feeds the player
doCreateItem(2677,3,topos) creates 3 blue berries on top of the bush.
doTransformItem(item.uid,2786) will change the bush to a bush with no blue berries on it.

Now save the file again. When you now start your server and use a blue berry bush you will eat, and 3 blue berries will be on top of the bush!
I haven’t found out how to let the bush decay so it will return back to a bush with berries again after some time.

This was just a simple usable item. Now let’s say we want to create a lever which would set a new “hometown” to a position. This is a nice action when you have more towns.
You will off course need to add a line in the actions.xml.
The first thing which you have to do is set the action id of the lever we are going to use in the editor. This is how I did this:
This image has been resized. Click this bar to view the full image. The original image is sized 1280x768 and weights 261KB.

Now the lever in the temple has the action id 2000. We will need to put a line in the actions.xml which would say that each time someone uses the item with the unique id 2000 a script will be carried out. I added this line

Now we need to make a changehometown.lua wich will be carried out when someone uses the lever with the unique id 2000. I made it like this:

Code:
function onUse(cid, item, frompos, item2, topos)
if item.itemid == 1945 then
doTransformItem(item.uid,1946)
newpos = {x=100, y=100, z=7}
doPlayerSetMasterPos(cid,newpos)
else
doTransformItem(item.uid,1945)
end
endThe if …else…end statement will look if the lever faces west, or east. When caing west the lever id will be 1945. When a player pulls the lever his master position will be changed to a new master position I have set in the newpos storage value. When the item id is not 1945 the lever is facing east, and then the lever will only be changed to face west.

These where two examples for quiet easy action scripts. But remember you can make way more advanced or bigger once then these!

----4 Making quests

Here I will give a quick lesson in how you can make advanced nice quests.

In the first quest I will explain a few general things.
First: Elevators (working with storage values and teleports).
This is how it looks on my map:
This image has been resized. Click this bar to view the full image. The original image is sized 1280x768 and weights 184KB.

This is the 3rd floor. With a elevator and maintenance. When a player wants to use the elevator but he hasn’t yet used any of the levers it won’t work. So he will have to use one of the levers before he will be send up or down.
This image has been resized. Click this bar to view the full image. The original image is sized 1280x768 and weights 182KB.

This is the 2nd floor. When you use the lever on the 3rd floor you will probable get teleported to the 2nd floor.
This image has been resized. Click this bar to view the full image. The original image is sized 1280x768 and weights 178KB.

This is the 1st floor. Notice it looks a little more “creepy” then the other two. This is because it is a floor where you only will get teleported to if you have all of the 4 levers in maintenance (first screenshot) in a correct position.

Here is the lever.lua I used for this script. Comments will be begin the coding with a “- -comment”


Code:
function onUse(cid, item, frompos, item2, topos)
if item.uid == 2000 then –Elevator lever (screen1)
queststatus = getPlayerStorageValue(cid,2000)- - if he has already used one of the levers in maintenance
if queststatus == -1 then - - if he hasn’t used them
if item.itemid == 1945 then –some simple text and movement of the lever
doTransformItem(item.uid, 1946)
doPlayerSendCancel(cid,"Nothing happends.")
else
doTransformItem(item.uid, 1945)
doPlayerSendCancel(cid,"The platform you are standing on shakes for a second.")
end
else - - if he has used one of the levers
if item.itemid == 1945 then - - if the lever is pulled east
doTransformItem(item.uid, 1946)
doPlayerSendCancel(cid,"You hear something move...")
else - - if the lever is pulled west (something happends)
doTransformItem(item.uid, 1945)
queststatus1 = getPlayerStorageValue(cid,2005) - - storage value of the 4 levers in the maintenance room. I didn’t want to look at the lever position because I felt everyone had to putt the levers in the right position.
queststatus2 = getPlayerStorageValue(cid,2006)
queststatus3 = getPlayerStorageValue(cid,2007)
queststatus4 = getPlayerStorageValue(cid,2008)
if queststatus1 == -1 and queststatus2 == -1 and queststatus3 == 1 and queststatus4 == -1 then - - if the position of the levers is so that you will get teleported to 1st floor
nplayer1pos = {x=273, y=433, z=11}
doSendMagicEffect(cid,2)
doTeleportThing(cid,nplayer1pos)
else - - if not you will get teleported to 2nd floor
nplayer1pos = {x=273, y=433, z=10}
doSendMagicEffect(cid,2)
doTeleportThing(cid,nplayer1pos)
end
end
end
elseif item.uid == 2001 or item.uid == 2002 then - - the elevator to get back to 3rd floor
if item.itemid == 1945 then
doTransformItem(item.uid, 1946)
else
doTransformItem(item.uid, 1945)
nplayer1pos = {x=273, y=433, z=9}
doSendMagicEffect(nplayer1pos,2)
doTeleportThing(cid,nplayer1pos)
end
elseif item.uid > 2004 and item.uid < 2009 then --switches for the elevator in the maintenance room
if item.uid == 2005 then
if item.itemid == 1945 then
doTransformItem(item.uid, 1946)
setPlayerStorageValue(cid,2005,1)
setPlayerStorageValue(cid,2000,1)
doPlayerSendCancel(cid,"You trigered something.")
else
doTransformItem(item.uid, 1945)
setPlayerStorageValue(cid,2005,-1)
end
elseif item.uid == 2006 then
if item.itemid == 1945 then
doTransformItem(item.uid, 1946)
setPlayerStorageValue(cid,2006,1)
setPlayerStorageValue(cid,2000,1)
doPlayerSendCancel(cid,"You trigered something.")
else
doTransformItem(item.uid, 1945)
setPlayerStorageValue(cid,2006,-1)
end
elseif item.uid == 2007 then
if item.itemid == 1945 then
doTransformItem(item.uid, 1946)
setPlayerStorageValue(cid,2007,1)
setPlayerStorageValue(cid,2000,1)
doPlayerSendCancel(cid,"You trigered something.")
else
doTransformItem(item.uid, 1945)
setPlayerStorageValue(cid,2007,-1)
end
else
if item.itemid == 1945 then
doTransformItem(item.uid, 1946)
setPlayerStorageValue(cid,2008,1)
setPlayerStorageValue(cid,2000,1)
doPlayerSendCancel(cid,"You trigered something.")
else
doTransformItem(item.uid, 1945)
setPlayerStorageValue(cid,2008,-1)
end
end
return 1
endSo with this code you’ve made a quiet advanced elevator script which can be part of a quest. Now for a second quest script. Creating pick holes!

If a person uses a pick I made the server carry out the pick.lua script. This is the pick.lua script.

Code:
function onUse(cid, item, frompos, item2, topos)
if topos.x == 209 and topos.y == 456 and topos.z == 12 then - - coordinates
doTransformItem(item2.uid,383) - - change to hole
else
return 0 - - return 0 means you get the message. This is not possible. (or something likewise)
end
return 1 - - return 1 means it has worked
endThis is a very simple code to use pick holes! And if you want to have more pick holes simply ad a elseif topos.x == … and so on.
However I haven’t found out how to make the hole decay, so it will return back to normal after an amount of time.

Someone asked me if it is possible to make readables. Yes it is. I worked this out once, but I lost the data of how. However I can give a good guess about how it will work.
doSetItemText(uid,"text")
With this function you can set the contents of for example an book, letters scrolls or other readables. uid is the unique id of the item of wich you want to change the text. Text is ofcourse the text you want to put in. However I noticed sometime you can only put in about 255 chars and not more. Don't know if every server has it like that. Also I believe if you put in "\n" this would be the same as an Enter (next line).

Author: Mindstorm

Related Articles
Open Tibia Server - creation
Open Tibia Server for absolute beginners
Ots map quests - otserv
Otserver - ot server general
Basic Tibia ots tutorials
Simple tutorials for Tibia 7.6
Making items on GM
Easy way to make a restarter
Raids


Previous article: Open Tibia Server - creation
Next article: Old Tibia features