• 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!
  • 2026 staff recruitment is open! Check it out and consider applying!

[1.0 Lua] Need Help with Errors and New Scripts! (Detailed)

Eldin

Eldin Projects
Joined
Jun 12, 2008
Messages
1,334
Reaction score
615
Location
Sweden
Greets fellow Scripters!
After being away from OpenTibia for about 2 years, I honestly got alot to Catch up on.
Therefor, I call upon you who go the knowledge to lead me! :rolleyes:

My first process, to even get the server started, was actually harder then I thought, but finally made it.
From what I learned, the new TFS 1.0 will be the future, so thats what I will work with.

Im "converting" everything I did 2 years ago to get the server up-to-date and to get everything working that I already fixed for the server 2 years ago. I used 0.2 versions back then but now Believe 1.0 will support the most 0.3+ / 0.4+ functions (or soon will).

--------------------------------------------------------------

ACTIONS

*StatusBook Solved - Thanks Evil Hero!

CREATURESCRIPTS

This script should send a text in your logg to simply inform you on what spell you get upon Advance.
I found it and it seems to be for 0.3.7, but I can't see why it shouldn't work.

CreatureScripts.xml
Code:
<event type="advance" name="SpellsInfo" script="SpellsInfo.lua"/>

SpellsInfo.lua
Code:
local s = { --SETUP
    repeatAfterDeath = false, -- true -> player will always get the msg at lvlup | false -> player will only get the 1st time the gets the new level
    detailedInfo = true, -- true -> player will get name, words, mana & mana% info of spells | false -> player will only get the name and the words of the spells
-- storage below is where the newlevel will be stored ONLY IF YOU USE repeatAfterDeath
    Storage = 15000,
    messageType = 'channel', -- options: 'popUp' or 'channel'
--this one below only used if messageType = channel
    channelClass = MESSAGE_STATUS_CONSOLE_ORANGE
    }
function onAdvance(cid, skill, oldlevel, newlevel)
    if skill ~= SKILL__LEVEL or not s.repeatAfterDeath and getCreatureStorage(cid, s.Storage) >= newlevel then
        return true
    end
    local t = {}
    for i = 0, getPlayerInstantSpellCount(cid) - 1 do
        local spell = getPlayerInstantSpellInfo(cid, i)
        if(spell.level ~= 0) and spell.level == newlevel then
            if(spell.manapercent > 0) then
                spell.mana = spell.manapercent .. '%'
            end
            table.insert(t, spell)
        end
    end
    table.sort(t, function(a, b) return a.level < b.level end)
    local text, prevLevel = '', -1
    for i, spell in ipairs(t) do
        local line = ''
        if(prevLevel ~= spell.level) then
            if(i ~= 1) then
                line = '\n'
            end
            line = line .. 'You have just advanced to level '..newlevel..' and learned new spells!\n'
            prevLevel = spell.level
        end
        text = text ..line..' ['..spell.name..'] "'..spell.words..'" '..(s.detailedInfo and 'Mana['..spell.mana..']'..(spell.mlevel > 0 and ' ML['..spell.mlevel..']' or '') or '')..'\n'
    end
    if text == '' then
        return true
    end
    doCreatureSetStorage(cid, s.Storage, newlevel)
    if s.messageType == 'popUp' then
        doShowTextDialog(cid, 2175, text)
    elseif s.messageType == 'channel' then
        doPlayerSendTextMessage(cid, s.channelClass, text)
    end
    return true
end

LOGG ERROR:
Code:
None

MOVEMENTS


TALKACTIONS

This script will show a highscore list, using uniform and ZnoteAAC if that helps.

TalkAction.xml
Code:
<talkaction words="!highscores" script="Highscores.lua"/>

