Module:ExpressShotGive feedback
Jump to navigation
Jump to search
Documentation for this module may be created at Module:ExpressShot/doc
local p = {}
local heroes_data = mw.loadJsonData("Data:HeroData.json")
local items_data = mw.loadJsonData("Data:ItemData.json")
-- Reads a property from Data:ItemData.json, unwrapping the {Value, Scale} form
-- that scaling properties use. Returns the unscaled base value.
local function get_item_prop(item_name, property)
for _, item in pairs(items_data) do
if item["Name"] == item_name and item["IsDisabled"] ~= true then
local value = item[property]
if type(value) == "table" then value = value["Value"] end
return tonumber(value)
end
end
return nil
end
-- Damage of a single Express Shot proc attack.
--
-- The proc fires two bursts. Every bullet of the second burst is bonused, but
-- only the first bullet of the first burst is. For non-burst weapons
-- (BulletsPerBurst == 1) this collapses to both shots being fully bonused.
-- Spreadshot pellets are each bonused; weapons that only register one hit
-- across all their bullets (HitOnceAcrossAllBullets) count as a single bullet.
--
-- @param {table} weapon a Weapon or Weapon.AltFire table
-- @param {number} percent proc bonus damage, in percent of Bullet Damage
-- @return {number, number} total attack damage, bonus damage over a normal attack
local function proc_damage(weapon, percent)
local damage = weapon["BulletDamage"] or 0
local bullets = weapon["HitOnceAcrossAllBullets"] and 1 or (weapon["BulletsPerShot"] or 1)
local burst = weapon["BulletsPerBurst"] or 1
local bonus_scale = percent / 100
local per_bullet = damage * bullets
local bonused_bullets = burst + 1
local total_bullets = burst * 2
local total = per_bullet * (total_bullets + bonused_bullets * bonus_scale)
local normal = per_bullet * burst
return total, total - normal
end
-- Builds one table row for a weapon.
local function build_row(html, frame, hero_name, weapon, percent, is_alt_fire)
local dps = weapon["DPS"]
if dps == nil or dps == 0 then return end
local total, bonus = proc_damage(weapon, percent)
local dps_increase = bonus / dps * 100
local label = frame:expandTemplate{ title = 'HeroIcon', args = { hero_name } }
local sort_name = hero_name:gsub("^The ", "")
if is_alt_fire then
label = label .. " (alt fire)"
sort_name = sort_name .. " (alt fire)"
end
local row = html:tag('tr')
row:tag('td'):attr('data-sort-value', sort_name):wikitext(label)
row:tag('td'):wikitext(string.format("%.1f", total))
row:tag('td'):wikitext(string.format("%.1f", bonus))
row:tag('td')
:attr('data-sort-value', string.format("%.4f", dps_increase))
:wikitext(string.format("%.1f%%", dps_increase))
end
--{{#invoke:ExpressShot|write_proc_damage_table|ITEM_NAME}}
--Generates a sortable wikitable of proc damage for every playable hero.
p.write_proc_damage_table = function(frame)
local item_name = frame.args[1] or "Express Shot"
local percent = get_item_prop(item_name, "ProcBaseAttackDamagePercent")
local percent_alt = get_item_prop(item_name, "ProcBaseAttackDamagePercentAltFire")
if percent == nil then
return "<span style=\"color:red;\">Item '" .. item_name .. "' has no ProcBaseAttackDamagePercent.</span>"
end
local hero_list = {}
for _, hero in pairs(heroes_data) do
local weapon = hero["Weapon"]
if hero["Name"] and weapon and weapon["BulletDamage"]
and not hero["InDevelopment"] and not hero["IsDisabled"] then
table.insert(hero_list, hero)
end
end
table.sort(hero_list, function(a, b)
return (a["Name"]:gsub("^The ", "")) < (b["Name"]:gsub("^The ", ""))
end)
local html = mw.html.create('table')
html:addClass('wikitable sortable')
local header = html:tag('tr')
header:tag('th'):wikitext('Hero')
header:tag('th'):wikitext('Attack damage')
header:tag('th'):wikitext('Bonus damage')
header:tag('th'):wikitext('DPS increase')
for _, hero in ipairs(hero_list) do
local weapon = hero["Weapon"]
build_row(html, frame, hero["Name"], weapon, percent, false)
local alt_fire = weapon["AltFire"]
if alt_fire and alt_fire["BulletDamage"] and percent_alt then
build_row(html, frame, hero["Name"], alt_fire, percent_alt, true)
end
end
return tostring(html)
end
return p