FANDOM


local m = {}
 
local root, row
 
-- ------------------------------- --
--             Helpers             --
-- ------------------------------- --
local function substing()
    return mw.getCurrentFrame():preprocess('{{NAMESPACE}}') == '{{NAMESPACE}}' 
end
 
local function temp(args)
    local rst = mw.getCurrentFrame():expandTemplate{title=table.remove(args,1), args=args}
    if substing() then
        local _, _, c = mw.ustring.find(rst, '|'..args[1]..'%s*=%s*([^}|]*)')
        return c and mw.text.trim(c) or '{{'..table.concat(args,'|')..'}}'
    else return rst end
end
 
local function conv(n)
    return string.gsub(n,'0000$','萬')
end
 
-- ------------------------------- --
--           Table Parts           --
-- ------------------------------- --
local function header(tbl)
    tbl = tbl or root
    tbl:tag('tr')
        :tag('th')
            :css{width='35px'}
            :wikitext('Battle')
            :done()
        :tag('th')
            :attr('colspan',2)
            :css{width='27%'}
            :wikitext('Monster')
            :done()
        :tag('th')
            :css{width='36px'}
            :wikitext('Attack')
            :done()
        :tag('th')
            :css{width='22px'}
            :wikitext('CD')
            :done()
        :tag('th')
            :css{width='50px'}
            :wikitext('HP')
            :done()
        :tag('th')
            :css{width='42px'}
            :wikitext('Defence')
            :done()
        :tag('th')
            :css{width='41px'}
            :wikitext('Loot')
            :done()
        :tag('th')
            :css{width='30px'}
            :wikitext('Coins')
            :done()
        :tag('th')
            :wikitext('Note')
    return tostring(h)
end
 
local function attr(id)
    local t = {['water']='water', ['fire']='fire', ['wind']='wind', ['thunder']='thunder', ['nihility']='nihility'}
    return t[temp{id,'attr'}]
end
 
local function extra(arg)
    if arg == nil then return '' end
    if arg == '' then return '<br/>'..temp{'Texttip2','亂入','在指定層數(未指定則代表隨機非固定層)稀有單獨出現',classes='line'}
    else return '<br/>'..temp{'Texttip2','隨機'..(arg~='1' and arg or ''), '隨機出現其中'..arg..'隻',classes='line'} end
end
 
local function name(id,num)
    local tbl = mw.html.create('table')
    tbl:addClass('stageDataName'):tag('tr')
        :tag('td')
            :wikitext(temp{id,45})
            :done()
        :tag('td')
            :wikitext(temp{id,'name'}..(num and ' ×'..num or ''))
    return tostring(tbl)
end
 
local function cd(nrm,init)
    return nrm .. (init and temp{'Texttip2', init, 'Cool Down value when battle starts'} or '')
end
 
local function icon(file,text)
    local div = mw.html.create('div')
        :css{
            position = 'relative',
            width = '39px',
            height = '39px',
            margin = '0 0 3.46px'
        }
        :wikitext('[[File:'..file..'.png|39px|link=]]')
        :tag('span')
            :addClass('monsterLv')
            :css{['font-size']='8pt', ['line-height']='18.92px',['text-align']='center',['white-space']='nowrap',['background-image']='none'}
            :wikitext(text)
            :allDone()
    return tostring(div)
end
 
local function drop(args)
    if args == nil then return 'No' end
 
    local div = mw.html.create('div'):addClass('stageDataDrop')
    local c = 0
    local last
    if args['card'] then
        last = div:tag('div'):wikitext(temp{'MonsterLv', args['card']['id'], args['card']['lv'], 39})
        c = c+1
    end
    if args['item'] then
        last = temp{'Item',args['item']}
        div:wikitext(last)
        c = c+1
    end
    if args['coin'] then
        last = temp{'Texttip2',icon('Coin',args['coin']),args['coin']..'金幣',classes='bottom'}
        div:wikitext(last)
        c = c+1
    end
 
    if c == 0 then return 'N/A'
    elseif c == 1 then return tostring(last)
    else return tostring(div)..'<div class="stageDataDropMore"><span class="stageDataDropPlus">+</span></div>' end
end
 
local function dropnote(drops)
    if drops == nil then return '' end
    local rare = {'黃','銅','銀','金','白金','白金','白金','白金'}
    if drops['rare'] or drops['card'] and not (drops['item'] or drops['coin'] or drops['soul'] or drops['craft']) then return temp{
        'Texttip2',
        ' [[File:'..(drops['rare'] or rare[tonumber(temp{drops['card']['id'],'rare'})])..'Card.png|x20px|link=]]',
        '必定掉落一張封印卡',
        classes = 'stageNote'
    } end
 
    if drops['item'] and not (drops['coin'] or drops['coin'] or drops['soul'] or drops['craft']) then return temp{
        'Texttip2',
        ' [[File:Item'..drops['item']..'.png|x20px|link=]]',
        '必定掉落指定物品。若物品已達上限則改為掉落寶箱(1500)',
        classes='stageNote'
    } end
 
    return temp{'Texttip2',' [[File:DownArrow.png|x20px|link=]]','此層必定掉落',classes='stageNote'}
