Module:Passive skill: Difference between revisions
Jump to navigation
Jump to search
(Trying to add some visuals and support for icons) |
(Undo revision 1125280 by Angelic knight (talk)) |
||
Line 1: | Line 1: | ||
-- | -- | ||
-- Module for | -- Module for passive skills | ||
-- | -- | ||
Line 15: | Line 15: | ||
local i18n = { | local i18n = { | ||
icon_name = 'File:%s | icon_name = 'File:%s passive skill icon.png', | ||
cats = { | cats = { | ||
data = 'Passive skill data', | data = 'Passive skill data', | ||
Line 40: | Line 40: | ||
}, | }, | ||
passive_box_table = { | |||
id = 'Id', | id = 'Id', | ||
int_id = 'Integer Id', | |||
flavour_text = 'Flavour Text', | |||
reminder_text = 'Reminder Text', | |||
skill_points = 'Skill Points Granted', | |||
ascendancy_class = 'Ascendancy Class', | |||
connections = 'Connections', | |||
}, | }, | ||
Line 52: | Line 57: | ||
errors = { | errors = { | ||
no_passives_found = 'No | no_passives_found = 'No passive skills with the given name found', | ||
}, | }, | ||
} | } | ||
Line 62: | Line 67: | ||
local tables = {} | local tables = {} | ||
tables. | tables.passive_skills = { | ||
table = ' | table = 'passive_skills', | ||
order = {'id', 'main_page', ' | order = {'id', 'int_id', 'name', 'main_page', 'flavour_text', 'reminder_text', 'buff_id', 'skill_points', 'icon', 'ascendancy_class', 'is_keystone', 'is_notable', 'is_multiple_choice_option', 'is_multiple_choice', 'is_icon_only', 'is_jewel_socket', 'is_ascendancy_starting_node', 'stat_text', 'stat_text_raw', 'connections',}, | ||
fields = { | fields = { | ||
id = { | id = { | ||
Line 70: | Line 75: | ||
type = 'String', | type = 'String', | ||
required = true, | required = true, | ||
}, | |||
int_id = { | |||
field = 'int_id', | |||
type = 'Integer', | |||
required = true, | |||
}, | |||
name = { | |||
field = 'name', | |||
type = 'String', | |||
}, | }, | ||
main_page = { | main_page = { | ||
field = 'main_page', | field = 'main_page', | ||
type = 'Page', | type = 'Page', | ||
}, | |||
flavour_text = { | |||
field = 'flavour_text', | |||
type = 'Text', | |||
}, | |||
reminder_text = { | |||
field = 'reminder_text', | |||
type = 'Text', | |||
}, | |||
buff_id = { | |||
field = 'buff_id', | |||
type = 'String', | |||
}, | |||
-- TODO: Other buff stuff | |||
skill_points = { | |||
field = 'skill_points', | |||
type = 'Integer', | |||
default = 0, | |||
}, | }, | ||
icon = { | icon = { | ||
Line 84: | Line 116: | ||
end | end | ||
}, | }, | ||
ascendancy_class = { | |||
field = ' | field = 'ascendancy_class', | ||
type = 'String', | |||
}, | |||
is_keystone = { | |||
field = 'is_keystone', | |||
type = 'Boolean', | |||
default = false, | |||
}, | |||
is_notable = { | |||
field = 'is_notable', | |||
type = 'Boolean', | |||
default = false, | |||
}, | |||
is_multiple_choice_option = { | |||
field = 'is_multiple_choice_option', | |||
type = 'Boolean', | |||
default = false, | |||
}, | |||
is_multiple_choice = { | |||
field = 'is_multiple_choice', | |||
type = 'Boolean', | |||
default = false, | |||
}, | |||
is_icon_only = { | |||
field = 'is_icon_only', | |||
type = 'Boolean', | |||
default = false, | |||
}, | |||
is_jewel_socket = { | |||
field = 'is_jewel_socket', | |||
type = 'Boolean', | |||
default = false, | |||
}, | |||
is_ascendancy_starting_node = { | |||
field = 'is_ascendancy_starting_node', | |||
type = 'Boolean', | |||
default = false, | |||
}, | |||
stat_text = { | |||
field = 'stat_text', | |||
type = 'Text', | |||
}, | |||
stat_text_raw = { | |||
field = 'stat_text', | |||
type = 'Text', | |||
func = function (tpl_args, frame) | |||
if tpl_args.stat_text then | |||
tpl_args.stat_text_raw = string.gsub( | |||
-- [[x]] -> x | |||
string.gsub( | |||
tpl_args.stat_text, '%[%[([^%]|]+)%]%]', '%1' | |||
), | |||
-- [[x|y]] -> y | |||
'%[%[[^|]+|([^%]|]+)%]%]', '%1' | |||
) | |||
end | |||
return tpl_args.stat_text_raw | |||
end | |||
}, | |||
-- from the graph file: | |||
connections = { | |||
field = 'connections', | |||
type = 'List (,) of String', | type = 'List (,) of String', | ||
}, | }, | ||
Line 91: | Line 184: | ||
} | } | ||
tables.passive_skill_stats = { | |||
table = 'passive_skill_stats', | |||
fields = { | |||
id = { | |||
field = 'id', | |||
type = 'String', | |||
}, | |||
value = { | |||
field = 'value', | |||
type = 'Integer', | |||
}, | |||
} | |||
} | |||
local display = {} | local display = {} | ||
Line 97: | Line 203: | ||
{ | { | ||
key = 'id', | key = 'id', | ||
header = i18n. | header = i18n.passive_box_table.id, | ||
display = nil, | |||
}, | |||
{ | |||
key = 'int_id', | |||
header = i18n.passive_box_table.int_id, | |||
display = nil, | |||
}, | |||
{ | |||
css = 'tc -flavour', | |||
key = 'flavour_text', | |||
header = i18n.passive_box_table.flavour_text, | |||
display = nil, | display = nil, | ||
}, | }, | ||
{ | { | ||
key = ' | key = 'reminder_text', | ||
header = i18n. | header = i18n.passive_box_table.reminder_text, | ||
display = nil, | |||
}, | |||
{ | |||
key = 'skill_points', | |||
header = i18n.passive_box_table.skill_points, | |||
display = nil, | |||
}, | |||
{ | |||
key = 'ascendancy_class', | |||
header = i18n.passive_box_table.ascendancy_class, | |||
display = function (tpl_args, frame, value) | |||
return string.format('[[%s]]', value) | |||
end, | |||
}, | |||
{ | |||
key = 'connections', | |||
header = i18n.passive_box_table.connections, | |||
display = function (tpl_args, frame, value) | display = function (tpl_args, frame, value) | ||
local results = m_cargo.map_results_to_id{ | local results = m_cargo.map_results_to_id{ | ||
field=' | field='passive_skills.id', | ||
results=m_cargo.array_query{ | results=m_cargo.array_query{ | ||
tables={' | tables={'passive_skills'}, | ||
fields={' | fields={'passive_skills.name', 'passive_skills._pageName'}, | ||
id_array=value, | id_array=value, | ||
id_field=' | id_field='passive_skills.id', | ||
ignore_missing=true, | ignore_missing=true, | ||
} | } | ||
Line 123: | Line 257: | ||
local text | local text | ||
if row then | if row then | ||
text = string.format('[[%s|%s]]', row[' | text = string.format('[[%s|%s]]', row['passive_skills._pageName'], row['passive_skills.name'] or row['passive_skills._pageName']) | ||
else | else | ||
text = key | text = key | ||
Line 144: | Line 278: | ||
local h = {} | local h = {} | ||
function h. | function h.format_passive_icon(passive, passive_type) | ||
if | if passive['passive_skills.icon'] == nil then | ||
return '' | return '' | ||
end | end | ||
local cls = 'passive-icon- | local cls = string.format('passive-icon-type__%s', passive_type) | ||
local main_page = | local main_page = passive['passive_skills.main_page'] or passive['main_pages._pageName'] or passive['passive_skills.name'] or passive['passive_skills.icon'] | ||
div = mw.html.create('div') | div = mw.html.create('div') | ||
div:addClass('passive-icon-container') | div:addClass('passive-icon-container') | ||
Line 160: | Line 294: | ||
string.format( | string.format( | ||
'[[%s|link=%s]]', | '[[%s|link=%s]]', | ||
passive[' | passive['passive_skills.icon'], | ||
main_page | main_page | ||
) | ) | ||
Line 168: | Line 302: | ||
end | end | ||
function h.make_stat_order(results) | |||
local stats = {} | |||
local stat_order = {} | |||
for _, row in ipairs(results) do | for _, row in ipairs(results) do | ||
local | local stat = row['passive_skills.stat_text'] | ||
-- Can't show results here that don't have a stat line | -- Can't show results here that don't have a stat line | ||
if | if stat then | ||
if | if stats[stat] == nil then | ||
stats[stat] = {row} | |||
table.insert( | table.insert(stat_order, stat) | ||
else | else | ||
table.insert( | table.insert(stats[stat], row) | ||
end | end | ||
end | end | ||
end | end | ||
return | return stats, stat_order | ||
end | end | ||
function h.stat_page_links(stat_order, stats) | |||
local out = {} | local out = {} | ||
for i, key in ipairs( | for i, key in ipairs(stat_order) do | ||
local links = {} | local links = {} | ||
for j, row in ipairs( | for j, row in ipairs(stats[key]) do | ||
links[#links+1] = string.format('[[%s|[%s]]]', row[' | links[#links+1] = string.format('[[%s|[%s]]]', row['passive_skills._pageName'], j) | ||
end | end | ||
out[i] = string.format('<span class="passive-line">%s <span class="passive-hover">%s</span></span>', key, table.concat(links, ' ')) | out[i] = string.format('<span class="passive-line">%s <span class="passive-hover">%s</span></span>', key, table.concat(links, ' ')) | ||
Line 236: | Line 334: | ||
end | end | ||
h.type_order = {'basic', 'notable', 'keystone', 'ascendancy_basic', 'ascendancy_notable'} | |||
function h.get_type(passive) | |||
local key | |||
if tonumber(passive['passive_skills.is_keystone']) == 1 then | |||
key = 'keystone' | |||
elseif tonumber(passive['passive_skills.is_notable']) == 1 then | |||
key = 'notable' | |||
else | |||
key = 'basic' | |||
end | |||
if passive['passive_skills.ascendancy_class'] ~= nil then | |||
key = 'ascendancy_' .. key | |||
end | |||
return key | |||
end | |||
function h.sort_by_type(results) | |||
local new = {} | |||
for _, key in ipairs(h.type_order) do | |||
new[key] = {} | |||
end | |||
for _, passive in ipairs(results) do | |||
table.insert(new[h.get_type(passive)], passive) | |||
end | |||
return new | |||
end | |||
function h.intro_text(tpl_args, frame) | |||
--[[ | |||
Display an introductory text about the passive skill. | |||
]] | |||
local out = {} | |||
if mw.ustring.find(tpl_args['id'], '_') then | |||
out[#out+1] = frame:expandTemplate{ | |||
title='Incorrect title', | |||
args = {title=tpl_args['id']} | |||
} | |||
end | |||
if tpl_args['name'] then | |||
out[#out+1] = string.format( | |||
i18n.intro.text_with_name, | |||
tpl_args['id'], | |||
tpl_args['main_page'] or tostring(mw.title.getCurrentTitle()), | |||
tpl_args['name'] | |||
) | |||
else | |||
out[#out+1] = string.format( | |||
i18n.intro.text_without_name, | |||
tpl_args['id'] | |||
) | |||
end | |||
return table.concat(out) | |||
end | |||
function h.stat_box(tpl_args, frame) | |||
--[[ | |||
Display the stat box. | |||
]] | |||
local container = mw.html.create('div') | |||
container | |||
:attr('class', 'modbox floatright') | |||
-- stat table | |||
tbl = container:tag('table') | |||
tbl | |||
:attr('class', 'wikitable sortable') | |||
-- :attr('style', 'style="width: 100%;"') | |||
:tag('tr') | |||
:tag('th') | |||
:attr('colspan', 3) | |||
:wikitext('Stats') | |||
:done() | |||
:done() | |||
:tag('tr') | |||
:tag('th') | |||
:wikitext('#') | |||
:done() | |||
:tag('th') | |||
:wikitext('Stat Id') | |||
:done() | |||
:tag('th') | |||
:wikitext('Value') | |||
:done() | |||
:done() | |||
:done() | |||
:done() | |||
local i = 0 | |||
local value = nil | |||
repeat | |||
i = i + 1 | |||
value = { | |||
id = tpl_args[string.format('stat%s_id', i)], | |||
value = tpl_args[string.format('stat%s_value', i)], | |||
} | |||
if value.id then | |||
tbl | |||
:tag('tr') | |||
:tag('td') | |||
:wikitext(i) | |||
:done() | |||
:tag('td') | |||
:wikitext(value.id) | |||
:done() | |||
:tag('td') | |||
:wikitext(value.value) | |||
:done() | |||
:done() | |||
:done() | |||
end | |||
until value.id == nil | |||
return tostring(container) | |||
end | |||
Line 338: | Line 467: | ||
-- Declare cargo tables: | -- Declare cargo tables: | ||
p. | p.table_passive_skills = m_cargo.declare_factory{data=tables.passive_skills} | ||
p.table_passive_skill_stats = m_cargo.declare_factory{data=tables.passive_skill_stats} | |||
function p. | function p.passive_skill(frame) | ||
--[[ | --[[ | ||
Stores data and displays a infobox about the passive skill. | Stores data and displays a infobox about the passive skill. | ||
Line 346: | Line 476: | ||
Examples | Examples | ||
-------- | -------- | ||
= p. | = p.passive_skill{ | ||
id = ' | id = 'life_life_leech1629', | ||
int_id = '27788', | |||
name = 'Blood Drinker', | |||
is_notable = 'True', | |||
icon = 'lifeleech', | |||
stat1_id = 'maximum_life_+%', | |||
stat1_value = '8', | |||
stat2_id = 'base_life_leech_from_attack_damage_permyriad', | |||
stat2_value = '40', | |||
stat_text = '8% increased maximum life<br>0.4% of Attack Damage Leeched as Life', | |||
connections = 'life1415,life1413', | |||
} | } | ||
Line 358: | Line 497: | ||
}) | }) | ||
frame = m_util.misc.get_frame(frame) | frame = m_util.misc.get_frame(frame) | ||
-- parse | |||
-- parse | |||
m_util.args.from_cargo_map{ | m_util.args.from_cargo_map{ | ||
tpl_args=tpl_args, | tpl_args=tpl_args, | ||
frame=frame, | frame=frame, | ||
table_map=tables. | table_map=tables.passive_skills, | ||
} | } | ||
-- parse stats | |||
m_util.args.stats(tpl_args, {}) | |||
for _, stat in ipairs(tpl_args.stats) do | |||
stat._table = tables.passive_skill_stats.table | |||
m_cargo.store(frame, stat) | |||
end | |||
-- | -- | ||
-- Infobox | -- Infobox | ||
-- | -- | ||
local passive = {} | |||
for _, key in ipairs(display.map_to_property) do | |||
local v = tpl_args[key] | |||
if type(v) == 'boolean' then | |||
if v then | |||
v = 1 | |||
else | |||
v = 0 | |||
end | |||
end | |||
passive[string.format('%s.%s', tables.passive_skills.table, tables.passive_skills.fields[key].field)] = v | |||
end | |||
local type_key = h.get_type(passive) | |||
local infocard_args = {} | |||
infocard_args.header = tpl_args.name | |||
infocard_args.subheader = i18n.passive_box[type_key] | |||
local tbl = mw.html.create('table') | |||
for _, data in ipairs(display.tbl) do | |||
local value = tpl_args[data.key] | |||
-- if default is nil, this will be compared against nil which is what we want, so value ~= nil isn't needed | |||
if value ~= tables.passive_skills.fields[data.key].default then | |||
local dsp | |||
if data.display then | |||
dsp = data.display(tpl_args, frame, value) | |||
else | |||
dsp = value | |||
end | |||
tbl | |||
:tag('tr') | |||
:tag('th') | |||
:wikitext(data.header) | |||
:done() | |||
:tag('td') | |||
:attr('class', data.css) | |||
:wikitext(dsp) | |||
:done() | |||
:done() | |||
end | |||
end | |||
infocard_args[1] = tostring(tbl) | |||
infocard_args[2] = tpl_args.stat_text | |||
infocard_args[3] = h.format_passive_icon(passive, type_key) | |||
local out = { | |||
f_infocard(infocard_args), | |||
h.intro_text(tpl_args, frame), | |||
h.stat_box(tpl_args, frame), | |||
} | |||
local cats = { | |||
i18n.cats.data, | |||
} | |||
return table.concat(out) .. m_util.misc.add_category(cats) | |||
end | end | ||
function p. | function p.passive_skill_box(frame) | ||
--[[ | --[[ | ||
Queries a | Queries a passive skill and displays it. | ||
Examples | Examples | ||
-------- | -------- | ||
= p. | = p.passive_skill_box{name='Ghost Reaver'} | ||
]] | ]] | ||
Line 447: | Line 592: | ||
if not tpl_args.q_where and tpl_args.name then | if not tpl_args.q_where and tpl_args.name then | ||
tpl_args.q_where = string.format(' | tpl_args.q_where = string.format('passive_skills.name="%s" AND passive_skills.stat_text IS NOT NULL', tpl_args.name) | ||
elseif not (tpl_args.q_where and not tpl_args.name) then | elseif not (tpl_args.q_where and not tpl_args.name) then | ||
error('q_where or name must be specified') | error('q_where or name must be specified') | ||
Line 453: | Line 598: | ||
local results = m_cargo.query( | local results = m_cargo.query( | ||
{' | {'passive_skills'}, | ||
{ | { | ||
' | 'passive_skills._pageName', | ||
' | 'passive_skills.main_page', | ||
' | 'passive_skills.name', | ||
'passive_skills.stat_text', | |||
-- TODO: only really need these once, maybe put in extra query | |||
'passive_skills.flavour_text', | |||
'passive_skills.icon', | |||
'passive_skills.is_keystone', | |||
'passive_skills.is_notable', | |||
'passive_skills.ascendancy_class', | |||
'passive_skills.id' | |||
}, | }, | ||
{ | { | ||
where=tpl_args.q_where, | where=tpl_args.q_where, | ||
orderBy=' | orderBy='passive_skills.stat_text', | ||
limit=5000, | limit=5000, | ||
} | } | ||
Line 469: | Line 622: | ||
end | end | ||
results = h.sort_by_type(results) | |||
local out = {} | local out = {} | ||
local cats = {} | local cats = {} | ||
if # | for _, type_key in ipairs(h.type_order) do | ||
local type_results = results[type_key] | |||
if #type_results > 0 then | |||
cats[#cats+1] = i18n.cats[type_key] | |||
local stats, stat_order = h.make_stat_order(type_results) | |||
local passive = type_results[1] | |||
local infocard_args = {} | |||
infocard_args.header = passive['passive_skills.name'] | |||
infocard_args.subheader = i18n.passive_box[type_key] | |||
infocard_args[1] = h.format_passive_icon(passive, type_key) | |||
infocard_args[2] = h.stat_page_links(stat_order, stats) | |||
infocard_args[3] = m_util.html.poe_color('flavour', passive['passive_skills.flavour_text']) | |||
out[#out+1] = f_infocard(infocard_args) | |||
-- Store as main page: | |||
for _, v in ipairs(type_results) do | |||
m_cargo.store( | |||
frame, | |||
{ | |||
_table='main_pages', | |||
id=v['passive_skills.id'], | |||
} | |||
) | |||
end | |||
end | end | ||
end | end | ||
Line 505: | Line 663: | ||
end | end | ||
function p.passive_skill_link(frame) | |||
--[[ | |||
Links a passive skill | |||
Examples | |||
-------- | |||
= p.passive_skill_link{id='AscendancyAscendant45', format='tablerow'} | |||
]] | |||
-- Get args | |||
tpl_args = getArgs(frame, { | |||
parentFirst = true | |||
}) | |||
frame = m_util.misc.get_frame(frame) | |||
tpl_args.name = tpl_args.name or tpl_args[1] | |||
if tpl_args.name then | |||
tpl_args.q_where = string.format('passive_skills.name="%s"', tpl_args.name) | |||
elseif tpl_args.id then | |||
tpl_args.q_where = string.format('passive_skills.id="%s"', tpl_args.id) | |||
elseif tpl_args.q_where then | |||
else | |||
error('Either name, id or q_where must be specified') | |||
end | |||
local results = m_cargo.query( | |||
{'passive_skills', 'main_pages'}, | |||
{ | |||
'passive_skills._pageName', | |||
'passive_skills.stat_text', | |||
'passive_skills.main_page', | |||
'passive_skills.name', | |||
'passive_skills.icon', | |||
'passive_skills.is_keystone', | |||
'passive_skills.is_notable', | |||
'passive_skills.ascendancy_class', | |||
'main_pages._pageName', | |||
}, | |||
{ | |||
join='passive_skills.id=main_pages.id', | |||
where=string.format('(%s) AND passive_skills.stat_text IS NOT NULL', tpl_args.q_where), | |||
orderBy='passive_skills.stat_text', | |||
limit=2, | |||
} | |||
) | |||
if #results > 1 then | |||
error('Too many passives found!') | |||
elseif #results < 1 then | |||
error('No passives found') | |||
end | |||
local passive = results[1] | |||
if tpl_args.format == 'tablerow' then | |||
local main_page = passive['passive_skills.main_page'] or passive['main_pages._pageName'] or passive['passive_skills.name'] | |||
return string.format( | |||
'| [[%s|%s]]%s\n| %s', | |||
main_page, | |||
passive['passive_skills.name'], | |||
h.format_passive_icon(passive, h.get_type(passive)), | |||
passive['passive_skills.stat_text'] | |||
) | |||
elseif tpl_args.format == nil then | |||
return | |||
else | |||
error(string.format('Invalid return format specified: %s', tpl_args.format)) | |||
end | |||
end | |||
-- Not sure whether we need a more sophisticated variant like item or mod tables here yet | |||
function p.passive_skill_table2(frame) | |||
-- Get args | |||
tpl_args = getArgs(frame, { | |||
parentFirst = true | |||
}) | |||
frame = m_util.misc.get_frame(frame) | |||
if tpl_args.q_tables then | |||
tpl_args.q_tables = tpl_args.q_tables .. ',' .. 'passive_skill_stats' | |||
else | |||
tpl_args.q_tables = 'passive_skill_stats' | |||
end | |||
if tpl_args.q_join then | |||
tpl_args.q_join = tpl_args.q_join .. ',' .. 'passive_skills._pageID=passive_skill_stats._pageID' | |||
else | |||
tpl_args.q_join = 'passive_skills._pageID=passive_skill_stats._pageID' | |||
end | |||
tpl_args.q_orderBy = 'passive_skills.ascendancy_class IS NULL DESC, passive_skills.is_keystone, passive_skills.is_notable, passive_skills.name' | |||
return m_cargo.table_query{ | |||
tpl_args=tpl_args, | |||
frame=frame, | |||
main_table='passive_skills', | |||
row_unique_fields = {'passive_skills.name'}, | |||
data={ | |||
tables = { | |||
passive_skill_stats = { | |||
join='passive_skills._pageID=passive_skill_stats._pageID', | |||
}, | |||
}, | |||
-- display data | |||
{ | |||
args = {'ascendancy'}, | |||
header = i18n.passive_table.ascendancy_class, | |||
fields = { | |||
'passive_skills.ascendancy_class', | |||
}, | |||
display = function (tpl_args, frame, tr, data) | |||
local passive = data[1] | |||
if passive['passive_skills.ascendancy_class'] then | |||
tr:tag('td') | |||
:wikitext(string.format('[[%s]]<br>[[File:%s avatar.png|link=%s]]', passive['passive_skills.ascendancy_class'], passive['passive_skills.ascendancy_class'], passive['passive_skills.ascendancy_class'])) | |||
else | |||
tr:wikitext(m_util.html.td.na{}) | |||
end | |||
end, | |||
order = 0, | |||
sort_type = 'text', | |||
}, | |||
{ | |||
args = nil, | |||
header = i18n.passive_table.name, | |||
fields = { | |||
'passive_skills._pageName', | |||
'passive_skills.main_page', | |||
'passive_skills.name', | |||
'passive_skills.icon', | |||
'passive_skills.is_keystone', | |||
'passive_skills.is_notable', | |||
'passive_skills.ascendancy_class', | |||
}, | |||
display = function (tpl_args, frame, tr, data) | |||
local passive = data[1] | |||
local type_key = h.get_type(passive) | |||
tr | |||
:tag('td') | |||
:attr('data-sort-value', passive['passive_skills.name'] .. type_key) | |||
:wikitext(string.format('[[%s|%s]]<br>%s', passive['passive_skills.main_page'] or passive['passive_skills.name'], passive['passive_skills.name'], h.format_passive_icon(passive, type_key))) | |||
:done() | |||
end, | |||
order = 1000, | |||
sort_type = 'text', | |||
options = { | |||
[7] = { | |||
optional=true, | |||
}, | |||
}, | |||
}, | |||
{ | |||
arg = {'default', 'stat', 'stats', 'stat_text'}, | |||
header = i18n.passive_table.stats, | |||
fields = { | |||
'passive_skills.stat_text', | |||
}, | |||
display = function (tpl_args, frame, tr, data) | |||
local passive = data[1] | |||
local stats, stat_order = h.make_stat_order(data) | |||
tr | |||
:tag('td') | |||
:wikitext(h.stat_page_links(stat_order, stats)) | |||
:done() | |||
end, | |||
order = 1001, | |||
sort_type = 'text', | |||
} | |||
}, | |||
} | |||
end | |||
function p.passive_skill_table(frame) | |||
-- Get args | |||
tpl_args = getArgs(frame, { | |||
parentFirst = true | |||
}) | |||
frame = m_util.misc.get_frame(frame) | |||
tpl_args.ascendancy = m_util.cast.boolean(tpl_args.ascendancy) | |||
local prepend = { | |||
q_join=true, | |||
} | |||
local query = { | |||
join='passive_skills._pageID=passive_skill_stats._pageID', | |||
limit=5000, | |||
groupBy='passive_skills._pageID', | |||
} | |||
for key, value in pairs(tpl_args) do | |||
if string.sub(key, 0, 2) == 'q_' then | |||
if prepend[key] then | |||
value = ',' .. value | |||
end | |||
query[string.sub(key, 3)] = value | |||
end | |||
end | |||
local results = m_cargo.query( | |||
{'passive_skills', 'passive_skill_stats'}, | |||
{ | |||
'passive_skills._pageName', | |||
'passive_skills.main_page', | |||
'passive_skills.name', | |||
'passive_skills.stat_text', | |||
'passive_skills.icon', | |||
'passive_skills.is_keystone', | |||
'passive_skills.is_notable', | |||
'passive_skills.ascendancy_class', | |||
}, | |||
query | |||
) | |||
result_map = m_cargo.map_results_to_id{ | |||
results=results, | |||
field='passive_skills.name', | |||
keep_id_field=true, | |||
} | |||
for key, rows in pairs(result_map) do | |||
result_map[key] = h.sort_by_type(rows) | |||
end | |||
-- header | |||
local tbl = mw.html.create('table') | |||
tbl:addClass('wikitable') | |||
tbl:addClass('sortable') | |||
local tr = tbl:tag('tr') | |||
if tpl_args.ascendancy then | |||
tr:tag('th') | |||
:wikitext(i18n.passive_table.ascendancy_class) | |||
end | |||
tr | |||
:tag('th') | |||
:wikitext(i18n.passive_table.name) | |||
:done() | |||
:tag('th') | |||
:wikitext(i18n.passive_table.stats) | |||
:done() | |||
-- rows | |||
local used_names = {} | |||
for _, passive_row in ipairs(results) do | |||
local pn = passive_row['passive_skills.name'] | |||
if used_names[pn] == nil then | |||
local type_results_map = result_map[passive_row['passive_skills.name']] | |||
used_names[pn] = true | |||
for _, type_key in ipairs(h.type_order) do | |||
local type_results = type_results_map[type_key] | |||
if #type_results > 0 then | |||
local row = type_results[1] | |||
tr = tbl:tag('tr') | |||
if tpl_args.ascendancy then | |||
if row['passive_skills.ascendancy_class'] then | |||
tr:tag('td') | |||
:wikitext(string.format('[[%s]]<br>[[File:%s avatar.png|link=%s]]', row['passive_skills.ascendancy_class'], row['passive_skills.ascendancy_class'], row['passive_skills.ascendancy_class'])) | |||
else | |||
tr:wikitext(m_util.html.td.na{}) | |||
end | |||
end | |||
local stats, stat_order = h.make_stat_order(type_results) | |||
tr | |||
:tag('td') | |||
:attr('data-sort-value', row['passive_skills.name'] .. type_key) | |||
:wikitext(string.format('[[%s|%s]]<br>%s', row['passive_skills.main_page'] or row['passive_skills.name'], row['passive_skills.name'], h.format_passive_icon(row, type_key))) | |||
:done() | |||
:tag('td') | |||
:wikitext(h.stat_page_links(stat_order, stats)) | |||
:done() | |||
end | |||
end | |||
end | |||
end | |||
return tostring(tbl) | |||
end | |||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- |
Revision as of 07:48, 12 November 2021
You might want to create a documentation page for this module.
Editors can experiment in this module's sandbox and testcases pages.
Please add categories to the /doc subpage. Subpages of this module.
Editors can experiment in this module's sandbox and testcases pages.
Please add categories to the /doc subpage. Subpages of this module.
--
-- Module for passive skills
--
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
local getArgs = require('Module:Arguments').getArgs
local f_infocard = require('Module:Infocard')._main
local p = {}
-- ----------------------------------------------------------------------------
-- Strings
-- ----------------------------------------------------------------------------
local i18n = {
icon_name = 'File:%s passive skill icon.png',
cats = {
data = 'Passive skill data',
keystone = 'Keystone passive skills',
notable = 'Notable passive skills',
basic = 'Basic passive skills',
ascendancy_notable = 'Ascendancy notable passive skills',
ascendancy_basic = 'Ascendancy basic passive skills',
},
passive_box = {
keystone = 'Keystone',
notable = 'Notable Passive Skill',
basic = 'Passive Skill',
ascendancy_notable = 'Ascendancy Notable Passive Skill',
ascendancy_basic = 'Ascendancy Passive Skill',
},
intro = {
text_with_name = "'''%s''' is the internal id for the [[%s|%s]] [[passive skill]]. ",
text_without_name = "'''%s''' is the internal id of an unnamed [[passive skill]]. ",
},
passive_box_table = {
id = 'Id',
int_id = 'Integer Id',
flavour_text = 'Flavour Text',
reminder_text = 'Reminder Text',
skill_points = 'Skill Points Granted',
ascendancy_class = 'Ascendancy Class',
connections = 'Connections',
},
passive_table = {
ascendancy_class = 'Ascendancy<br>Class',
name = 'Name',
stats = 'Stats',
},
errors = {
no_passives_found = 'No passive skills with the given name found',
},
}
-- ----------------------------------------------------------------------------
-- Cargo
-- ----------------------------------------------------------------------------
local tables = {}
tables.passive_skills = {
table = 'passive_skills',
order = {'id', 'int_id', 'name', 'main_page', 'flavour_text', 'reminder_text', 'buff_id', 'skill_points', 'icon', 'ascendancy_class', 'is_keystone', 'is_notable', 'is_multiple_choice_option', 'is_multiple_choice', 'is_icon_only', 'is_jewel_socket', 'is_ascendancy_starting_node', 'stat_text', 'stat_text_raw', 'connections',},
fields = {
id = {
field = 'id',
type = 'String',
required = true,
},
int_id = {
field = 'int_id',
type = 'Integer',
required = true,
},
name = {
field = 'name',
type = 'String',
},
main_page = {
field = 'main_page',
type = 'Page',
},
flavour_text = {
field = 'flavour_text',
type = 'Text',
},
reminder_text = {
field = 'reminder_text',
type = 'Text',
},
buff_id = {
field = 'buff_id',
type = 'String',
},
-- TODO: Other buff stuff
skill_points = {
field = 'skill_points',
type = 'Integer',
default = 0,
},
icon = {
field = 'icon',
type = 'Page',
func = function(tpl_args, frame, value)
if value then
return string.format(i18n.icon_name, value)
end
end
},
ascendancy_class = {
field = 'ascendancy_class',
type = 'String',
},
is_keystone = {
field = 'is_keystone',
type = 'Boolean',
default = false,
},
is_notable = {
field = 'is_notable',
type = 'Boolean',
default = false,
},
is_multiple_choice_option = {
field = 'is_multiple_choice_option',
type = 'Boolean',
default = false,
},
is_multiple_choice = {
field = 'is_multiple_choice',
type = 'Boolean',
default = false,
},
is_icon_only = {
field = 'is_icon_only',
type = 'Boolean',
default = false,
},
is_jewel_socket = {
field = 'is_jewel_socket',
type = 'Boolean',
default = false,
},
is_ascendancy_starting_node = {
field = 'is_ascendancy_starting_node',
type = 'Boolean',
default = false,
},
stat_text = {
field = 'stat_text',
type = 'Text',
},
stat_text_raw = {
field = 'stat_text',
type = 'Text',
func = function (tpl_args, frame)
if tpl_args.stat_text then
tpl_args.stat_text_raw = string.gsub(
-- [[x]] -> x
string.gsub(
tpl_args.stat_text, '%[%[([^%]|]+)%]%]', '%1'
),
-- [[x|y]] -> y
'%[%[[^|]+|([^%]|]+)%]%]', '%1'
)
end
return tpl_args.stat_text_raw
end
},
-- from the graph file:
connections = {
field = 'connections',
type = 'List (,) of String',
},
}
}
tables.passive_skill_stats = {
table = 'passive_skill_stats',
fields = {
id = {
field = 'id',
type = 'String',
},
value = {
field = 'value',
type = 'Integer',
},
}
}
local display = {}
display.map_to_property = {'icon', 'is_keystone', 'is_notable', 'ascendancy_class'}
display.tbl = {
{
key = 'id',
header = i18n.passive_box_table.id,
display = nil,
},
{
key = 'int_id',
header = i18n.passive_box_table.int_id,
display = nil,
},
{
css = 'tc -flavour',
key = 'flavour_text',
header = i18n.passive_box_table.flavour_text,
display = nil,
},
{
key = 'reminder_text',
header = i18n.passive_box_table.reminder_text,
display = nil,
},
{
key = 'skill_points',
header = i18n.passive_box_table.skill_points,
display = nil,
},
{
key = 'ascendancy_class',
header = i18n.passive_box_table.ascendancy_class,
display = function (tpl_args, frame, value)
return string.format('[[%s]]', value)
end,
},
{
key = 'connections',
header = i18n.passive_box_table.connections,
display = function (tpl_args, frame, value)
local results = m_cargo.map_results_to_id{
field='passive_skills.id',
results=m_cargo.array_query{
tables={'passive_skills'},
fields={'passive_skills.name', 'passive_skills._pageName'},
id_array=value,
id_field='passive_skills.id',
ignore_missing=true,
}
}
local ul = mw.html.create('ul')
for _, key in ipairs(value) do
local row = results[key]
if row then
row = row[1]
end
local text
if row then
text = string.format('[[%s|%s]]', row['passive_skills._pageName'], row['passive_skills.name'] or row['passive_skills._pageName'])
else
text = key
end
ul
:tag('li')
:wikitext(text)
:done()
end
return tostring(ul)
end,
},
}
-- ----------------------------------------------------------------------------
-- Helper functions
-- ----------------------------------------------------------------------------
local h = {}
function h.format_passive_icon(passive, passive_type)
if passive['passive_skills.icon'] == nil then
return ''
end
local cls = string.format('passive-icon-type__%s', passive_type)
local main_page = passive['passive_skills.main_page'] or passive['main_pages._pageName'] or passive['passive_skills.name'] or passive['passive_skills.icon']
div = mw.html.create('div')
div:addClass('passive-icon-container')
div:addClass(cls)
div:tag('div')
:addClass('passive-icon-frame')
:done()
div:wikitext(
string.format(
'[[%s|link=%s]]',
passive['passive_skills.icon'],
main_page
)
)
return tostring(div)
end
function h.make_stat_order(results)
local stats = {}
local stat_order = {}
for _, row in ipairs(results) do
local stat = row['passive_skills.stat_text']
-- Can't show results here that don't have a stat line
if stat then
if stats[stat] == nil then
stats[stat] = {row}
table.insert(stat_order, stat)
else
table.insert(stats[stat], row)
end
end
end
return stats, stat_order
end
function h.stat_page_links(stat_order, stats)
local out = {}
for i, key in ipairs(stat_order) do
local links = {}
for j, row in ipairs(stats[key]) do
links[#links+1] = string.format('[[%s|[%s]]]', row['passive_skills._pageName'], j)
end
out[i] = string.format('<span class="passive-line">%s <span class="passive-hover">%s</span></span>', key, table.concat(links, ' '))
end
return table.concat(out, '<hr>')
end
h.type_order = {'basic', 'notable', 'keystone', 'ascendancy_basic', 'ascendancy_notable'}
function h.get_type(passive)
local key
if tonumber(passive['passive_skills.is_keystone']) == 1 then
key = 'keystone'
elseif tonumber(passive['passive_skills.is_notable']) == 1 then
key = 'notable'
else
key = 'basic'
end
if passive['passive_skills.ascendancy_class'] ~= nil then
key = 'ascendancy_' .. key
end
return key
end
function h.sort_by_type(results)
local new = {}
for _, key in ipairs(h.type_order) do
new[key] = {}
end
for _, passive in ipairs(results) do
table.insert(new[h.get_type(passive)], passive)
end
return new
end
function h.intro_text(tpl_args, frame)
--[[
Display an introductory text about the passive skill.
]]
local out = {}
if mw.ustring.find(tpl_args['id'], '_') then
out[#out+1] = frame:expandTemplate{
title='Incorrect title',
args = {title=tpl_args['id']}
}
end
if tpl_args['name'] then
out[#out+1] = string.format(
i18n.intro.text_with_name,
tpl_args['id'],
tpl_args['main_page'] or tostring(mw.title.getCurrentTitle()),
tpl_args['name']
)
else
out[#out+1] = string.format(
i18n.intro.text_without_name,
tpl_args['id']
)
end
return table.concat(out)
end
function h.stat_box(tpl_args, frame)
--[[
Display the stat box.
]]
local container = mw.html.create('div')
container
:attr('class', 'modbox floatright')
-- stat table
tbl = container:tag('table')
tbl
:attr('class', 'wikitable sortable')
-- :attr('style', 'style="width: 100%;"')
:tag('tr')
:tag('th')
:attr('colspan', 3)
:wikitext('Stats')
:done()
:done()
:tag('tr')
:tag('th')
:wikitext('#')
:done()
:tag('th')
:wikitext('Stat Id')
:done()
:tag('th')
:wikitext('Value')
:done()
:done()
:done()
:done()
local i = 0
local value = nil
repeat
i = i + 1
value = {
id = tpl_args[string.format('stat%s_id', i)],
value = tpl_args[string.format('stat%s_value', i)],
}
if value.id then
tbl
:tag('tr')
:tag('td')
:wikitext(i)
:done()
:tag('td')
:wikitext(value.id)
:done()
:tag('td')
:wikitext(value.value)
:done()
:done()
:done()
end
until value.id == nil
return tostring(container)
end
-- ----------------------------------------------------------------------------
-- Page functions
-- ----------------------------------------------------------------------------
local p = {}
-- This way the helper functions can be used in other modules
p.h = h
-- Declare cargo tables:
p.table_passive_skills = m_cargo.declare_factory{data=tables.passive_skills}
p.table_passive_skill_stats = m_cargo.declare_factory{data=tables.passive_skill_stats}
function p.passive_skill(frame)
--[[
Stores data and displays a infobox about the passive skill.
Examples
--------
= p.passive_skill{
id = 'life_life_leech1629',
int_id = '27788',
name = 'Blood Drinker',
is_notable = 'True',
icon = 'lifeleech',
stat1_id = 'maximum_life_+%',
stat1_value = '8',
stat2_id = 'base_life_leech_from_attack_damage_permyriad',
stat2_value = '40',
stat_text = '8% increased maximum life<br>0.4% of Attack Damage Leeched as Life',
connections = 'life1415,life1413',
}
]]
-- Get args
tpl_args = getArgs(frame, {
parentFirst = true
})
frame = m_util.misc.get_frame(frame)
-- parse
m_util.args.from_cargo_map{
tpl_args=tpl_args,
frame=frame,
table_map=tables.passive_skills,
}
-- parse stats
m_util.args.stats(tpl_args, {})
for _, stat in ipairs(tpl_args.stats) do
stat._table = tables.passive_skill_stats.table
m_cargo.store(frame, stat)
end
--
-- Infobox
--
local passive = {}
for _, key in ipairs(display.map_to_property) do
local v = tpl_args[key]
if type(v) == 'boolean' then
if v then
v = 1
else
v = 0
end
end
passive[string.format('%s.%s', tables.passive_skills.table, tables.passive_skills.fields[key].field)] = v
end
local type_key = h.get_type(passive)
local infocard_args = {}
infocard_args.header = tpl_args.name
infocard_args.subheader = i18n.passive_box[type_key]
local tbl = mw.html.create('table')
for _, data in ipairs(display.tbl) do
local value = tpl_args[data.key]
-- if default is nil, this will be compared against nil which is what we want, so value ~= nil isn't needed
if value ~= tables.passive_skills.fields[data.key].default then
local dsp
if data.display then
dsp = data.display(tpl_args, frame, value)
else
dsp = value
end
tbl
:tag('tr')
:tag('th')
:wikitext(data.header)
:done()
:tag('td')
:attr('class', data.css)
:wikitext(dsp)
:done()
:done()
end
end
infocard_args[1] = tostring(tbl)
infocard_args[2] = tpl_args.stat_text
infocard_args[3] = h.format_passive_icon(passive, type_key)
local out = {
f_infocard(infocard_args),
h.intro_text(tpl_args, frame),
h.stat_box(tpl_args, frame),
}
local cats = {
i18n.cats.data,
}
return table.concat(out) .. m_util.misc.add_category(cats)
end
function p.passive_skill_box(frame)
--[[
Queries a passive skill and displays it.
Examples
--------
= p.passive_skill_box{name='Ghost Reaver'}
]]
-- Get args
tpl_args = getArgs(frame, {
parentFirst = true
})
frame = m_util.misc.get_frame(frame)
tpl_args.name = tpl_args.name or tpl_args[1]
if not tpl_args.q_where and tpl_args.name then
tpl_args.q_where = string.format('passive_skills.name="%s" AND passive_skills.stat_text IS NOT NULL', tpl_args.name)
elseif not (tpl_args.q_where and not tpl_args.name) then
error('q_where or name must be specified')
end
local results = m_cargo.query(
{'passive_skills'},
{
'passive_skills._pageName',
'passive_skills.main_page',
'passive_skills.name',
'passive_skills.stat_text',
-- TODO: only really need these once, maybe put in extra query
'passive_skills.flavour_text',
'passive_skills.icon',
'passive_skills.is_keystone',
'passive_skills.is_notable',
'passive_skills.ascendancy_class',
'passive_skills.id'
},
{
where=tpl_args.q_where,
orderBy='passive_skills.stat_text',
limit=5000,
}
)
if #results == 0 then
error(i18n.errors.no_passives_found)
end
results = h.sort_by_type(results)
local out = {}
local cats = {}
for _, type_key in ipairs(h.type_order) do
local type_results = results[type_key]
if #type_results > 0 then
cats[#cats+1] = i18n.cats[type_key]
local stats, stat_order = h.make_stat_order(type_results)
local passive = type_results[1]
local infocard_args = {}
infocard_args.header = passive['passive_skills.name']
infocard_args.subheader = i18n.passive_box[type_key]
infocard_args[1] = h.format_passive_icon(passive, type_key)
infocard_args[2] = h.stat_page_links(stat_order, stats)
infocard_args[3] = m_util.html.poe_color('flavour', passive['passive_skills.flavour_text'])
out[#out+1] = f_infocard(infocard_args)
-- Store as main page:
for _, v in ipairs(type_results) do
m_cargo.store(
frame,
{
_table='main_pages',
id=v['passive_skills.id'],
}
)
end
end
end
if tpl_args.cats == nil or m_util.cast.boolean(tpl_args.cats) then
out[#out+1] = m_util.misc.add_category(cats)
end
return table.concat(out)
end
function p.passive_skill_link(frame)
--[[
Links a passive skill
Examples
--------
= p.passive_skill_link{id='AscendancyAscendant45', format='tablerow'}
]]
-- Get args
tpl_args = getArgs(frame, {
parentFirst = true
})
frame = m_util.misc.get_frame(frame)
tpl_args.name = tpl_args.name or tpl_args[1]
if tpl_args.name then
tpl_args.q_where = string.format('passive_skills.name="%s"', tpl_args.name)
elseif tpl_args.id then
tpl_args.q_where = string.format('passive_skills.id="%s"', tpl_args.id)
elseif tpl_args.q_where then
else
error('Either name, id or q_where must be specified')
end
local results = m_cargo.query(
{'passive_skills', 'main_pages'},
{
'passive_skills._pageName',
'passive_skills.stat_text',
'passive_skills.main_page',
'passive_skills.name',
'passive_skills.icon',
'passive_skills.is_keystone',
'passive_skills.is_notable',
'passive_skills.ascendancy_class',
'main_pages._pageName',
},
{
join='passive_skills.id=main_pages.id',
where=string.format('(%s) AND passive_skills.stat_text IS NOT NULL', tpl_args.q_where),
orderBy='passive_skills.stat_text',
limit=2,
}
)
if #results > 1 then
error('Too many passives found!')
elseif #results < 1 then
error('No passives found')
end
local passive = results[1]
if tpl_args.format == 'tablerow' then
local main_page = passive['passive_skills.main_page'] or passive['main_pages._pageName'] or passive['passive_skills.name']
return string.format(
'| [[%s|%s]]%s\n| %s',
main_page,
passive['passive_skills.name'],
h.format_passive_icon(passive, h.get_type(passive)),
passive['passive_skills.stat_text']
)
elseif tpl_args.format == nil then
return
else
error(string.format('Invalid return format specified: %s', tpl_args.format))
end
end
-- Not sure whether we need a more sophisticated variant like item or mod tables here yet
function p.passive_skill_table2(frame)
-- Get args
tpl_args = getArgs(frame, {
parentFirst = true
})
frame = m_util.misc.get_frame(frame)
if tpl_args.q_tables then
tpl_args.q_tables = tpl_args.q_tables .. ',' .. 'passive_skill_stats'
else
tpl_args.q_tables = 'passive_skill_stats'
end
if tpl_args.q_join then
tpl_args.q_join = tpl_args.q_join .. ',' .. 'passive_skills._pageID=passive_skill_stats._pageID'
else
tpl_args.q_join = 'passive_skills._pageID=passive_skill_stats._pageID'
end
tpl_args.q_orderBy = 'passive_skills.ascendancy_class IS NULL DESC, passive_skills.is_keystone, passive_skills.is_notable, passive_skills.name'
return m_cargo.table_query{
tpl_args=tpl_args,
frame=frame,
main_table='passive_skills',
row_unique_fields = {'passive_skills.name'},
data={
tables = {
passive_skill_stats = {
join='passive_skills._pageID=passive_skill_stats._pageID',
},
},
-- display data
{
args = {'ascendancy'},
header = i18n.passive_table.ascendancy_class,
fields = {
'passive_skills.ascendancy_class',
},
display = function (tpl_args, frame, tr, data)
local passive = data[1]
if passive['passive_skills.ascendancy_class'] then
tr:tag('td')
:wikitext(string.format('[[%s]]<br>[[File:%s avatar.png|link=%s]]', passive['passive_skills.ascendancy_class'], passive['passive_skills.ascendancy_class'], passive['passive_skills.ascendancy_class']))
else
tr:wikitext(m_util.html.td.na{})
end
end,
order = 0,
sort_type = 'text',
},
{
args = nil,
header = i18n.passive_table.name,
fields = {
'passive_skills._pageName',
'passive_skills.main_page',
'passive_skills.name',
'passive_skills.icon',
'passive_skills.is_keystone',
'passive_skills.is_notable',
'passive_skills.ascendancy_class',
},
display = function (tpl_args, frame, tr, data)
local passive = data[1]
local type_key = h.get_type(passive)
tr
:tag('td')
:attr('data-sort-value', passive['passive_skills.name'] .. type_key)
:wikitext(string.format('[[%s|%s]]<br>%s', passive['passive_skills.main_page'] or passive['passive_skills.name'], passive['passive_skills.name'], h.format_passive_icon(passive, type_key)))
:done()
end,
order = 1000,
sort_type = 'text',
options = {
[7] = {
optional=true,
},
},
},
{
arg = {'default', 'stat', 'stats', 'stat_text'},
header = i18n.passive_table.stats,
fields = {
'passive_skills.stat_text',
},
display = function (tpl_args, frame, tr, data)
local passive = data[1]
local stats, stat_order = h.make_stat_order(data)
tr
:tag('td')
:wikitext(h.stat_page_links(stat_order, stats))
:done()
end,
order = 1001,
sort_type = 'text',
}
},
}
end
function p.passive_skill_table(frame)
-- Get args
tpl_args = getArgs(frame, {
parentFirst = true
})
frame = m_util.misc.get_frame(frame)
tpl_args.ascendancy = m_util.cast.boolean(tpl_args.ascendancy)
local prepend = {
q_join=true,
}
local query = {
join='passive_skills._pageID=passive_skill_stats._pageID',
limit=5000,
groupBy='passive_skills._pageID',
}
for key, value in pairs(tpl_args) do
if string.sub(key, 0, 2) == 'q_' then
if prepend[key] then
value = ',' .. value
end
query[string.sub(key, 3)] = value
end
end
local results = m_cargo.query(
{'passive_skills', 'passive_skill_stats'},
{
'passive_skills._pageName',
'passive_skills.main_page',
'passive_skills.name',
'passive_skills.stat_text',
'passive_skills.icon',
'passive_skills.is_keystone',
'passive_skills.is_notable',
'passive_skills.ascendancy_class',
},
query
)
result_map = m_cargo.map_results_to_id{
results=results,
field='passive_skills.name',
keep_id_field=true,
}
for key, rows in pairs(result_map) do
result_map[key] = h.sort_by_type(rows)
end
-- header
local tbl = mw.html.create('table')
tbl:addClass('wikitable')
tbl:addClass('sortable')
local tr = tbl:tag('tr')
if tpl_args.ascendancy then
tr:tag('th')
:wikitext(i18n.passive_table.ascendancy_class)
end
tr
:tag('th')
:wikitext(i18n.passive_table.name)
:done()
:tag('th')
:wikitext(i18n.passive_table.stats)
:done()
-- rows
local used_names = {}
for _, passive_row in ipairs(results) do
local pn = passive_row['passive_skills.name']
if used_names[pn] == nil then
local type_results_map = result_map[passive_row['passive_skills.name']]
used_names[pn] = true
for _, type_key in ipairs(h.type_order) do
local type_results = type_results_map[type_key]
if #type_results > 0 then
local row = type_results[1]
tr = tbl:tag('tr')
if tpl_args.ascendancy then
if row['passive_skills.ascendancy_class'] then
tr:tag('td')
:wikitext(string.format('[[%s]]<br>[[File:%s avatar.png|link=%s]]', row['passive_skills.ascendancy_class'], row['passive_skills.ascendancy_class'], row['passive_skills.ascendancy_class']))
else
tr:wikitext(m_util.html.td.na{})
end
end
local stats, stat_order = h.make_stat_order(type_results)
tr
:tag('td')
:attr('data-sort-value', row['passive_skills.name'] .. type_key)
:wikitext(string.format('[[%s|%s]]<br>%s', row['passive_skills.main_page'] or row['passive_skills.name'], row['passive_skills.name'], h.format_passive_icon(row, type_key)))
:done()
:tag('td')
:wikitext(h.stat_page_links(stat_order, stats))
:done()
end
end
end
end
return tostring(tbl)
end
-- ----------------------------------------------------------------------------
-- End
-- ----------------------------------------------------------------------------
return p