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

Lua Runes with Talkactions [TFS 1.2]

Ramirow

Veteran OT User
Joined
Aug 22, 2009
Messages
584
Solutions
15
Reaction score
301
Location
Argentina
YouTube
ramirogrant
I'm facing a weird problem now and I don't know how to address it.
The script is supposed to do the following:
Check if player is knight/elite knight and terminates execution.
Check then if player is Sorcerer and can conjure the rune.
Check if it is Druid and can conjure the rune.
And check if it is Paladin and can conjure the rune.

No problems with Sorcerer or Druid's checks, they work flawlessly.
The issue arises with Paladin's, they can cast all spells marked with the var 'usable = 3' which is only used for Druid/Sorcerer spells they share.
But I don't see how it's possible, it may be a dumb error, but I can't seem to find it..

I know this script could be written better, I was just experimenting!

Code:
local exhaust = Condition(CONDITION_SPELLCOOLDOWN)
exhaust:setParameter(CONDITION_PARAM_TICKS, (configManager.getNumber(configKeys.EX_ACTIONS_DELAY_INTERVAL) + 500))

-- Runes Table.
-- 'Usable' var. stands for: 1 - sorcerer only, 2 - druid only, 3 - sor/druid, 4 - paladin only and 5 -- stands for sor/druid/pala
local runes = {
{name = "adura gran", runeID = 2265, runeAmount = 1, manaCost = 120, levelReq = 15, soul = 2, usable = 2},
{name = "adori min vis", runeID = 2287, runeAmount = 10, manaCost = 120, levelReq = 15, soul = 1, usable = 3},
{name = "adori mas flam", runeID = 2304, runeAmount = 4, manaCost = 530, levelReq = 30, soul = 3, usable = 1},
{name = "adito grav", runeID = 2261, runeAmount = 3, manaCost = 120, levelReq = 17, soul = 2, usable = 5},
{name = "adori san", runeID = 2295, runeAmount = 5, manaCost = 350, levelReq = 27, soul = 3, usable = 4}
}

local noSoul = "You do not have enough soul points."
local noBlank = "You need a blank rune to cast this spell."
local noMana = "You do not have enough mana."
local noVoc = "Your vocation cannot use this spell."

function onSay(player, words, param)
local voc = player:getVocation():getId()

if player:getCondition(CONDITION_SPELLCOOLDOWN) then
   player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_YOUAREEXHAUSTED))
   player:getPosition():sendMagicEffect(CONST_ME_POFF)
   return false
end

if isInArray({4, 8}, voc) then
   player:sendTextMessage(MESSAGE_STATUS_SMALL, noVoc)
   player:getPosition():sendMagicEffect(CONST_ME_POFF)
   return true
end

for i=1,#runes,1 do
   if runes[i].name == string.lower((words.." "..param)) then
   local noLvl = "You need level " .. (runes[i].levelReq) .. " to conjure this rune."
     if isInArray({1,5}, voc) and runes[i].usable == 1 or runes[i].usable == 3 or runes[i].usable == 5 then
       if player:getLevel() >= runes[i].levelReq then
         if player:getMana() >= runes[i].manaCost then
           if player:getSoul() >= runes[i].soul then
             if player:removeItem(2260, 1) then
               player:addMana(-(runes[i].manaCost))
               player:addManaSpent(runes[i].manaCost)
               player:addSoul(-(runes[i].soul))
               player:addItem(runes[i].runeID, runes[i].runeAmount)
               player:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
               player:addCondition(exhaust)
               player:say(runes[i].name, TALKTYPE_MONSTER_SAY)
               return false
             else
               player:sendTextMessage(MESSAGE_STATUS_SMALL, noBlank)
               player:getPosition():sendMagicEffect(CONST_ME_POFF)
               return
             end
           else
             player:sendTextMessage(MESSAGE_STATUS_SMALL, noSoul)
             player:getPosition():sendMagicEffect(CONST_ME_POFF)
             return
           end
         else
           player:sendTextMessage(MESSAGE_STATUS_SMALL, noMana)
           player:getPosition():sendMagicEffect(CONST_ME_POFF)
           return
         end
       else
         player:sendTextMessage(MESSAGE_STATUS_SMALL, noLvl)
         player:getPosition():sendMagicEffect(CONST_ME_POFF)
         return
   end