Highscores.lua
Code:
local highscores = {
['fist'] = {0},
['club'] = {1},
['sword'] = {2},
['axe'] = {3},
['distance'] = {4},
['shield'] = {5},
['fish'] = {6},
['magic'] = {7},
['level'] = {8},
}
function onSay(cid, words, param)
local msg = string.lower(param)
    if highscores[msg] ~= nil then
        str = getHighscoreString((highscores[msg][1]))
    else
        str = getHighscoreString((8))
    end
        doShowTextDialog(cid,6500, str)
    return TRUE
end

LOGG ERROR:
Code:
Lua Script Error: [Action Interface]
data/talkactions/script/Highscores.lua :onSay
data/talkactions/script/Highscores.lua :22: atempt to call global 'getHighscoreString' <a nil value>
stack traceback:
[C]: in function 'getHighscoreString'
data/talkactions/script/Highscores.lua :22: in function <data/talkactions/script/Highscores.lua :16:>

NPCS

POSTED ONE A FEW POSTS DOWN AS IT WAS TOO BIG HERE!

SPELLS:

My intention is the make the Magic Wall Rune show time ticks above it, 20, 19, 18 etc until its gone.

Code:
local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY)
setCombatParam(combat, COMBAT_PARAM_CREATEITEM, 1497)
function onCastSpell(cid, var)
function MagicWallTime(pos, delay)
doSendAnimatedText(pos, delay, 145)
if delay ~= 1 then addEvent(MagicWallTime, 1000, pos, delay -1) end
end

local pos,duration = variantToPosition(var),20
MagicWallTime(pos,duration)
return doCombat(cid, combat, var)
end

LOGG ERROR:
Code:
The error pointed towards "doSendAnimatedText" and I changed it to: doCreatureSay instead.
I had no error but the MagicWall wont show tics. Anyone? :)

TALKING SIGNS FOR TFS 1.0, MAYBE SOMETHING THAT I COULD COMBINE FOR M-WALL?
Code:
local t = {
  {"test", {x=1000, y=1000, z=7}, CONST_ME_TELEPORT},
  {"test2", {x=1001, y=1000, z=7}, CONST_ME_GIFT_WRAPS},
  {"test3", {x=1002, y=1000, z=7}, CONST_ME_POFF}
}

function onThink(interval)
  local people = getOnlinePlayers()
  if #people == 0 then
  return true
  end

  for i = 1, #t do
  local v = t[i]
  doCreatureSay(people[1], v[1], TALKTYPE_ORANGE_1, false, 0, v[2])
  doSendMagicEffect(v[2], v[3])
  end
  return true
end


OTHER/BIGGER:

MAIN SCRIPT IDEA FOR THE SERVER:
Here is my idea, feel free to bring new ones/change my thinking.
The server will be a Race against a Race, but I'll explain with normal Vocs to make it easy.

*I will create an NPC that sells you a certain item in each town for each voc. (Don't need help here)
*I'll also create a kind of "pedestal/sacrifice place" where you will place this item. (Don't need help here)

So what I need is a script that will let you drop the X item on this X, Y, Z place and you have simply "Conquered" that "area".

(A lever or whatever if the drop function wont work or is too hard to make)

The "Conquer" part can be 2 things unless you got a better idea:

1. Give every Vocation (example Druids AND Sorcerers) faster HP and MANA regeneration in the entire game. (Must be able to set how much). If someone then puts Another item, one for Knights AND Paladins, THEY will INSTEAD get the bonus!
2. Give every vocation hunting in that area from X, Y, Z to X, Y, Z a higher XP rate/Regeneration.
(I prefer nr 1 but Im happy with anything that can make you "Conquer" an area, it will be race against race)

Also:
-Delay: The outcome can't be changed within 30 Minutes to prevent mass drop and simply give an ownership for some time.
-Broadcast: If the X item was the Druids AND Sorcerer Item, it will send a Broadcast like "The Druids and Sorcerers now Conquered the Plains of Havoc and will get a higher HP/Mana Regeneration" and Vice-Versa for Knights AND Paladin Item. (Or something like that, would like this text to appear White on the screen like Raids do)
-Note that I will put 5-10 places like this on the map so Races want to Conquer areas!

