Module:Damage: Difference between revisions

no edit summary
No edit summary
No edit summary
Line 1: Line 1:
-- pystart
require('Module:CommonFunctions');
require('Module:CommonFunctions');
local getArgs = require('Module:Arguments').getArgs
local getArgs = require('Module:Arguments').getArgs
Line 27: Line 26:
         for _, mode in ipairs(modes) do
         for _, mode in ipairs(modes) do
             func(mode)
             func(mode)
        end
    end
    function forEachDamageType(func)
        for _, damage_type in ipairs({ 'min', 'max' }) do
            func(damage_type)
         end
         end
     end
     end
Line 312: Line 317:
         for config_key, config_value in pairs(DAMAGE_CONFIG) do
         for config_key, config_value in pairs(DAMAGE_CONFIG) do
             for k, v in pairs(config_value) do
             for k, v in pairs(config_value) do
                 local output_value = v
                 local output_value = {}
                 for _, v2 in ipairs(v) do
 
                     local arg_from_template = args[prefix .. v2] or args[v2]
                -- When both min and max are found, we need to break from the loop.
                    if arg_from_template ~= nil then
                local isValueFound = { min = false, max = false }
                        output_value = arg_from_template
 
                        if k == 'provided' then
                 for _, v2 in ipairs(v) do -- This array holds the argument names with fallbacks
                            output_value = true
                     forEachDamageType(function(damage_type)
                            -- Do not generate total_damage values at all if the skill can't reach them.
                        -- If there already is a value for this damage type (min or max), do not continue.
                            if string.find(config_key, 'total_') and OPTIONS.no_max then
                        if isValueFound[damage_type] == true then
                            return
                        end
 
                        local arg_from_template =
                            args[prefix .. v2 .. '_' .. damage_type]
                            or args[v2 .. '_' .. damage_type]
                            or args[prefix .. v2]
                            or args[v2];
 
                        if arg_from_template ~= nil then
                            if k == 'provided' then
                                output_value = true
                                -- Do not generate total_damage values at all if the skill can't reach them.
                                if string.find(config_key, 'total_') and OPTIONS.no_max then
                                    output_value = false
                                end
                            else
                                if type(output_value) ~= "table" then
                                    output_value = {}
                                end
                                output_value[damage_type] = arg_from_template
                            end
                            -- Mark the value as found.
                            isValueFound[damage_type] = true
                        else
                            if k == 'provided' then
                                 output_value = false
                                 output_value = false
                            else
                                output_value[damage_type] = {}
                             end
                             end
                         end
                         end
                    end)
                    -- Both values found, we can now break the loop.
                    if isValueFound.min and isValueFound.max then
                         break
                         break
                    else
                        if k == 'provided' then
                            output_value = false
                        else
                            output_value = {}
                        end
                     end
                     end
                 end
                 end
Line 351: Line 382:
                     local new_value = table.deep_copy(damage_value)
                     local new_value = table.deep_copy(damage_value)


                     for k, hit_count in ipairs(new_value.hit_counts) do
                     forEachDamageType(function(damage_type)
                        hit_count = hit_count == '' and 1 or hit_count
                        for k, hit_count in ipairs(new_value.hit_counts[damage_type]) do
                        new_value.hit_counts[k] = hit_count *
                            hit_count = hit_count == '' and 1 or hit_count
                            ((string.find(damage_key, 'awk_') and args.awk_count) and args.awk_count[1] or args.count[1])
                            new_value.hit_counts[damage_type][k] = hit_count *
                     end
                                ((string.find(damage_key, 'awk_') and args.awk_count) and args.awk_count[1] or args.count[1])
                        end
                     end)


                     WITH_EACH[mode][damage_key:gsub("total_", "each_")] = damage_value
                     WITH_EACH[mode][damage_key:gsub("total_", "each_")] = damage_value
Line 372: Line 405:
         for mode, mode_content in pairs(DAMAGE_PARSED) do
         for mode, mode_content in pairs(DAMAGE_PARSED) do
             for damage_key, damage_value in pairs(mode_content) do
             for damage_key, damage_value in pairs(mode_content) do
                 local i = 1
                 forEachDamageType(function(damage_type)
                local output = 0
                    local i = 1
                -- Check if to even generate the damage.
                    local output = 0
                if damage_value.provided then
                    -- Check if to even generate the damage.
                    -- Loop through damage numbers and multiply them with hits.
                    if damage_value.provided then
                    for k, damage_number in ipairs(damage_value.damage_numbers) do
                        -- Loop through damage numbers and multiply them with hits.
                        local hit_count = damage_value.hit_counts[i]
                        for k, damage_number in ipairs(damage_value.damage_numbers[damage_type]) do
                        hit_count = hit_count == '' and 1 or hit_count
                            local hit_count = damage_value.hit_counts[damage_type][i]
                        output = output + (damage_number * hit_count)
                            hit_count = hit_count == '' and 1 or hit_count
                        i = i + 1
                            output = output + (damage_number * hit_count)
                            i = i + 1
                        end
                        -- Write the result to a separate object.
                        if not BASIC_DAMAGE[mode][damage_key] then
                            BASIC_DAMAGE[mode][damage_key] = {}
                        end
                        BASIC_DAMAGE[mode][damage_key][damage_type] = output
                     end
                     end
                    -- Write the result to a separate object.
                 end)
                    BASIC_DAMAGE[mode][damage_key] = output
                 end
             end
             end
         end
         end