end
     if isInArray({2,6}, voc) and runes[i].usable == 2 or runes[i].usable == 3 or runes[i].usable == 5 then
       if player:getLevel() >= runes[i].levelReq then
         if player:getMana() >= runes[i].manaCost then
           if player:getSoul() >= runes[i].soul then
             if player:removeItem(2260, 1) then
               player:addMana(-(runes[i].manaCost))
               player:addManaSpent(runes[i].manaCost)
               player:addSoul(-(runes[i].soul))
               player:addItem(runes[i].runeID, runes[i].runeAmount)
               player:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
               player:addCondition(exhaust)
               player:say(runes[i].name, TALKTYPE_MONSTER_SAY)
               return false
             else
               player:sendTextMessage(MESSAGE_STATUS_SMALL, noBlank)
               player:getPosition():sendMagicEffect(CONST_ME_POFF)
               return
             end
           else
             player:sendTextMessage(MESSAGE_STATUS_SMALL, noSoul)
             player:getPosition():sendMagicEffect(CONST_ME_POFF)
             return
           end
         else
           player:sendTextMessage(MESSAGE_STATUS_SMALL, noMana)
           player:getPosition():sendMagicEffect(CONST_ME_POFF)
           return
         end
       else
         player:sendTextMessage(MESSAGE_STATUS_SMALL, noLvl)
         player:getPosition():sendMagicEffect(CONST_ME_POFF)
         return
   end
       end
   if isInArray({3,7}, voc) and runes[i].usable == 4 or runes[i].usable == 5 then
       if player:getLevel() >= runes[i].levelReq then
         if player:getMana() >= runes[i].manaCost then
           if player:getSoul() >= runes[i].soul then
             if player:removeItem(2260, 1) then
               player:addMana(-(runes[i].manaCost))
               player:addManaSpent(runes[i].manaCost)
               player:addSoul(-(runes[i].soul))
               player:addItem(runes[i].runeID, runes[i].runeAmount)
               player:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
               player:addCondition(exhaust)
               player:say(runes[i].name, TALKTYPE_MONSTER_SAY)
               return false
             else
               player:sendTextMessage(MESSAGE_STATUS_SMALL, noBlank)
               player:getPosition():sendMagicEffect(CONST_ME_POFF)
               return
             end
           else
             player:sendTextMessage(MESSAGE_STATUS_SMALL, noSoul)
             player:getPosition():sendMagicEffect(CONST_ME_POFF)
             return
           end
         else
           player:sendTextMessage(MESSAGE_STATUS_SMALL, noMana)
           player:getPosition():sendMagicEffect(CONST_ME_POFF)
           return
         end
       else
         player:sendTextMessage(MESSAGE_STATUS_SMALL, noLvl)
         player:getPosition():sendMagicEffect(CONST_ME_POFF)
         return
   end
       end
   else
     return true
   end
   end
   return true
end
 
i didnt know you could fetch the words from the variant in 1.2, that makes it a bit easier :)
when i was trying it out in 0.3.6 it didnt pass the words in any way though
I don't have a 0.3.6 server setup so i can't test the var table, but I am sure if you dig deep enough you will find the string table since heal friend uses the same argument as the 1.2 script i wrote.

Code:
    <instant name="Heal Friend" words="exura sio" lvl="18" mana="140" prem="1" aggressive="0" needtarget="1" params="1" exhaustion="2000" needlearn="0" event="script" value="healing/heal friend.lua">
        <vocation id="2"/>
        <vocation id="6"/>
    </instant>

The params = "1", indicates that the var has a string index
 
if i use params="1" and pass it with a spell like this
Code:
<instant name="conjure" words="adori" lvl="0" mana="0" params="1" exhaustion="2000" needlearn="0" event="script" value="support/adito.lua">
</instant>
that means i have to have 1 function for each of the first words, since i cant identify that inside the function, and the player would also have to cast all spells in the form of adori "~~
this would mean you need one function for each of the first words available as far as i can see

print_r(var) for a spell with params returns
Code:
[10/05/2016 15:37:49] table: 0F1C3328 {
[10/05/2016 15:37:49]   [string] => "k"
[10/05/2016 15:37:49]   [type] => 4
[10/05/2016 15:37:49] }
where string is whats after ", which unfortunately doesnt really help, since the first word still isnt passed
 
if i use params="1" and pass it with a spell like this
Code:
<instant name="conjure" words="adori" lvl="0" mana="0" params="1" exhaustion="2000" needlearn="0" event="script" value="support/adito.lua">
</instant>
that means i have to have 1 function for each of the first words, since i cant identify that inside the function, and the player would also have to cast all spells in the form of adori "~~
this would mean you need one function for each of the first words available as far as i can see
Indeed.
 
