Module:Damage

From Elwiki
Revision as of 16:17, 7 April 2022 by Ritsu (talk | contribs)

Documentation for this module may be created at Module:Damage/doc

require('Module:CommonFunctions')
local getArgs = require('Module:Arguments').getArgs
local p = {}

-- Main process
function p.main(frame)
    local args = getArgs(frame)

    function inArgs(key)
        if args[key] ~= nil then
            return true
        end
    end

    -- Function wrapper for vardefine syntax in MW.
    function var(name, dmg, prefix)
        if prefix == nil then prefix = '' else prefix = prefix .. '_' end
        if (args.format == 'false') then
            return '{{#vardefine:' .. prefix .. name .. '|' .. round(dmg) .. '}}'
        else
            return '{{#vardefine:' .. prefix .. name .. '|{{formatnum:' .. round(dmg) .. '}}%}}'
        end
    end

    -- Collect data from the input
    local data = {}
    local data_types = {
        'dmg', 'pvp_dmg', 'awk_dmg', 'pvp_awk_dmg',
        'hits', 'avg_hits',
        'awk_hits', 'avg_awk_hits',
        'hits_useful', 'avg_hits_useful',
        'awk_hits_useful', 'avg_awk_hits_useful'
    }
    for k,v in spairs(data_types) do
        local i = 1
        if (inArgs(v)) then
            local x = split(args[v])
            for k2,v2 in spairs(x) do
                data[v .. i] = v2
                i = i + 1
            end
        end
    end

    -- Handle trait table
    local traits = {}

    if (inArgs('heavy')) then
        traits.heavy = 1.44
    end

    if (inArgs('enhanced')) then
        traits.enhanced = 0.8
    end

    -- Customizable for empowered, it had to be special lol.
    if (inArgs('empowered')) then
        if (args.empowered == 'true') then
            traits.empowered = 1.2
        else
            traits.empowered = args.empowered
        end
    end

    -- Output passives if provided
    local passives = {0, 0, 0}
    for i=1, 3 do
        if inArgs('passive' .. i) then
            passives[i] = args['passive' .. i]
            passives[i] = split(frame:preprocess('{{:' .. passives[i] .. '}}{{#arrayprint:' .. passives[i] .. '}}'))
        end
    end
    

    function list(ispvp)

        -- Define tables that hold the subsequent damage values.
        -- I know this isn't the best, but I don't want to work with nested tables in this language.
        local fvals = {}
        local tvals = {}
        local pvals = {
            [1]={},
            [2]={},
            [3]={},
            [12]={},
            [13]={},
            [23]={},
            [123]={},
        }

        -- Check the specified mode and define the prefixes/suffixes first.
        local pr = ''
        local su = ''
        local p_index = 1
        if ispvp then
            p_index = 2
        end

        if (ispvp) then
            pr = 'pvp_'
            su = '_pvp'
        end

        -- Define total/average damage calculation based on damage per hit and hit amount.
        function getTotal(dmg, hits, fval)
            local i = 1
            fvals[fval] = 0
            for k, v in spairs(split(args.dmg)) do
                -- Proceed to combine
                fvals[fval] = fvals[fval] + data[dmg .. i] * data[hits .. i]
                i = i + 1
            end
            -- Apply Useful modifier.
            if string.find(fval, 'useful') then
                fvals[fval] = fvals[fval] * args.useful_penalty
            end
        end

        -- Actually generate the values depending on arguments provided.
        -- TODO: Change how this works once the old input method is removed.
        if inArgs(pr .. 'dmg') then
            getTotal(pr .. 'dmg', 'hits', 'total_damage' .. su)
        end
        
        if inArgs('avg_hits') then
            getTotal(pr .. 'dmg', 'avg_hits', 'avg_damage' .. su)
        end

        if inArgs(pr .. 'awk_dmg') then
            getTotal(pr .. 'awk_dmg', 'awk_hits', 'total_damage_awk' .. su)
        end

        if inArgs('avg_awk_hits') then
            getTotal(pr .. 'awk_dmg', 'avg_awk_hits', 'avg_damage_awk' .. su)
        end

        -- Handling traits
        -- Useful handled separately
        if inArgs('useful_penalty') then
            getTotal(pr .. 'dmg', 'hits_useful', 'total_damage_useful' .. su)

            if (inArgs('avg_hits_useful')) then
                getTotal(pr .. 'dmg', 'avg_hits_useful', 'avg_damage_useful' .. su)
            end

            if inArgs(pr .. 'awk_dmg') then
                getTotal(pr .. 'awk_dmg', 'awk_hits_useful', 'total_damage_awk_useful' .. su)
            end

            if inArgs('avg_awk_hits') then
                getTotal(pr .. 'awk_dmg', 'avg_awk_hits_useful', 'avg_damage_awk_useful' .. su)
            end
        end

        -- Multiply all values with traits and store them in another table.
        for k, v in spairs(fvals) do
            if not string.find(k, 'useful') then
                for kt, vt in spairs(traits) do
                    if inArgs(kt) then
                        local dmg_name = k .. '_' .. kt
                        if ispvp then
                            dmg_name = dmg_name:gsub(su, '') .. su
                        end
                        local dmg_formula = v * vt
                        tvals[dmg_name] = dmg_formula
                    end
                end
            end
        end

        -- Get a table of merged base & trait values
        local ftvals = fvals
        tableMerge(ftvals, tvals)

        function addPassive(num, loop_table)
            local pval_index
            if loop_table == nil then
                pval_index = num
                loop_table = ftvals
            else
                pval_index = tonumber(loop_table .. num)
                loop_table = pvals[loop_table]
            end
            for k, v in spairs(loop_table) do
                local dmg_name = k .. '_passive' .. num
                if ispvp then
                    dmg_name = dmg_name:gsub(su, '') .. su
                end
                local dmg_formula = v * passives[num][p_index]
                pvals[pval_index][dmg_name] = dmg_formula
            end
        end

        -- Add passives and combine them.
        if inArgs('passive2') then
            addPassive(2)
            if inArgs('passive3') then addPassive(3, 2) end
        end

        if inArgs('passive1') then
            addPassive(1)
            if inArgs('passive2') then
                addPassive(2, 1)
                if inArgs('passive3') then addPassive(3, 12) end
            end
            if inArgs('passive3') then addPassive(3, 1) end
        end

        if inArgs('passive3') then addPassive(3) end

        -- Merge all tables into one.
        tableMerge(fvals, tvals)
        for k, v in spairs(pvals) do
            tableMerge(fvals, v)
        end

        return fvals
    end

    local out = list(false)

    -- Merge the output to a unified table.
    tableMerge(out, list(true))

    -- Get the actual variables with MW syntax.
    local vars = {}
    for k, v in spairs(out) do
        table.insert(vars, var(k, v, args.prefix))
    end

    -- Dump all values if wanted.
    if args.dump == 'true' then
        local ret = {}
        for k, v in spairs(out) do
            table.insert(ret, k .. ': ' .. v)
        end
        return frame:preprocess(table.concat(ret, "<br/>"))
    else
        -- Parse all variables - end point
        return frame:preprocess(table.concat(vars))
    end

end

return p