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

Lua 10.77 Enchanting system

Jfrye

Mapper, trying to learn scripting
Joined
Jan 8, 2009
Messages
366
Solutions
5
Reaction score
86
Location
Mexico Missouri
I have been trying for hours to get a working Enchanting system on 10.77. I have the places in DPs setup so you walk through them, and teleport to a shrine, so you can enchant a small gem. The problem seems to be, that I cannot use a small gem on the shrine to make it become enchanted. When I use the small gem on the shrine, nothing happens. Do I need to set an actionID for the shrines?

Also, how do I setup a teleport near the shrines to teleport them back to the town they CAME from.
 
I have been trying for hours to get a working Enchanting system on 10.77. I have the places in DPs setup so you walk through them, and teleport to a shrine, so you can enchant a small gem. The problem seems to be, that I cannot use a small gem on the shrine to make it become enchanted. When I use the small gem on the shrine, nothing happens. Do I need to set an actionID for the shrines?

Also, how do I setup a teleport near the shrines to teleport them back to the town they CAME from.

post your script and tfs version
 
Actions.XML
Code:
<action fromid="2146" toid="2147" script="XXX/enchanting.lua" />
<action fromid="2149" toid="2150" script="XXX/enchanting.lua" />
<action fromid="7759" toid="7762" script="XXX/enchanting.lua" />

Edit the XXX to fit your server folders

Enchanting.lua (In actions folder)
Code:
local config = {
manaCost = 300,
soulCost = 2,
}
local spheres = {
[7759] = {3, 7},
[7760] = {1, 5},
[7761] = {2, 6},
[7762] = {4, 8}
}
local enchantableGems = {2147, 2146, 2149, 2150}
local enchantableItems = {2383, 7383, 7384, 7406, 7402, 2429, 2430, 7389, 7380, 2454, 2423, 2445, 7415, 7392, 2391, 2544, 8905}
local enchantingAltars = {
{7504, 7505, 7506, 7507},
{7508, 7509, 7510, 7511},
{7516, 7517, 7518, 7519},
{7512, 7513, 7514, 7515}
}
local enchantedGems = {7760, 7759, 7761, 7762}
local enchantedItems = {
[2383] = {7744, 7763, 7854, 7869},
[7383] = {7745, 7764, 7855, 7870},
[7384] = {7746, 7765, 7856, 7871},
[7406] = {7747, 7766, 7857, 7872},
[7402] = {7748, 7767, 7858, 7873},
[2429] = {7749, 7768, 7859, 7874},
[2430] = {7750, 7769, 7860, 7875},
[7389] = {7751, 7770, 7861, 7876},
[7380] = {7752, 7771, 7862, 7877},
[2454] = {7753, 7772, 7863, 7878},
[2423] = {7754, 7773, 7864, 7879},
[2445] = {7755, 7774, 7865, 7880},
[7415] = {7756, 7775, 7866, 7881},
[7392] = {7757, 7776, 7867, 7882},
[2391] = {7758, 7777, 7868, 7883},
[2544] = {7840, 7839, 7850, 7838},
[8905] = {8906, 8907, 8909, 8908}
}
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
if isInArray({33268, 33269}, toPosition.x) and toPosition.y == 31830 and toPosition.z == 10 and player:getStorageValue(Storage.ElementalSphere.QuestLine) > 0 then
if not isInArray(spheres[item.itemid], player:getVocation():getId()) then
return false
elseif isInArray({7915, 7916}, target.itemid) then
player:say('Turn off the machine first.', TALKTYPE_MONSTER_SAY)
return true
else
player:setStorageValue(Storage.ElementalSphere.MachineGemCount, math.max(1, player:getStorageValue(Storage.ElementalSphere.MachineGemCount) + 1))
toPosition:sendMagicEffect(CONST_ME_PURPLEENERGY)
item:transform(item.itemid, item.type - 1)
return true
end
end
if item.itemid == 2147 and target.itemid == 2342 then
target:transform(2343)
target:decay()
item:remove(1)
toPosition:sendMagicEffect(CONST_ME_MAGIC_RED)
return true
end
if item.itemid == 7760 and isInArray({9934, 10022}, target.itemid) then
target:transform(9933)
item:remove(1)
toPosition:sendMagicEffect(CONST_ME_MAGIC_RED)
return true
end
if isInArray(enchantableGems, item.itemid) then
local subtype = item.type
if subtype == 0 then
subtype = 1
end
local mana = config.manaCost * subtype
if player:getMana() < mana then
player:sendCancelMessage(RETURNVALUE_NOTENOUGHMANA)
return false
end
local soul = config.soulCost * subtype
if player:getSoul() < soul then
player:sendCancelMessage(RETURNVALUE_NOTENOUGHSOUL)
return false
end
local targetId = table.find(enchantableGems, item.itemid)
if not targetId or not isInArray(enchantingAltars[targetId], target.itemid) then
return false
end
player:addMana(-mana)
player:addSoul(-soul)
item:transform(enchantedGems[targetId])
player:addManaSpent(mana * configManager.getNumber(configKeys.RATE_MAGIC))
player:getPosition():sendMagicEffect(CONST_ME_HOLYDAMAGE)
return true
end
if item.itemid == 7761 and isInArray({9949, 9954}, target.itemid) then
target:transform(target.itemid - 1)
target:decay()
item:remove(1)
toPosition:sendMagicEffect(CONST_ME_MAGIC_GREEN)
return true
end
if isInArray(enchantedGems, item.itemid) then
if not isInArray(enchantableItems, target.itemid) then
fromPosition:sendMagicEffect(CONST_ME_POFF)
return false
end
local targetId = table.find(enchantedGems, item.itemid)
if not targetId then
return false
end
local subtype = target.type
if not isInArray({2544, 8905}, target.itemid) then
subtype = 1000
end
target:transform(enchantedItems[target.itemid][targetId], subtype)
target:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
item:remove(1)
return true
end
return false
end