if i cast exura sio "zothion
var.string is "zothion" in both 0.3.6 and 1.2 for me, neither actually passes the actual spell words... :(
 
what? it works exactly like it does for you, aka it passes whats after the " sign, so in ur case "adori gran mort"
it does not pass the entire string as in "conjure "adori gran mort", which is what i was hoping for :p
right now i can say "conjure adori blank" to conjure a blank rune, but the ideal scenario would be saying just "adori blank" and having it pass the entire string (normal spell words and param), so you can just have one big table with all the info, but as far as i can see to do it like that you'd need to have one function for each of the first words, e.g "adori", "adevo" etc, and then concatenate that with param inside the function (but that would require several nearly identical scripts..)
 
what? it works exactly like it does for you, aka it passes whats after the " sign, so in ur case "adori gran mort"
it does not pass the entire string as in "conjure "adori gran mort", which is what i was hoping for :p
conjure is the spell words, just like you would cast any normal spell, what the script i wrote does is allows you to use 1 spell for anything you want to conjure up, i don't need to set cool downs or whatever because you can configure that in the xml, the example i gave in xml is barebones.

Just configure the table to what you want to create.

No point in including the spell words.
 
yes, i had it like that at first, but the guy who requested the script specifically wanted the normal words e.g just "adori vita vis" to conjure an sd, not "conjure adori vita vis", other than that, this way is definitely superior though, since you can add literally anything you want into the spells table, instead of having to add a talkaction with the first word and the rest into the table :)
 
Do this right please: http://pastebin.com/vzUULF85

Folder:
uIwmrYs.png

Output: http://pastebin.com/SrZQHfDv

Just remove all conjure tags and put that in the place.
 
Last edited:
Code:
local exhaustTime = 1000
local blank = 2260

local exhaust = Condition(CONDITION_EXHAUST)
exhaust:setParameter(CONDITION_PARAM_TICKS, exhaustTime)

local runes = {
    ["adori blank"] = {runeID = 2260, runeAmount = 1, blankAmount = 0, manaCost = 20, levelReq = 8, soul = 0, vocations = {1,2,3,4,5,6,7,8}},
    ["adori vita vis"] = {runeID = 2268, runeAmount = 3, blankAmount = 1, manaCost = 200, levelReq = 200, soul = 0, vocations = {1, 2, 3}},
    ["adori vis"] = {runeID = 2311, runeAmount = 15, blankAmount = 1, manaCost = 200, levelReq = 200, soul = 0, vocations = {1, 2, 3}}
}

local function conjuration(player, t, word)

end

function onSay(player, words, param)
    if(player:getCondition(CONDITION_EXHAUST)) then
        doPlayerSendDefaultCancel(player, RETURNVALUE_YOUAREEXHAUSTED)
        return false
    end
 
    local cast = string.lower(words.." "..param)
    local voc = getPlayerVocation(player)
    local errorMessage = nil
 
    if runes[cast] then
        if isInArray(runes[cast].vocations, voc) then
            if player:getLevel() >= runes[cast].levelReq then
                if player:getMana() >= runes[cast].manaCost then
                    if player:getSoul() > runes[cast].soul then
                        if doPlayerRemoveItem(player, blank, runes[cast].blankAmount)then
                            doPlayerAddMana(player, -(runes[cast].manaCost))
                            doPlayerAddItem(player, runes[cast].runeID, runes[cast].runeAmount)
                            doPlayerAddManaSpent(player, runes[cast].manaCost)
                            doPlayerAddSoul(player, runes[cast].soul)
                            doCreatureSay(played, cast, TALKTYPE_ORANGE_1)
                            doSendMagicEffect(getCreaturePosition(player), CONST_ME_MAGIC_BLUE)
                            doPlayerSendTextMessage(player, MESSAGE_STATUS_CONSOLE_BLUE, "You conjured "..(runes[cast].runeAmount).." "..(getItemName(runes[cast].runeID)).." runes.")
                        else
                            errorMessage = "You do not have enough blank runes.."
                        end
                    else
                        errorMessage = "You do not have enough soul."
                    end
                else
                    errorMessage = "You do not have enough mana."
                end
            else
                errorMessage = "You do not have the required level for this. You need level "..(runes[cast].levelReq).."."
            end
        else
            errorMessage = "Your vocation cannot cast that spell."
        end 
    else
        errorMessage = "That conjuration spell does not exist."
    end
    if errorMessage then
        errorMessage = errorMessage.."\n--- Valid conjuration spells for you are ---" 
        for pos,val in pairs(runes) do
            if isInArray(runes[pos].vocations, voc) then
                errorMessage = errorMessage.."\n"..pos.." --- which costs "..(runes[pos].manaCost).." mana, "..(runes[pos].soul).." soul and gives you "..(runes[pos].runeAmount).." "..(getItemName(runes[pos].runeID))..""
                if runes[pos].runeAmount > 1 then
                    errorMessage = errorMessage.."s."
                else
                    errorMessage = errorMessage.."."
                end
            end
        end
        doSendMagicEffect(getCreaturePosition(player), CONST_ME_POFF)
        doPlayerSendTextMessage(player, MESSAGE_STATUS_CONSOLE_BLUE, errorMessage)
    end
    player:addCondition(exhaust) 
    return false