The Bonus can be whatever fits and will work. The best thing would be alittle faster hp/mana regeneration to prevent any abuse.
Can also be skills, armor or whatever if thats what you can do!
Would be cool with some kind of cool effect when dropping the item, if possible!
Just tell me if anything is unclear!


-----------------------------------------------------------------
I will probably be adding/editing/deleting during any progress.
Thanks in Advance!

Kind Regards,
Eldin.
 
Last edited:
1st problem:
Code:
getPlayerGuildName(cid).."\n Your Rank In The Guild Is: \n"..getPlayerGuildRank(cid)
I'm pretty sure that they cause the problem, as if the character has no guild it'll throw an error, so try to remove them and test again to confirm if they are the cause.

2nd problem:
It seems that 1.0 is missing the getHighscoreString function or it's named different.
Just look through your sources to confirm.
 
1st problem solved thanks to Evil Hero.
Will check the 2nd any min, sadly have to fix a thing.

Kind Regards,
Eldin.
 
NPC Problem:

This NPC should be giving a person a "Buff" if they are the right Vocation for the right amount of Cash. It shows no error but simply wont proceed. I tryed for hours and edited, changed etc to find the NPC giving a distance buff to simply not giving anything at all again. It stopped answer when I was supposed to say "Yes" and get the Buff. I tryed to go back to where it actually worked with only Distance Buff, but that didn't work either, therefor, I posted the original script to see if ANYONE may see any error at all that could cause this. Important for my Elfs to get those Buffs aswell as Humans getting others. I will have to split the script into 2 parts as its too big, but its THE SAME SCRIPT IN ONE.


Even found the base script:
http://otland.net/threads/buffer.131246/
Also note that I got my "Human Edition" to work perfectly, something happend during my Elf Edit.

Elathriel.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Elathriel" script="data/npc/scripts/AbDendrielBuffer.lua" walkinterval="2000" floorchange="0">
    <health now="100" max="100"/>
    <look type="64" head="69" body="0" legs="69" feet="0" addons="3"/>

    <parameters>
        <parameter key="message_greet" value="{Nature} is Power!" />
        <parameter key="module_keywords" value="1" />
        <parameter key="keywords" value="nature" />
        <parameter key="keyword_reply1" value="As an Elf, you have the power of nature within you. I can show you how to use it, ask me for {help} any time." />
    </parameters>
</npc>[/PHP]

AbDendrielBuffer.lua
[PHP]local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

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

-- Buff Config beginning --

-- configs
local config = {
    storage = 77700,
    value = 1,
}
money = 500
invisibleseconds = 3600
magicshieldseconds = 3600
regeseconds = 3600
speedseconds = 3600
skillsseconds = 3600
skillsupgrade = {}
skillsupgrade['distance'] = 15
skillsupgrade['ml'] = 10
-- end configs

-- Configs of buffs

local conditionMagic = createConditionObject(CONDITION_ATTRIBUTES)
setConditionParam(conditionMagic, CONDITION_PARAM_BUFF, true)
setConditionParam(conditionMagic, CONDITION_PARAM_TICKS, skillsseconds * 1000)
setConditionParam(conditionMagic, CONDITION_PARAM_STAT_MAGICLEVEL, skillsupgrade['ml'])

local combatInvisible = createConditionObject(CONDITION_INVISIBLE)
setConditionParam(combatInvisible, CONDITION_PARAM_BUFF, true)
setConditionParam(combatInvisible, CONDITION_PARAM_TICKS, invisibleseconds*1000)

local conditionDistance = createConditionObject(CONDITION_ATTRIBUTES)
setConditionParam(conditionDistance, CONDITION_PARAM_BUFF, true)
setConditionParam(conditionDistance, CONDITION_PARAM_TICKS, skillsseconds*1000)
setConditionParam(conditionDistance, CONDITION_PARAM_SKILL_DISTANCE, skillsupgrade['distance'])

