• 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!

I'm here to learn, not steal and leave. (Please teach me masters.)

Ranyo13

ManCausingMayhem
Joined
Aug 22, 2009
Messages
981
Reaction score
38
Hello,
I'm writing this to request help explaining a hard and large script like this one I'm going to copy and paste, please if you got the time try to explain to me every line or at least tell me how to learn to script such large scripts, and make events scripts etc. I really want to learn scripting and be good at it to contribute to the community.
Code:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}

function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end
function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end
function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end
function onThink() npcHandler:onThink() end

function creatureSayCallback(cid, type, msg)
if(not npcHandler:isFocused(cid)) then
return false
end

local talkUser = NPCHANDLER_CONVBEHAVIOR == CONVERSATION_DEFAULT and 0 or cid

if(msgcontains(msg, 'prestige')) then
selfSay('Are you ready to prestige and start a new life?', cid)
talkState[talkUser] = 1
elseif(msgcontains(msg, 'yes') and talkState[talkUser] == 1) then
-------CONFIGS-------
local level = 717217
local cost = 0
------/CONFIGS-------
-----LOCALS-----
local id = getPlayerGUID(cid)
local name = getCreatureName(cid)
local vocation = getPlayerVocation(cid)
local storage = getCreatureStorage(cid, 85987)
----/LOCALS-----
if(getPlayerLevel(cid) >= level) then
if(doPlayerRemoveMoney(cid, cost) == TRUE) then
if(isInArray({1, 2, 3, 4, 5, 6, 7, 8}, vocation)) then
doCreatureSetStorage(cid, 85987, storage == -1 and 1 or storage + 1)
doRemoveCreature(cid)
db.executeQuery("UPDATE `players` SET `level` = 8, `experience` = 4200, `promotion` = 0 WHERE `id` ='"..id.."';")
db.executeQuery("UPDATE `players` SET `name` = '"..name.."' WHERE `id` ='"..id.."';")
else
selfSay('Please talk with Forgotten King and promote first.', cid)
talkState[talkUser] = 0
end
else
selfSay('You don\'t have enough money. You need to pay 1 gold coin to be rebirthed.', cid)
talkState[talkUser] = 0
end
else
selfSay('Only characters of level 717217 or higher can be rebirthed.', cid)
talkState[talkUser] = 0
end
elseif(msgcontains(msg, 'no') and talkState[talkUser] == 1) then
selfSay('Okey. Come back when you feel ready.', cid)
talkState[talkUser] = 0
end

return true
end

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
If you need help understanding the configs etc just ask.

4-Onlook- for yall that dont know what this is it basicly just adds this to when u look at a character
----Past the following script below in your Creaturescripts scripts folder, and save it as RebirthDescription.lua
Code:
Efunction onLook(cid, thing, position, lookDistance)
if(isPlayer(thing.uid) and thing.uid ~= cid and getCreatureStorage(thing.uid, 85987) ~= -1) then
doPlayerSetSpecialDescription(thing.uid, (getPlayerSex(thing.uid) == PLAYERSEX_FEMALE and ".\nShe" or ".\nHe") .. " has prestiged " .. getCreatureStorage(thing.uid, 85987) .. " " .. (getCreatureStorage(thing.uid, 85987) == 1 and "time" or "times"))
elseif(thing.uid == cid and getCreatureStorage(cid, 85987) ~= -1) then
local message = "You see yourself."
if(getPlayerFlagValue(cid, PLAYERFLAG_SHOWGROUPINSTEADOFVOCATION)) then
message = message .. " You are " .. getPlayerGroupName(cid) .. "."
elseif(getPlayerVocation(cid) ~= 0) then
message = message .. " You are a " .. getPlayerVocationName(cid):lower() .. "."
else
message = message .. " You have no vocation."
end

if(getPlayerNameByGUID(getPlayerPartner(cid), false, false) ~= nil) then
message = message .. " You are " .. (getPlayerSex(cid) == PLAYERSEX_FEMALE and "wife" or "husband") .. " of " .. getPlayerNameByGUID(getPlayerPartner(cid)) .. "."
end

