打开/关闭菜单
8
231
3
1270
夜幕之下 Wiki - Reign of Nightfall 中文资料站
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

模块:StyleAttributeGrowth

来自夜幕之下 Wiki - Reign of Nightfall 中文资料站

此模块的文档可以在模块:StyleAttributeGrowth/doc创建

-- Module:StyleAttributeGrowth
-- 风格等级属性成长计算。只处理数据,不负责风格页样式。

local p = {}

local BREAK_LEVELS = {
    [0] = 20,
    [1] = 40,
    [2] = 60,
    [3] = 80,
    [4] = 100,
}

local function num(value)
    if value == nil or value == "" then return nil end
    local n = tonumber(value)
    if not n then return nil end
    return n
end

local function firstGrowth(input)
    if type(input) ~= "table" then return nil end
    local rows = input.attribute_growths
    if type(rows) == "table" then
        for _, row in ipairs(rows) do
            if type(row) == "table" and (row.status == "published" or row.status == nil) then
                return row
            end
        end
        return rows[1]
    end
    return input
end

function p.breakLevels()
    return BREAK_LEVELS
end

function p.levelToBreakCount(level)
    local lv = tonumber(level) or 1
    if lv <= 20 then return 0 end
    if lv <= 40 then return 1 end
    if lv <= 60 then return 2 end
    if lv <= 80 then return 3 end
    return 4
end

function p.normalizeGrowth(input)
    if type(input) == "table" and input.base and input.rate and input.break_bonus then
        return input
    end

    local row = firstGrowth(input)
    if type(row) ~= "table" then return nil end

    local growth = {
        status = row.status,
        source_style_id = row.source_style_id,
        source_hero_card_id = row.source_hero_card_id,
        attr_rank = row.attr_rank,
        formula_version = row.formula_version or "hero_level_growth_v1",
        base = {
            hp = num(row.base_hp),
            atk = num(row.base_atk),
            def = num(row.base_def),
        },
        rate = {
            hp = num(row.hp_rate),
            atk = num(row.atk_rate),
            def = num(row.def_rate),
        },
        break_bonus = {
            hp = num(row.break_hp),
            atk = num(row.break_atk),
            def = num(row.break_def),
        },
    }

    if not growth.base.hp or not growth.base.atk or not growth.base.def
        or not growth.rate.hp or not growth.rate.atk or not growth.rate.def
        or not growth.break_bonus.hp or not growth.break_bonus.atk or not growth.break_bonus.def then
        return nil
    end

    return growth
end

local function clamp(value, minValue, maxValue)
    value = tonumber(value) or minValue
    if value < minValue then return minValue end
    if value > maxValue then return maxValue end
    return value
end

local function calcOne(base, rate, breakBonus, level, breakCount)
    return math.floor(base + (level - 1) * rate + breakCount * breakBonus)
end

function p.calculate(input, level, breakCount)
    local growth = p.normalizeGrowth(input)
    if not growth then return nil end

    local lv = math.floor(clamp(level or 100, 1, 100))
    local bc = breakCount
    if bc == nil then
        bc = p.levelToBreakCount(lv)
    else
        bc = math.floor(clamp(bc, 0, 4))
        lv = math.floor(clamp(lv, 1, BREAK_LEVELS[bc] or 100))
    end

    local hpGrowth = (lv - 1) * growth.rate.hp
    local atkGrowth = (lv - 1) * growth.rate.atk
    local defGrowth = (lv - 1) * growth.rate.def
    local hpBreak = bc * growth.break_bonus.hp
    local atkBreak = bc * growth.break_bonus.atk
    local defBreak = bc * growth.break_bonus.def

    return {
        level = lv,
        break_count = bc,
        max_level = BREAK_LEVELS[bc] or 100,
        hp = calcOne(growth.base.hp, growth.rate.hp, growth.break_bonus.hp, lv, bc),
        atk = calcOne(growth.base.atk, growth.rate.atk, growth.break_bonus.atk, lv, bc),
        def = calcOne(growth.base.def, growth.rate.def, growth.break_bonus.def, lv, bc),
        parts = {
            hp = { base = growth.base.hp, growth = hpGrowth, break_bonus = hpBreak },
            atk = { base = growth.base.atk, growth = atkGrowth, break_bonus = atkBreak },
            def = { base = growth.base.def, growth = defGrowth, break_bonus = defBreak },
        },
    }
end

function p.payload(input, defaultLevel)
    local growth = p.normalizeGrowth(input)
    if not growth then return nil end
    local result = p.calculate(growth, defaultLevel or 100)
    return {
        growth = growth,
        result = result,
        data = {
            default_level = result.level,
            formula_version = growth.formula_version,
            base_hp = growth.base.hp,
            base_atk = growth.base.atk,
            base_def = growth.base.def,
            hp_rate = growth.rate.hp,
            atk_rate = growth.rate.atk,
            def_rate = growth.rate.def,
            break_hp = growth.break_bonus.hp,
            break_atk = growth.break_bonus.atk,
            break_def = growth.break_bonus.def,
        },
    }
end

return p