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

Solved Conjure runes from backpack - TFS 0.4 - 8.6

hanzoha

New Member
Joined
May 8, 2016
Messages
87
Reaction score
2
Hello guys, I was wondering if someone could help me with this.

In my ot, the players have to put the blank rune in the hand in order to conjure the rune. What I need is to remove that action and let player being able to conjure runes without putting the blank rune in the hand.

I found this thread, and it suggest to remove the reagentId="" from spells.xml. It works but the problem is that blank runes become useless and I need them too.

Is there a way to edit this without editing sources and just edit the Lua? What can I do?

Thanks in advance!
 
Code:
local exhaustTime = 1000

local exhaust = createConditionObject(CONDITION_EXHAUST)
setConditionParam(exhaust, CONDITION_PARAM_TICKS, exhaustTime)

local function conjuration(cid, t, word)
    doPlayerAddMana(cid, -(t[word].manaCost))
    doPlayerAddItem(cid, t[word].runeID, t[word].runeAmount)
    doSendMagicEffect(getCreaturePosition(cid), CONST_ME_MAGIC_BLUE)
    doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You conjured "..(t[word].runeAmount).." "..(getItemNameById(t[word].runeID)).." runes.")
    doAddCondition(cid, exhaust)
end

function onSay(cid, words, param, channel)
    if(hasCondition(cid, CONDITION_EXHAUST)) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_YOUAREEXHAUSTED)
        return true
    end
    local vocations = {"Sorcerer", "Druid", "Paladin", "Knight", "Master sorcerer", "Elder druid", "Royal paladin", "Elite knight"}
    local cast = string.lower(words.." "..param)
    local voc = getPlayerVocation(cid)
    local lvl = getPlayerLevel(cid)
    local mana = getPlayerMana(cid)
    local errorMessage = ""
    local invalidSpell = "--- Valid conjuration spells for you are ---"
    local runes = {
    ["adori blank"] = {runeID = 2260, runeAmount = 1, manaCost = 20, levelReq = 8, vocations = {1,2,3,4,5,6,7,8}},
    ["adori vita vis"] = {runeID = 2268, runeAmount = 3, manaCost = 200, levelReq = 200, vocations = {1,2,3,4,5,6,7,8}},
    ["adori vis"] = {runeID = 2311, runeAmount = 15, manaCost = 200, levelReq = 200, vocations = {1,2,3,4,5,6,7,8}}
    }
    if runes[cast] then
        if isInArray(runes[cast].vocations, voc) then
            if lvl >= runes[cast].levelReq then
                if mana >= runes[cast].manaCost then
                    if cast ~= "adori blank" and doPlayerRemoveItem(cid, 2260, runes[cast].runeAmount) then
                        conjuration(cid, runes, cast)
                        return true
                    elseif cast == "adori blank" then
                        conjuration(cid, runes, cast)
                        return true
                    else
                        errorMessage = "You do not have enough blank runes. You need "..(runes[cast].runeAmount).."."
                    end
                else
                    errorMessage = "You do not have enough mana. You have "..mana.." and you need "..runes[cast].manaCost.."."
                end
            else
                errorMessage = "You do not have the required level for this. You need level "..runes[cast].levelReq.."."
            end
        else
            errorMessage = "That spell can only be used by:\n"
            for i=1,#(runes[cast].vocations),1 do
                if i == #(runes[cast].vocations) then
                    errorMessage = errorMessage..vocations[i].."."
                else
                    errorMessage = errorMessage..vocations[i]..", "
                end
            end
        end 
    else
        errorMessage = "That conjuration spell does not exist."
    end
    for pos,val in pairs(runes) do
        if isInArray(runes[pos].vocations, voc) then
            invalidSpell = invalidSpell.."\n"..pos.." --- which costs "..(runes[pos].manaCost).." mana and gives you "..(runes[pos].runeAmount).." "..(getItemNameById(runes[pos].runeID))..""
            if runes[pos].runeAmount > 1 then
                invalidSpell = invalidSpell.."s."
            else
                invalidSpell = invalidSpell.."."
            end
        end
    end
    invalidSpell = errorMessage.."\n"..invalidSpell
    doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, invalidSpell)
    doAddCondition(cid, exhaust)     
    return true