if(getPlayerGuildId(cid) > 0) then
message = message .. " You are " .. (getPlayerGuildRank(cid) == "" and "a member" or getPlayerGuildRank(cid)) .. " of the " .. getPlayerGuildName(cid)
message = getPlayerGuildNick(cid) ~= "" and message .. " (" .. getPlayerGuildNick(cid) .. ")." or message .. "."
end

if(getPlayerFlagValue(cid, PLAYERCUSTOMFLAG_CANSEECREATUREDETAILS)) then
message = message .. "\nHealth: [" .. getCreatureHealth(cid) .. " / " .. getCreatureMaxHealth(cid) .. "], Mana: [" .. getCreatureMana(cid) .. " / " .. getCreatureMaxMana(cid) .. "]."
message = message .. "\nIP: " .. doConvertIntegerToIp(getPlayerIp(cid)) .. ", Client: " .. getClientVersion(cid) .. "."
end

if(getPlayerFlagValue(cid, PLAYERCUSTOMFLAG_CANSEEPOSITION)) then
message = message .. "\nPosition: [X: " .. position.x .. "] [Y: " .. position.y .. "] [Z: " .. position.z .. "]."
end

return false, doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, message .. " \nYou have prestiged " .. getCreatureStorage(cid, 85987) .. " " .. (getCreatureStorage(cid, 85987) == 1 and "time." or "times."))
end

return true
end
Code:
Efunction onLook(cid, thing, position, lookDistance)
if(isPlayer(thing.uid) and thing.uid ~= cid and getCreatureStorage(thing.uid, 85987) ~= -1) then
doPlayerSetSpecialDescription(thing.uid, (getPlayerSex(thing.uid) == PLAYERSEX_FEMALE and ".\nShe" or ".\nHe") .. " has prestiged " .. getCreatureStorage(thing.uid, 85987) .. " " .. (getCreatureStorage(thing.uid, 85987) == 1 and "time" or "times"))
elseif(thing.uid == cid and getCreatureStorage(cid, 85987) ~= -1) then
local message = "You see yourself."
if(getPlayerFlagValue(cid, PLAYERFLAG_SHOWGROUPINSTEADOFVOCATION)) then
message = message .. " You are " .. getPlayerGroupName(cid) .. "."
elseif(getPlayerVocation(cid) ~= 0) then
message = message .. " You are a " .. getPlayerVocationName(cid):lower() .. "."
else
message = message .. " You have no vocation."
end

if(getPlayerNameByGUID(getPlayerPartner(cid), false, false) ~= nil) then
message = message .. " You are " .. (getPlayerSex(cid) == PLAYERSEX_FEMALE and "wife" or "husband") .. " of " .. getPlayerNameByGUID(getPlayerPartner(cid)) .. "."
end

if(getPlayerGuildId(cid) > 0) then
message = message .. " You are " .. (getPlayerGuildRank(cid) == "" and "a member" or getPlayerGuildRank(cid)) .. " of the " .. getPlayerGuildName(cid)
message = getPlayerGuildNick(cid) ~= "" and message .. " (" .. getPlayerGuildNick(cid) .. ")." or message .. "."
end

if(getPlayerFlagValue(cid, PLAYERCUSTOMFLAG_CANSEECREATUREDETAILS)) then
message = message .. "\nHealth: [" .. getCreatureHealth(cid) .. " / " .. getCreatureMaxHealth(cid) .. "], Mana: [" .. getCreatureMana(cid) .. " / " .. getCreatureMaxMana(cid) .. "]."
message = message .. "\nIP: " .. doConvertIntegerToIp(getPlayerIp(cid)) .. ", Client: " .. getClientVersion(cid) .. "."
end

if(getPlayerFlagValue(cid, PLAYERCUSTOMFLAG_CANSEEPOSITION)) then
message = message .. "\nPosition: [X: " .. position.x .. "] [Y: " .. position.y .. "] [Z: " .. position.z .. "]."
end