Source: ORTS Repo @ https://github.com/orts/server/tree/master/data/actions
 
Ok, so I can now use the shrines to enchant small gems, but with this script, there are a couple Issues.

First off, any vocation can enchant gems. I would like it to be like real tibia, where sorcs can only enchant rubys and amethysts, and druids only doings sapphires and emeralds.

Secondly, if I have a stack of 5 gems, it will automatically enchant all 5 gems at one time. Is there anyway to change it so that it will just take 1 of the 5 and enchant them 1 by 1? Also, after it enchants the gems, they will not auto stack. If anyone has any way to fix my script, that would be awesome.


I am using TFS 1.1, and the script is as follows.
Code:
function onUse(cid, item, fromPosition, itemEx, toPosition)

--CONFIG
local config = {
mana = 300,
soul = 2,
messNotEnoughSoul = "You don't have enough soul points.",
messNotEnoughMana = "You don't have enough mana points.",
effect = 39 --you can test effects with !z command (ex. !z 23)
}
--/CONFIG

local array = { [7759] = 8907, [7760] = 8906, [7761] = 8909, [7762] = 8908 }
local altars = {{7516, 7517, 7518, 7519}, {7504, 7505, 7506, 7507}, {7512, 7513, 7514, 7515}, {7508, 7509, 7510, 7511}}
local gems = {2149, 2147, 2150, 2146}
local enchantedGems = {7761, 7760, 7762, 7759}
local weapons = {
-- {earth, fire, energy, ice}
[2430] = {7860, 7750, 7875, 7769},
[2423] = {7864, 7754, 7879, 7773},
[7406] = {7857, 7747, 7872, 7766},
[7383] = {7855, 7745, 7870, 7764},
[7384] = {7856, 7746, 7871, 7765},
[7415] = {7866, 7756, 7881, 7775},
[7380] = {7862, 7752, 7877, 7771},
[7402] = {7858, 7784, 7873, 7767},
[2391] = {7868, 7758, 7883, 7777},
[7389] = {7861, 7751, 7876, 7770},
[2383] = {7854, 7744, 7869, 7763},
[7392] = {7867, 7757, 7882, 7776},
[2429] = {7859, 7749, 7874, 7768},
[2445] = {7865, 7755, 7880, 7774},
[2408] = {7863, 7753, 7878, 7772}
}


