• 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 Monster parser

Jotran

Banned User
Joined
Feb 8, 2015
Messages
349
Reaction score
109
Inspired by @zbizu items parser :)
http://otland.net/threads/tfs-1-1-items-parser-useful-for-searching-ids.228705/

I wanted to make a monster parser for in game use for scripts and stuff but I am having an issue getting some of the nodes to line up properly, I am stuck at the flags / flag node.

Here is the code so far, any help would be greatly appreciated :)
Code:
local name = '' -- make it global

local strStart = '%s*=%s*"(.-)"%s'
local strEnd = '%s*=%s*"(.-)"'

local mainMonsterFile = {
    '*name'..strStart,
    '*file'..strEnd

}

local monsterNode = {
    '*name'..strStart,
    '*nameDescription'..strStart,
    '*race'..strStart,
    '*experience'..strStart,
    '*speed'..strStart,
    '*manacost'..strEnd
}

local health = {
    '*now'..strStart,
    '*max'..strEnd

}
local look = {
    '*type'..strStart,
    '*head'..strStart,
    '*body'..strStart,
    '*legs'..strStart,
    '*feet'..strStart,
    --'*addons'..strStart,
    '*corpse'..strEnd
}

local target = {
    '*interval'..strStart,
    '*chance'..strEnd
}

local flags = {
    value = {
        '*summonable'..strEnd,
        '*attackable'..strEnd,
        '*hostile'..strEnd,
        '*illusionable'..strEnd,
        '*convinceable'..strEnd,
        '*pushable'..strEnd,
        '*canpushitems'..strEnd,
        '*canpushcreatures'..strEnd,
        '*targetdistance'..strEnd,
        '*staticattack'..strEnd,
        '*runonhealth'..strEnd
    },
    attr = {
        'summonable',
        'attackable',
        'hostile',
        'illusionable',
        'convinceable',
        'pushable',
        'canpushitems',
        'canpushcreatures',
        'targetdistance',
        'staticattack',
        'runonhealth'
    }
}

local attacks = {
    atk = {
        '*name'..strStart,
        '*interval'..strStart,
        '*chance'..strStart,
        '*range'..strStart,
        '*radius'..strStart,
        '*target'..strStart,
        '*min'..strStart,
        '*max'..strEnd

    },
    attributes = {
        '*key'..strStart,
        '*value'..strEnd
    }
}

local defenses = {
    def = {
        '*armor'..strStart,
        '*defense'..strEnd
    }
}

local elements = {
    value = {
        '*physicalPercent'..strEnd,
        '*icePercent'..strEnd,
        '*poisonPercent'..strEnd,
        '*earthPercent'..strEnd,
        '*firePercent'..strEnd,
        '*energyPercent'..strEnd,
        '*holyPercent'..strEnd,
        '*deathPercent'..strEnd,
        '*drownPercent'..strEnd,
        '*lifedrainPercent'..strEnd,
        '*manadrainPercent'..strEnd
    },
    attr = {
        physicalPercent = 0,
        icePercent = 0,
        poisonPercent = 0,
        earthPercent = 0,
        firePercent = 0,
        energyPercent = 0,
        holyPercent = 0,
        deathPercent = 0,
        drownPercent = 0,
        lifedrainPercent = 0,
        manadrainPercent = 0
    }
}


function parseMonsters(param)
    local dir = 'data/monster/'
    local file = dir..'monsters.xml'
    local fileEx = 'monsters.lua'
    local outputFile = fileEx

    local monsters = {}

    for line in io.lines(file) do
        for mtag, n, file in line:gmatch('<(%a-)%s'..table.concat(mainMonsterFile)) do
            if mtag == 'monster' then
                for submtag in io.lines(dir..file) do
                    for mt in submtag:gmatch('<(%a-)%s') do
                        --print(mt)
                        if mt == 'monster' then
                            for cname, des, race, exp, speed in submtag:gmatch('<monster '..table.concat(monsterNode)) do
                                name = cname
                                monsters[name] = {}
                                monsters[name].des = des
                                monsters[name].race = race
                                monsters[name].exp = exp
                                monsters[name].speed = speed
                            end
                        elseif mt == 'health' then
                            for now, max in submtag:gmatch('<health '..table.concat(health)) do
                                --print(name)
                                monsters[name].health = {}
                                monsters[name].health.now = now
                                monsters[name].health.max = max
                                --print(monsters[name].health.now)
                            end
                        elseif mt == 'look' then -- needs work to support addons
                            for type, head, body, legs, feet, corpse in submtag:gmatch('<look '..table.concat(look)) do
                                monsters[name].look = {}
                                monsters[name].look.type = type
                                monsters[name].look.head = head
                                monsters[name].look.body = body
                                monsters[name].look.legs = legs
                                monsters[name].look.feet = feet
                                monsters[name].look.corpse = corpse
                            end
                        elseif mt == 'targetchange' then
                            for interval, chance in submtag:gmatch('<targetchange '..table.concat(target)) do
                                monsters[name].targetchange = {}
                                monsters[name].targetchange.interval = interval
                                monsters[name].targetchange.chance = chance
                            end
                        elseif mt == 'flag' then
                            local i = 1
                            repeat
                                for f in submtag:gmatch('<flag '..flags.value[i]) do
                                    monsters[name].flag = {}
                                    monsters[name].flag[flags.attr[i]] = f
                                    --print(monsters[name].flag[flags.attr[i]])
                                    -- flags don't seem to line up properly :(
                                end
                                i = i + 1

                            until(i <= #flags.attr)

                        elseif mt == 'attack' then
                            for a, b, c, d, e, f, g, h, i in submtag:gmatch('<attack '..table.concat(attacks.atk)) do
                                --print(a,b,c,d,e,f,g,h,i)
                            end
                        elseif mt == 'attribute' then
                            for key, value in submtag:gmatch('<attribute '..table.concat(attacks.attributes)) do
                                --print(key, value)
                            end
                        elseif mt == 'defenses' then
                            --print(mt)
                            for armor, def in submtag:gmatch('<defenses '..table.concat(defenses.def)) do
                                --print(armor, def)
                            end
                        elseif mt == 'element' then
                            for i = 1, #elements.value do
                                for element in submtag:gmatch('<element '..elements.value[i]) do
                                    elements.attr[i] = element
                                    --print(i.." "..elements.attr[i])
                                end
                            end
                        end
                    end
                end
            end
        end
    end
    print(monsters['Amazon'].flag.hostile)
    return true
end

parseMonsters()
 
Last edited:
It was lining up fine, the problem was that you were re-initializing the flag table through each iteration in the repeat-until loop.
You are also ending the repeat-until loop prematurely as i (when = 1 initially) will always be <= #flags.attr, just flip the sign the other way to >.
 
Last edited:
All you need to do is move: monsters[name].flag = {} outside of the repeat-until loop. I put it below monsters[name].speed = speed near the top.
Then change until(i <= #flags.attr) to until(i > #flags.attr)
 
Still needs tons of work, like not all the values are being read from all the monsters.. I'm sure this will keep me busy for awhile :)
 
Back
Top