return false, doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, message .. " \nYou have prestiged " .. getCreatureStorage(cid, 85987) .. " " .. (getCreatureStorage(cid, 85987) == 1 and "time." or "times."))
end

return true
end
Excuse my language and thanks in advance
 
Code:
if(getPlayerLevel(cid) >= level) then -- if getPlayerLevel (cid) searches for the players's level (the player who contacted the npc) and if it's more than or equal to the level of prestige then something will happen
if(doPlayerRemoveMoney(cid, cost) == TRUE) then -- searches if player has money.
if(isInArray({1, 2, 3, 4, 5, 6, 7, 8}, vocation)) then -- searches if he's in the vocations 1 --> 8, you can use this to make it only possible for a certain vocation to prestige.
doCreatureSetStorage(cid, 85987, storage == -1 and 1 or storage + 1) -- sets a storage.
doRemoveCreature(cid) -- removes the creature, i.e does /r on them
db.executeQuery("UPDATE `players` SET `level` = 8, `experience` = 4200, `promotion` = 0 WHERE `id` ='"..id.."';") -- demotes the player (if ED he becomes druid only), and makes him level 8
db.executeQuery("UPDATE `players` SET `name` = '"..name.."' WHERE `id` ='"..id.."';")
else
selfSay('Please talk with Forgotten King and promote first.', cid) -- not needed since u have the 8 vocations XD
talkState[talkUser] = 0
end
else
selfSay('You don\'t have enough money. You need to pay 1 gold coin to be rebirthed.', cid) -- if u dont have enough money u get this, notice that they are in order bottom to top from the functions above.
talkState[talkUser] = 0
end
else
selfSay('Only characters of level 717217 or higher can be rebirthed.', cid) -- self explanatory
talkState[talkUser] = 0
end
elseif(msgcontains(msg, 'no') and talkState[talkUser] == 1) then
selfSay('Okey. Come back when you feel ready.', cid) -- if player says no it gives him this message
talkState[talkUser] = 0
end

return true
end

pretty late here but I explained a few things, btw this is not a "big" script XD
 
doCreatureSetStorage(cid, 85987, storage == -1 and 1 or storage + 1) -- sets a storage.
^ Is the essence that needs explanation in details never understood the storages thing in any script which plays a vital role in most scripts. like why this id and when to be -1 +1 or 1
EDIT: thank you very much for the rest, and I hope u can explain more things later when u wake up maybe
 
Last edited:
Do you know the basics of LUA?
It sounds like you want to learn, but starting with a huge (& messy) script might not be the best idea.
Once again, I don't know how much you already know about LUA, but the best way to start is to study some simple scripts that come packed in TFS by default - such as:
  • 6 sided dice roll & how it transforms the item and sends that effect to the position of the dice
  • Study the machete script to learn a bit about arrays and how you can use and draw information from them.
  • preventWalk / pushback in movement scripts that pushes the player back to the tile where he came from
  • etc.
You can then go into the documentation and open the file called LUA_FUNCTIONS that is very helpful for beginners. It contains 90% of the functions in TFS and a lot of descriptions and small code snippets that describe how to use those functions.

The next step would be to take a look at which options you have to trigger your functions.
You have actions (when something with an attached aid/uid is used), creaturescripts (when something dies, logs in, logs out, advances in skill, prepares to die, etc.), movements (when something moves, either an item or a player from a position/slot to another position/slot), spells (when someone casts a spell configured in spells.xml), talkactions (when someone says a configured word or command), globalevents (when the server is starting, closing, when time passes while the server is running, etc.).

Now when you know all the different kinds of triggers for your scripts, you can imagine something. For example, a doll that gives you an addon when you use it, and start creating such a simple script by looking at the functions in LUA_FUNCTIONS and modifying them to fit your requirements in your action script for the doll.

Here is a great website where you can read up on anything lua related if you're looking to learn some new tricks (now we're talking about the language, syntax and mechanics), for example how to use tables/arrays, how to use loops, conditions and whatnot:

