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

[1.3+] Spell Converter

Codinablack

Dreamer
Content Editor
Joined
Dec 26, 2013
Messages
1,613
Solutions
11
Reaction score
850
Ok so I was working on a converter to turn the spells.xml file and the scripts for each spell in the spells.xml. The aim or goal was to read the .xml file and rewrite all the information to Revscripts for spells. This allows each spell to become modular and easily transferred or shared between compatible servers. I set out with the intention to convert my spells from an old 1.0 - 1.1 project to revscripts to create a sort of personal datapack. Then I decided I would convert the spells for otland/TFS but, turns out someone already made a PR containing all the spells from TFS converted, and also, TFS isn't set to do a complete conversion until 2.0.

HUGE THANKS TO @forgee for all his help and patience with me and string manipulations :D

Well I made the script, and it worked, it converted every single "Instant" spell for me, and later on I may finish it and do the "Rune" spells as well, but for now I share with you all, so enjoy


Lua:
local spellsFile = io.open("data/test/spells.xml", "r")
local spellsFolder = "data/test/scripts/"
local convertsFolder = "data/test/converts/"
local instantSpells = {}

local function tobool(v)
    return v and ( (type(v)=="number") and (v==1) or ( (type(v)=="string") and (v=="true") ) )
end

local function cleanSpaces(s)
   return s:match( "^%s*(.-)%s*$" )
end