local combatUtamo = createConditionObject(CONDITION_MANASHIELD)
setConditionParam(combatUtamo, CONDITION_PARAM_BUFF, true)
setConditionParam(combatUtamo, CONDITION_PARAM_TICKS, magicshieldseconds*1000)

local conditionRege = createConditionObject(CONDITION_REGENERATION)
setConditionParam(conditionRege, CONDITION_PARAM_BUFF, true)
setConditionParam(conditionRege, CONDITION_PARAM_TICKS, regeseconds*1000)
setConditionParam(conditionRege, CONDITION_PARAM_HEALTHGAIN, 5)
setConditionParam(conditionRege, CONDITION_PARAM_HEALTHTICKS, 2000)

local conditionspeed = createConditionObject(CONDITION_HASTE)
setConditionParam(conditionspeed, CONDITION_PARAM_BUFF, true)
setConditionParam(conditionspeed, CONDITION_PARAM_TICKS, speedseconds*1000)
setConditionFormula(conditionspeed, 1.0, -86, 1.0, -86)
 
Last edited:
CONTINUE, SAME SCRIPT

Code:
-- Configs of buffs

function magicl(cid, message, keywords, parameters, node)
    local guid = getPlayerGUID(cid)

    if not npcHandler:isFocused(cid) then
        return false
    end

    if(getPlayerVocation(cid) == 7) == true and getPlayerStorageValue(cid, config.storage) == -1 then
        if getPlayerMoney(cid) >= 500 then
            doPlayerRemoveMoney(cid, 500)
            doAddCondition(cid, conditionMagic)
            npcHandler:say('Well done, your Magic level has increased by 10 for 1 Hour.', cid)
            setPlayerStorageValue(cid, config.storage, config.value)     
            addEvent(db.executeQuery, skillsseconds * 1000, "UPDATE `player_storage` SET `key` = " .. config.storage .. ", `value` = -1 WHERE `player_id` = " .. guid .. " LIMIT 1;")
        else
            npcHandler:say('Im sorry, I forgot to tell you that I need 500 Gold to help you. Its cheap afterall.', cid)
        end
    else
        npcHandler:say('Good choise, but only Elf Aracanists are mentaly strong for this.', cid)
    end
end

function invisible(cid, message, keywords, parameters, node)
    local guid = getPlayerGUID(cid)

    if not npcHandler:isFocused(cid) then
        return false
    end

    if(getPlayerVocation(cid) == 6) == true then elseif(getPlayerVocation(cid) == 7) == true and getPlayerStorageValue(cid, config.storage) == -1 then
        if getPlayerMoney(cid) >= 500 then
            doPlayerRemoveMoney(cid, 500)
            npcHandler:say('Well done, you will stay invisible for 1 Hour.', cid)
            doAddCondition(cid, combatInvisible)
            setPlayerStorageValue(cid, config.storage, config.value)     
            addEvent(db.executeQuery, invisibleseconds * 1000, "UPDATE `player_storage` SET `key` = " .. config.storage .. ", `value` = -1 WHERE `player_id` = " .. guid .. " LIMIT 1;")
        else
            npcHandler:say('Im sorry, I forgot to tell you that I need 500 Gold to help you. My supplies are not cheap.', cid)
        end
    else
        npcHandler:say('You are too weak.', cid)
    end
end