Line 397: Line 435:
             for damage_key, damage_value in pairs(mode_content) do
             for damage_key, damage_value in pairs(mode_content) do
                 local cancel_candidate = BASIC_DAMAGE[mode]['cancel_' .. damage_key]
                 local cancel_candidate = BASIC_DAMAGE[mode]['cancel_' .. damage_key]
                 if not string.find(damage_key, 'cancel_') and cancel_candidate then
                 forEachDamageType(function(damage_type)
                    BASIC_DAMAGE[mode][damage_key] = damage_value + cancel_candidate
                    if not string.find(damage_key, 'cancel_') and cancel_candidate then
                 end
                        BASIC_DAMAGE[mode][damage_key][damage_type] = damage_value[damage_type] +
                            cancel_candidate[damage_type]
                    end
                 end)
             end
             end
         end
         end
Line 421: Line 462:
                     --]]
                     --]]
                     if (trait.value and trait.key ~= 'useful') or (string.find(damage_key, 'useful') and trait.key == 'useful') then
                     if (trait.value and trait.key ~= 'useful') or (string.find(damage_key, 'useful') and trait.key == 'useful') then
                         WITH_TRAITS[mode][damage_key .. ((trait.key == 'useful' or trait.key == '') and "" or ('_' .. trait.key))] =
                         forEachDamageType(function(damage_type)
                             damage_value * trait.value
                            local new_key = damage_key ..
                                ((trait.key == 'useful' or trait.key == '') and "" or ('_' .. trait.key));
                            if not WITH_TRAITS[mode][new_key] then
                                WITH_TRAITS[mode][new_key] = {}
                            end
                             WITH_TRAITS[mode][new_key][damage_type] = damage_value[damage_type] * trait.value
                        end)
                     end
                     end
                 end
                 end
Line 441: Line 488:
         for mode, mode_content in pairs(WITH_TRAITS) do
         for mode, mode_content in pairs(WITH_TRAITS) do
             for damage_key, damage_value in pairs(mode_content) do
             for damage_key, damage_value in pairs(mode_content) do
                 local combinations = { {} }
                 forEachDamageType(function(damage_type)
                for passive_key, passive in pairs(PASSIVES) do
                    local combinations = { {} }
                    local count = #combinations
                    for passive_key, passive in pairs(PASSIVES) do
                    for i = 1, count do
                        local count = #combinations
                        local new_combination = { unpack(combinations[i]) }
                        for i = 1, count do
                        table.insert(new_combination, passive_key)
                            local new_combination = { unpack(combinations[i]) }
                        table.insert(combinations, new_combination)
                            table.insert(new_combination, passive_key)
                            table.insert(combinations, new_combination)
                        end
                     end
                     end
                end
                    for _, combination in pairs(combinations) do
                for _, combination in pairs(combinations) do
                        local passive_multiplier = 1
                    local passive_multiplier = 1
                        local name_suffix = ''
                    local name_suffix = ''
                        if #combination > 0 then
                    if #combination > 0 then
                            table.sort(combination)
                        table.sort(combination)
                            for _, passive_key in pairs(combination) do
                        for _, passive_key in pairs(combination) do
                                passive_multiplier = passive_multiplier *
                            passive_multiplier = passive_multiplier *
                                    tonumber(PASSIVES[passive_key][mode == 'PvE' and 'value' or 'value_pvp'])
                                tonumber(PASSIVES[passive_key][mode == 'PvE' and 'value' or 'value_pvp'])
                                name_suffix = name_suffix .. '_passive' .. passive_key
                            name_suffix = name_suffix .. '_passive' .. passive_key
                            end
                        end
                        local new_damage_key = damage_key .. name_suffix;
                        if not WITH_PASSIVES[mode][new_damage_key] then
                            WITH_PASSIVES[mode][new_damage_key] = {}
                         end
                         end
                        WITH_PASSIVES[mode][new_damage_key][damage_type] = damage_value[damage_type] * passive_multiplier
                     end
                     end
                    WITH_PASSIVES[mode][damage_key .. name_suffix] = damage_value * passive_multiplier
                 end)
                 end
             end
             end
         end
         end
Line 488: Line 541:
             for damage_key, damage_value in pairs(mode_content) do
             for damage_key, damage_value in pairs(mode_content) do
                 WITH_RANGE[mode][damage_key] = { min = 0, max = 0 }
                 WITH_RANGE[mode][damage_key] = { min = 0, max = 0 }
                 for _, range in ipairs({ 'min', 'max' }) do
                 forEachDamageType(function(damage_type)
                     local final_damage_value = damage_value * (1 + ((RANGE[mode][range] - 1) * RANGE[range .. '_count'])) *
                    local range_count = RANGE[damage_type .. '_count'];
                        OPTIONS.perm_buff[mode]
                     local range_multiplier = RANGE[mode][damage_type];
                     WITH_RANGE[mode][damage_key][range] = not OPTIONS.format and final_damage_value or
                    local final_range_multiplier = (1 + ((range_multiplier - 1) * range_count));
                    local perm_buff = OPTIONS.perm_buff[mode];
 
                    local final_damage_value = damage_value[damage_type] * final_range_multiplier * perm_buff;
                     WITH_RANGE[mode][damage_key][damage_type] = not OPTIONS.format and final_damage_value or
                         formatDamage(final_damage_value)
                         formatDamage(final_damage_value)
                 end
                 end)
             end
             end
         end
         end
Line 830: Line 887:
     end
     end


     doTable()
     if OPTIONS.do_table then
        doTable()
    end


     -- Dump all values if wanted.
     -- Dump all values if wanted.
Line 860: Line 919:


return p
return p
-- pyend