if itemEx.itemid == 8905 and isInArray(enchantedGems, item.itemid) then
for k, v in pairs(array) do
if item.itemid == k then
doTransformItem(itemEx.uid, v)
doRemoveItem(item.uid, 1)
doSendMagicEffect(fromPosition, config.effect)
return TRUE
end
end
elseif isInArray(gems, item.itemid) == TRUE then
for i=1, #gems do
if isInArray(altars, itemEx.itemid) == TRUE and item.itemid == gems then
if getPlayerMana(cid) >= config.mana then
if getPlayerSoul(cid) >= config.soul then
doRemoveItem(item.uid, 1)
doPlayerAddItem(cid, enchantedGems, 1)
doPlayerAddSoul(cid,-config.soul)
doPlayerAddMana(cid,-config.mana)
else
doPlayerSendTextMessage(cid, MESSAGE_EVENT_ORANGE, config.messNotEnoughSoul)
doSendMagicEffect(fromPosition, 2)
return FALSE
end
else
doPlayerSendTextMessage(cid, MESSAGE_EVENT_ORANGE, config.messNotEnoughMana)
doSendMagicEffect(fromPosition, 2)
return FALSE
end
doSendMagicEffect(toPosition, config.effect)
return TRUE
end
end

else
for k, v in pairs(weapons) do
if itemEx.itemid == k then
for i=1, #enchantedGems do
if item.itemid == enchantedGems then
doTransformItem(itemEx.uid, v, 1000)
doRemoveItem(item.uid, 1)
doSendMagicEffect(fromPosition, config.effect)
return TRUE
end
end
end
end
end
return TRUE
end
 
Last edited:
Use code tags, the icon is right next to the disk icon in the editor, most of us don't like reading code without it, and try formatting the code so its legible. (indentation)
 
@Codex NG this is exactly how the code is in the server. Now that I know how to post using code tags, Ill do that from now on.

Also this is the code I found for movements. The code was found with the previous code used in actions.
Code:
local positions = {
    [25007] = {x=121, y=261, z=7},
    [25008] = {x=121, y=261, z=7},
}

function onStepIn(cid, item, oldPos)
    if isPlayer(cid) == TRUE then
        local newPos = positions[item.actionid]
        if newPos then
            doSendMagicEffect(oldPos, CONST_ME_POFF)
            doTeleportThing(cid, newPos, TRUE)
            doSendMagicEffect(newPos, CONST_ME_TELEPORT)
        end
    end
    return TRUE
end

Since there are multiple altars to step into for the player to get to the shrine, I add the actionID followed by cordinates, but when I put a mystic flame near the shrine, how to I code that for the player to return to the altar they came from? Like in real Tibia, if I use the altar in Thais temple, I will go back to Thais temple, and if I use the altar in Ab, I will go to the shrine, and then return to the altar in Ab.

Bump. Any help is appreciated.
 
Last edited by a moderator:
Script to enter the alter room
Code:
local positions = {
    [25007] = {x=121, y=261, z=7},
    [25008] = {x=121, y=261, z=7},
}

local base = 18000

function savePosition(cid, pos, base)
    setPlayerStorageValue(cid, base+1, pos.x)
    setPlayerStorageValue(cid, base+2, pos.y)
    setPlayerStorageValue(cid, base+3, pos.z)
end

function onStepIn(cid, item, pos, fromPos)
    if isPlayer(cid) then
        local newPos = positions[item.actionid]
        if newPos then
            -- store the old position
            savePosition(cid, fromPos, base)
            doSendMagicEffect(fromPos, CONST_ME_POFF)
            doTeleportThing(cid, newPos, TRUE)
            doSendMagicEffect(newPos, CONST_ME_TELEPORT)
        end
    end
    return TRUE
end

Script to use to leave the alter room
Code:
local base = 18000
function getSavedPosition(cid, base)
    local pos = {}
    pos.x = getPlayerStorageValue(cid, base+1)
    pos.y = getPlayerStorageValue(cid, base+2)
    pos.z = getPlayerStorageValue(cid, base+3)
    return pos