function distance(cid, message, keywords, parameters, node)
    local guid = getPlayerGUID(cid)

    if not npcHandler:isFocused(cid) then
        return false
    end

    if(getPlayerVocation(cid) == 6) == true then elseif(getPlayerVocation(cid) == 7) == true and getPlayerStorageValue(cid, config.storage) == -1 then
        if getPlayerMoney(cid) >= 500 then
            doPlayerRemoveMoney(cid, 500)
                doAddCondition(cid, conditionDistance)
            npcHandler:say('Well done, your Distance fighting has increased by 10 for 1 Hour.', cid)
            setPlayerStorageValue(cid, config.storage, config.value)     
            addEvent(db.executeQuery, skillsseconds * 1000, "UPDATE `player_storage` SET `key` = " .. config.storage .. ", `value` = -1 WHERE `player_id` = " .. guid .. " LIMIT 1;")
        else
            npcHandler:say('Im sorry, I forgot to tell you that I need 500 Gold to help you. My supplies are not cheap.', cid)
        end
    else
        npcHandler:say('You are too weak.', cid)
    end
end

function magicshield(cid, message, keywords, parameters, node)
    local guid = getPlayerGUID(cid)

    if not npcHandler:isFocused(cid) then
        return false
    end

    if(getPlayerVocation(cid) == 7) == true and getPlayerStorageValue(cid, config.storage) == -1 then
        if getPlayerMoney(cid) >= 500 then
            doPlayerRemoveMoney(cid, 500)
                  doAddCondition(cid, combatUtamo)
            npcHandler:say('Well done, you will have Mana Shield for 1 Hour.', cid)
            setPlayerStorageValue(cid, config.storage, config.value)     
            addEvent(db.executeQuery, magicshieldseconds * 1000, "UPDATE `player_storage` SET `key` = " .. config.storage .. ", `value` = -1 WHERE `player_id` = " .. guid .. " LIMIT 1;")
        else
            npcHandler:say('Im sorry, I forgot to tell you that I need 500 Gold to help you. My supplies are not cheap.', cid)
        end
    else
        npcHandler:say('Good choise, but only Elf Aracanists are mentaly strong for this', cid)
    end
end

function regener(cid, message, keywords, parameters, node)
    local guid = getPlayerGUID(cid)

    if not npcHandler:isFocused(cid) then
        return false
    end

    if(getPlayerVocation(cid) == 6) == true then elseif(getPlayerVocation(cid) == 7) == true and getPlayerStorageValue(cid, config.storage) == -1 then
        if getPlayerMoney(cid) >= 500 then
            doPlayerRemoveMoney(cid, 500)
                  doAddCondition(cid, conditionRege)
            npcHandler:say('Well done, your HP will regenerate faster for 1 Hour.', cid)
            setPlayerStorageValue(cid, config.storage, config.value)     
            addEvent(db.executeQuery, regeseconds * 1000, "UPDATE `player_storage` SET `key` = " .. config.storage .. ", `value` = -1 WHERE `player_id` = " .. guid .. " LIMIT 1;")
        else
            npcHandler:say('Im sorry, I forgot to tell you that I need 500 Gold to help you. My supplies are not cheap.', cid)
        end
    else
        npcHandler:say('You are too weak.', cid)
    end
end

function speed(cid, message, keywords, parameters, node)
    local guid = getPlayerGUID(cid)

    if not npcHandler:isFocused(cid) then
        return false
    end

    if(getPlayerVocation(cid) == 6) == true then elseif(getPlayerVocation(cid) == 7) == true and getPlayerStorageValue(cid, config.storage) == -1 then
        if getPlayerMoney(cid) >= 500 then
            doPlayerRemoveMoney(cid, 500)
                doAddCondition(cid, conditionSpeed)
            npcHandler:say('Well done, your speed has increased for 1 Hour.', cid)
            setPlayerStorageValue(cid, config.storage, config.value)     
            addEvent(db.executeQuery, speedseconds * 1000, "UPDATE `player_storage` SET `key` = " .. config.storage .. ", `value` = -1 WHERE `player_id` = " .. guid .. " LIMIT 1;")
        else
            npcHandler:say('Im sorry, I forgot to tell you that I need 500 Gold to help you. My supplies are not cheap.', cid)
        end
    else
        npcHandler:say('You are too weak.', cid)
    end
end
-- Buff Config End --

