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

Understood, thanks a ton.:oops:

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.
I'm not that bad at English haha, however, it isn't my mother language.
I used to be a leecher to be honest back when I created this otland's account in 2009-2012 but it got me to nowhere.
Thank you for your contribution to this thread and yeah, I hope that I reach the same scripting level as yours one day.:D


I edited the script by myself no errors but it ain't working
Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)
if item.itemid == 1945 then
doRemoveItem (getTileItemById({x=989, y=998, z=7}, 387).uid)
event = addEvent(reset, {5 * 60 * 1000}, toPosition)
doTransformItem(item.uid, 1946)
else
stopEvent(event)
reset(toPosition)
end
return true
end
Wow this one worked!!:eek::eek:
Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)
if item.itemid == 1945 then
doRemoveItem (getTileItemById({x=989, y=998, z=7}, 387).uid)
doTransformItem(item.uid, 1946)
end
return true
end
 
Last edited:
Good! Yeah, just start small, get it right, and then start adding things. ;)
I got this fully working, 0 errors.
I cheated the local reset thingy and the events part from a very old script here though :(
And deleted tables just as you said (From what I understood).
Code:
local function reset(p)
doTransformItem(getTileItemById(p, 1946).uid, 1945)
doCreateItem(387, 1, {x=989, y=998, z=7})
doSendMagicEffect({x=989, y=998, z=7}, 34)
end
function onUse(cid, item, fromPosition, itemEx, toPosition)
if item.itemid == 1945 then
doRemoveItem (getTileItemById({x=989, y=998, z=7}, 387).uid)
doTransformItem(item.uid, 1946)
doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You hear a noise from the west.")
addEvent(reset, 2 * 60 * 1000, toPosition)
else
stopEvent(event)
reset(toPosition)
end
return true
end
Though, I don't understand what does the initial "P" do.
 
I got this fully working, 0 errors.
I cheated the local reset thingy and the events part from a very old script here though :(
And deleted tables just as you said (From what I understood).
Code:
local function reset(p)
doTransformItem(getTileItemById(p, 1946).uid, 1945)
doCreateItem(387, 1, {x=989, y=998, z=7})
doSendMagicEffect({x=989, y=998, z=7}, 34)
end
function onUse(cid, item, fromPosition, itemEx, toPosition)
if item.itemid == 1945 then
doRemoveItem (getTileItemById({x=989, y=998, z=7}, 387).uid)
doTransformItem(item.uid, 1946)
doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You hear a noise from the west.")
addEvent(reset, 2 * 60 * 1000, toPosition)
else
stopEvent(event)
reset(toPosition)
end
return true
end
Though, I don't understand what does the initial "P" do.

The 'p' parameter is only used in 2 lines, line 1 and line 2.
In line: local function reset(p), you're creating/defining a function with the name reset, and a parameter 'p'. At this point, you're basically sayin:

"Okay, when I use this function reset somewhere, I'm gonna put in a parameter here instead of this 'p', and my parameter will replace every 'p' inside this function once I use it that way."

So in line 2:
doTransformItem(getTileItemById(p, 1946).uid, 1945)

This parameter 'p' is used as the first parameter of the getTileItemById function.
This function requires its first parameter to be a coordinate array (position), which basically means that this 'p' is meant to be a position when you use the reset function, so you'd call it like:

reset({x = 100, y= 100, z=7})

or, in your case, it is toPosition - which is a position parameter obtained from your main onUse function and usually points to the position you're using your item onto (with crosshair) or position at which the item currently is (without crosshair).
 
The 'p' parameter is only used in 2 lines, line 1 and line 2.
In line: local function reset(p), you're creating/defining a function with the name reset, and a parameter 'p'. At this point, you're basically sayin:

"Okay, when I use this function reset somewhere, I'm gonna put in a parameter here instead of this 'p', and my parameter will replace every 'p' inside this function once I use it that way."

So in line 2:
doTransformItem(getTileItemById(p, 1946).uid, 1945)

This parameter 'p' is used as the first parameter of the getTileItemById function.
This function requires its first parameter to be a coordinate array (position), which basically means that this 'p' is meant to be a position when you use the reset function, so you'd call it like:

reset({x = 100, y= 100, z=7})

or, in your case, it is toPosition - which is a position parameter obtained from your main onUse function and usually points to the position you're using your item onto (with crosshair) or position at which the item currently is (without crosshair).
Let's say the parameter "p" is useless in this script then? Correct me if Im wrong.
Oh wait, it gets the position of the lever, then uses "it" (THE POSITION) to transform the lever into another ID in 2 minutes right?
 
Let's say the parameter "p" is useless in this script then? Correct me if Im wrong.
Oh wait, it gets the position of the lever, then uses "it" (THE POSITION) to transform the lever into another ID in 2 minutes right?

It's not useless. The letter 'p' is just the name the author chose to give to the parameter, and it's used in the following way:

- Function reset is defined to have a single parameter named 'p', and it uses the 'p' parameter as a position for the function on line 2
- A position parameter toPosition is passed to the function reset when it's used, effectively making use of 'p'

Basically, this is what happens with your current script:
When reset(toPosition) is called, it activates the reset function, and if you wrote out what it activates that way, it would look like this:

-- calling reset(toPosition): --

doTransformItem(getTileItemById(toPosition, 1946).uid, 1945)
doCreateItem(387, 1, {x=989, y=998, z=7})
doSendMagicEffect({x=989, y=998, z=7}, 34)


-----------------------------------------------------
 
It's not useless. The letter 'p' is just the name the author chose to give to the parameter, and it's used in the following way:

- Function reset is defined to have a single parameter named 'p', and it uses the 'p' parameter as a position for the function on line 2
- A position parameter toPosition is passed to the function reset when it's used, effectively making use of 'p'

Basically, this is what happens with your current script:
When reset(toPosition) is called, it activates the reset function, and if you wrote out what it activates that way, it would look like this:

-- calling reset(toPosition): --

doTransformItem(getTileItemById(toPosition, 1946).uid, 1945)
doCreateItem(387, 1, {x=989, y=998, z=7})
doSendMagicEffect({x=989, y=998, z=7}, 34)


-----------------------------------------------------
I got it! Thanks shadow you're a legend.
 
@Ranyo13 Love how you misspelled Shadowsong on ur signature :p

Ontopic: We want you to show us ur scripting knowledge :D
Fixed signature, aaaaand... Ask me for a normal script and I can try and do it.

EDIT: COMMON! :p Gimme an idea and I will try to script it, I ran out of ideas lmao, Everything is already scripted out there on the resources board.
 
Last edited:
Love that you created this thread.
Whehter you like it or not I shall accompany you on this learning jouney :D
Awesome advice and guidance so far. Really liking and appreciate how supportive all the sensei's have been
 
Love that you created this thread.
Whehter you like it or not I shall accompany you on this learning jouney :D
Awesome advice and guidance so far. Really liking and appreciate how supportive all the sensei's have been
Yep, it's really fun and relaxing to be in a very good community like this one.
I'm enjoying it here tbh.
 
Back
Top