end
to use this all you have to do is add this in talkactions.xml
Code:
<talkaction words="adori" event="script" value="conjure.lua"/>
    <talkaction words="adevo" event="script" value="conjure.lua"/>
    <talkaction words="adana" event="script" value="conjure.lua"/>
    <talkaction words="adura" event="script" value="conjure.lua"/>
    <talkaction words="adeto" event="script" value="conjure.lua"/>
    <talkaction words="adito" event="script" value="conjure.lua"/>

and then to add more conjuration spells put them in
Code:
local runes = {...}
in the form of
Code:
{["spellname"] = {runeID = 1, runeAmount = 2, manaCost = 3, levelReq = 4, vocations = {1,2,3}, ["spellname2"] = {runeID = 1, runeAmount = 2, manaCost = 3, levelReq = 4, vocations = {1,2,3}}
and for example for a conjuration spell for SDs it would look like this:
Code:
["adori vita vis"] = {runeID = 2268, runeAmount = 3, manaCost = 200, levelReq = 200, vocations = {1, 2, 5, 6}}
this means the words you have to say is "adori vita vis", the rune it gives you has ID 2268 (SD rune), it gives you 3 of those, it costs 200 mana to cast it, you have to be lvl 200+, and you have to be vocation 1/2/5/6 (sorc, druid, MS, ED)

no need to read further if you're just gonna use the script
i changed the table around so its now
Code:
runes["cast name"]
so the function doesn't loop through entire runes table every cast, but rather goes to the rigth index directly (afaik it should be better performance..)
i added "adori blank" to the runes table just like a regular rune, so its easy to change however you want it

i found no issues with it, and it also returns what type of error you have (e.g too low mana / level or wrong vocation and what vocations can use it.)

it does still loop through entire runes table incase you cast an invalid spell, but that shouldnt be a problem since most people should be casting a valid conjuration spell anyway..

if the player casts a valid conjuration spell its not really a long function to loop through, it creates the necessary tables/values, check a couple ifs straight to the rune table index then does conjuration, and exits the function
it may look long but its not really inefficient if people are casting valid spells
Too complicated :p, too many loops too.
 
Just one more thing and this would be perfect... I see that you added a function to use the blank rune, but in game you dont need the amount of blank runes for the runes charges.

I mean, if the Sudden Death rune has 3 charges I only need 1 blank rune, not 3 :D

Can you please help me with that? Thx! and sorry for the troubles :p
 
too many loops? theres only 2 of them o_O

@hanzoha change
Code:
doPlayerRemoveItem(cid, 2260, runes[cast].runeAmount)
to
Code:
doPlayerRemoveItem(cid, 2260, 1)
and
Code:
errorMessage = "You do not have enough blank runes. You need "..(runes[cast].runeAmount).."."
to
Code:
errorMessage = "You do not have enough blank runes."
 
It's perfect! You are awesome man!
Thanks to all!

(For me, this is actually a better way to conjure runes, cuz I can see which runes my voc can conjure :D )
 
Code:
local player = {}

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

local blank = 2260

function onSay(cid, words, param, channel)
    if hasCondition(cid, CONDITION_EXHAUST) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_YOUAREEXHAUSTED)
        return true
    end
   
    player.vocation = getPlayerVocation(cid)
    player.cast = param:lower()
    player.level = getPlayerLevel(cid)
    player.mana = getPlayerMana(cid)

    local msg = nil
   
    if runes[cast] then
        if isInArray(runes[cast].vocation, player.vocation) then
            if player.level >= runes[cast].levelReq then
                if player.mana >= runes[cast].manaCost then
                    if getPlayerItemCount(cid, blank) >= runes[cast].runeAmount then
                        doPlayerRemoveItem(cid, blank, runes[cast].runeAmount)
                        doCreatureSay(cid, cast, TALKTYPE_ORANGE_1)
                        doCreateItem(runes[cast].runeID, runes[cast].make)
                        doCreatureAddMana(cid, -runes[cast].manaCost)
                        doPlayerAddSpentMana(cid, runes[cast].manaCost)
                    else
                        msg = "You do not have enough blank runes. You need "..(runes[cast].runeAmount).."."
                    end
                else
                    msg = "You do not have enough mana. You have "..mana.." and you need "..runes[cast].manaCost.."."
                end
            else
                msg = "You do not have the required level for this. You need level "..runes[cast].levelReq.."."
            end
        else
             msg = "Your vocation cannot cast this spell."
        end
    else
        msg = "That conjuration spell does not exist."
    end
   
    if msg then
        doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, msg)
    end
   
    doAddCondition(cid, exhaust)    
    return true