end
 
local function addRow(args,class,tbl)
    tbl = tbl or root
    local row = tbl:tag('tr'):addClass(class)
    local td1,td2
    if args['stage']=='' then td1 = row:tag('td'):wikitext(args[1]):addClass('random')
    elseif args['stage']==nil then td1 = ''
    else td1 = row:tag('td'):wikitext(args['stage']):addClass('stage') end
 
    if args['special']==nil then
        td2 = nil
        row:tag('td'):attr('colspan',2):wikitext(name(args['id'],args['num']))
    elseif args['special']=='' then
        td2 = ''
        row:tag('td'):wikitext(name(args['id'],args['num']))
    else
        td2 = row:tag('td'):wikitext(mw.getCurrentFrame():preprocess(args['special']))
        row:tag('td'):wikitext(name(args['id'],args['num']))
    end
 
    local atk = conv(args['atk'])
    local cell = row:tag('td'):wikitext(atk)
    if mw.ustring.len(atk)>5 then cell:css('letter-spacing','-1px') end
 
    row:tag('td'):wikitext(args['cd'] and cd(args['cd'],args['init']) or temp{args['id'],'turn'})
 
    local hp = conv(args['hp'])
    local cell = row:tag('td'):wikitext(hp)
    if mw.ustring.len(hp)>7 then cell:css('letter-spacing','-1px') end
 
    local def = conv(args['def'] or temp{args['id'],'def'})
    local cell = row:tag('td'):wikitext(def)
    if mw.ustring.len(def)>6 then cell:css('letter-spacing','-1px') end
 
    local spec = args['special'] and args['special']~=''
 
    row:tag('td'):css({position='relative', overflow='hidden'}):wikitext(drop(spec and {} or args['drop']))
    row:tag('td'):wikitext(spec and 0 or args['coin'] or '')
    row:tag('td'):wikitext(args['note'] and mw.getCurrentFrame():preprocess(args['note']) or '')
 
    return td1,td2
end
 
-- ------------------------------- --
--            Parsers              --
-- ------------------------------- --
local function parse(str,patt,pos)
    local ret,orig = {},pos or 1
    pos = orig
    for i,p in ipairs(patt) do
        if type(p) == 'table' then ret[i],pos = parse(str,p,pos)
        else
            local op = (string.sub(p,1,1) ~= '^')
            local j,k,cap = string.find(str, (op and p or string.sub(p,2)), pos)
            if j ~= pos then
                if op then ret[i] = nil
                else return nil,orig end
            else
                ret[i] = cap or string.sub(str,j,k)
                pos = k+1
            end
        end
    end
    return ret,pos
end
 
local function parseRow(row)
    local p = parse(row,{
      {'%*','^%d+','/(%d*)'},'^%s*:','%s*([^;]-)%s*;','^%s*(%d+)','[x×](%d+)','^%s+(%d*)/',{'^%d+','%(%d+%)'},'^/(%d*)/','%d+',
      {'^%s+%[',{'%d+','^@(%d+)'},'%s*%f[^%s%[]#(%d+)','%s*%f[^%s%[]$(%d+)','%s*%f[^%s%[]O(%d+)','^%]%s*'}
      ,'%s*[%s%+]$(%d+)','%s*:(.+)'
    })
 
    return p and {
        fixdrop = p[1] and p[1][1],
        stage = p[1] and (p[1][2]=='0' and '' or p[1][2]),
        extra = p[1] and p[1][3],
        special = p[3],
        id = p[4],
        num = p[5],
        atk = p[6],
        cd = p[7] and p[7][1],
        init = p[7] and p[7][2],
        hp = p[8],
        def = p[9],
        drop = p[10] and (p[10][2] or p[10][3] or p[10][4] or p[10][5]) and {
            card = p[10][2] and {id = p[10][2][1] or p[4], lv = p[10][2][2]},
            item = p[10][3],
            coin = p[10][4],
            soul = p[10][5],
            craft = p[10][6]
        },
        coin = p[11],
        note = p[12]
    }
end
 
local function parseRows(rows)
    local rst = {}
    for i,row in ipairs(rows) do
        if row ~= '' then
            local pr = parseRow(row)
            if pr then table.insert(rst, pr) end
        end
    end
    return rst
end
 
