| Latest revision |
Your text |
| Line 45: |
Line 45: |
| end | | end |
| return nil, nil, nil | | return nil, nil, nil |
| end
| |
|
| |
| -- Sums the non-zero values of `fields` within a single record layer (the base
| |
| -- ability record, or one upgrade tier). Returns nil when none are present.
| |
| local function sum_fields(layer, fields)
| |
| local total = nil
| |
| for _, field in ipairs(fields) do
| |
| local v = unwrap_value(layer[field])
| |
| if v and v ~= 0 then total = (total or 0) + math.abs(v) end
| |
| end
| |
| return total
| |
| end
| |
|
| |
| -- Sums the barrier value and Spirit scaling contributed by a single record
| |
| -- layer (the base ability record, or one upgrade tier). Returns nil when the
| |
| -- layer grants no barrier at all; a tier that only raises the scaling still
| |
| -- counts, so "+0 value, +1.0 scaling" upgrades are not lost.
| |
| local function sum_barrier(layer, fields)
| |
| local value, scale, found = 0, 0, false
| |
| for _, field in ipairs(fields) do
| |
| local entry = layer[field]
| |
| if entry ~= nil then
| |
| local v = unwrap_value(entry) or 0
| |
| local s = 0
| |
| if type(entry) == "table" and type(entry["Scale"]) == "table" then
| |
| s = entry["Scale"]["Value"] or 0
| |
| end
| |
| if v ~= 0 or s ~= 0 then found = true end
| |
| value = value + v
| |
| scale = scale + s
| |
| end
| |
| end
| |
| if not found then return nil end
| |
| return value, scale
| |
| end
| |
|
| |
| -- Pads a whole-number scaling out to one decimal, so a running total of 2
| |
| -- reads "2.0" next to its "1.5" neighbours instead of "2". Values that already
| |
| -- carry decimals are left alone, which keeps precision on things like 0.75.
| |
| local function format_scale(scale)
| |
| local text = tostring(scale)
| |
| if not text:find(".", 1, true) then text = text .. ".0" end
| |
| return text
| |
| end
| |
|
| |
| -- Formats one barrier step. Spirit scaling goes through the compact {{Ss}}
| |
| -- form, expanded via the frame the surrounding #invoke is already running
| |
| -- under: module return values are not re-expanded, so a literal "{{Ss|0.8}}"
| |
| -- would reach the page as text. The plain fallback covers a nil frame
| |
| -- (module console).
| |
| local function format_barrier(value, scale)
| |
| local out = tostring(value)
| |
| if scale and scale ~= 0 then
| |
| local scale_text = format_scale(scale)
| |
| local frame = mw.getCurrentFrame()
| |
| if frame then
| |
| out = out .. " " .. frame:expandTemplate{
| |
| title = "Ss",
| |
| args = { scale_text, compact = "1", show_value = "1" },
| |
| }
| |
| else
| |
| out = out .. " ×" .. scale_text
| |
| end
| |
| end
| |
| return out
| |
| end | | end |
|
| |
|
| Line 168: |
Line 103: |
|
| |
|
| local p = {} | | local p = {} |
|
| |
| -- Renders the barrier an ability grants, with its Spirit Power scaling.
| |
| -- Both the value and the scaling accumulate across upgrades, so every step
| |
| -- after the first shows the running total: "100 x0.8 → 180 x1.5 (T2)".
| |
| -- A tier that only improves the scaling still gets its own segment.
| |
| function p.RenderBarrier(ability)
| |
| local fields = Lists.lists["barrier"]
| |
| local segments = {}
| |
|
| |
| local value, scale = sum_barrier(ability, fields)
| |
| if value then
| |
| table.insert(segments, format_barrier(value, scale))
| |
| else
| |
| value, scale = 0, 0
| |
| end
| |
|
| |
| local upgrades = ability["Upgrades"]
| |
| if type(upgrades) == "table" then
| |
| for i, tier in ipairs(upgrades) do
| |
| if type(tier) == "table" then
| |
| local delta_value, delta_scale = sum_barrier(tier, fields)
| |
| if delta_value then
| |
| value, scale = value + delta_value, scale + delta_scale
| |
| table.insert(segments,
| |
| format_barrier(value, scale) .. " (T" .. i .. ")")
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| if #segments == 0 then return {} end
| |
| return { ["Barrier"] = table.concat(segments, " → ") }
| |
| end
| |
|
| |
|
| -- Renders charge count and time between charges. | | -- Renders charge count and time between charges. |
| Line 206: |
Line 108: |
| function p.RenderCharges(ability) | | function p.RenderCharges(ability) |
| local base_charges = unwrap_value(ability["AbilityCharges"]) | | local base_charges = unwrap_value(ability["AbilityCharges"]) |
| local base_cooldown = unwrap_value(ability["AbilityCooldownBetweenCharge"]) | | local base_cooldown = ability["AbilityCooldownBetweenCharge"] |
| local has_base = base_charges ~= nil and base_charges > 0 | | local has_base = base_charges ~= nil and base_charges > 0 |
| local upgrade_info = find_in_upgrades(ability, "AbilityCharges") | | local upgrade_info = find_in_upgrades(ability, "AbilityCharges") |
| Line 399: |
Line 301: |
| end | | end |
| end | | end |
| end
| |
|
| |
| return cells
| |
| end
| |
|
| |
| -- Renders Spirit Power scaling.
| |
| -- Shows the Scale.Value for abilities whose Scale.Type is "spirit".
| |
| function p.RenderSpiritScaling(ability)
| |
| local base_scale = nil
| |
| local base_prop = nil
| |
|
| |
| -- Find base Spirit scaling
| |
| for k, v in pairs(ability) do
| |
| if k ~= "Upgrades" and type(v) == "table" then
| |
| local scale = v["Scale"]
| |
| if type(scale) == "table"
| |
| and scale["Type"] == "spirit"
| |
| and type(scale["Value"]) == "number"
| |
| and scale["Value"] ~= 0 then
| |
| base_scale = scale["Value"]
| |
| base_prop = k
| |
| break
| |
| end
| |
| end
| |
| end
| |
|
| |
| local cells = {}
| |
|
| |
| if base_scale then
| |
| cells["Spirit Scaling"] = "×" .. base_scale
| |
| end
| |
|
| |
| local upgrades = ability["Upgrades"]
| |
| if type(upgrades) ~= "table" then return cells end
| |
|
| |
| local notes = {}
| |
|
| |
| for i, tier in ipairs(upgrades) do
| |
| if type(tier) == "table" then
| |
| local upgrade_scale = nil
| |
|
| |
| for k, v in pairs(tier) do
| |
| if type(v) == "table" then
| |
| local scale = v["Scale"]
| |
| if type(scale) == "table"
| |
| and scale["Type"] == "spirit"
| |
| and type(scale["Value"]) == "number"
| |
| and scale["Value"] ~= 0 then
| |
| upgrade_scale = scale["Value"]
| |
| break
| |
| end
| |
| end
| |
| end
| |
|
| |
| if upgrade_scale then
| |
| table.insert(notes,
| |
| "on T" .. i .. " gets +×" .. upgrade_scale .. " Spirit scaling")
| |
| end
| |
| end
| |
| end
| |
|
| |
| if #notes > 0 then
| |
| cells["Notes"] = table.concat(notes, ". ")
| |
| end | | end |
|
| |
|
| Line 486: |
Line 325: |
| end | | end |
| return render_upgradable_stat(ability, "Heal Reduction", filtered, "%") | | return render_upgradable_stat(ability, "Heal Reduction", filtered, "%") |
| | end |
| | |
| | -- Renders "Is Ultimate" column for Divine Barrier. |
| | -- Receives ability info (hero name, slot number) as second parameter. |
| | function p.RenderDivineBarrier(ability, info) |
| | local cells = {} |
| | if info and info.abilityNum == 4 then |
| | cells["Is Ultimate"] = "✔" |
| | end |
| | return cells |
| end | | end |
|
| |
|
| Line 556: |
Line 405: |
|
| |
|
| return cells | | return cells |
| end
| |
|
| |
| -- Renders the amount of Debuff Resist an ability grants.
| |
| -- Upgrades stack additively onto the base value, so every step after the first
| |
| -- shows the running total: "20% (T3)" when granted only by an upgrade,
| |
| -- "10% → 25% (T2)" when a base value is later increased. Chains for any number
| |
| -- of steps. No ability currently has both a base and an upgrade value.
| |
| function p.RenderExtraDebuffResist(ability)
| |
| local fields = Lists.lists["extradebuffresist"]
| |
| local segments = {}
| |
|
| |
| local running = sum_fields(ability, fields)
| |
| if running then
| |
| table.insert(segments, running .. "%")
| |
| end
| |
|
| |
| local upgrades = ability["Upgrades"]
| |
| if type(upgrades) == "table" then
| |
| for i, tier in ipairs(upgrades) do
| |
| if type(tier) == "table" then
| |
| local delta = sum_fields(tier, fields)
| |
| if delta then
| |
| running = (running or 0) + delta
| |
| table.insert(segments, running .. "% (T" .. i .. ")")
| |
| end
| |
| end
| |
| end
| |
| end
| |
|
| |
| if #segments == 0 then return {} end
| |
| return { ["Debuff Resist"] = table.concat(segments, " → ") }
| |
| end | | end |
|
| |
|
| return p | | return p |