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

TFS 0.3 - 0.3.7-r5969-v8.60 - exhaust system

Pluto

Member
Joined
Jun 14, 2017
Messages
22
Reaction score
9
Location
Poland
It uses old exh system (can't cast attack and defensive spells at the same time). What could I do to fix that, and add something like "spell groups" to spells.xml? What I know is it should be changed in source files (configmanager.cpp, spells.cpp, configmanager.h), seen solution, but the links are dead. Could anybody help? I'm too new to do it myself.
 
I know this is old topic, but seen some people on forum with the same problem looking for the answer. You may fix not working groups on lua level by adding few variables.

Step 1: Create a file in data/lib folder, name it as you want, for example "exhaustion.lua". In this file you may change exhaust time and storage, if already using ones.
Step 2: Paste this into exhaustion.lua:
Lua:
exhaust_heal = 1000
exhaust_attack = 1000
exhaust_support = 2000
storage_heal = 20005
storage_attack = 20006
storage_support = 20007

spellEX = {
    add = function (cid, storage, Time)
        setPlayerStorageValue(cid, storage, os.mtime()%(10^9) + Time)
    end,
    
    set = function (cid, storage, Time)
        setPlayerStorageValue(cid, storage, Time)
    end,
    
    check = function (cid, storage)
                if (getPlayerStorageValue(cid, storage) - os.mtime()%(10^9) <= 0) or (getPlayerStorageValue(cid, storage) - os.mtime()%(10^9) > 1000*10) then
                    return true
                else
                    return false
                end
    end
}
3. Now you need to edit data/spells folder. Lets start with spells.xml -> here you need to CHANGE (not delete) all the "exhaustion" values to 0, so you have exhaustion="0" with every rune and instant spell. You make leave "groups" as they are, doesn't make any difference. To make your job easier, download attachment.
XML:
<?xml version="1.0" encoding="UTF-8"?>
    <instant name="Death Strike" words="exori mort" exhaustion="0" lvl="16" mana="20" prem="1" range="3" casterTargetOrDirection="1" blockwalls="1"  groups="1,2000" icon="87" needlearn="0" event="script" value="attack/death strike.lua">
        <vocation id="1;5"/>
    </instant>
4. Edit onCastSpell function in all spell files (data\spells\scripts). Download ready file from attachments OR do it yourself like below (use notepad++ to spend 2 minutes on it).
Lua:
function onCastSpell(cid, var)

if (os.time() > getPlayerStorageValue(cid, storage_heal)) then
        setPlayerStorageValue(cid, storage_heal, os.time() + (exhaust_heal * 0.001))
        return doCombat(cid, combat, var) else
        doSendMagicEffect(getCreaturePosition(cid), 2)
    end

end
Functions are bit different for few spells, you have to add
Lua:
if (os.time() > getPlayerStorageValue(cid, storage_heal)) then

        setPlayerStorageValue(cid, storage_heal, os.time() + (exhaust_heal * 0.001))
at the beggining of the function, and
Lua:
else
        doSendMagicEffect(getCreaturePosition(cid), 2)
    end
at the last line of the function, like this:
Lua:
function onCastSpell(cid, var)
    if (os.time() > getPlayerStorageValue(cid, storage_support)) then
    setPlayerStorageValue(cid, storage_support, os.time() + (exhaust_support * 0.001))
   
    local pos, membersList = getCreaturePosition(cid), getPartyMembers(cid)
    if(membersList == nil or type(membersList) ~= 'table' or table.maxn(membersList) <= 1) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOPARTYMEMBERSINRANGE)
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    local affectedList = {}
    for _, pid in ipairs(membersList) do
        if(getDistanceBetween(getCreaturePosition(pid), pos) <= 36) then
            table.insert(affectedList, pid)
        end
    end

    local tmp = table.maxn(affectedList)
    if(tmp <= 1) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOPARTYMEMBERSINRANGE)
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    local mana = math.ceil((0.9 ^ (tmp - 1) * config.baseMana) * tmp)
    if(getCreatureMana(cid) < mana) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTENOUGHMANA)
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    if(not doCombat(cid, combat, var)) then
        doPlayerSendDefaultCancel(cid, RETURNVALUE_NOTPOSSIBLE)
        doSendMagicEffect(pos, CONST_ME_POFF)
        return false
    end

    doCreatureAddMana(cid, -(mana - config.baseMana), false)
    if(not getPlayerFlagValue(cid, PlayerFlag_NotGainMana) and (not getTileInfo(getThingPosition(cid)).hardcore or config.hardcoreManaSpent)) then
        doPlayerAddSpentMana(cid, (mana - config.baseMana))
    end

    for _, pid in ipairs(affectedList) do
        doAddCondition(pid, condition)
    end

    return true else
        doSendMagicEffect(getCreaturePosition(cid), 2)
    end
end

You have to use "exhaust_heal" and "storage_heal" for healing spells, "attack_heal" and "attack_storage" for attack spells, "exhaust_support" and "storage_support" for support spells. Again, variable names and values are stored in data/lib folder.

5. That's it, if done correctly, you will have different exhaustion for all the spell groups. You may want to edit data\actions\scripts\liquids\potions.lua, becouse right now you are able to use "exura" and health potion at the same time. Simply add there a group for health potions and check storages like in spells on drink function (not sure if you may use healing spells and potions at the same time in rl tibia). Have fun!
 

Attachments

Last edited:
That function had to be edited: use os.mtime to count MS, instead of os.time. Check spellEX functions I've updated, and use like that:

Lua:
function onCastSpell(cid, var)

    if spellEX.check(cid, storage_attack) then
        spellEX.add(cid, storage_attack, exhaust_attack)
        return doCombat(cid, combat, var)
            else
        doSendMagicEffect(getCreaturePosition(cid), 2)
    end

end
 
Back
Top