end

function onStepIn(cid, item, pos, fromPos)
    local savedPos = getSavedPosition(cid, base)
    if isPlayer(cid) then
        doSendMagicEffect(fromPos, CONST_ME_POFF)
        doTeleportThing(cid, savedPos, TRUE)
        doSendMagicEffect(savedPos, CONST_ME_TELEPORT)
    end
    return TRUE
end
 
Last edited:
@Codex NG, im a little confused here. What should I set the actionID of the mystic flame to? Currently, I was using 25007 and 25008 as different altar locations within the temples. The old script showed the same locations, but that was before I got it saved.


I have an alter 1 at 373, 257, 6 and altar 2 at 741, 143, 6. My biggest thing is that once I get the player to the shrine located near 908, 154, 15, is that I would like them to go back to the altar that they originally went into. So they went into altar 1, enchanted some gems, and then return near altar 1 location/temple.

Also, for local defaultPos, do I need to add multiple lines here since there are multiple altars, or do I need to make a separate script for each town?

@Codex NG, do I juse add an actionID of my choice to the mystical flame, and then add it as a StepIn in movements?


attempt to call global 'savePlayerPostions' a nil value. is the error that pops up as I try to enter the altar.
 
Last edited by a moderator:
@Codex NG, do I juse add an actionID of my choice to the mystical flame, and then add it as a StepIn in movements?


attempt to call global 'savePlayerPostions' a nil value. is the error that pops up as I try to enter the altar.
Yea I was renaming the functions and forgot to do it in the stepin, its been updated
 
@Codex NG. You are the man. Thank you for helping me fix this. It all works as it should now for that part.

Would you mind taking a look at this script though? Any vocation can enchant the gems. Also, it will try to enchant the gems in a stack instead of 1 by 1. It also will not auto stack the enchanted gems after it is finished.
Code:
unction onUse(cid, item, frompos, item2, topos)

local gems = {2146, 2147, 2149, 2150}
local egems = {7759, 7760, 7761, 7762}
local altars = {{7508, 7509, 7510, 7511}, {7504, 7505, 7506, 7507}, {7516, 7517, 7518, 7519}, {7512, 7513, 7514, 7515}}
local weapons = {2383, 7384, 7389, 7406, 7402, 2429, 2430, 2435, 7380, 2454, 2423, 2445, 7415, 7392, 2391, 2544, 8905}
local eweapons = {{7763, 7744, 7854, 7869}, {7765, 7746, 7856, 7871}, {7770, 7751, 7861, 7876}, {7766, 7747, 7857, 7872}, {7767, 7748, 7858, 7873}, {7768, 7749, 7859, 7874}, {7769, 7750, 7860, 7875}, {7770, 7751, 7861, 7876}, {7771, 7752, 7862, 7877}, {7772, 7753, 7863, 7878}, {7773, 7754, 7864, 7879}, {7774, 7755, 7865, 7880}, {7775, 7756, 7866, 7881}, {7776, 7757, 7867, 7882}, {7777, 7758, 7868, 7883}, {7839, 7840, 7838, 7850}, {8907, 8906, 8909, 8908}}


local type = item.type
if type == 0 then
type = 1
end

local mana = 300 * type
local soul = 2 * type

if isInArray(gems, item.itemid)== TRUE then
for aa=1, #gems do
if item.itemid == gems[aa] then
a=aa
end
end
if isInArray(altars[a], item2.itemid)== TRUE then
if getPlayerMana(cid) >= mana and getPlayerSoul(cid) >= soul then
doTransformItem(item.uid,egems[a])
doPlayerAddMana(cid,-mana)
doPlayerAddSoul(cid,-soul)
doSendMagicEffect(frompos,39)
else
doPlayerSendCancel(cid,"You dont have mana or soul points.")
end
else
return 2
end