keywordHandler:addKeyword({'help'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = "I can help you increase your {distance}, {magic level}, {regeneration}, {invisibility}, {magic shield} and {speed}."})

local node1 = keywordHandler:addKeyword({'magic level'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to increase your magic level for a certain time?'})
    node1:addChildKeyword({'yes'}, magicl, {npcHandler = npcHandler, onlyFocus = true, reset = true})
    node1:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'May the Nature be with you, come back when you are ready.', reset = true})

local node2 = keywordHandler:addKeyword({'invisibility'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to be invisible for a certain time?'})
    node2:addChildKeyword({'yes'}, invisible, {npcHandler = npcHandler, onlyFocus = true, reset = true})
    node2:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'May the Nature be with you, come back when you are ready.', reset = true})

local node3 = keywordHandler:addKeyword({'distance'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to increase your distance skills for a certain time?'})
    node3:addChildKeyword({'yes'}, distance, {npcHandler = npcHandler, onlyFocus = true, reset = true})
    node3:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'May the Nature be with you, come back when you are ready.', reset = true})

local node4 = keywordHandler:addKeyword({'magic shield'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to receive a mana shield for a certain time?'})
    node4:addChildKeyword({'yes'}, magicshield, {npcHandler = npcHandler, onlyFocus = true, reset = true})
    node4:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'May the Nature be with you, come back when you are ready.', reset = true})

local node5 = keywordHandler:addKeyword({'regeneration'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to increase your HP regeneration for a certain time?'})
    node5:addChildKeyword({'yes'}, regener, {npcHandler = npcHandler, onlyFocus = true, reset = true})
    node5:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'May the Nature be with you, come back when you are ready.', reset = true})

local node6 = keywordHandler:addKeyword({'speed'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to increase your speed for a certain time?'})
    node6:addChildKeyword({'yes'}, speed, {npcHandler = npcHandler, onlyFocus = true, reset = true})
    node6:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'May the Nature be with you, come back when you are ready.', reset = true})

npcHandler:addModule(FocusModule:new())

LOGG ERROR:
Code:
None
 
Last edited:
ALSO:

Does anyone know if 1.0 Supports (or maybe will support?) CreatureScripts like:
preparedeath
kill
combat


Im as for example trying to add 2 scripts: (I got both scripts if someone would like to look)
<event type="kill" name="BonusExp" script="BonusExp.lua>
<event type="kill" name="KilledMonstersCounter" script="MonsterCounter.lua"/>

The "BonusExp" would give a certain Bonus if someone is killing a bug at as for example lvl 1-5, this would make people willing to hunt in the "right" areas.
The "KilledMonsterCounter" will simply keep in mind how many "Bugs" "Dragons" etc you have killed to show you in the chat-channel or such after each kill.

preparedeath would be good aswell as combat, unless my ideas can be solved anyway, but good to know ^^

Kind Regards,
Eldin.
 
Changed the PHP to CODE, tell me if you prefer to look at the scripts at PHP instead.
Updated info and status.

Kind Regards,
Eldin.
 
Consider adding this at end of compat.lua, could be useful:
Code:
getThingFromPos = getThingfromPos
getThingPosition = getThingPos
table.find = function(table, value)
   for i, v in pairs(table) do
     if v == value then
       return i
     end
   end
   return nil
end

string.trim = function (str)
 return str:gsub("^%s*(.-)%s*$", "%1")
end

string.explode = function (str, sep, limit)
if(type(sep) ~= 'string' or isInArray({tostring(str):len(), sep:len()}, 0)) then
   return {}
end

 local i, pos, tmp, t = 0, 1, "", {}
 for s, e in function() return string.find(str, sep, pos) end do
  tmp = str:sub(pos, s - 1):trim()
  table.insert(t, tmp)
  pos = e + 1

  i = i + 1
  if(limit ~= nil and i == limit) then
  break
  end
 end

 tmp = str:sub(pos):trim()
 table.insert(t, tmp)
 return t
end
 
Back
Top