http://www.lua.org/pil/contents.html#P1

Here are some neat posts by OTLand users that can help you learn more about scripting in lua:

https://otland.net/threads/list-of-tutorials.180156/
https://otland.net/threads/beginner-scripters-dummy-proof.233921/
https://otland.net/threads/lua-understanding-storages.189075/
https://otland.net/threads/how-to-using-addevent.225292/

Take note, various server engines operate with slightly different versions of these same functions.
In TFS 1.0, some things are written a bit different from TFS 0.2.x or TFS 0.3.x.

Once you learn more, you can even make your own functions and use them in your server.

If you're already experienced, then, I suppose, you may disregard what I said as you probably know all of that, but eh, leaving this out here for anyone who might find it helpful.
 
Last edited:
^ Is the essence that needs explanation in details never understood the storages thing in any script which plays a vital role in most scripts. like why this id and when to be -1 +1 or 1
EDIT: thank you very much for the rest, and I hope u can explain more things later when u wake up maybe
By default, all storages are -1 you can then set a storage to whatever you want to represent your own meaning. So say you do a quest, and you want it to only a be a 1 time quest. You would use doCreatureSetStorage(cid, questId, 1) upon finishing the quest.

As a result of finishing a quest you may allow someone to access a new area. In order to see if a player finished the quest, you use if getCreatureStorage(cid, questId) == 1 then player may enter.
 
By default, all storages are -1 you can then set a storage to whatever you want to represent your own meaning. So say you do a quest, and you want it to only a be a 1 time quest. You would use doCreatureSetStorage(cid, questId, 1) upon finishing the quest.

As a result of finishing a quest you may allow someone to access a new area. In order to see if a player finished the quest, you use if getCreatureStorage(cid, questId) == 1 then player may enter.
always too quick xD
 
The site, is pretty much complicated for me, even the examples because my English is poor, other than that, thank you very much sir.

By default, all storages are -1 you can then set a storage to whatever you want to represent your own meaning. So say you do a quest, and you want it to only a be a 1 time quest. You would use doCreatureSetStorage(cid, questId, 1) upon finishing the quest.

As a result of finishing a quest you may allow someone to access a new area. In order to see if a player finished the quest, you use if getCreatureStorage(cid, questId) == 1 then player may enter.
Thanks I got it.
 
Will you explain this line for me please?
Code:
     if(fromPosition.x ~= CONTAINER_POSITION) then
and what does "~=" mean?

It's a relation operator (or in simpler words, a comparison). You can compare between two values using the following symbols:

something == something2 (is something equal to something2?)
something ~= something2 (is something different from something2?)
something <= something2 (is something equal to or lesser than something2?)
something >= something2 (is something equal to or greater than something2?)
something > something2 (is something greater than something2?)
something < something2 (is something lesser than something2?)

Here's an example of how you can use this:

local something = 5
local something2 = 8

if something ~= something2 then
doCreatureSay(cid, "Something and something2 are different values.")
else
doCreatureSay(cid, "Something and something2 are same values.")
end


 
It's a relation operator (or in simpler words, a comparison). You can compare between two values using the following symbols:

something == something2 (is something equal to something2?)
something ~= something2 (is something different from something2?)
something <= something2 (is something equal to or lesser than something2?)
something >= something2 (is something equal to or greater than something2?)
something > something2 (is something greater than something2?)
something < something2 (is something lesser than something2?)

Here's an example of how you can use this:

local something = 5
local something2 = 8

if something ~= something2 then
doCreatureSay(cid, "Something and something2 are different values.")
else
doCreatureSay(cid, "Something and something2 are same values.")
end

I'm amazed by your organized and "to the point" work, thanks a lot for the help, I got it.
Wish I was as professional as you are.
 
If there's one thing you need to understand that's more important than anything else when it goes for lua scripting or any other type of coding, it's this: You will spend far more time reading code than writing code, so whenever you write code, make sure it's clean, neat and organized. Maybe you'll acquire a team in the future and they need to read your code, you'll save a lot of time by being organized from the start.