elseif isInArray(egems, item.itemid)== TRUE then
for bb=1, #egems do
if item.itemid == egems[bb] then
b=bb
end
end
if isInArray(weapons, item2.itemid)== TRUE then
for cc=1, #weapons do
if item2.itemid == weapons[cc] then
c=cc
end
end
doTransformItem(item2.uid,eweapons[c][b],1000)
doSendMagicEffect(frompos,39)
doRemoveItem(item.uid,1)
else
doPlayerSendCancel(cid,"You can't enchanted this.")
end
else
return 0
end
return 1
end

If there is any chance you could take a look at this, I would greatly appreciate it.

Also how hard would it be to add a random teleport option to the movement script you did above? Like if I wanted to add 2 different fire shrines, how hard would it be to script in a random teleport option? If its gonna be too difficult, then I will not worry about it.

Also, once I have enchanted gems, they will not enchant a weapon. I just get the message that you cannot use this item.
 
Last edited:
@Codex NG. You are the man. Thank you for helping me fix this. It all works as it should now for that part.

Would you mind taking a look at this script though? Any vocation can enchant the gems. Also, it will try to enchant the gems in a stack instead of 1 by 1. It also will not auto stack the enchanted gems after it is finished.
Code:
unction onUse(cid, item, frompos, item2, topos)

local gems = {2146, 2147, 2149, 2150}
local egems = {7759, 7760, 7761, 7762}
local altars = {{7508, 7509, 7510, 7511}, {7504, 7505, 7506, 7507}, {7516, 7517, 7518, 7519}, {7512, 7513, 7514, 7515}}
local weapons = {2383, 7384, 7389, 7406, 7402, 2429, 2430, 2435, 7380, 2454, 2423, 2445, 7415, 7392, 2391, 2544, 8905}
local eweapons = {{7763, 7744, 7854, 7869}, {7765, 7746, 7856, 7871}, {7770, 7751, 7861, 7876}, {7766, 7747, 7857, 7872}, {7767, 7748, 7858, 7873}, {7768, 7749, 7859, 7874}, {7769, 7750, 7860, 7875}, {7770, 7751, 7861, 7876}, {7771, 7752, 7862, 7877}, {7772, 7753, 7863, 7878}, {7773, 7754, 7864, 7879}, {7774, 7755, 7865, 7880}, {7775, 7756, 7866, 7881}, {7776, 7757, 7867, 7882}, {7777, 7758, 7868, 7883}, {7839, 7840, 7838, 7850}, {8907, 8906, 8909, 8908}}


local type = item.type
if type == 0 then
type = 1
end

local mana = 300 * type
local soul = 2 * type

if isInArray(gems, item.itemid)== TRUE then
for aa=1, #gems do
if item.itemid == gems[aa] then
a=aa
end
end
if isInArray(altars[a], item2.itemid)== TRUE then
if getPlayerMana(cid) >= mana and getPlayerSoul(cid) >= soul then
doTransformItem(item.uid,egems[a])
doPlayerAddMana(cid,-mana)
doPlayerAddSoul(cid,-soul)
doSendMagicEffect(frompos,39)
else
doPlayerSendCancel(cid,"You dont have mana or soul points.")
end
else
return 2
end

elseif isInArray(egems, item.itemid)== TRUE then
for bb=1, #egems do
if item.itemid == egems[bb] then
b=bb
end
end
if isInArray(weapons, item2.itemid)== TRUE then
for cc=1, #weapons do
if item2.itemid == weapons[cc] then
c=cc
end
end
doTransformItem(item2.uid,eweapons[c][b],1000)
doSendMagicEffect(frompos,39)
doRemoveItem(item.uid,1)
else
doPlayerSendCancel(cid,"You can't enchanted this.")
end
else
return 0
end
return 1
end

If there is any chance you could take a look at this, I would greatly appreciate it.

Also how hard would it be to add a random teleport option to the movement script you did above? Like if I wanted to add 2 different fire shrines, how hard would it be to script in a random teleport option? If its gonna be too difficult, then I will not worry about it.

Also, once I have enchanted gems, they will not enchant a weapon. I just get the message that you cannot use this item.
Why don't I just hook up your donation shop to my paypal account this way when people donate the money goes to me.. don't worry i'll save you some cash for hosting :)

