Used by {{Skill Hero List}} on individual skill pages, to show which heroes learn this skill.
The above documentation is transcluded from Module:SkillHeroList/doc. (edit | history)
local Util = require('Module:Util')
local HeroUtil = require 'Module:HeroUtil'
local cargo = mw.ext.cargo
local p = {}
local List = require 'Module:ListUtil'
local Hash = require 'Module:HashUtil'
local escq = require 'Module:EscQ'.main1
-- unobtainable rarity value
local BAD_RARITY = 5 + 1
-- breadth-first search, input node goes to index 0
local bfs = function (node, graph)
local i = 0
local list = {[i] = node}
local included = {[node] = true}
while true do
local current = list[i]
if not current then
break
end
i = i + 1
local neighbours = graph[current]
if neighbours then
for _, v in ipairs(neighbours) do
if not included[v] then
list[#list + 1] = v
included[v] = true
end
end
end
end
return list
end
local getPreEvolved = function (wikiName, pagename)
local frame = mw.getCurrentFrame()
local baseWeaponQuery = cargo.query('WeaponEvolutions,Skills', 'Skills.WikiName=name', {
join = 'WeaponEvolutions.BaseWeapon=Skills.WikiName',
where = ("EvolvesInto='%s'"):format(escq(wikiName)),
groupBy = 'BaseWeapon',
})
if #baseWeaponQuery > 0 then
local links = List.map(baseWeaponQuery, function (v)
return frame:expandTemplate{title = 'Wt', args = {v.name}}
end)
local last = table.remove(links)
local wepList = #links == 0 and last or (table.concat(links, ', ') .. (#links >= 2 and ', or ' or ' or ') .. last)
return ('[[Category:Evolved weapons]][[%s]] can be evolved from %s using the [[Weapon Refinery]].<br>'):format(pagename, wepList)
else
return ''
end
end
local heroList = function (args)
local pagename = args[1]
-- any skill from the page can be used
local skillQuery = cargo.query('Skills', 'WikiName,Scategory', {
where = ("_pageName='%s'"):format(escq(pagename)),
limit = 1,
})[1] or {}
local wikiName = skillQuery.WikiName or ''
local cat = skillQuery.Scategory or ''
local header = cat == 'weapon' and getPreEvolved(wikiName, pagename) or ''
local heroesWithSkill = cargo.query(
'Units,UnitSkills',
"Units._pageName=page,Units.WikiName=wikiname,IFNULL(CONCAT(Name,': ',Title),Name)=name", {
join = 'Units.WikiName=UnitSkills.WikiName',
where = ("skill='%s'"):format(escq(wikiName)),
groupBy = 'Units._pageName',
limit = 500,
})
if #heroesWithSkill == 0 then
return header .. "This skill is currently not owned by any unit."
end
local avail = HeroUtil.getLowestRarities {current = true}
local heroSkills = Hash.from_ipairs(heroesWithSkill, function (hero)
local lowestRarity = avail[hero.page] and avail[hero.page]:bounds() or BAD_RARITY
return hero.name, List.map_self(cargo.query('UnitSkills,Skills', 'Skills.WikiName=tag,Skills.Name=name,Skills._pageName=page,defaultRarity=dr,unlockRarity=ur', {
join = 'Skills.WikiName=UnitSkills.skill',
where = ("UnitSkills.WikiName='%s' AND Scategory='%s'"):format(escq(hero.wikiname), escq(cat)),
limit = 1000,
}), function (v)
v.rarity = math.max(math.min(tonumber(v.dr) or BAD_RARITY, tonumber(v.ur) or BAD_RARITY), lowestRarity)
return v
end)
end)
local skillSet = {}
for _, skills in pairs(heroSkills) do
for _, skill in ipairs(skills) do
skillSet[skill.tag] = true
end
end
local prereq_graph, after_graph = Util.getSkillChains(Hash.keys(skillSet))
local prereqs = List.reverse_self(bfs(wikiName, prereq_graph))
local afters = bfs(wikiName, after_graph)
local skillOrder = Hash.invert(List.concat(prereqs, List.concat({wikiName}, afters)))
Hash.map_self(heroSkills, function (skills)
local chainSkills = List.select(skills, function (skill) return skillOrder[skill.tag] end)
table.sort(chainSkills, function (lhs, rhs) return skillOrder[lhs.tag] < skillOrder[rhs.tag] end)
return chainSkills
end)
local maxColumns = math.max(0, unpack(List.map(Hash.values(heroSkills), function (skills) return #skills end)))
-- Initialize the table
local tbl = mw.html.create('table')
:addClass('wikitable striped sortable')
:css('text-align','center')
-- Table Headers
tbl:tag('th')
:wikitext('Unit')
tbl:tag('th')
:attr('colspan', maxColumns)
:wikitext('Skill chain')
local RARITY_TXT = Util.getRarityTexts()
RARITY_TXT[BAD_RARITY] = 'N/A'
for _, hero in ipairs(heroesWithSkill) do
local cells = List.map(heroSkills[hero.name], function (skill)
return ("[[%s%s]]<br>%s"):format(skill.page, skill.page == skill.name and '' or ('|' .. skill.name), RARITY_TXT[skill.rarity])
end)
local tr = tbl:tag('tr')
-- Hero Name
tr:tag('td')
:tag('div')
:wikitext(Util.getHeroIcon(hero.page, '51px') .. '<br>')
:css('margin-top','5px')
:done()
:tag('div')
:wikitext('[[' .. hero.page .. '|' .. hero.name .. ']]')
for j = 1, maxColumns do
tr:tag('td')
:wikitext(cells[j] or '–')
:css('min-width','80px')
end
end
return header .. tostring(tbl)
end
return require 'Module:MakeMWModule'.makeMWModule {heroList = heroList}