-- ------------------------------- --
--              MAIN               --
-- ------------------------------- --
function m.stage(frame)
    root = mw.html.create('table')
    root:addClass('wikitable stageData')
    header()
 
    rows = parseRows(mw.text.split(frame.args[1], '\n'))
 
    local c1, c2, row, td1, td2, dr, ex = 1,1
    while 1 do
        repeat row = table.remove(rows,1) until row ~= ''
        if row == nil then break end
        local _td1, _td2 = addRow(row,'attr-'..attr(row['id']))
        local _dr, _ex = row['fixdrop'] and (row['drop'] or {}), row['stage'] and extra(row['extra'])
        if _td1 == nil then error(row) end
        if _td2 == '' then c2 = c2 + 1
        elseif _td2 then
            if td2 then td2:attr('rowspan',c2) end
            td2, c2 = _td2, 1
        end
        if _ex == nil then
            if _dr then dr = dr and {'', dr['card'] or _dr['card'], dr['item'] or _dr['item'], dr['coin'] or _dr['coin'], dr['soul'] or _dr['soul'], dr['craft'] or _dr['craft'],''} end
            c1 = c1 + 1
        else
            if td1 then td1:attr('rowspan',c1):wikitext(dropnote(dr)):wikitext(ex) end
            td1, dr, ex, c1 = _td1, _dr, _ex, 1
        end
    end
    if td2 then td2:attr('rowspan',c2) end
    if td1 then td1:attr('rowspan',c1):wikitext(dropnote(dr)):wikitext(ex) end
 
    return tostring(root)
end
 
function m.subst(frame)
    local rst = '{{StageHeader}}\n'
    local rows = parseRows(mw.text.split(frame.args[1], '\n'))
    local rare = {'黃','銅','銀','金','白金','白金','白金','白金'}
 
    for i,row in ipairs(rows) do
        rst = rst .. '{{StageData|' .. row.id
 
        if row.stage~='' then
            rst = rst .. '|stage=' .. (row.stage or '')
            if row.fixdrop then
                local j,dr = i,{card=nil, item=nil, coin=nil, soul=nil}
                repeat
                    if rows[j].drop then for k,v in pairs(rows[j].drop) do dr[k] = dr[k] or v end end
                    j = j+1
                until not rows[j] or rows[j].stage
 
                rst = rst .. '{{掉落'
                if dr.card and not (dr.item or dr.coin or dr.soul) then rst = rst .. '|' .. (rare[tonumber(temp{row.id,'rare'})] or 'Platinum')
                elseif dr.item and not (dr.card or dr.coin or dr.soul) then rst = rst .. '|' .. dr.item
                elseif not (dr.card or dr.item or dr.coin or dr.soul) then table.insert(errors, 'Fixdrop: No drop in stage '..row.stage) end
                rst = rst .. '}}'
            end
            if row.extra then rst = rst .. (row.extra=='' and '{{亂入}}' or '{{random'..(row.extra=='1' and '' or '|'..row.extra)..'}}') end
        end
 
        if row.num then rst = rst .. '|num=' .. row.num end
        if row.special then rst = rst .. '|special=' .. row.special end
        rst = rst .. '|damage=' .. conv(row.atk)
        rst = rst .. '|turn=' .. (row.cd or temp{row.id, 'turn'})
        if row.init then rst = rst .. '{{StartCD|' .. row.init .. '}}' end
        rst = rst .. '|hp=' .. conv(row.hp)
        rst = rst .. '|def=' .. (row.def and conv(row.def) or temp{row.id, 'def'})
 
        if row.drop then
            if row.drop.card and row.drop.card.id ~= row.id then rst = rst .. '|drop=' .. row.drop.card.id end
            if row.drop.card and row.drop.card.lv then rst = rst .. '|lv=' .. row.drop.card.lv end
            if row.drop.item then rst = rst .. '|item=' .. row.drop.item end
            if row.drop.chest then rst = rst .. '|coin=' .. row.drop.coin end
            if row.drop.soul then rst = rst .. '|soul=' .. row.drop.soul end
            if row.drop.craft then rst = rst .. '|craft=' .. row.drop.craft end
        end
 
        if row.coin then rst = rst .. '|coin=' .. row.coin end
        if row.note then rst = rst .. '|note=' .. row.note end
 
        rst = rst .. '}}\n'
    end
    rst = rst .. '|}'
 
    return rst
end
 
function m.header(frame) return header(mw.html.create('')) end
function m.drop(frame)
    local args = frame:getParent().args
    local drps = {}
    for k,v in pairs(args) do
        drps[k] = (v~='' or nil) and v
    end
    drps['card'] = drps['lv'] and {id=drps['drop'], lv=drps['lv']}
    return drop(drps)
end
function m.dropnote(frame)
    local arg = frame:getParent().args[1]
    if not arg then
        return dropnote{}
    elseif string.find(arg,'^%d+$') then
        return dropnote{item=arg}
    else
        return dropnote{rare=arg}
    end
end
 
return m

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.