end

Code:
<talkaction words="adori" filter="word-spaced" event="script" value="conjure.lua"/>
 
Code:
local player = {}

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

local blank = 2260

function onSay(cid, words, param, channel)
    if hasCondition(cid, CONDITION_EXHAUST) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_YOUAREEXHAUSTED)
        return true
    end
  
    player.vocation = getPlayerVocation(cid)
    player.cast = param:lower()
    player.level = getPlayerLevel(cid)
    player.mana = getPlayerMana(cid)

    local msg = nil
  
    if runes[cast] then
        if isInArray(runes[cast].vocation, player.vocation) then
            if player.level >= runes[cast].levelReq then
                if player.mana >= runes[cast].manaCost then
                    if getPlayerItemCount(cid, blank) >= runes[cast].runeAmount then
                        doPlayerRemoveItem(cid, blank, runes[cast].runeAmount)
                        doCreatureSay(cid, cast, TALKTYPE_ORANGE_1)
                        doCreateItem(runes[cast].runeID, runes[cast].make)
                        doCreatureAddMana(cid, -runes[cast].manaCost)
                        doPlayerAddSpentMana(cid, runes[cast].manaCost)
                    else
                        msg = "You do not have enough blank runes. You need "..(runes[cast].runeAmount).."."
                    end
                else
                    msg = "You do not have enough mana. You have "..mana.." and you need "..runes[cast].manaCost.."."
                end
            else
                msg = "You do not have the required level for this. You need level "..runes[cast].levelReq.."."
            end
        else
             msg = "Your vocation cannot cast this spell."
        end
    else
        msg = "That conjuration spell does not exist."
    end
  
    if msg then
        doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, msg)
    end
  
    doAddCondition(cid, exhaust)   
    return true
end

Code:
<talkaction words="adori" filter="word-spaced" event="script" value="conjure.lua"/>
You forgot to define exhaust in the top of the script.
 
Code:
local player = {}

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

local blank = 2260

function onSay(cid, words, param, channel)
    if hasCondition(cid, CONDITION_EXHAUST) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_YOUAREEXHAUSTED)
        return true
    end

    player.vocation = getPlayerVocation(cid)
    player.cast = param:lower()
    player.level = getPlayerLevel(cid)
    player.mana = getPlayerMana(cid)

    local msg = nil

    if runes[cast] then
        if isInArray(runes[cast].vocation, player.vocation) then
            if player.level >= runes[cast].levelReq then
                if player.mana >= runes[cast].manaCost then
                    if getPlayerItemCount(cid, blank) >= runes[cast].runeAmount then
                        doPlayerRemoveItem(cid, blank, runes[cast].runeAmount)
                        doCreatureSay(cid, cast, TALKTYPE_ORANGE_1)
                        doCreateItem(runes[cast].runeID, runes[cast].make)
                        doCreatureAddMana(cid, -runes[cast].manaCost)
                        doPlayerAddSpentMana(cid, runes[cast].manaCost)
                    else
                        msg = "You do not have enough blank runes. You need "..(runes[cast].runeAmount).."."
                    end
                else
                    msg = "You do not have enough mana. You have "..mana.." and you need "..runes[cast].manaCost.."."
                end
            else
                msg = "You do not have the required level for this. You need level "..runes[cast].levelReq.."."
            end
        else
             msg = "Your vocation cannot cast this spell."
        end
    else
        msg = "That conjuration spell does not exist."
    end

    if msg then
        doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, msg)
    end

    doAddCondition(cid, exhaust) 
    return true