local function populateInstantSpells()
    for i in spellsFile:read("*a"):gmatch("<instant (.-)</instant>") do
        local spellData = {}
        spellData.vocations = {}

        spellData.name = i:match('name.-=.-"(.-)"')
        spellData.id = tonumber(i:match('spellid.-=.-"(.-)"'))
        spellData.group = i:match('group.-=.-"(.-)"')
        spellData.cooldown = tonumber(i:match('cooldown.-=.-"(.-)"')) or tonumber(i:match('exhaustion.-=.-"(.-)"'))
        spellData.groupCooldown = tonumber(i:match('groupcooldown.-=.-"(.-)"'))
        spellData.level = tonumber(i:match('level.-=.-"(.-)"')) or tonumber(i:match('lvl.-=.-"(.-)"'))
        spellData.magicLevel = tonumber(i:match('magiclevel.-=.-"(.-)"')) or tonumber(i:match('maglv.-=.-"(.-)"'))
        spellData.mana = tonumber(i:match('mana.-=.-"(.-)"'))
        spellData.manaPercent = tonumber(i:match('manapercent.-=.-"(.-)"'))
        spellData.soul = tonumber(i:match('soul.-=.-"(.-)"'))
        spellData.range = tonumber(i:match('range.-=.-"(.-)"'))
        spellData.isPremium = tobool(tonumber(i:match('premium.-=.-"(.-)"'))) or tobool(tonumber(i:match('prem.-=.-"(.-)"')))
        spellData.isEnabled = tobool(tonumber(i:match('enabled.-=.-"(.-)"')))
        spellData.needTarget = tobool(tonumber(i:match('needtarget.-=.-"(.-)"')))
        spellData.needWeapon = tobool(tonumber(i:match('needweapon.-=.-"(.-)"')))
        spellData.needLearn = tobool(tonumber(i:match('needlearn.-=.-"(.-)"')))
        spellData.isSelfTarget = tobool(tonumber(i:match('selfTarget.-=.-"(.-)"')))
        spellData.isBlocking = tobool(tonumber(i:match('blocking.-=.-"(.-)"')))
        spellData.isAggressive = tobool(tonumber(i:match('aggressive.-=.-"(.-)"')))
        spellData.pzLock = tobool(tonumber(i:match('pzlock.-=.-"(.-)"')))
        spellData.words = i:match('words.-=.-"(.-)"')
        spellData.needDirection = tobool(tonumber(i:match('direction.-=.-"(.-)"')))
        spellData.hasParams = tobool(tonumber(i:match('params.-=.-"(.-)"')))
        spellData.hasPlayerNameParam = tobool(tonumber(i:match('playernameparam.-=.-"(.-)"')))
        spellData.needCasterTargetOrDirection = tobool(tonumber(i:match('casterTargetOrDirection.-=.-"(.-)"')))
        spellData.isBlockingWalls = tobool(tonumber(i:match('blockwalls.-=.-"(.-)"')))
        spellData.scriptPath = i:match('script.-=.-"(.-)"')

        for x in i:gmatch("<vocation (.-)/>") do
            spellData.vocations[#spellData.vocations + 1] = x:match('name.-=.-"(.-)"')
        end

        instantSpells[spellData.name] = spellData
    end
end

local function formatInstantSpellStringData()

    for key, spell in pairs(instantSpells) do
        local stringData = "----------------- \nlocal spell = Spell(SPELL_INSTANT)\n"

        if spell.name then
            stringData = stringData .. "\n---" .. spell.name .. "---"
            stringData = stringData .. "\nspell:name('" .. spell.name .. "')"
        end

        if spell.words then
            stringData = stringData .. "\nspell:words('" .. spell.words .. "')"
        end

        if spell.id then
            stringData = stringData .. "\nspell:id(" .. spell.id .. ")"
        end

        if spell.group then
            stringData = stringData .. "\nspell:group('" .. spell.group .. "')"
        end

        if spell.cooldown then
            stringData = stringData .. "\nspell:cooldown(" .. spell.cooldown .. ")"
        end

        if spell.groupCooldown then
            stringData = stringData .. "\nspell:groupCooldown(" .. spell.groupCooldown .. ")"
        end

        if spell.level then
            stringData = stringData .. "\nspell:level(" .. spell.level .. ")"
        end

        if spell.magicLevel then
            stringData = stringData .. "\nspell:magicLevel(" .. spell.magicLevel .. ")"
        end

        if spell.mana then
            stringData = stringData .. "\nspell:mana(" .. spell.mana .. ")"
        end

        if spell.manapercent then
            stringData = stringData .. "\nspell:manaPercent(" .. spell.manaPercent .. ")"
        end

        if spell.soul then
            stringData = stringData .. "\nspell:soul(" .. spell.soul .. ")"
        end
        if spell.range then
            stringData = stringData .. "\nspell:range(" .. spell.range .. ")"
        end

        if spell.isPremium then
            stringData = stringData .. "\nspell:isPremium(" .. tostring(spell.isPremium) .. ")"
        end

        if spell.isEnabled then
            stringData = stringData .. "\nspell:isEnabled(" .. tostring(spell.isEnabled) .. ")"
        end

        if spell.needTarget then
            stringData = stringData .. "\nspell:needTarget(" .. tostring(spell.needTarget) .. ")"
        end

        if spell.needLearn then
            stringData = stringData .. "\nspell:needLearn(" .. tostring(spell.needLearn) .. ")"
        end

        if spell.isSelfTarget then
            stringData = stringData .. "\nspell:isSelfTarget(" .. tostring(spell.isSelfTarget) .. ")"
        end

        if spell.isBlocking then
            stringData = stringData .. "\nspell:isBlocking(" .. tostring(spell.isBlocking) .. ")"
        end

        if spell.isAggressive then
            stringData = stringData .. "\nspell:isAggressive(" .. tostring(spell.isAggressive) .. ")"
        end

        if spell.pzLock then
            stringData = stringData .. "\nspell:isPzLock(" .. tostring(spell.pzLock) .. ")"
        end

        if spell.needDirection then
            stringData = stringData .. "\nspell:needDirection(" .. tostring(spell.needDirection) .. ")"
        end

        if spell.hasParams then
            stringData = stringData .. "\nspell:hasParams(" .. tostring(spell.hasParams) .. ")"
        end

        if spell.hasPlayerNameParam then
            stringData = stringData .. "\nspell:hasPlayerNameParam(" .. tostring(spell.hasPlayerNameParam) .. ")"
        end

        if spell.needCasterTargetOrDirection then
            stringData = stringData .. "\nspell:needCasterTargetOrDirection(" .. tostring(spell.needCasterTargetOrDirection) .. ")"
        end

        if spell.isBlockingWalls then
            stringData = stringData .. "\nspell:blockWalls(" .. tostring(spell.isBlockingWalls) .. ")"
        end

        if #spell.vocations > 0 then
            for i = 1, #spell.vocations do
                stringData = stringData .. "\nspell:vocation('" .. spell.vocations[i] .. "')"
            end
        end

        local scriptData = io.open(spellsFolder .. spell.scriptPath .. "", "r"):read("*a")

        stringData = stringData .. "\n"

        scriptData = scriptData:gsub("onCastSpell", "spell.onCastSpell")

        stringData = stringData .. scriptData
        stringData = stringData .. "\nspell:register()"

        instantSpells[key].stringData = stringData
        stringData = ""
    end
end

local function dumpSpells()
    for k,v in pairs(instantSpells) do
        local file = io.open(convertsFolder .. "" ..v.name..".lua", "w+")
        file:write(v.stringData)
        file:close()
        print(v.stringData)
    end
end


local function populateRuneSpells()

end

local start = TalkAction("/runconverts")

function start.onSay()
    populateInstantSpells()
    formatInstantSpellStringData()
    dumpSpells()
    return true
end

start:register()

Things to know:

spellsFile is the location of the spells.xml file.
spellsFolder is the location of the SCRIPTS for each spell. This is expected to be inside the directory that contains the spells.xml file
convertsFolder is the location you wish the converted scripts to go to. THIS DIRECTORY MUST EXIST ALREADY

Installation is easy as its a revscript, just drop this file into your data/scripts folder, and in game use the talkaction command

/runconverts

Then check your folder.
Enjoy.
 
Great release gonna try to convert nostalrius or othire spells with this
Let me know how that works out, I have never used either of those before, not sure what kind of compatibility issues there would be between those distro's, but I suppose it would matter if you were converting for a newer version of same server because that server also adopted revscripts as a feature, or if not, then how complex the script itself is, if it has any custom functions that only exist in the lib or in that servers core.
 
Let me know how that works out, I have never used either of those before, not sure what kind of compatibility issues there would be between those distro's, but I suppose it would matter if you were converting for a newer version of same server because that server also adopted revscripts as a feature, or if not, then how complex the script itself is, if it has any custom functions that only exist in the lib or in that servers core.
going to test it right away
Post automatically merged:

do know where the converted files are but i use command /runoconverts nothings happen no errors either
 
Last edited:
going to test it right away
Post automatically merged:

do know where the converted files are but i use command /runoconverts nothings happen no errors either
Did you make sure that the place you are trying to send the converterd files exists as a folder already???

THIS DIRECTORY MUST EXIST ALREADY
 
Did you make sure that the place you are trying to send the converterd files exists as a folder already???
yeah i reverted as they come by default and now it gives error on use
Lua:
Lua Script Error: [Scripts Interface]
C:\Users\FeR\Desktop\Server\WAR-TFS-1.5\data\scripts\convert.lua:callback
...pe R\Desktop\Server\WAR-TFS-1.5\data\scripts\convert.lua:15: attempt to index upvalue 'spellsFile' (a nil value)
stack traceback:
        [C]: in function '__index'
        ...FeR\Desktop\Server\WAR-TFS-1.5\data\scripts\convert.lua:15: in function 'populateInstantSpells'
        ...FeR\Desktop\Server\WAR-TFS-1.5\data\scripts\convert.lua:197: in function <...pe R\Desktop\Server\WAR-TFS-1.5\data\scripts\convert.lua:196>
 
Yeah, it is saying what I am saying. The path for spellsFile is wrong. Look closely at the default I shared with, I had my test example in a completely different location than where users keep their spells, and for a good reason.

If you just copied and didn't change the script but also have your spells.xm and a folder of scripts for spells located inside data/spells, then here is what to do. You can either A. Make a folder called test located inside your data folder, then inside that folder, copy the contents of data/spells. Or you can simply alter the script from:
Lua:
local spellsFile = io.open("data/test/spells.xml", "r")
local spellsFolder = "data/test/scripts/"
local convertsFolder = "data/test/converts/"

To:

Code:
local spellsFile = io.open("data/spells/spells.xml", "r")
local spellsFolder = "data/spells/scripts/"
local convertsFolder = "data/spells/converts/"

and make sure either way, that you create a folder called "converts" as well, for whichever way you do it
 
Back
Top