end
that works for me in 1.1
i dont have a 1.2 rev on computer but there shouldnt be any different, tell me if you get an error :)

@StreamSide i meant 0.4 -> 1.2 as in converting a script from 0.4 to 1.2 isnt much difference, i know 1.2 is far superior (although i use 1.1 cus im 2 lazy to get 1.2 :()

Hello Zothion and Ramirow,

I've been trying to figure out a way to implement a enchant weapon talkaction in my server and I realised I could try to tweak your code in order make it work for me.
I hope that you guys don't mind and that it is not against any rules. If this is the case, could you guys help me here?

I have 3 weapons that I want to enchant into 5 different variations each (energy, earth, fiery, icy, death).
To enchant(or lets say conjure)into all 15 of these, I only want to use 5 talkactions.

Thats when I started tweaking your code into the following:
Code:
local slotItem = player:getSlotItem(CONST_SLOT_LEFT)

    if not slotItem then return false end -- Player has no itens on left hand slot
    if slotItem:getId() ~= 1111 and  slotItem:getId() ~= 2222 and  slotItem:getId() ~= 3333 then
        player:sendCancelMessage("You need to equipp an enchantable weapon first.")
        return false
    end
  
    if slotItem:getId() == 1111 then -- Enchantable Sword is equipped
        local ENERGYenchantedID = 1112 -- Energy Sword ID
        local EARTHenchantedID = 1113 -- Earth Sword ID
        local FIREenchantedID = 1114 -- Fiery Sword ID
        local ICEenchantedID = 1115 -- Icy Sword ID
        local DEATHenchantedID = 1116 -- Death Sword ID
    end
  
    if slotItem:getId() == 2222 then -- Enchantable Axe is equipped
        local ENERGYenchantedID = 2221 -- Energy Axe ID
        local EARTHenchantedID = 2223 -- Earth Axe ID
        local FIREenchantedID = 2224 -- Fiery Axe ID
        local ICEenchantedID = 2225 -- Icy Axe ID
        local DEATHenchantedID = 2226 -- Death Axe ID
    end
  
    if slotItem:getId() == 3333 then -- Enchantable Club is equipped
        local ENERGYenchantedID = 3331 -- Energy Club ID
        local EARTHenchantedID = 3332 -- Earth Club ID
        local FIREenchantedID = 3334 -- Fiery Club ID
        local ICEenchantedID = 3335 -- Icy Club ID
        local DEATHenchantedID = 3336 -- Death Club ID
    end
  
local exhaustTime = 1000
  
local exhaust = Condition(CONDITION_EXHAUST)
exhaust:setParameter(CONDITION_PARAM_TICKS, exhaustTime)

local blank = slotItem:getId()

local runes = {
    ["enchant vis"] = {runeID = ENERGYenchantedID , runeAmount = 1, blankAmount = 1, manaCost = 500, levelReq = 80, soul = 20, vocations = {1, 5, 9, 10}}
    ["enchant tera"] = {runeID = EARTHenchantedID, runeAmount = 1, blankAmount = 1, manaCost = 500, levelReq = 80, soul = 20, vocations = {1, 5, 9, 10}}
    ["enchant flam"] = {runeID = FIREenchantedID, runeAmount = 1, blankAmount = 1, manaCost = 500, levelReq = 80, soul = 20, vocations = {1, 5, 9, 10}}
    ["enchant frigo"] = {runeID = ICEenchantedID, runeAmount = 1, blankAmount = 1, manaCost = 500, levelReq = 80, soul = 20, vocations = {1, 5, 9, 10}}
    ["enchant mort"] = {runeID = DEATHenchantedID, runeAmount = 1, blankAmount = 1, manaCost = 500, levelReq = 80, soul = 20, vocations = {1, 5, 9, 10}}
}

-- REST IS THE SAME AS THE ZOTHION'S VERSION OF THE CODE

I feel like I am in the right direction. I'm just not sure if my code syntax is right at all.
I can't test on my server for 2 days, so I would appreciate your opinion on this.

Thank you for your time.
 
since onUse where player is defined is after that it wont work, but you could use a table like this (and fill it in obv)
Code:
local transform = {
    [1111] = {["enchant vis"] = 1112,}
    [2222] = {["enchant vis"] = 2221}
    [3333] = {}
    }
and then in the code where you use runeID you would rather use transform[slotItem:getId()]
however, you should not use addItem/removeItem here, you should use doTransformItem(item.uid, id)
you should go to
https://otland.net/threads/tfs-1-2-conjure-rune-ammo-etc.242844/
the code base on that one is better :)
 
Back
Top