end

Code:
<talkaction words="adori" filter="word-spaced" event="script" value="conjure.lua"/>
i think you mixed up .runeAmount and .make (although if i made it with how many blanks / how many to get in runes table id call them runeAmount and blankAmount to make it clea

i dont really see any big difference though, other than the fact that you removed the entire end (which is just error reporting back to the user, giving them information on what vocations can cast that spell (although that is probably unnecessary) and all available conjuration spells)

why create a player table with data in it? better to just define level/vocation as their own variables than to put that all into a table if you care about efficiency :)
 
i think you mixed up .runeAmount and .make (although if i made it with how many blanks / how many to get in runes table id call them runeAmount and blankAmount to make it clea

i dont really see any big difference though, other than the fact that you removed the entire end (which is just error reporting back to the user, giving them information on what vocations can cast that spell (although that is probably unnecessary) and all available conjuration spells)
I removed the loops and the function, i didn't see a reason for them, however that was a quick write, i am sure I could of shortened it up more.. anyway i just made the comment it was too complex and too long because.. it just look that way.

All scripts start out this way, then we eventually shorten them up :)
 
the function was unnecessary yes, i just added it because i was too lazy to make a good blank rune option

however the loops near the end is, in my opinion necessary because if you cast an invalid conjuration spell, you need to get some information on which you can actually cast, whereas in your case they'd have no idea which ones existed
 
lib/100-compat.lua
Code:
runes = {
["adori blank"] = {runeID = 2260, runeAmount = 1, blankAmount = 0, manaCost = 20, soulCost = 1, levelReq = 8, vocations = {1,2,3,4,5,6,7,8}},
["adori vita vis"] = {runeID = 2268, runeAmount = 3, blankAmount = 1, manaCost = 200, soulCost = 0, levelReq = 200, vocations = {1,2,3,4,5,6,7,8}},
["adori vis"] = {runeID = 2311, runeAmount = 15, blankAmount = 1, manaCost = 200, soulCost = 0, levelReq = 200, vocations = {1,2,3,4,5,6,7,8}}
}
talkactions.xml
Code:
<talkaction words="adori" event="script" value="conjure.lua"/>
<talkaction words="adevo" event="script" value="conjure.lua"/>
<talkaction words="adana" event="script" value="conjure.lua"/>
<talkaction words="adura" event="script" value="conjure.lua"/>
<talkaction words="adeto" event="script" value="conjure.lua"/>
<talkaction words="adito" event="script" value="conjure.lua"/>
<talkaction words="!conjures" event="script" value="conjures.lua"/>
conjure.lua
Code:
local exhaustTime = 1000

local exhaust = createConditionObject(CONDITION_EXHAUST)
setConditionParam(exhaust, CONDITION_PARAM_TICKS, exhaustTime)

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

local blank = 2260

