Module:AttackStyles

From Outward Wiki
Jump to navigation Jump to search
Template-info.svg Documentation

Lua module used by the AttackStyles Template.


local p = {}

function p.main(frame)
    if frame == mw.getCurrentFrame() then
		args = require('Module:ProcessArgs').merge(true)
	else
		frame = mw.getCurrentFrame()
    end

    local item = args.item or mw.title.getCurrentTitle().text

    -- iterate over unnamed args, put into table
    local ip = {}
    for k, v in ipairs(args) do
        ip[k] = v
    end

    local itemResult = mw.ext.cargo.query(
        'ItemData', 
        '_pageName, class, type, physical, ethereal, decay, lightning, frost, fire, impact, stamcost', 
        {
            where = '_pageName="' .. item .. '"',
            limit = 1
        }
    )

    if not itemResult[1] then return '' end
    local itemData = itemResult[1]
    local class = itemData.class
    local type = ''
    if (class ~= 'Polearm' and class ~= 'Spear' and class ~= 'Gauntlet') then
        type = itemData.type
    end

    local classWhere = 'name="' ..  class .. '"'
    if (type ~= nil and type ~= '') then
        classWhere = classWhere .. ' AND type="' .. type .. '"'        
    end

    local classResult = mw.ext.cargo.query(
        'WeaponClasses',
        'name, type, lightDescription, lightHits, specialDmg, specialImpact, specialStam, specialDescription, specialHits, combo1Dmg, combo1Impact, combo1Stam, combo1Description, combo1Hits, combo2Dmg, combo2Impact, combo2Stam, combo2Description, combo2Hits',
        {
            where = classWhere,
            limit = 1
        }
    )

    if not classResult[1] then return frame:preprocess('[[Category: Pages with broken class data]]') end
    local classData = classResult[1]

    -- calculate scaled damages
    local baseDamage = {
        phys      = itemData.physical ~= '' and tonumber(itemData.physical) or 0,
        ethereal  = itemData.ethereal ~= '' and tonumber(itemData.ethereal) or 0,
        decay     = itemData.decay ~= '' and tonumber(itemData.decay) or 0,
        lightning = itemData.lightning ~= '' and tonumber(itemData.lightning) or 0,
        frost     = itemData.frost ~= '' and tonumber(itemData.frost) or 0,
        fire      = itemData.fire ~= '' and tonumber(itemData.fire) or 0
    }
    local baseImpact = itemData.impact ~= '' and tonumber(itemData.impact)
    local baseStam = (itemData.stamcost ~= '' and tonumber(itemData.stamcost)) or ip[1]

    local attackData = {}

    if (args.manual ~= nil) then
        attackData = {
            standard = {
                stamcost = ip[1],
                impact = ip[2],
                damage = ip[3]
            },
            special = {
                stamcost = ip[4],
                impact = ip[5],
                damage = ip[6]
            },
            combo1 = {
                stamcost = ip[7],
                impact = ip[8],
                damage = ip[9]
            },
            combo2 = {
                stamcost = ip[10],
                impact = ip[11],
                damage = ip[12]
            }
        } 
    else
         attackData = {
            standard = {
                damage = buildDamage(baseDamage, 1.0, bonuses),
                impact = tostring(baseImpact),
                stamcost = tostring(baseStam)
            },
            special = {
                damage = buildDamage(baseDamage, tonumber(classData.specialDmg)),
                impact = tostring(round(baseImpact * classData.specialImpact, 2)),
                stamcost = tostring(round(baseStam * classData.specialStam, 2))
            },
            combo1 = {
                damage = buildDamage(baseDamage, tonumber(classData.combo1Dmg)),
                impact = tostring(round(baseImpact * classData.combo1Impact, 2)),
                stamcost = tostring(round(baseStam * classData.combo1Stam, 2))
            },
            combo2 = {
                damage = buildDamage(baseDamage, tonumber(classData.combo2Dmg)),
                impact = tostring(round(baseImpact * classData.combo2Impact, 2)),
                stamcost = tostring(round(baseStam * classData.combo2Stam, 2))
            },
        }    
    end

    -- build wikitable
    local html = mw.html.create()
    
    local seealso = class .. 's'
    local type2 = ''
    if type ~= '' then 
        seealso = seealso .. '#' .. type .. '_2' -- eg, "Swords#One-Handed_2" 
        type2 = type .. ' ' -- for adding the "X-Handed " before the displayed text, when needed
    else
        seealso = seealso .. '#Animations' -- eg "Polearms#Animations"
    end
    html:wikitext(frame:preprocess('{{hatnote|<i>See also: [[' .. seealso .. '|' .. type2 .. class .. ' Animations' .. ']]</i>}}'))

    local tbl = html:tag('table'):addClass('wikitable sortable')

    local trHeader = tbl:tag('tr')
    trHeader:tag('th'):cssText('min-width:100px'):wikitext('Input')
    trHeader:tag('th'):cssText('min-width:130px'):wikitext('Damage')
    trHeader:tag('th'):cssText('min-width:65px'):wikitext('Impact')
    trHeader:tag('th'):cssText('min-width:45px'):wikitext('Cost')
    trHeader:tag('th'):wikitext('Attacks')
    trHeader:tag('th'):cssText('min-width:170px'):wikitext('Description')

    -- standard row
    buildRow(frame, tbl, '<b>Standard > Standard</b>', attackData.standard, '<i>' .. classData.lightDescription .. '</i>', classData.lightHits)
    -- special row
    buildRow(frame, tbl, '<b>Special</b>', attackData.special, '<i>' .. classData.specialDescription .. '</i>', classData.specialHits)
    -- combo 1 row
    buildRow(frame, tbl, '<i style="color:#AAA">Standard</i> > <b>Special</b>', attackData.combo1, '<i>' .. classData.combo1Description .. '</i>', classData.combo1Hits)
    -- combo 2 row
    buildRow(frame, tbl, '<i style="color:#AAA">Standard</i> > <i style="color:#AAA">Standard</i> > <b>Special</b>', attackData.combo2, '<i>' .. classData.combo2Description .. '</i>', classData.combo2Hits)

    return html
end

function buildRow(frame, tbl, pattern, attackdata, description, hits) 
    local tr = tbl:tag('tr')
    tr:tag('td'):wikitext(frame:preprocess(pattern))
    tr:tag('td'):cssText('text-align: center;'):wikitext(frame:preprocess(attackdata.damage))
    tr:tag('td'):cssText('text-align: center;'):wikitext(frame:preprocess(attackdata.impact .. ' {{impact}}'))
    tr:tag('td'):cssText('text-align: center;'):wikitext(frame:preprocess(attackdata.stamcost .. ' {{stamina}}'))
    tr:tag('td'):cssText('text-align: center;'):wikitext(hits)
    tr:tag('td'):wikitext(frame:preprocess(description))
end

function buildDamage(baseDamage, classDmg)
    local dmgString = ''
    local types = {'phys','ethereal','decay','lightning','frost','fire'}
    for i, type in ipairs(types) do
        local v = baseDamage[type]
        if v > 0 then
            local dmg = v * classDmg 
            dmg = round(dmg, 2)
            if (dmgString ~= '') then dmgString = dmgString .. '<br class="mobileonly"> ' end
            dmgString = dmgString .. tostring(dmg) .. ' {{' .. type .. '}}'
        end
    end
    return dmgString
end

function round(num, numDecimalPlaces)
    local mult = 10^(numDecimalPlaces or 0)
    return math.floor(num * mult + 0.5) / mult
end

return p