For example, the code you posted is terrible. I don't even like looking at it the way that it is displayed.
 
If there's one thing you need to understand that's more important than anything else when it goes for lua scripting or any other type of coding, it's this: You will spend far more time reading code than writing code, so whenever you write code, make sure it's clean, neat and organized. Maybe you'll acquire a team in the future and they need to read your code, you'll save a lot of time by being organized from the start.

For example, the code you posted is terrible. I don't even like looking at it the way that it is displayed.
Couldn't agree more with you, will keep this advice in mind as long as I script. Tyvm.
 
I'm amazed by your organized and "to the point" work, thanks a lot for the help, I got it.
Wish I was as professional as you are.

You're welcome. If you take the nerve to overlook the excess amount of professional terminology, you'll find that the website I gave you is very useful and contains all of this same information, nicely formatted with examples. I've been using it whenever I needed some clarification on how some things in LUA are done.
 
You're welcome. If you take the nerve to overlook the excess amount of professional terminology, you'll find that the website I gave you is very useful and contains all of this same information, nicely formatted with examples. I've been using it whenever I needed some clarification on how some things in LUA are done.
I will keep that in mind, already bookmarked it. Thanks again.
 
Code:
local t, event = {
Id = 386,
pos = {x=989, y=998, z=7},
time = 5 * 60 * 1000
}
function onUse(cid, item, fromPosition, itemEx, toPosition)
if item.itemid == 1945 then
doRemoveItem (getTileItemById(t.pos, t.Id).uid)
event = addEvent(reset, t.time, toPosition)
doTransformItem(item.uid, 1946)
else
stopEvent(event)
reset(toPosition)
end
return true
end
event = addEvent(reset, t.time, toPosition)
stopEvent(event)
reset(toPosition)
WHAT THE HELL?
Explanation?
 
You can use addEvent to create an event (a function that is executed at a set time delay), and stopEvent to stop this function from executing while it's already in motion.

addEvent(function, delay, ... [parameters])

Some examples:

addEvent(function()
doCreatureSay(cid, "Three seconds have passed since I used this item.")
end, 3000)


Or, like this:

function saySomething(cid)
doCreatureSay(cid, "Three seconds have passed since I used this item")
end

addEvent(saySomething, 3000, cid)


//the parameter cid, that would usually go in a bracket next to the function name, is now added to addEvent as an extra parameter after function and delay.
 
This is a great thread, and I'm happy to see someone isn't just here to leech. :cool: Believe it or not, most of us started out as beggars. (I even looked through my first OtLand account and wow... :D). But what made us stand apart - and what allowed OpenTibia to evolve - was our willingness to learn. I eventually came to a point where asking for things got me nowhere, so I began learning and coding myself: trial and error. With that said, I'd like to make a tiny contribution to this thread:

Hopefully you are able to understand the following. :)


As you're coding, you should think about the most efficient way to write a proper piece of code. For example, if you want a player to be able to forge a new item (like a crafting system) with nice magic effects and messages, think about the process. What's the first step? You'll most likely want to remove something upon clicking. So, search for a function within the server (e.g. doRemoveItem) and place that among the first of executions within the code, before messages, magic effects, etc. But what if they don't have the item?! Good catch! You should put the check BEFORE everything else, because if he/she doesn't have it, it will react much faster to cancel the action as opposed to going throug the ENTIRE code first only to reach a "cancel" at the last moment. You also want to avoid putting tables (e.g. configs) inside the function or body of the script. o_O You can see what I'm speaking of here. No hard feelings, Limos.
heart.gif


I see a lot of code written improperly or "inefficiently." When it comes to performance, it's not a big deal, particularly for OpenTibia... But you do notice memory leaks occurring in large projects (e.g. real maps) when code is carelessly made. Either way, it's a good thing to "get into the habit" of doing. ;) Not only does it allow you to properly code (in an efficient manner) but it helps you learn how processes work, and also easily allows a more organized layout (as mentioned above).

Good luck.
 
Last edited:
Back
Top