See how outrageous and ridiculous that sounds?

I don't mind helping resolve some problems but i won't build your server for you.

The whole point of otland is to learn new skill sets, what you get from this community is a free education in game / web development.. the only place you can use lazyness & begging is on the welfare line.
 
Last edited:
Alright, well thanks for the help. Even though these two scripts don't build a server, thanks again for the help given to me and the rest of the community.
 
I was trying to add a Random spawn to this for multiple locations

Code:
local positions = {
    [3001] = {x=72, y=53, z=15},
    [3001] = {x=807, y=1635, z=7}
}
local base = 18000

function savePosition(cid, pos, base)
    setPlayerStorageValue(cid, base+1, pos.x)
    setPlayerStorageValue(cid, base+2, pos.y)
    setPlayerStorageValue(cid, base+3, pos.z)
end

function onStepIn(cid, item, pos, fromPos)
    if isPlayer(cid) then
        local newPos = positions[item.actionid]
        if newPos then
            -- store the old position
            savePosition(cid, fromPos, base)
            doSendMagicEffect(fromPos, CONST_ME_POFF)
            local rand = math.random(1, #pos)
            doTeleportThing(cid, newPos[rand], TRUE)
            doSendMagicEffect(newPos, CONST_ME_TELEPORT)
        end
    end
    return TRUE
end

I dont think I added it right. Any input @Codex NG , since you got the original working awesome.
 
You cannot do this:
local positions = {
[3001] = {x=72, y=53, z=15},
[3001] = {x=807, y=1635, z=7}
}

It must be done something like this:
Code:
local positions = {
    [3001] = {
        {x=72, y=53, z=15},
        {x=807, y=1635, z=7}
    }
}
 
Im gonna bump this thread bc I still have a small issue with this code.

The multiple random teleport locations are working great. I can step into the place at a temple, and it will take me to 2 different places at random, which is what I was trying to acheive. The problem now is, that when you step into the place at the temple, it will not send the teleport magic effect as you step through the magic fields to enter the shrine location. If that doesnt make sense I can try to explain it better.

Code:
local positions = {
    [3001] = {
        {x=72, y=53, z=15},
        {x=805, y=1637, z=7}
    }
}
local base = 18000

function savePosition(cid, pos, base)
    setPlayerStorageValue(cid, base+1, pos.x)
    setPlayerStorageValue(cid, base+2, pos.y)
    setPlayerStorageValue(cid, base+3, pos.z)
end

function onStepIn(cid, item, pos, fromPos)
    if isPlayer(cid) then
        local newPos = positions[item.actionid]
        local rand = math.random(1, #newPos)
        if newPos then
            -- store the old position
            savePosition(cid, fromPos, base)
            doSendMagicEffect(fromPos, CONST_ME_TELEPORT)
            doTeleportThing(cid, newPos[rand], TRUE)
            doSendMagicEffect(newPos, CONST_ME_TELEPORT)
        end
    end
    return TRUE
end

Again, this will not send the teleport magicc effect when stepping into the "archways" at the temple.


I will post a code below for a different shrine, that DOES send magic effect when stepping in the "archway" but that code does NOT have multiple locations yet.
Code:
local positions = {
    [3003] = {x=96, y=65, z=7}
}
local base = 18000

function savePosition(cid, pos, base)
    setPlayerStorageValue(cid, base+1, pos.x)
    setPlayerStorageValue(cid, base+2, pos.y)
    setPlayerStorageValue(cid, base+3, pos.z)
end

function onStepIn(cid, item, pos, fromPos)
    if isPlayer(cid) then
        local newPos = positions[item.actionid]
        if newPos then
            -- store the old position
            savePosition(cid, fromPos, base)
            doSendMagicEffect(fromPos, CONST_ME_POFF)
            doTeleportThing(cid, newPos, TRUE)
            doSendMagicEffect(newPos, CONST_ME_TELEPORT)
        end
    end
    return TRUE
end
This does send magic effect, but only has 1 location.

EDIT Also, once at the shrine, I still cannot enchant a gem. So if anyone has a working script for that, that would be awesome.
 
Back
Top