function onSay(cid, words, param, channel)
    if(hasCondition(cid, CONDITION_EXHAUST)) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_YOUAREEXHAUSTED)
        return true
    end

    local cast = (words.." "..param):lower()
    local vocation = getPlayerVocation(cid)
    local errorMessage = nil
    local pz = getTilePzInfo(getCreaturePosition(cid))

    if runes[cast] then  
        if not pz or (pz == runes[cast].allowPz) then
            if isInArray(runes[cast].vocations, vocation) then
                if getPlayerLevel(cid) >= runes[cast].levelReq then
                    if getPlayerMana(cid) >= runes[cast].manaCost then
                        if getPlayerSoul(cid) > runes[cast].soulCost then
                            if doPlayerRemoveItem(cid, blank, runes[cast].blankAmount) then
                                doPlayerAddMana(cid, -(runes[cast].manaCost))
                                doPlayerAddItem(cid, runes[cast].runeID, runes[cast].runeAmount)
                                doPlayerAddSoul(cid, -(runes[cast].soulCost))
                                doCreatureSay(cid, cast, TALKTYPE_ORANGE_1)
                                doSendMagicEffect(getCreaturePosition(cid), CONST_ME_MAGIC_BLUE)
                                doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You conjured "..(runes[cast].runeAmount).." "..(getItemNameById(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 = "That spell can not be used by your vocation."
            end
        else
            errorMessage = "You cannot cast that spell while in a protection zone."
        end
    else
        errorMessage = "That conjuration spell does not exist."
    end
    if errorMessage then
        doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
        doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, errorMessage)
    end

    doAddCondition(cid, exhaust)
    return true
end
conjures.lua
Code:
local exhaustTime = 1000

local exhaust = createConditionObject(CONDITION_EXHAUST)
setConditionParam(exhaust, CONDITION_PARAM_TICKS, exhaustTime)

function onSay(cid, words, param, channel)
    if(hasCondition(cid, CONDITION_EXHAUST)) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_YOUAREEXHAUSTED)
        return true
    end
   
    local cast = (words.." "..param):lower()
    local vocation = getPlayerVocation(cid)
    local conjure = ""
   
    doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "--- Valid conjuration spells for you are ---")
    for pos,val in pairs(runes) do
        if isInArray(runes[pos].vocations, vocation) then
            conjure = pos.." --- which costs "..(runes[pos].manaCost).." mana, "..(runes[pos].soulCost).." soul and gives you "..(runes[pos].runeAmount).." "..(getItemNameById(runes[pos].runeID))..""
            if runes[pos].runeAmount > 1 then
                conjure = conjure.."s."
            else
                conjure = conjure.."."
            end
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, conjure)
            conjure = ""
        end
    end
    doAddCondition(cid, exhaust)   
    return true       
end
i fixed it up slightly, and removed the "this spell can only be cast by ..." since it was kinda unnecessary
however i left the last loop since its the only way for people to find out what conjuration spells they can actually cast (since a spellbook wont help for a talkaction command with more work...). it only gets called if they cast an invalid spell so it shouldnt be executed that often anyway.
values such as getPlayerLevel(cid) which is only used once, i moved straight in to the ifs instead of defining variables like level = getPlayerLevel(cid), since its completely unnecessary to declare them before all the ifs, incase of errors you have to call fewer of those functions to declare variables

putting the runes table in global.lua would however drastically increase performance considering it now has to initialize the entire runes table on every cast :(

edit: edited it a bit more, and split up conjuration and the error reporting to be different functions, if something goes wrong trying to conjure the player will only get a simple error message now, using !conjures will print the entire list of available conjuration spells to the player, runes table moved to compat.lua to be loaded globally on start
 
Last edited:
Wow, this is great!

1. Should I create the file compat.lua in Data/lib/compat.lua? or Data/talkactions/lib/compat.lua ?
2. If I created in Data/lib/ .... should I add a number before the compat.lua? like 02-compat.lua like the others files?
3. What should I add if I don't want a player with PZ conjure a blank rune?

Thanks again!
 
there should be a file in data/lib/ thats named 100-compat.lua, just put it in there
i added pz check, you can remove it by addin
Code:
allowPz = true
for runes, if there is no allowPz at all it wont be allowed inside pz
 
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:
Hello.
This is working great so far, only 2 details...
1. The !conjures only shows 4 runes. In every vocation
2. Is it possible to add restriction to "adori blank (conjure blank rune)" when player is attacking other (pz locked)? but not in party.

Thanks!
 
you can use isPlayerPzLocked(cid) to check if player is pz locked from pvp where you check combat
how does ur runes table look when it only shows 4 runes? can you link a screenshot of the 4 runes print also?
 
Back
Top