Нет описания правки |
Нет описания правки |
||
(не показано 25 промежуточных версий 2 участников) | |||
Строка 1: | Строка 1: | ||
+ | ------------------------------------------------------------------------------- |
||
− | --[[ |
||
+ | -- |
||
− | Module responsible for displaying modifiers in various ways. |
||
+ | -- Module:Modifier table |
||
− | |||
+ | -- |
||
− | ]] |
||
+ | -- Module responsible for displaying modifiers in various ways. Implements |
||
+ | -- Template:Modifier table and Template:Item modifiers |
||
+ | ------------------------------------------------------------------------------- |
||
+ | require('Module:No globals') |
||
local m_util = require('Module:Util') |
local m_util = require('Module:Util') |
||
− | local getArgs = require('Module:Arguments').getArgs |
||
− | local m_game = require('Module:Game') |
||
− | local f_item_link = require('Module:Item link').item_link |
||
local m_cargo = require('Module:Cargo') |
local m_cargo = require('Module:Cargo') |
||
+ | -- Should we use the sandbox version of our submodules? |
||
− | local cargo = mw.ext.cargo |
||
+ | local use_sandbox = m_util.misc.maybe_sandbox('Modifier table') |
||
− | local |
+ | local m_game = mw.loadData('Module:Game') |
+ | -- Lazy loading |
||
− | -- ---------------------------------------------------------------------------- |
||
+ | local f_item_link -- require('Module:Item link').item_link |
||
− | -- Strings |
||
− | -- ---------------------------------------------------------------------------- |
||
− | -- This section contains strings used by this module. |
||
− | -- Add new strings here instead of in-code directly, this will help other |
||
− | -- people to correct spelling mistakes easier and help with translation to |
||
− | -- other PoE wikis. |
||
+ | -- The cfg table contains all localisable strings and configuration, to make it |
||
− | local i18n = { |
||
+ | -- easier to port this module to another wiki. |
||
− | mod_table = { |
||
+ | local cfg = use_sandbox and mw.loadData('Module:Modifier table/config/sandbox') or mw.loadData('Module:Modifier table/config') |
||
− | name = m_util.html.abbr('Наименование', 'Название модификатора, если оно доступно, или его внутренний идентификатор'), |
||
− | mod_group = m_util.html.abbr('Группа', 'При обычных обстоятельствах одновременно может отображаться только один модификатор из указанной группы'), |
||
− | mod_type = 'Тип', |
||
− | domain = '[[Modifiers#Mod_Domain|Domain]]', |
||
− | generation_type = '[[Modifiers#Mod_Generation_Type|Generation Type]]', |
||
− | required_level = '[[Image:Level_up_icon_small.png|link=|For generated item/monster modifiers the minimum item/monster level respectively. Some generation types may not require this condition to be met, however item level restrictions may be raised to 80% of this value.]]', |
||
− | labyrinth = '[[Лабиринт правителя|Лабиринт]]', |
||
− | stat_text = m_util.html.abbr('Свойства', 'Свойства модификатора и диапазон, в котором они могут действовать (если применимо)'), |
||
− | buff = m_util.html.abbr('Эффект', 'Идентификатор предоставленного эффекта и связанные с ним значения'), |
||
− | granted_skill = m_util.html.abbr('Умение', 'Идентификатор предоставленного умения'), |
||
− | tags = '[[Tags]]', |
||
− | |||
− | iiq = m_util.html.abbr('IIQ', 'увеличение количества найденных предметов'), |
||
− | iir = m_util.html.abbr('IIR', 'повышение редкости найденных предметов'), |
||
− | pack_size = m_util.html.abbr('Размер<br>группы', 'Размер групп монстров'), |
||
− | |||
− | spawn_weights = m_util.html.abbr('Spawn Weighting', 'List of applicable tags and their values for weighting (i.e. calculating the chances) of the spawning of this modifier'), |
||
− | generation_weights = m_util.html.abbr('Generation Weighting', 'List of applicable tags and their values for weighting (i.e. calculating the chances) of the spawning of this modifier'), |
||
− | |||
− | normal_labyrinth = 'Первый Лабиринт', |
||
− | cruel_labyrinth = 'Жестокий Лабиринт', |
||
− | merciless_labyrinth = 'Безжалостный Лабиринт', |
||
− | eternal_labyrinth = 'Вечный Лабиринт', |
||
− | }, |
||
− | |||
− | drop_down_table = { |
||
− | collapse_all = 'Свернуть все', |
||
− | expand_all = 'Развернуть все', |
||
− | table_intro = 'В приведенных ниже таблицах представлены доступные [[свойства]] для таких [[предмет]]ов, как', |
||
− | prefix = 'Префикс', |
||
− | suffix = 'Суффикс', |
||
− | corrupted = 'Оскверненный', |
||
− | enchant = 'Зачарование', |
||
− | elder_prefix = 'Префикс Древнего', |
||
− | elder_suffix = 'Суффикс Древнего', |
||
− | shaper_prefix = 'Префикс Создателя', |
||
− | shaper_suffix = 'Суффикс Создателя', |
||
− | delve_prefix = 'Префикс Спуска', |
||
− | delve_suffix = 'Суффикс Спуска', |
||
− | mod_group = 'Группа свойств:', |
||
− | }, |
||
− | |||
− | errors = { |
||
− | -- |
||
− | -- Mod template |
||
− | -- |
||
− | sell_price_duplicate_name = 'Do not specify a sell price item name multiple times. Adjust the amount instead.', |
||
− | sell_price_missing_argument = 'Both %s and %s must be specified', |
||
− | |||
− | -- |
||
− | -- Modifier link template |
||
− | -- |
||
− | undefined_statid = 'Please define any of these stat ids: %s', |
||
− | incorrect_modid = 'Измените название с "%s" на любой из этих идентификаторов модификатора:<br>%s', |
||
− | multiple_results = 'Выберите только один из этих идентификаторов модификатора:<br>%s', |
||
− | no_results = 'Результатов не найдено.', |
||
− | }, |
||
− | } |
||
+ | local i18n = cfg.i18n |
||
+ | -- ---------------------------------------------------------------------------- |
||
− | -- |
||
− | -- Helper |
+ | -- Helper functions |
+ | -- ---------------------------------------------------------------------------- |
||
− | -- |
||
local h = {} |
local h = {} |
||
+ | |||
+ | -- Lazy loading for Module:Item link |
||
+ | function h.item_link(args) |
||
+ | if not f_item_link then |
||
+ | f_item_link = require('Module:Item link').item_link |
||
+ | end |
||
+ | return f_item_link(args) |
||
+ | end |
||
function h.header(str) |
function h.header(str) |
||
--[[ |
--[[ |
||
− | This function replaces specific numbers with a generic #. |
+ | This function replaces specific numbers with a generic #. |
]] |
]] |
||
+ | |||
− | |||
local s = table.concat(m_util.string.split(str, '%(%d+%.*%d*%-%d+%.*%d*%)'), '#') |
local s = table.concat(m_util.string.split(str, '%(%d+%.*%d*%-%d+%.*%d*%)'), '#') |
||
s = table.concat(m_util.string.split(s, '%d+%.*%d*'), '#') |
s = table.concat(m_util.string.split(s, '%d+%.*%d*'), '#') |
||
s = table.concat(m_util.string.split(s, '<br>'), ', ') |
s = table.concat(m_util.string.split(s, '<br>'), ', ') |
||
s = table.concat(m_util.string.split(s, '<br />'), ' ') |
s = table.concat(m_util.string.split(s, '<br />'), ' ') |
||
+ | |||
− | |||
return s |
return s |
||
end |
end |
||
function h.query_weights(table_name, page_ids) |
function h.query_weights(table_name, page_ids) |
||
+ | return m_cargo.map_results_to_id{ |
||
− | results = cargo.query( |
||
+ | results=m_cargo.query( |
||
− | string.format('mods,%s', table_name), |
||
− | + | {'mods', table_name}, |
|
− | { |
+ | { |
− | + | 'mods._pageID', |
|
− | + | table_name .. '.tag', |
|
− | + | table_name .. '.weight' |
|
− | + | }, |
|
− | + | { |
|
+ | where=page_ids, |
||
− | ) |
||
+ | join=string.format('mods._pageID=%s._pageID', table_name), |
||
− | if #results == 5000 then |
||
+ | orderBy=string.format('mods.id ASC,%s.ordinal ASC', table_name), |
||
− | error('Hit maximum cargo results') |
||
− | + | } |
|
− | + | ), |
|
− | + | field='mods._pageID', |
|
+ | } |
||
end |
end |
||
Строка 128: | Строка 78: | ||
for i,v in pairs(results) do |
for i,v in pairs(results) do |
||
str[#str+1] = string.format( |
str[#str+1] = string.format( |
||
− | '%s - %s ([[%s|page]])', |
+ | '%s - %s ([[%s|page]])', |
v['mods.id'] or v['mods._pageName'] or '', |
v['mods.id'] or v['mods._pageName'] or '', |
||
string.gsub( |
string.gsub( |
||
− | v['mods.stat_text_raw'] or 'N/A', |
+ | v['mods.stat_text_raw'] or 'N/A', |
− | '<br>', |
+ | '<br>', |
', ' |
', ' |
||
) or '', |
) or '', |
||
v['mods._pageName'] or '' |
v['mods._pageName'] or '' |
||
) |
) |
||
− | end |
+ | end |
return table.concat(str, '<br>') |
return table.concat(str, '<br>') |
||
end |
end |
||
+ | h.tbl = {} |
||
− | function h.cargo_query(tpl_args) |
||
+ | h.tbl.display = {} |
||
+ | h.tbl.display.factory = {} |
||
+ | function h.tbl.display.factory.value(args) |
||
+ | -- Format options for each field: |
||
+ | args.options = args.options or {} |
||
+ | |||
+ | -- Separator between fields: |
||
+ | args.delimiter = args.delimiter or ', ' |
||
+ | |||
+ | return function(tpl_args, tr, data, fields) |
||
+ | local values = {} |
||
+ | local fmt_values = {} |
||
+ | |||
+ | for index, field in ipairs(fields) do |
||
+ | local value = { |
||
+ | min=data[field], |
||
+ | max=data[field], |
||
+ | base=data[field], |
||
+ | } |
||
+ | if value.min then |
||
+ | values[#values+1] = value.max |
||
+ | local opts = args.options[index] or {} |
||
+ | -- Global colour is set, no overrides. |
||
+ | if args.color ~= nil or opts.color == nil then |
||
+ | opts.no_color = true |
||
+ | end |
||
+ | fmt_values[#fmt_values+1] = m_util.html.format_value(nil, value, opts) |
||
+ | end |
||
+ | end |
||
+ | |||
+ | if #values == 0 then |
||
+ | tr |
||
+ | :wikitext(m_util.html.td.na()) |
||
+ | else |
||
+ | local td = tr:tag('td') |
||
+ | td |
||
+ | :attr('data-sort-value', table.concat(values, args.delimiter)) |
||
+ | :wikitext(table.concat(fmt_values, args.delimiter)) |
||
+ | if args.color then |
||
+ | td:attr('class', 'tc -' .. args.color) |
||
+ | end |
||
+ | end |
||
+ | end |
||
+ | end |
||
+ | |||
+ | function h.get_spawn_chance(args) |
||
--[[ |
--[[ |
||
− | + | Calculates the spawn chance of a set of mods that all have a |
|
− | + | spawn weight. |
|
+ | |||
− | tpl_args to be added to the cargo table needs to prefixed with q_. |
||
− | * tpl_args.q_* |
||
− | |||
]] |
]] |
||
+ | |||
− | |||
− | -- |
+ | -- Get the table: |
− | local |
+ | local tbl = args['tbl'] |
+ | |||
− | limit = 5000, |
||
+ | -- Probabilities affecting the result besides the spawn weight: |
||
− | offset = 0, |
||
+ | local chance_multiplier = tonumber(args['chance_multiplier']) or 1 |
||
− | } |
||
+ | |||
− | for key, value in pairs(tpl_args) do |
||
+ | -- Total number of outcomes. |
||
− | if string.sub(key, 0, 2) == 'q_' then |
||
+ | local N = 0 |
||
− | query[string.sub(key, 3)] = value |
||
− | + | for i,_ in ipairs(tbl) do |
|
+ | N = N + tbl[i]['spawn_weights.weight'] |
||
end |
end |
||
+ | |||
− | |||
+ | for i,_ in ipairs(tbl) do |
||
− | -- Query cargo table. If there are too many results then repeat, |
||
− | + | -- Number of ways it can happen: |
|
+ | local n = tbl[i]['spawn_weights.weight'] |
||
− | local results = {} |
||
+ | |||
− | repeat |
||
− | + | -- Truncated value: |
|
+ | tbl[i]['spawn_weights.chance'] = string.format( |
||
− | query.tables, |
||
− | + | "%0.2f%%", |
|
− | + | n/N * chance_multiplier*100 |
|
) |
) |
||
+ | end |
||
− | query.offset = query.offset + #result |
||
+ | return tbl |
||
− | for _,v in ipairs(result) do |
||
− | results[#results + 1] = v |
||
− | end |
||
− | until #result < query.limit |
||
− | |||
− | return results |
||
end |
end |
||
-- ---------------------------------------------------------------------------- |
-- ---------------------------------------------------------------------------- |
||
+ | -- Additional configuration |
||
− | -- Template: Mod table |
||
-- ---------------------------------------------------------------------------- |
-- ---------------------------------------------------------------------------- |
||
Строка 195: | Строка 185: | ||
}, |
}, |
||
}, |
}, |
||
− | display = function(tpl_args |
+ | display = function(tpl_args, tr, data, fields) |
local name |
local name |
||
if data['mods.name'] then |
if data['mods.name'] then |
||
Строка 202: | Строка 192: | ||
name = data['mods.id'] |
name = data['mods.id'] |
||
end |
end |
||
+ | |||
tr |
tr |
||
:tag('td') |
:tag('td') |
||
Строка 213: | Строка 204: | ||
header = i18n.mod_table.domain, |
header = i18n.mod_table.domain, |
||
fields = {'mods.domain'}, |
fields = {'mods.domain'}, |
||
− | display = function(tpl_args |
+ | display = function(tpl_args, tr, data, fields) |
− | local |
+ | local k = 'mods.domain' |
− | + | local i = tonumber(data[k]) |
|
− | + | if m_game.constants.mod.domains[i] == nil then |
|
− | + | error('Undefined Modifier Domain ['..i..'] needs to be added to Module:Game') |
|
+ | end |
||
− | :wikitext(m_game.constants.mod.domains[tonumber(value)]['short_upper']) |
||
+ | data[k] = m_game.constants.mod.domains[i]['short_upper'] |
||
+ | h.tbl.display.factory.value({})(tpl_args, tr, data, fields) |
||
end, |
end, |
||
order = 2000, |
order = 2000, |
||
Строка 227: | Строка 220: | ||
header = i18n.mod_table.generation_type, |
header = i18n.mod_table.generation_type, |
||
fields = {'mods.generation_type'}, |
fields = {'mods.generation_type'}, |
||
− | display = function(tpl_args |
+ | display = function(tpl_args, tr, data, fields) |
− | local |
+ | local k = 'mods.generation_type' |
− | + | local i = tonumber(data[k]) |
|
− | + | if m_game.constants.mod.generation_types[i] == nil then |
|
− | + | error('Undefined Modifier Generation Type ['..i..'] needs to be added to Module:Game') |
|
+ | end |
||
− | :wikitext(m_game.constants.mod.generation_types[tonumber(value)]['short_upper']) |
||
+ | data[k] = m_game.constants.mod.generation_types[i]['short_upper'] |
||
+ | h.tbl.display.factory.value{}(tpl_args, tr, data, fields) |
||
end, |
end, |
||
order = 2001, |
order = 2001, |
||
Строка 241: | Строка 236: | ||
header = i18n.mod_table.mod_group, |
header = i18n.mod_table.mod_group, |
||
fields = {'mods.mod_group'}, |
fields = {'mods.mod_group'}, |
||
− | display = |
+ | display = h.tbl.display.factory.value{}, |
− | tr |
||
− | :tag('td') |
||
− | :wikitext(data['mods.mod_group']) |
||
− | end, |
||
order = 2002, |
order = 2002, |
||
sort_type = 'text', |
sort_type = 'text', |
||
Строка 253: | Строка 244: | ||
header = i18n.mod_table.mod_type, |
header = i18n.mod_table.mod_type, |
||
fields = {'mods.mod_type'}, |
fields = {'mods.mod_type'}, |
||
− | display = |
+ | display = h.tbl.display.factory.value{}, |
− | tr |
||
− | :tag('td') |
||
− | :wikitext(data['mods.mod_type']) |
||
− | end, |
||
order = 2003, |
order = 2003, |
||
sort_type = 'text', |
sort_type = 'text', |
||
Строка 265: | Строка 252: | ||
header = i18n.mod_table.required_level, |
header = i18n.mod_table.required_level, |
||
fields = {'mods.required_level'}, |
fields = {'mods.required_level'}, |
||
− | display = |
+ | display = h.tbl.display.factory.value{}, |
− | tr |
||
− | :tag('td') |
||
− | :wikitext(data['mods.required_level']) |
||
− | end, |
||
order = 2004, |
order = 2004, |
||
}, |
}, |
||
Строка 276: | Строка 259: | ||
header = i18n.mod_table.labyrinth, |
header = i18n.mod_table.labyrinth, |
||
fields = {string.format([[ |
fields = {string.format([[ |
||
− | CONCAT( |
+ | CONCAT( |
− | CASE mods.required_level |
+ | CASE mods.required_level |
− | WHEN 32 THEN "%s" |
+ | WHEN 32 THEN "%s" |
− | WHEN 53 THEN "%s" |
+ | WHEN 53 THEN "%s" |
− | WHEN 66 THEN "%s" |
+ | WHEN 66 THEN "%s" |
− | WHEN 75 THEN "%s" |
+ | WHEN 75 THEN "%s" |
− | END |
+ | END |
− | )=labyrinth_text |
+ | )=labyrinth_text]], |
− | + | i18n.mod_table.normal_labyrinth, |
|
+ | i18n.mod_table.cruel_labyrinth, |
||
− | display = function(tpl_args, frame, tr, data) |
||
− | + | i18n.mod_table.merciless_labyrinth, |
|
− | + | i18n.mod_table.eternal_labyrinth) |
|
+ | }, |
||
− | :wikitext(data['labyrinth_text']) |
||
+ | display = h.tbl.display.factory.value{}, |
||
− | end, |
||
order = 2005, |
order = 2005, |
||
sort_type = 'text', |
sort_type = 'text', |
||
Строка 297: | Строка 280: | ||
header = i18n.mod_table.stat_text, |
header = i18n.mod_table.stat_text, |
||
fields = {'mods.stat_text'}, |
fields = {'mods.stat_text'}, |
||
− | display = function(tpl_args |
+ | display = function(tpl_args, tr, data, fields) |
− | local |
+ | local value |
-- map display type shows this in another column, remove this text to avoid clogging up the list |
-- map display type shows this in another column, remove this text to avoid clogging up the list |
||
if tpl_args.type == 'map' then |
if tpl_args.type == 'map' then |
||
local texts = m_util.string.split(data['mods.stat_text'], '<br>') |
local texts = m_util.string.split(data['mods.stat_text'], '<br>') |
||
local out = {} |
local out = {} |
||
+ | |||
− | |||
local valid |
local valid |
||
for _, v in ipairs(texts) do |
for _, v in ipairs(texts) do |
||
Строка 313: | Строка 296: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
if valid then |
if valid then |
||
table.insert(out, v) |
table.insert(out, v) |
||
end |
end |
||
end |
end |
||
+ | |||
− | |||
− | + | value = table.concat(out, '<br>') |
|
else |
else |
||
− | + | value = data['mods.stat_text'] |
|
end |
end |
||
− | + | data['mods.stat_text'] = value |
|
+ | h.tbl.display.factory.value{color='mod'}(tpl_args, tr, data, fields) |
||
− | tr |
||
− | :tag('td') |
||
− | :wikitext(text) |
||
end, |
end, |
||
order = 3000, |
order = 3000, |
||
sort_type = 'text', |
sort_type = 'text', |
||
}, |
}, |
||
− | |||
{ |
{ |
||
arg = 'buff', |
arg = 'buff', |
||
header = i18n.mod_table.buff, |
header = i18n.mod_table.buff, |
||
fields = {'mods.granted_buff_id', 'mods.granted_buff_value'}, |
fields = {'mods.granted_buff_id', 'mods.granted_buff_value'}, |
||
− | display = |
+ | display = h.tbl.display.factory.value{delimiter=' '}, |
− | tr |
||
− | :tag('td') |
||
− | :wikitext(string.format('%s %s', data['mods.granted_buff_id'], data['mods.granted_buff_value'])) |
||
− | end, |
||
order = 4000, |
order = 4000, |
||
sort_type = 'text', |
sort_type = 'text', |
||
Строка 348: | Строка 324: | ||
header = i18n.mod_table.granted_skill, |
header = i18n.mod_table.granted_skill, |
||
fields = {'mods.granted_skill'}, |
fields = {'mods.granted_skill'}, |
||
− | display = |
+ | display = h.tbl.display.factory.value{}, |
− | tr |
||
− | :tag('td') |
||
− | :wikitext(data['mods.granted_skill']) |
||
− | end, |
||
order = 4001, |
order = 4001, |
||
sort_type = 'text', |
sort_type = 'text', |
||
Строка 360: | Строка 332: | ||
header = i18n.mod_table.tags, |
header = i18n.mod_table.tags, |
||
fields = {'mods.tags'}, |
fields = {'mods.tags'}, |
||
− | display = function(tpl_args |
+ | display = function(tpl_args, tr, data, fields) |
− | + | local k = 'mods.tags' |
|
− | + | data[k] = table.concat(m_util.string.split(data[k], ',%s*'), ', ') |
|
− | + | h.tbl.display.factory.value{}(tpl_args, tr, data, fields) |
|
end, |
end, |
||
order = 5000, |
order = 5000, |
||
Строка 385: | Строка 357: | ||
mod_table.weights = {'spawn_weights', 'generation_weights'} |
mod_table.weights = {'spawn_weights', 'generation_weights'} |
||
+ | -- ---------------------------------------------------------------------------- |
||
− | function p.mod_table(frame) |
||
+ | -- Main functions |
||
+ | -- ---------------------------------------------------------------------------- |
||
+ | |||
+ | local function _mod_table(tpl_args) |
||
--[[ |
--[[ |
||
Creates a generic table for modifiers. |
Creates a generic table for modifiers. |
||
+ | |||
− | |||
Examples |
Examples |
||
-------- |
-------- |
||
Строка 400: | Строка 376: | ||
enchantment=1, |
enchantment=1, |
||
} |
} |
||
− | |||
]] |
]] |
||
+ | |||
− | |||
− | |||
− | tpl_args = getArgs(frame, { |
||
− | parentFirst = true |
||
− | }) |
||
− | frame = m_util.misc.get_frame(frame) |
||
− | |||
-- default to enabled |
-- default to enabled |
||
tpl_args.name = tpl_args.name or true |
tpl_args.name = tpl_args.name or true |
||
+ | |||
− | |||
for _, key in ipairs(mod_table.weights) do |
for _, key in ipairs(mod_table.weights) do |
||
tpl_args[key] = m_util.cast.boolean(tpl_args[key]) |
tpl_args[key] = m_util.cast.boolean(tpl_args[key]) |
||
end |
end |
||
+ | |||
− | |||
if string.find(tpl_args.q_where, '%[%[') ~= nil then |
if string.find(tpl_args.q_where, '%[%[') ~= nil then |
||
error('SMW leftover in where clause') |
error('SMW leftover in where clause') |
||
end |
end |
||
+ | |||
− | |||
local row_infos = {} |
local row_infos = {} |
||
for _, row_info in ipairs(mod_table.data) do |
for _, row_info in ipairs(mod_table.data) do |
||
Строка 427: | Строка 396: | ||
elseif type(row_info.arg) == 'string' and m_util.cast.boolean(tpl_args[row_info.arg]) then |
elseif type(row_info.arg) == 'string' and m_util.cast.boolean(tpl_args[row_info.arg]) then |
||
enabled = true |
enabled = true |
||
− | elseif type(row_info.arg) == 'table' then |
+ | elseif type(row_info.arg) == 'table' then |
for _, argument in ipairs(row_info.arg) do |
for _, argument in ipairs(row_info.arg) do |
||
if m_util.cast.boolean(tpl_args[argument]) then |
if m_util.cast.boolean(tpl_args[argument]) then |
||
Строка 435: | Строка 404: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
if enabled then |
if enabled then |
||
row_info.options = row_info.options or {} |
row_info.options = row_info.options or {} |
||
Строка 441: | Строка 410: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
-- sort the rows |
-- sort the rows |
||
table.sort(row_infos, function (a, b) |
table.sort(row_infos, function (a, b) |
||
return (a.order or 0) < (b.order or 0) |
return (a.order or 0) < (b.order or 0) |
||
end) |
end) |
||
+ | |||
− | |||
− | -- Set tables |
+ | -- Set required and extra tables: |
− | local tables = 'mods' |
+ | local tables = {'mods'} |
− | + | for _, v in ipairs(m_util.string.split_args(tpl_args.q_tables, {',%s*'})) do |
|
− | tables = |
+ | tables[#tables+1] = v |
end |
end |
||
+ | |||
− | |||
+ | -- Set required and extra fields: |
||
− | |||
− | -- Set required fields |
||
local fields = { |
local fields = { |
||
'mods._pageID', |
'mods._pageID', |
||
} |
} |
||
− | for _, |
+ | for _, row_info in ipairs(row_infos) do |
− | if type( |
+ | if type(row_info.fields) == 'function' then |
− | + | row_info.fields = row_info.fields() |
|
end |
end |
||
− | for index, field in ipairs( |
+ | for index, field in ipairs(row_info.fields) do |
− | + | row_info.options[index] = row_info.options[index] or {} |
|
fields[#fields+1] = field |
fields[#fields+1] = field |
||
end |
end |
||
end |
end |
||
+ | tpl_args._extra_fields = m_util.string.split_args(tpl_args.q_fields, {',%s*'}) |
||
− | |||
+ | for _, v in ipairs(tpl_args._extra_fields) do |
||
− | -- Parse query arguments |
||
+ | fields[#fields+1] = v |
||
+ | end |
||
+ | |||
+ | -- Parse query arguments: |
||
local query = { |
local query = { |
||
-- Workaround: fix duplicates |
-- Workaround: fix duplicates |
||
groupBy='mods._pageID', |
groupBy='mods._pageID', |
||
} |
} |
||
− | for key, value in pairs(tpl_args) do |
+ | for key, value in pairs(tpl_args) do |
if string.sub(key, 0, 2) == 'q_' then |
if string.sub(key, 0, 2) == 'q_' then |
||
query[string.sub(key, 3)] = value |
query[string.sub(key, 3)] = value |
||
end |
end |
||
end |
end |
||
+ | |||
− | |||
+ | local results = m_cargo.query(tables, fields, query) |
||
− | |||
+ | |||
− | fields = table.concat(fields, ',') |
||
− | if tpl_args.q_fields then |
||
− | fields = fields .. ' ,' .. tpl_args.q_fields |
||
− | end |
||
− | |||
− | local results = cargo.query( |
||
− | tables, |
||
− | fields, |
||
− | query |
||
− | ) |
||
− | |||
if #results == 0 then |
if #results == 0 then |
||
if tpl_args.default ~= nil then |
if tpl_args.default ~= nil then |
||
Строка 498: | Строка 460: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
− | -- this might be needed in other queries, currently not checking if |
+ | -- this might be needed in other queries, currently not checking if |
− | -- because performance impact should be neglible |
+ | -- it's actually needed because performance impact should be neglible |
local page_ids = {} |
local page_ids = {} |
||
for _, row in ipairs(results) do |
for _, row in ipairs(results) do |
||
− | page_ids[#page_ids+1] = string.format( |
+ | page_ids[#page_ids+1] = string.format( |
+ | 'mods._pageID="%s"', |
||
+ | row['mods._pageID'] |
||
+ | ) |
||
end |
end |
||
page_ids = table.concat(page_ids, ' OR ') |
page_ids = table.concat(page_ids, ' OR ') |
||
+ | |||
− | |||
local weights = {} |
local weights = {} |
||
for _, key in ipairs(mod_table.weights) do |
for _, key in ipairs(mod_table.weights) do |
||
Строка 513: | Строка 478: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
local stats |
local stats |
||
if tpl_args.type == 'map' then |
if tpl_args.type == 'map' then |
||
Строка 520: | Строка 485: | ||
query_stat_ids[#query_stat_ids+1] = string.format('mod_stats.id="%s"', k) |
query_stat_ids[#query_stat_ids+1] = string.format('mod_stats.id="%s"', k) |
||
end |
end |
||
+ | |||
− | |||
− | + | stats = m_cargo.map_results_to_id{ |
|
− | + | results=m_cargo.query( |
|
− | 'mods |
+ | {'mods', 'mod_stats'}, |
− | { |
+ | { |
− | + | 'mods._pageID', |
|
− | + | 'mod_stats.id', |
|
− | + | 'mod_stats.min', |
|
− | + | 'mod_stats.max', |
|
− | } |
+ | }, |
− | + | { |
|
+ | where=string.format( |
||
− | if #stat_results == 5000 then |
||
− | + | '(%s) AND (%s)', |
|
− | + | page_ids, |
|
+ | table.concat(query_stat_ids, ' OR ') |
||
− | |||
+ | ), |
||
− | stats = m_util.cargo.map_results_to_id{results=stat_results, field='mods._pageID'} |
||
+ | join='mods._pageID=mod_stats._pageID', |
||
+ | orderBy='mods.id ASC', |
||
+ | } |
||
+ | ), |
||
+ | field='mods._pageID' |
||
+ | } |
||
+ | |||
-- In addition map stats to stat <-> min/max pairs |
-- In addition map stats to stat <-> min/max pairs |
||
for page_id, rows in pairs(stats) do |
for page_id, rows in pairs(stats) do |
||
local stat_id_map = {} |
local stat_id_map = {} |
||
for _, row in ipairs(rows) do |
for _, row in ipairs(rows) do |
||
− | stat_id_map[row['mod_stats.id']] = { |
+ | stat_id_map[row['mod_stats.id']] = { |
+ | min=tonumber(row['mod_stats.min']), |
||
+ | max=tonumber(row['mod_stats.max']) |
||
+ | } |
||
end |
end |
||
stats[page_id] = stat_id_map |
stats[page_id] = stat_id_map |
||
end |
end |
||
end |
end |
||
+ | |||
− | |||
-- |
-- |
||
-- Display |
-- Display |
||
-- |
-- |
||
+ | |||
− | |||
-- Preformance optimization |
-- Preformance optimization |
||
− | + | for index, field in ipairs(tpl_args._extra_fields) do |
|
− | + | field = m_util.string.split(field, '%s*=%s*') |
|
+ | -- field[2] will be nil if there is no alias |
||
− | for index, field in ipairs(tpl_args._extra_fields) do |
||
− | + | tpl_args._extra_fields[index] = field[2] or field[1] |
|
− | -- field[2] will be nil if there is no alias |
||
− | tpl_args._extra_fields[index] = field[2] or field[1] |
||
− | end |
||
− | else |
||
− | tpl_args._extra_fields = {} |
||
end |
end |
||
+ | |||
− | |||
local tbl = mw.html.create('table') |
local tbl = mw.html.create('table') |
||
tbl:attr('class', 'wikitable sortable modifier-table') |
tbl:attr('class', 'wikitable sortable modifier-table') |
||
-- Header |
-- Header |
||
+ | |||
− | |||
local tr = tbl:tag('tr') |
local tr = tbl:tag('tr') |
||
+ | local display_fields = {} |
||
− | for _, row_info in ipairs(row_infos) do |
||
+ | for i, row_info in ipairs(row_infos) do |
||
+ | for j, field in ipairs(row_info.fields) do |
||
+ | -- Aliased name is used as keys in the results: |
||
+ | field = m_util.string.split(field, '%s*=%s*') |
||
+ | field = field[2] or field[1] |
||
+ | |||
+ | -- Make a new field table since mod_table.data will remain |
||
+ | -- modified the 2nd time a function is run and then crash. |
||
+ | if j == 1 then |
||
+ | display_fields[i] = {} |
||
+ | end |
||
+ | display_fields[i][j] = field |
||
+ | end |
||
+ | |||
tr |
tr |
||
:tag('th') |
:tag('th') |
||
Строка 574: | Строка 558: | ||
:done() |
:done() |
||
end |
end |
||
+ | |||
− | |||
if tpl_args.type == 'map' then |
if tpl_args.type == 'map' then |
||
for stat_id, data in pairs(mod_table.stat_ids) do |
for stat_id, data in pairs(mod_table.stat_ids) do |
||
Строка 584: | Строка 568: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
for _, key in ipairs(mod_table.weights) do |
for _, key in ipairs(mod_table.weights) do |
||
if tpl_args[key] then |
if tpl_args[key] then |
||
Строка 592: | Строка 576: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
for _, field in ipairs(tpl_args._extra_fields) do |
for _, field in ipairs(tpl_args._extra_fields) do |
||
tr |
tr |
||
Строка 598: | Строка 582: | ||
:wikitext(field) |
:wikitext(field) |
||
end |
end |
||
+ | |||
− | |||
-- Body |
-- Body |
||
+ | |||
− | |||
for _, row in ipairs(results) do |
for _, row in ipairs(results) do |
||
tr = tbl:tag('tr') |
tr = tbl:tag('tr') |
||
+ | |||
− | |||
− | for |
+ | for i, row_info in ipairs(row_infos) do |
-- this has been cast from a function in an earlier step |
-- this has been cast from a function in an earlier step |
||
local display = true |
local display = true |
||
− | for |
+ | for j, field in ipairs(display_fields[i]) do |
-- this will bet set to an empty value not nil confusingly |
-- this will bet set to an empty value not nil confusingly |
||
− | if row[field] == '' then |
+ | if row[field] == nil or row[field] == '' then |
− | if |
+ | if row_info.options[j].optional ~= true then |
display = false |
display = false |
||
break |
break |
||
Строка 619: | Строка 603: | ||
end |
end |
||
if display then |
if display then |
||
− | + | row_info.display(tpl_args, tr, row, display_fields[i]) |
|
else |
else |
||
tr:wikitext(m_util.html.td.na()) |
tr:wikitext(m_util.html.td.na()) |
||
end |
end |
||
end |
end |
||
+ | |||
− | |||
if tpl_args.type == 'map' then |
if tpl_args.type == 'map' then |
||
for stat_id, data in pairs(mod_table.stat_ids) do |
for stat_id, data in pairs(mod_table.stat_ids) do |
||
Строка 646: | Строка 630: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
for _, key in ipairs(mod_table.weights) do |
for _, key in ipairs(mod_table.weights) do |
||
if tpl_args[key] then |
if tpl_args[key] then |
||
local weight_out = {} |
local weight_out = {} |
||
for _, wrow in ipairs(weights[key][row['mods._pageID']]) do |
for _, wrow in ipairs(weights[key][row['mods._pageID']]) do |
||
− | + | if wrow[key .. '.tag'] and wrow[key .. '.weight'] then |
|
+ | weight_out[#weight_out+1] = string.format( |
||
+ | '%s %s', |
||
+ | wrow[key .. '.tag'], |
||
+ | wrow[key .. '.weight'] |
||
+ | ) |
||
+ | end |
||
end |
end |
||
+ | |||
if #weight_out > 0 then |
if #weight_out > 0 then |
||
tr |
tr |
||
− | + | :tag('td') |
|
− | + | :wikitext(table.concat(weight_out, '<br>')) |
|
− | + | :done() |
|
− | else |
+ | else |
tr:wikitext(m_util.html.td.na()) |
tr:wikitext(m_util.html.td.na()) |
||
end |
end |
||
end |
end |
||
end |
end |
||
+ | |||
− | |||
for _, field in ipairs(tpl_args._extra_fields) do |
for _, field in ipairs(tpl_args._extra_fields) do |
||
if row[field] then |
if row[field] then |
||
Строка 674: | Строка 665: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
return tostring(tbl) |
return tostring(tbl) |
||
end |
end |
||
+ | local function _drop_down_table(tpl_args) |
||
− | |||
− | |||
− | |||
− | -- --------------------------------------------------------------------- |
||
− | -- Modifier link |
||
− | -- --------------------------------------------------------------------- |
||
− | |||
− | |||
− | function p.modifier_link(frame) |
||
--[[ |
--[[ |
||
+ | This function queries mods that can spawn on an item. It compares |
||
− | Finds and links to a modifier in formatted form. |
||
+ | the item tags and the spawn weight tags. If there's a match and |
||
− | |||
+ | the spawn weight is larger than zero, then that mod is added to a |
||
− | Examples: |
||
− | = p.modifier_link{"Tyrannical"} |
||
− | = p.modifier_link{"Flaring"} |
||
− | = p.modifier_link{"Dictator's"} |
||
− | = p.modifier_link{"StrDexMaster%"} |
||
− | = p.modifier_link{"LocalIncreasedPhysicalDamagePercentAndAccuracyRating8", display='max', statid='local_physical_damage_+%'} |
||
− | |||
− | ]] |
||
− | |||
− | -- Get template args: |
||
− | local tpl_args = getArgs(frame, {parentFirst = true}) |
||
− | local frame = m_util.misc.get_frame(frame) |
||
− | |||
− | -- Aliases: |
||
− | tpl_args.modid = tpl_args.modid or tpl_args.id or tpl_args[1] or '' |
||
− | |||
− | -- Define query arguments: |
||
− | local tables = {'mods', 'mod_stats', 'spawn_weights'} |
||
− | local fields = {'mods.name', 'mods.stat_text', 'mods.stat_text_raw', 'mods.generation_type', 'mods.tags', 'mods._pageName', 'mod_stats.max', 'mod_stats.min', 'spawn_weights.tag', 'spawn_weights.weight', 'mods.id', 'mod_stats.id'} |
||
− | local query = { |
||
− | join = 'mods._pageName=mod_stats._pageName, mods._pageName=spawn_weights._pageName', |
||
− | where = string.format( |
||
− | '(mods.name LIKE "%s" or mods.id LIKE "%s" or mods.stat_text LIKE "%s" or mods.stat_text_raw LIKE "%s") AND mod_stats.id LIKE "%%%s%%"', |
||
− | tpl_args.modid, |
||
− | tpl_args.modid, |
||
− | tpl_args.modid, |
||
− | tpl_args.modid, |
||
− | tpl_args.statid or '%' |
||
− | ), |
||
− | -- groupBy = 'mods._pageID, mod_stats.id, spawn_weights.tag', |
||
− | } |
||
− | |||
− | -- Query cargo rows: |
||
− | local results = m_util.cargo.query(tables, fields, query, args) |
||
− | |||
− | -- Create own list for each cargo table and group by page name: |
||
− | tpl_args.tbl = {} |
||
− | for _,v in ipairs(tables) do |
||
− | tpl_args.tbl[v] = {} |
||
− | end |
||
− | |||
− | tpl_args.results_unique = {} |
||
− | local hash = {} |
||
− | for _,v in ipairs(results) do |
||
− | for ii, vv in pairs(tpl_args.tbl) do |
||
− | if tpl_args.tbl[ii][v['mods._pageName']] == nil then |
||
− | tpl_args.tbl[ii][v['mods._pageName']] = {} |
||
− | end |
||
− | local n = #tpl_args.tbl[ii][v['mods._pageName']] or 0 |
||
− | tpl_args.tbl[ii][v['mods._pageName']][n+1] = v |
||
− | |||
− | -- Get a sorted list that only has unique page names: |
||
− | if hash[v['mods._pageName']] ~= true then |
||
− | local m = #tpl_args.results_unique |
||
− | tpl_args.results_unique[m+1] = v |
||
− | hash[v['mods._pageName']] = true |
||
− | end |
||
− | end |
||
− | end |
||
− | |||
− | -- If no results are found then just create a empty list to avoid |
||
− | -- index errors. |
||
− | if tpl_args.results_unique[1] == nil then |
||
− | tpl_args.results_unique[1] = {} |
||
− | end |
||
− | |||
− | -- Helpful error handling: |
||
− | local err_tbl = { |
||
− | { |
||
− | bool = #results == 0, |
||
− | disp = { |
||
− | i18n.errors.no_results, |
||
− | } |
||
− | }, |
||
− | { |
||
− | bool = #tpl_args.results_unique > 1, |
||
− | disp = { |
||
− | i18n.errors.multiple_results, |
||
− | h.disambiguate_mod_name(tpl_args.results_unique), |
||
− | }, |
||
− | }, |
||
− | { |
||
− | bool = tpl_args.modid ~= tpl_args.results_unique[1]['mods.id'], |
||
− | disp = { |
||
− | string.gsub( |
||
− | i18n.errors.incorrect_modid, |
||
− | '%%s', |
||
− | tpl_args.modid, |
||
− | 1 |
||
− | ), |
||
− | h.disambiguate_mod_name(tpl_args.results_unique), |
||
− | }, |
||
− | }, |
||
− | } |
||
− | for _,v in ipairs(err_tbl) do |
||
− | if v.bool then |
||
− | local cats = {'Pages with modifier link errors'} |
||
− | return m_util.html.error( |
||
− | {msg = string.format(v.disp[1], v.disp[2]) .. m_util.misc.add_category(cats)} |
||
− | ) |
||
− | end |
||
− | end |
||
− | |||
− | -- Display formats: |
||
− | local display = { |
||
− | abbr = { |
||
− | display = function(tpl_args, frame) |
||
− | local name = m_util.html.poe_color( |
||
− | 'mod', |
||
− | string.format( |
||
− | '[[%s|%s]]', |
||
− | tpl_args.results_unique[1]['mods._pageName'], |
||
− | tpl_args.results_unique[1]['mods.name'] or tpl_args.results_unique[1]['mods.id'] |
||
− | ) |
||
− | ) |
||
− | |||
− | local tooltip_table = { |
||
− | m_util.html.poe_color( |
||
− | 'mod', |
||
− | tpl_args.results_unique[1]['mods.name'] or tpl_args.results_unique[1]['mods.id'] |
||
− | ), |
||
− | m_util.html.poe_color( |
||
− | 'help', |
||
− | m_game.constants.mod.generation_types[ |
||
− | tonumber( |
||
− | tpl_args.results_unique[1]['mods.generation_type'] |
||
− | ) |
||
− | ].full |
||
− | ), |
||
− | -- m_util.html.poe_color( |
||
− | -- 'help', |
||
− | -- table.concat( |
||
− | -- m_util.string.split(tpl_args.results_unique[1]['mods.tags'] or '', ','), |
||
− | -- ', ' |
||
− | -- ) |
||
− | -- ), |
||
− | m_util.html.poe_color( |
||
− | 'normal', |
||
− | tpl_args.results_unique[1]['mods.stat_text_raw'] |
||
− | ), |
||
− | } |
||
− | |||
− | local tt_tbl_fltrd = {} |
||
− | for _,v in ipairs(tooltip_table) do |
||
− | if v ~= nil and v ~= '' then |
||
− | tt_tbl_fltrd[#tt_tbl_fltrd+1] = v |
||
− | end |
||
− | end |
||
− | local tooltip = table.concat(tt_tbl_fltrd, '<br>') |
||
− | |||
− | return m_util.html.tooltip(name, tooltip, class) |
||
− | end, |
||
− | }, |
||
− | verbose = { |
||
− | display = function(tpl_args, frame) |
||
− | return string.format( |
||
− | '%s - %s (%s)', |
||
− | m_util.html.poe_color( |
||
− | 'mod', |
||
− | string.format( |
||
− | '[[%s|%s]]', |
||
− | tpl_args.results_unique[1]['mods._pageName'], |
||
− | tpl_args.results_unique[1]['mods.name'] or tpl_args.results_unique[1]['mods.id'] |
||
− | ) |
||
− | ), |
||
− | m_util.html.poe_color( |
||
− | 'mod', |
||
− | string.gsub( |
||
− | tpl_args.results_unique[1]['mods.stat_text'], |
||
− | '<br>', |
||
− | ', ' |
||
− | ) |
||
− | ), |
||
− | m_game.constants.mod.generation_types[ |
||
− | tonumber( |
||
− | tpl_args.results_unique[1]['mods.generation_type'] |
||
− | ) |
||
− | ].full |
||
− | ) |
||
− | end, |
||
− | }, |
||
− | stat_text = { |
||
− | display = function(tpl_args, frame) |
||
− | return m_util.html.poe_color( |
||
− | 'mod', |
||
− | tpl_args.results_unique[1]['mods.stat_text'] |
||
− | ) |
||
− | end, |
||
− | }, |
||
− | max = { |
||
− | display = function(tpl_args, frame) |
||
− | local statid = {} |
||
− | for _,v in ipairs(tpl_args.tbl.mod_stats[tpl_args.results_unique[1]['mods._pageName']]) do |
||
− | statid[#statid+1] = v['mod_stats.id'] |
||
− | if tpl_args.statid == v['mod_stats.id'] then |
||
− | return v['mod_stats.max'] |
||
− | end |
||
− | end |
||
− | |||
− | if tpl_args.statid == nil then |
||
− | return m_util.html.error( |
||
− | { |
||
− | msg = string.format( |
||
− | i18n.errors.undefined_statid, |
||
− | table.concat(statid, ', ') |
||
− | ) |
||
− | } |
||
− | ) |
||
− | end |
||
− | end |
||
− | }, |
||
− | min = { |
||
− | display = function(tpl_args, frame) |
||
− | local statid = {} |
||
− | for _,v in ipairs(tpl_args.tbl.mod_stats[tpl_args.results_unique[1]['mods._pageName']]) do |
||
− | statid[#statid+1] = v['mod_stats.id'] |
||
− | if tpl_args.statid == v['mod_stats.id'] then |
||
− | return v['mod_stats.min'] |
||
− | end |
||
− | end |
||
− | |||
− | if tpl_args.statid == nil then |
||
− | return m_util.html.error( |
||
− | { |
||
− | msg = string.format( |
||
− | i18n.errors.undefined_statid, |
||
− | table.concat(statid, ', ') |
||
− | ) |
||
− | } |
||
− | ) |
||
− | end |
||
− | end |
||
− | }, |
||
− | } |
||
− | |||
− | return display[tpl_args.display or 'abbr'].display(tpl_args, frame) |
||
− | end |
||
− | |||
− | |||
− | |||
− | |||
− | -- --------------------------------------------------------------------- |
||
− | -- Drop down list |
||
− | -- --------------------------------------------------------------------- |
||
− | |||
− | function h.get_spawn_chance(frame) |
||
− | --[[ |
||
− | Calculates the spawn chance of a set of mods that all have a |
||
− | spawn weight. |
||
− | |||
− | ]] |
||
− | |||
− | -- Get template arguments: |
||
− | local tpl_args = getArgs(frame, {parentFirst=true}) |
||
− | local frame = m_util.misc.get_frame(frame) |
||
− | |||
− | -- Get the table: |
||
− | local tbl = tpl_args['tbl'] |
||
− | |||
− | -- Probabilities affecting the result besides the spawn weight: |
||
− | local chance_multiplier = tonumber(tpl_args['chance_multiplier']) or 1 |
||
− | |||
− | -- Total number of outcomes. |
||
− | local N = 0 |
||
− | for i,_ in ipairs(tbl) do |
||
− | N = N + tbl[i]['spawn_weights.weight'] |
||
− | end |
||
− | |||
− | for i,_ in ipairs(tbl) do |
||
− | -- Number of ways it can happen: |
||
− | local n = tbl[i]['spawn_weights.weight'] |
||
− | |||
− | -- Truncated value: |
||
− | tbl[i]['spawn_weights.chance'] = string.format( |
||
− | "%0.2f%%", |
||
− | n/N * chance_multiplier*100 |
||
− | ) |
||
− | end |
||
− | |||
− | return tbl |
||
− | end |
||
− | |||
− | function p.drop_down_table(frame) |
||
− | --[[ |
||
− | This function queries mods that can spawn on an item. It compares |
||
− | the item tags and the spawn weight tags. If there's a match and |
||
− | the spawn weight is larger than zero, then that mod is added to a |
||
drop down list. |
drop down list. |
||
+ | |||
− | |||
To Do: |
To Do: |
||
* Add support to: |
* Add support to: |
||
* Forsaken masters |
* Forsaken masters |
||
* Bestiary |
* Bestiary |
||
− | * Add a proper expand/collapse toggle for the entire header row so |
+ | * Add a proper expand/collapse toggle for the entire header row so |
− | it reacts together with mw-collapsible. |
+ | it reacts together with mw-collapsible. |
− | * Show Mod group in a better way perhaps: |
+ | * Show Mod group in a better way perhaps: |
Mod group [Collapsible, default=Expanded] |
Mod group [Collapsible, default=Expanded] |
||
# to Damage [Collapsible, default=Collapsed] |
# to Damage [Collapsible, default=Collapsed] |
||
3 to Damage |
3 to Damage |
||
5 to Damage |
5 to Damage |
||
− | * Add a where condition that somehow filters out mods that obviously |
+ | * Add a where condition that somehow filters out mods that obviously |
− | wont match with the item. spawn_weights.weight>0 isn't enough due |
+ | wont match with the item. spawn_weights.weight>0 isn't enough due |
to possible edge cases. |
to possible edge cases. |
||
+ | |||
− | |||
+ | |||
− | |||
− | Examples: |
+ | Examples: |
Weapons |
Weapons |
||
− | = p.drop_down_table{item |
+ | = p.drop_down_table{item='Rusted Hatchet', header='One Handed Axes'} |
− | = p.drop_down_table{item |
+ | = p.drop_down_table{item='Stone Axe', header='Two Handed Axes'} |
Accessories |
Accessories |
||
− | = p.drop_down_table{item |
+ | = p.drop_down_table{item='Amber Amulet', header='Amulets'} |
+ | |||
− | |||
Jewels |
Jewels |
||
− | = p.drop_down_table{item |
+ | = p.drop_down_table{item='Cobalt Jewel', header='Jewels'} |
+ | |||
− | |||
Armour |
Armour |
||
− | = p.drop_down_table{item |
+ | = p.drop_down_table{item='Plate Vest', header='Body armours'} |
+ | |||
− | |||
Boots |
Boots |
||
− | = p.drop_down_table{item |
+ | = p.drop_down_table{item='Iron Greaves', header='Boots'} |
+ | |||
− | |||
= p.drop_down_table{ |
= p.drop_down_table{ |
||
− | item |
+ | item='Fishing Rod', |
− | header |
+ | header='FISH PLEASE', |
− | item_tags |
+ | item_tags='fishing_rod', |
− | extra_fields |
+ | extra_fields='mods.tags' |
} |
} |
||
+ | |||
− | |||
= p.drop_down_table{ |
= p.drop_down_table{ |
||
− | item |
+ | item='Fishing Rod', |
− | item_tags |
+ | item_tags='axe, one_hand_weapon, onehand, weapon, default', |
− | extra_item_tags |
+ | extra_item_tags='fishing_rod' |
} |
} |
||
+ | |||
− | |||
= p.drop_down_table{ |
= p.drop_down_table{ |
||
− | item |
+ | item='Vaal Blade', |
} |
} |
||
+ | |||
− | |||
]] |
]] |
||
− | -- Get template arguments: |
||
− | local tpl_args = getArgs(frame, {parentFirst=true}) |
||
− | local frame = m_util.misc.get_frame(frame) |
||
− | |||
-- Format the cargo query: |
-- Format the cargo query: |
||
local where |
local where |
||
Строка 1040: | Строка 733: | ||
{tpl_args.page, 'items._pageName = "%s"'}, |
{tpl_args.page, 'items._pageName = "%s"'}, |
||
{tpl_args.item, 'items.name = "%s"'}, |
{tpl_args.item, 'items.name = "%s"'}, |
||
− | }) do |
+ | }) do |
if v[1] ~= nil then |
if v[1] ~= nil then |
||
where = string.format(v[2], v[1]) |
where = string.format(v[2], v[1]) |
||
Строка 1046: | Строка 739: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
local item_info = m_cargo.query( |
local item_info = m_cargo.query( |
||
{'items'}, |
{'items'}, |
||
+ | { |
||
− | {'items.name', 'items.tags', 'items.class', 'items.class_id', 'items.inventory_icon', 'items.html', 'items.release_version', 'items._pageName'}, |
||
+ | 'items.name', |
||
+ | 'items.tags', |
||
+ | 'items.class_id', |
||
+ | 'items.inventory_icon', |
||
+ | 'items.html', |
||
+ | 'items.release_version', |
||
+ | 'items._pageName' |
||
+ | }, |
||
{ |
{ |
||
where=where, |
where=where, |
||
groupBy='items._pageName', |
groupBy='items._pageName', |
||
− | orderBy |
+ | orderBy='items.name, items.release_version DESC', |
} |
} |
||
)[1] |
)[1] |
||
+ | |||
− | |||
− | -- Set the item class as key and the corresponding mod domain as |
+ | -- Set the item class as key and the corresponding mod domain as |
-- value: |
-- value: |
||
+ | local value |
||
local class_to_domain = { |
local class_to_domain = { |
||
− | [' |
+ | ['LifeFlask']=2, |
− | [' |
+ | ['ManaFlask']=2, |
− | [' |
+ | ['HybridFlask']=2, |
− | [' |
+ | ['UtilityFlask']=2, |
− | [' |
+ | ['UtilityFlaskCritical']=2, |
− | [' |
+ | ['Map']=5, |
− | [' |
+ | ['Jewel']=10, |
− | [' |
+ | ['Leaguestone']=12, |
− | [' |
+ | ['AbyssJewel']=13, |
} |
} |
||
− | -- Get the domain, if it's not defined in the table assume it's |
+ | -- Get the domain, if it's not defined in the table assume it's |
-- in the item domain. |
-- in the item domain. |
||
− | item_info['items.domain'] = class_to_domain[item_info['items. |
+ | item_info['items.domain'] = tonumber(tpl_args.domain) or class_to_domain[item_info['items.class_id']] or 1 |
+ | |||
− | |||
-- Convert the mod domain number to understandable text: |
-- Convert the mod domain number to understandable text: |
||
item_info['items.domain_text'] = m_game.constants.mod.domains[item_info['items.domain']]['short_lower'] |
item_info['items.domain_text'] = m_game.constants.mod.domains[item_info['items.domain']]['short_lower'] |
||
+ | |||
− | |||
− | -- |
+ | -- Format item tags: |
+ | tpl_args.item_tags = m_util.string.split_args( |
||
− | -- separated any more. |
||
− | + | tpl_args.item_tags or item_info['items.tags'], |
|
+ | {sep=',%s*'} |
||
− | tpl_args.item_tags = m_util.string.split(tpl_args.item_tags, ', ') |
||
− | + | ) |
|
− | + | for _,v in ipairs(m_util.string.split_args(tpl_args.extra_item_tags, {sep=',%s*'})) do |
|
+ | tpl_args.item_tags[#tpl_args.item_tags+1] = v |
||
− | end |
||
− | if tpl_args.extra_item_tags then |
||
− | local extra_item_tags = m_util.string.split(tpl_args.extra_item_tags, ', ') |
||
− | for _,v in ipairs(extra_item_tags) do |
||
− | tpl_args.item_tags[#tpl_args.item_tags+1] = v |
||
− | end |
||
end |
end |
||
+ | |||
− | |||
+ | -- Format extra fields: |
||
+ | local extra_fields = m_util.string.split_args(tpl_args.extra_fields, {sep=',%s*'}) |
||
+ | |||
+ | |||
+ | -- Get tags that are appended to special items: |
||
+ | local tags_cfg = m_game.constants.item.classes[item_info['items.class_id']].tags or {} |
||
+ | |||
-- Create drop down lists in these sections and query in these |
-- Create drop down lists in these sections and query in these |
||
-- generation types. |
-- generation types. |
||
+ | local section = { |
||
− | |||
− | local elder_tag = m_game.constants.item.classes[item_info['items.class_id']]['elder_tag'] |
||
− | local shaper_tag = m_game.constants.item.classes[item_info['items.class_id']]['shaper_tag'] |
||
− | |||
− | local section = {} |
||
− | section = { |
||
{ |
{ |
||
header = i18n.drop_down_table.prefix, |
header = i18n.drop_down_table.prefix, |
||
− | where = function(tpl_args |
+ | where = function(tpl_args, value) |
local where = {} |
local where = {} |
||
− | for _, item_tag in ipairs(tpl_args.item_tags) do |
+ | for _, item_tag in ipairs(tpl_args.item_tags) do |
where[#where+1] = string.format( |
where[#where+1] = string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
item_tag, |
item_tag, |
||
1, |
1, |
||
Строка 1111: | Строка 815: | ||
) |
) |
||
end |
end |
||
+ | |||
− | |||
− | return table.concat(where, ' OR ') |
+ | return table.concat(where, ' OR ') |
end, |
end, |
||
}, |
}, |
||
{ |
{ |
||
header = i18n.drop_down_table.suffix, |
header = i18n.drop_down_table.suffix, |
||
− | where = function(tpl_args |
+ | where = function(tpl_args, value) |
local where = {} |
local where = {} |
||
− | for _, item_tag in ipairs(tpl_args.item_tags) do |
+ | for _, item_tag in ipairs(tpl_args.item_tags) do |
where[#where+1] = string.format( |
where[#where+1] = string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
item_tag, |
item_tag, |
||
2, |
2, |
||
Строка 1127: | Строка 836: | ||
) |
) |
||
end |
end |
||
+ | |||
− | |||
− | return table.concat(where, ' OR ') |
+ | return table.concat(where, ' OR ') |
end, |
end, |
||
}, |
}, |
||
{ |
{ |
||
− | tags = { |
+ | tags = {tags_cfg.elder}, |
header = i18n.drop_down_table.elder_prefix, |
header = i18n.drop_down_table.elder_prefix, |
||
− | where = function(tpl_args |
+ | where = function(tpl_args, value) |
return string.format( |
return string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
− | + | (spawn_weights.tag="%s" |
|
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.elder, |
||
1, |
1, |
||
item_info['items.domain'] |
item_info['items.domain'] |
||
Строка 1144: | Строка 858: | ||
}, |
}, |
||
{ |
{ |
||
− | tags = { |
+ | tags = {tags_cfg.elder}, |
header = i18n.drop_down_table.elder_suffix, |
header = i18n.drop_down_table.elder_suffix, |
||
− | where = function(tpl_args |
+ | where = function(tpl_args, value) |
return string.format( |
return string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
− | + | (spawn_weights.tag="%s" |
|
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.elder, |
||
2, |
2, |
||
item_info['items.domain'] |
item_info['items.domain'] |
||
Строка 1156: | Строка 875: | ||
}, |
}, |
||
{ |
{ |
||
− | tags = { |
+ | tags = {tags_cfg.shaper}, |
header = i18n.drop_down_table.shaper_prefix, |
header = i18n.drop_down_table.shaper_prefix, |
||
− | where = function(tpl_args |
+ | where = function(tpl_args, value) |
return string.format( |
return string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
− | + | (spawn_weights.tag="%s" |
|
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.shaper, |
||
1, |
1, |
||
item_info['items.domain'] |
item_info['items.domain'] |
||
Строка 1168: | Строка 892: | ||
}, |
}, |
||
{ |
{ |
||
− | tags = { |
+ | tags = {tags_cfg.shaper}, |
header = i18n.drop_down_table.shaper_suffix, |
header = i18n.drop_down_table.shaper_suffix, |
||
− | where = function(tpl_args |
+ | where = function(tpl_args, value) |
return string.format( |
return string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
− | + | (spawn_weights.tag="%s" |
|
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.shaper, |
||
2, |
2, |
||
item_info['items.domain'] |
item_info['items.domain'] |
||
Строка 1181: | Строка 910: | ||
{ |
{ |
||
header = i18n.drop_down_table.delve_prefix, |
header = i18n.drop_down_table.delve_prefix, |
||
− | where = function(tpl_args |
+ | where = function(tpl_args, value) |
local where = {} |
local where = {} |
||
− | for _, item_tag in ipairs(tpl_args.item_tags) do |
+ | for _, item_tag in ipairs(tpl_args.item_tags) do |
where[#where+1] = string.format( |
where[#where+1] = string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
item_tag, |
item_tag, |
||
1, |
1, |
||
Строка 1191: | Строка 925: | ||
) |
) |
||
end |
end |
||
+ | |||
− | |||
− | return table.concat(where, ' OR ') |
+ | return table.concat(where, ' OR ') |
end, |
end, |
||
}, |
}, |
||
{ |
{ |
||
header = i18n.drop_down_table.delve_suffix, |
header = i18n.drop_down_table.delve_suffix, |
||
− | where = function(tpl_args |
+ | where = function(tpl_args, value) |
local where = {} |
local where = {} |
||
− | for _, item_tag in ipairs(tpl_args.item_tags) do |
+ | for _, item_tag in ipairs(tpl_args.item_tags) do |
where[#where+1] = string.format( |
where[#where+1] = string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
item_tag, |
item_tag, |
||
2, |
2, |
||
Строка 1207: | Строка 946: | ||
) |
) |
||
end |
end |
||
+ | |||
− | |||
− | return table.concat(where, ' OR ') |
+ | return table.concat(where, ' OR ') |
end, |
end, |
||
}, |
}, |
||
{ |
{ |
||
− | + | tags = {tags_cfg.crusader}, |
|
− | + | header = i18n.drop_down_table.crusader_prefix, |
|
+ | where = function(tpl_args, value) |
||
+ | return string.format( |
||
+ | [[ |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.crusader, |
||
+ | 1, |
||
+ | item_info['items.domain'] |
||
+ | ) |
||
+ | end, |
||
+ | }, |
||
+ | { |
||
+ | tags = {tags_cfg.crusader}, |
||
+ | header = i18n.drop_down_table.crusader_suffix, |
||
+ | where = function(tpl_args, value) |
||
+ | return string.format( |
||
+ | [[ |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.crusader, |
||
+ | 2, |
||
+ | item_info['items.domain'] |
||
+ | ) |
||
+ | end, |
||
+ | }, |
||
+ | { |
||
+ | tags = {tags_cfg.eyrie}, |
||
+ | header = i18n.drop_down_table.eyrie_prefix, |
||
+ | where = function(tpl_args, value) |
||
+ | return string.format( |
||
+ | [[ |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.eyrie, |
||
+ | 1, |
||
+ | item_info['items.domain'] |
||
+ | ) |
||
+ | end, |
||
+ | }, |
||
+ | { |
||
+ | tags = {tags_cfg.eyrie}, |
||
+ | header = i18n.drop_down_table.eyrie_suffix, |
||
+ | where = function(tpl_args, value) |
||
+ | return string.format( |
||
+ | [[ |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.eyrie, |
||
+ | 2, |
||
+ | item_info['items.domain'] |
||
+ | ) |
||
+ | end, |
||
+ | }, |
||
+ | { |
||
+ | tags = {tags_cfg.basilisk}, |
||
+ | header = i18n.drop_down_table.basilisk_prefix, |
||
+ | where = function(tpl_args, value) |
||
+ | return string.format( |
||
+ | [[ |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.basilisk, |
||
+ | 1, |
||
+ | item_info['items.domain'] |
||
+ | ) |
||
+ | end, |
||
+ | }, |
||
+ | { |
||
+ | tags = {tags_cfg.basilisk}, |
||
+ | header = i18n.drop_down_table.basilisk_suffix, |
||
+ | where = function(tpl_args, value) |
||
+ | return string.format( |
||
+ | [[ |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.basilisk, |
||
+ | 2, |
||
+ | item_info['items.domain'] |
||
+ | ) |
||
+ | end, |
||
+ | }, |
||
+ | { |
||
+ | tags = {tags_cfg.adjudicator}, |
||
+ | header = i18n.drop_down_table.adjudicator_prefix, |
||
+ | where = function(tpl_args, value) |
||
+ | return string.format( |
||
+ | [[ |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.adjudicator, |
||
+ | 1, |
||
+ | item_info['items.domain'] |
||
+ | ) |
||
+ | end, |
||
+ | }, |
||
+ | { |
||
+ | tags = {tags_cfg.adjudicator}, |
||
+ | header = i18n.drop_down_table.adjudicator_suffix, |
||
+ | where = function(tpl_args, value) |
||
+ | return string.format( |
||
+ | [[ |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | tags_cfg.adjudicator, |
||
+ | 2, |
||
+ | item_info['items.domain'] |
||
+ | ) |
||
+ | end, |
||
+ | }, |
||
+ | { |
||
+ | header = i18n.drop_down_table.veiled_prefix, |
||
+ | where = function(tpl_args, value) |
||
local where = {} |
local where = {} |
||
− | for _, item_tag in ipairs(tpl_args.item_tags) do |
+ | for _, item_tag in ipairs(tpl_args.item_tags) do |
where[#where+1] = string.format( |
where[#where+1] = string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '' |
||
+ | AND mods.id LIKE "%%Master%%") |
||
+ | ]], |
||
item_tag, |
item_tag, |
||
− | + | 1, |
|
− | + | 9 |
|
) |
) |
||
end |
end |
||
+ | |||
− | |||
− | return table.concat(where, ' OR ') |
+ | return table.concat(where, ' OR ') |
end, |
end, |
||
− | chance_multiplier = 1/4, -- See Vaal orb, for the 4 possible events. |
||
}, |
}, |
||
{ |
{ |
||
− | header = i18n.drop_down_table. |
+ | header = i18n.drop_down_table.veiled_suffix, |
− | where = function(tpl_args |
+ | where = function(tpl_args, value) |
local where = {} |
local where = {} |
||
− | for _, item_tag in ipairs(tpl_args.item_tags) do |
+ | for _, item_tag in ipairs(tpl_args.item_tags) do |
where[#where+1] = string.format( |
where[#where+1] = string.format( |
||
+ | [[ |
||
− | '(spawn_weights.tag="%s" AND mods.generation_type=%s AND mods.domain=%s AND mods.stat_text IS NOT NULL)', |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '' |
||
+ | AND mods.id LIKE "%%Master%%") |
||
+ | ]], |
||
item_tag, |
item_tag, |
||
− | + | 2, |
|
+ | 9 |
||
+ | ) |
||
+ | end |
||
+ | |||
+ | return table.concat(where, ' OR ') |
||
+ | end, |
||
+ | }, |
||
+ | { |
||
+ | header = i18n.drop_down_table.corrupted, |
||
+ | where = function(tpl_args, value) |
||
+ | local where = {} |
||
+ | for _, item_tag in ipairs(tpl_args.item_tags) do |
||
+ | where[#where+1] = string.format( |
||
+ | [[ |
||
+ | (spawn_weights.tag="%s" |
||
+ | AND mods.generation_type=%s |
||
+ | AND mods.domain=%s |
||
+ | AND mods.stat_text > '') |
||
+ | ]], |
||
+ | item_tag, |
||
+ | 5, |
||
item_info['items.domain'] |
item_info['items.domain'] |
||
) |
) |
||
end |
end |
||
+ | |||
− | |||
− | return table.concat(where, ' OR ') |
+ | return table.concat(where, ' OR ') |
end, |
end, |
||
+ | chance_multiplier = 1/4, -- See Vaal orb, for the 4 possible events. |
||
+ | is_implicit = true, |
||
}, |
}, |
||
+ | -- Reduce template expansion size by disabling enchantments, there are |
||
+ | -- other good pages with enchantment lists: |
||
+ | -- { |
||
+ | -- header = i18n.drop_down_table.enchant, |
||
+ | -- where = function(tpl_args, value) |
||
+ | -- local where = {} |
||
+ | -- for _, item_tag in ipairs(tpl_args.item_tags) do |
||
+ | -- where[#where+1] = string.format( |
||
+ | -- [[ |
||
+ | -- (spawn_weights.tag="%s" |
||
+ | -- AND mods.generation_type=%s |
||
+ | -- AND mods.domain=%s |
||
+ | -- AND mods.stat_text > '') |
||
+ | -- ]], |
||
+ | -- item_tag, |
||
+ | -- 10, |
||
+ | -- item_info['items.domain'] |
||
+ | -- ) |
||
+ | -- end |
||
+ | |||
+ | -- return table.concat(where, ' OR ') |
||
+ | -- end, |
||
+ | -- is_implicit = true, |
||
+ | -- }, |
||
} |
} |
||
+ | |||
− | |||
− | |||
− | -- Introductory text: |
||
− | local out = {} |
||
− | out[#out+1] = string.format( |
||
− | '==%s== \n', |
||
− | tpl_args['header'] or table.concat(tpl_args.item_tags, ', ') |
||
− | ) |
||
− | out[#out+1] = string.format( |
||
− | '<div style="float: right; text-align:center"><div class="mw-collapsible-collapse-all" style="cursor:pointer;">[%s]</div><hr><div class="mw-collapsible-expand-all" style="cursor:pointer;">[%s]</div></div>', |
||
− | i18n.drop_down_table.collapse_all, |
||
− | i18n.drop_down_table.expand_all |
||
− | ) |
||
− | out[#out+1] = string.format('%s %s.<br><br><br>', |
||
− | i18n.drop_down_table.table_intro, |
||
− | f_item_link{ |
||
− | page=item_info['items._pageName'], |
||
− | name=item_info['items.name'], |
||
− | inventory_icon=item_info['items.inventory_icon'] or '', |
||
− | html=item_info['items.html'] or '', |
||
− | skip_query=true |
||
− | } |
||
− | ) |
||
− | |||
-- Save the original tag format: |
-- Save the original tag format: |
||
local item_tags_orig = {} |
local item_tags_orig = {} |
||
Строка 1274: | Строка 1184: | ||
item_tags_orig[i] = v |
item_tags_orig[i] = v |
||
end |
end |
||
+ | |||
− | |||
local item_mods = {} |
local item_mods = {} |
||
local mod_group_counter = {} |
local mod_group_counter = {} |
||
mod_group_counter['all'] = {} |
mod_group_counter['all'] = {} |
||
− | local |
+ | local extra_fieldss = {} |
+ | local table_index_base = -1 |
||
for _, sctn in ipairs(section) do |
for _, sctn in ipairs(section) do |
||
+ | item_mods[sctn['header']] = {} |
||
+ | |||
+ | -- Preallocate the mod group counter, implicit and explicit mods |
||
+ | -- are counted separetely because they can spawn together: |
||
+ | mod_group_counter[sctn['header']] = {} |
||
+ | local adj = 'explicit' |
||
+ | if sctn['is_implicit'] then |
||
+ | adj = 'implicit' |
||
+ | end |
||
+ | for _, header in ipairs({sctn['header'], 'all'}) do |
||
+ | if mod_group_counter[header][adj] == nil then |
||
+ | mod_group_counter[header][adj] = {} |
||
+ | end |
||
+ | end |
||
+ | |||
local continue = true |
local continue = true |
||
local current_tags |
local current_tags |
||
if sctn['tags'] then |
if sctn['tags'] then |
||
− | -- some item classes do not have shaper/elder items, so the table |
+ | -- some item classes do not have shaper/elder items, so the table |
+ | -- will not contain any tags: |
||
if #sctn['tags'] == 0 then |
if #sctn['tags'] == 0 then |
||
continue = false |
continue = false |
||
Строка 1296: | Строка 1223: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
if continue then |
if continue then |
||
− | -- Create html container: |
||
− | local container = mw.html.create('div') |
||
− | :attr('style', 'vertical-align:top; display:inline-block;') |
||
− | |||
-- Cargo preparation: |
-- Cargo preparation: |
||
− | + | local q_fields = { |
|
+ | 'mods._pageName', |
||
− | tpl_args.q_fields = 'mods.name, mods.id, mods.required_level, mods.generation_type, mods.domain, mods.mod_group, mods.mod_type, mods.stat_text, mods.tags, mods._pageName, mod_stats.id, spawn_weights.tag, spawn_weights.weight, spawn_weights.ordinal, spawn_weights._pageName' |
||
+ | 'mods.name', |
||
− | tpl_args.q_join = 'mods._pageName=spawn_weights._pageName, mods._pageName=mod_stats._pageName' |
||
− | + | 'mods.id', |
|
− | + | 'mods.required_level', |
|
− | + | 'mods.generation_type', |
|
− | + | 'mods.domain', |
|
− | + | 'mods.mod_group', |
|
− | + | 'mods.mod_type', |
|
− | + | 'mods.stat_text', |
|
− | + | 'mods.stat_text_raw', |
|
− | + | 'mods.tags', |
|
− | + | 'mod_stats.id', |
|
− | + | 'spawn_weights.tag', |
|
− | + | 'spawn_weights.weight', |
|
+ | 'spawn_weights.ordinal', |
||
+ | 'spawn_weights._pageName' |
||
+ | } |
||
+ | for i, v in ipairs(extra_fields) do |
||
+ | q_fields[#q_fields+1] = v |
||
end |
end |
||
+ | |||
− | |||
− | -- Query mods: |
+ | -- Query mods and map the results to the pagename: |
− | results = |
+ | local results = m_cargo.map_results_to_id{ |
− | + | results=m_cargo.query( |
|
− | + | {'mods', 'spawn_weights', 'mod_stats'}, |
|
− | + | q_fields, |
|
− | + | { |
|
− | + | join = [[ |
|
+ | mods._pageName=spawn_weights._pageName, |
||
− | for _,v in ipairs(results) do |
||
+ | mods._pageName=mod_stats._pageName |
||
− | if spawn_weights[v['mods._pageName']] == nil then |
||
− | + | ]], |
|
− | + | where = sctn['where'](tpl_args, value), |
|
− | + | groupBy = [[ |
|
− | + | mods._pageName, |
|
− | + | spawn_weights.tag, |
|
− | + | spawn_weights.weight |
|
− | + | ]], |
|
− | + | orderBy = [[ |
|
− | + | mods.generation_type, |
|
− | + | mods.mod_group, |
|
− | + | mods.mod_type, |
|
− | + | mods.required_level, |
|
− | + | mods._pageName, |
|
− | + | spawn_weights.ordinal |
|
− | + | ]], |
|
− | + | } |
|
+ | ), |
||
+ | field='mods._pageName', |
||
+ | keep_id_field=true, |
||
+ | append_id_field=true, |
||
+ | } |
||
+ | |||
+ | if #results > 0 then |
||
-- Loop through all found modifiers: |
-- Loop through all found modifiers: |
||
local last |
local last |
||
− | for _, |
+ | for _, id in ipairs(results) do |
− | + | -- Loop through all the modifier tags until they match |
|
− | |||
− | if sctn['header'] == i18n.drop_down_table.elder_prefix then |
||
− | -- error(mw.dumpObject(spawn_weights)) |
||
− | end |
||
− | -- Loop through all the modifier tags until they match |
||
-- the item tags: |
-- the item tags: |
||
local j = 0 |
local j = 0 |
||
local tag_match_stop |
local tag_match_stop |
||
− | repeat |
+ | repeat |
j = j+1 |
j = j+1 |
||
− | local mod_tag = |
+ | local mod_tag = results[id][j]['spawn_weights.tag'] |
local mod_tag_weight = tonumber( |
local mod_tag_weight = tonumber( |
||
− | + | results[id][j]['spawn_weights.weight'] |
|
) |
) |
||
− | -- Loop through the item tags until it matches the |
+ | -- Loop through the item tags until it matches the |
− | -- spawn weight tag and the mod tag has a value larger than |
+ | -- spawn weight tag and the mod tag has a value larger than |
-- zero: |
-- zero: |
||
local y = 0 |
local y = 0 |
||
local tag_match_add = false |
local tag_match_add = false |
||
− | repeat |
+ | repeat |
y = y+1 |
y = y+1 |
||
− | tag_match_stop = ((mod_tag == current_tags[y]) and ((mod_tag_weight or -1) >= 0)) or ( |
+ | tag_match_stop = ((mod_tag == current_tags[y]) and ((mod_tag_weight or -1) >= 0)) or (results[id][j] == nil) |
tag_match_add = (mod_tag == current_tags[y]) and ((mod_tag_weight or -1) > 0) |
tag_match_add = (mod_tag == current_tags[y]) and ((mod_tag_weight or -1) > 0) |
||
until tag_match_stop or y == #current_tags |
until tag_match_stop or y == #current_tags |
||
+ | |||
− | |||
− | -- If there's a match then save that mod and other |
+ | -- If there's a match then save that mod and other |
-- interesting information: |
-- interesting information: |
||
− | if tag_match_add then |
+ | if tag_match_add then |
+ | |||
− | |||
− | -- Assume that the mod is global then go through |
+ | -- Assume that the mod is global then go through |
− | -- all the stat ids and check if any of the |
+ | -- all the stat ids and check if any of the |
-- stats are local: |
-- stats are local: |
||
− | local mod_scope = 'Глобальный' |
+ | local mod_scope = 'Глобальный' |
− | for _, vv in ipairs( |
+ | for _, vv in ipairs(results[id]) do |
− | if vv['mod_stats.id']:find('.*local.*') ~= nil then |
+ | if vv['mod_stats.id']:find('.*local.*') ~= nil then |
mod_scope = 'Локальный' |
mod_scope = 'Локальный' |
||
end |
end |
||
− | end |
+ | end |
+ | |||
− | |||
-- Save the matching modifier tag: |
-- Save the matching modifier tag: |
||
local a = #item_mods[sctn['header']] |
local a = #item_mods[sctn['header']] |
||
− | item_mods[sctn['header']][a+1] = |
+ | item_mods[sctn['header']][a+1] = results[id][j] |
+ | |||
− | |||
-- Save other interesting fields: |
-- Save other interesting fields: |
||
− | item_mods[sctn['header']][a+1]['mods.scope'] = mod_scope |
+ | item_mods[sctn['header']][a+1]['mods.scope'] = mod_scope |
− | item_mods[sctn['header']][a+1]['spawn_weight.idx_match'] = j |
+ | item_mods[sctn['header']][a+1]['spawn_weight.idx_match'] = j |
− | item_mods[sctn['header']][a+1]['mods.add'] = tag_match_add |
+ | item_mods[sctn['header']][a+1]['mods.add'] = tag_match_add |
item_mods[sctn['header']][a+1]['mods.stop'] = tag_match_stop |
item_mods[sctn['header']][a+1]['mods.stop'] = tag_match_stop |
||
+ | |||
− | -- Mod group counter: |
||
+ | -- Count the mod groups: |
||
local group = item_mods[sctn['header']][a+1]['mods.mod_group'] or 'nil_group' |
local group = item_mods[sctn['header']][a+1]['mods.mod_group'] or 'nil_group' |
||
− | + | for _, header in ipairs({sctn['header'], 'all'}) do |
|
− | + | if mod_group_counter[header][adj][group] == nil then |
|
+ | mod_group_counter[header][adj][group] = {} |
||
+ | end |
||
+ | local tp = results[id][j]['mods.mod_type'] |
||
+ | local bef = mod_group_counter[header][adj][group][tp] or 0 |
||
+ | mod_group_counter[header][adj][group][tp] = 1 + bef |
||
+ | end |
||
end |
end |
||
− | until tag_match_stop |
+ | until tag_match_stop |
end |
end |
||
+ | |||
− | |||
− | -- If the user wants to see the spawn chance then do the |
+ | -- If the user wants to see the spawn chance then do the |
-- calculations and save that result as well: |
-- calculations and save that result as well: |
||
− | if tpl_args.spawn_chance ~= nil then |
+ | if tpl_args.spawn_chance ~= nil then |
extra_fields[#extra_fields+1] = 'spawn_weights.chance' |
extra_fields[#extra_fields+1] = 'spawn_weights.chance' |
||
item_mods[sctn['header']] = h.get_spawn_chance{ |
item_mods[sctn['header']] = h.get_spawn_chance{ |
||
− | tbl = item_mods[sctn['header']], |
+ | tbl = item_mods[sctn['header']], |
chance_multiplier = sctn['chance_multiplier'] |
chance_multiplier = sctn['chance_multiplier'] |
||
} |
} |
||
end |
end |
||
+ | |||
− | |||
+ | extra_fieldss[sctn['header']] = extra_fields |
||
− | -- Create the drop down table with <table></table>: |
||
− | + | end |
|
+ | end |
||
− | if #item_mods[sctn['header']] > 0 then |
||
+ | end |
||
− | headers |
||
+ | |||
− | :tag('h3') |
||
+ | |||
− | :wikitext(string.format( |
||
+ | -- |
||
− | '%s', |
||
+ | -- Display the item mods |
||
− | sctn['header'] |
||
+ | -- |
||
− | ) |
||
+ | |||
+ | -- Introductory text: |
||
+ | local out = {} |
||
+ | out[#out+1] = string.format( |
||
+ | '==%s== \n', |
||
+ | tpl_args['header'] or table.concat(tpl_args.item_tags, ', ') |
||
+ | ) |
||
+ | local expand_button = string.format( |
||
+ | '<div style="float: right; text-align:center"><div class="mw-collapsible-collapse-all" style="cursor:pointer;">[%s]</div><hr><div class="mw-collapsible-expand-all" style="cursor:pointer;">[%s]</div></div>', |
||
+ | i18n.drop_down_table.collapse_all, |
||
+ | i18n.drop_down_table.expand_all |
||
+ | ) |
||
+ | out[#out+1] = expand_button |
||
+ | out[#out+1] = string.format('%s %s.<br><br><br>', |
||
+ | i18n.drop_down_table.table_intro, |
||
+ | h.item_link{ |
||
+ | page=item_info['items._pageName'], |
||
+ | name=item_info['items.name'], |
||
+ | inventory_icon=item_info['items.inventory_icon'] or '', |
||
+ | html=item_info['items.html'] or '', |
||
+ | skip_query=true |
||
+ | } |
||
+ | ) |
||
+ | |||
+ | -- Loop through the sections: |
||
+ | for _, sctn in ipairs(section) do |
||
+ | local extra_fields = extra_fieldss[sctn['header']] |
||
+ | local adj = 'explicit' |
||
+ | if sctn['is_implicit'] then |
||
+ | adj = 'implicit' |
||
+ | end |
||
+ | |||
+ | -- Create html container: |
||
+ | local container = mw.html.create('div') |
||
+ | :attr('style', 'vertical-align:top; display:inline-block;') |
||
+ | |||
+ | -- Create the drop down table with <table></table>: |
||
+ | local headers = container |
||
+ | if #item_mods[sctn['header']] > 0 then |
||
+ | headers |
||
+ | :tag('h3') |
||
+ | :wikitext(string.format('%s', sctn['header'])) |
||
+ | :done() |
||
+ | :done() |
||
+ | end |
||
+ | |||
+ | local total_mod_groups = 0 |
||
+ | for _ in pairs(mod_group_counter[sctn['header']][adj]) do |
||
+ | total_mod_groups = 1+total_mod_groups |
||
+ | end |
||
+ | |||
+ | -- Loop through and add all matching mods to the <table>. |
||
+ | local tbl, last_group, last_type, table_index |
||
+ | for _, rows in ipairs(item_mods[sctn['header']]) do |
||
+ | |||
+ | -- If the last mod group is different to the current |
||
+ | -- mod group then assume the mod isn't related and start |
||
+ | -- a new drop down list, if there's only one mod group |
||
+ | -- then use mod type instead: |
||
+ | if rows['mods.mod_group'] ~= last_group or (total_mod_groups == 1 and rows['mods.mod_type'] ~= last_type) then |
||
+ | -- Check through all the mods and see if there are |
||
+ | -- multiple mod types within the same mod group: |
||
+ | local count = {} |
||
+ | for _, n in ipairs(item_mods[sctn['header']]) do |
||
+ | |||
+ | -- If the mod has the same mod group, then add |
||
+ | -- the mod type to the counter. Only unique mod |
||
+ | -- types matter so the number is just a dummy |
||
+ | -- value: |
||
+ | if n['mods.mod_group'] == rows['mods.mod_group'] then |
||
+ | count[n['mods.mod_type']] = 1 |
||
+ | end |
||
+ | end |
||
+ | |||
+ | -- Calculate how many unique mod types with the |
||
+ | -- same mod group there are for all explicit or implicit |
||
+ | -- sections since a mod with the same mod group can't |
||
+ | -- spawn. Doesn't matter if it's prefix or suffix. |
||
+ | local number_of_mod_types = 0 |
||
+ | for _ in pairs(mod_group_counter['all'][adj][rows['mods.mod_group']]) do |
||
+ | number_of_mod_types = 1 + number_of_mod_types |
||
+ | end |
||
+ | |||
+ | -- If there are multiple unique mod types with the |
||
+ | -- same mod group then change the style of the drop |
||
+ | -- down list to indicate it, if there's only one |
||
+ | -- mod group in the generation type then ignore it: |
||
+ | local table_index_mod_group |
||
+ | local tbl_caption |
||
+ | if number_of_mod_types > 1 and total_mod_groups > 1 then |
||
+ | table_index_mod_group = table.concat( |
||
+ | {string.byte(rows['mods.mod_group'], 1, #rows['mods.mod_group'])}, |
||
+ | '' |
||
+ | ) |
||
+ | |||
+ | tbl_caption = string.format( |
||
+ | '%s', |
||
+ | m_util.html.poe_color( |
||
+ | 'stat', |
||
+ | string.format( |
||
+ | '%s %s', |
||
+ | i18n.drop_down_table.mod_group, |
||
+ | rows['mods.mod_group'] |
||
) |
) |
||
− | + | ) or '' |
|
− | + | ) |
|
+ | |||
+ | else |
||
+ | tbl_caption = string.format( |
||
+ | '%s (%s)', |
||
+ | m_util.html.poe_color( |
||
+ | 'mod', |
||
+ | h.header(rows['mods.stat_text_raw']) |
||
+ | ) or '', |
||
+ | rows['mods.scope'] |
||
+ | ) |
||
end |
end |
||
+ | |||
− | |||
− | + | -- Create a table index for handling the collapsible: |
|
− | + | table_index_base = table_index_base+1 |
|
− | + | if table_index_mod_group ~= nil then |
|
+ | table_index = table_index_mod_group |
||
+ | else |
||
+ | table_index = table_index_base |
||
end |
end |
||
+ | |||
− | |||
− | -- |
+ | -- Add class and style to the <table>: |
− | + | tbl = container:tag('table') |
|
− | + | tbl |
|
− | + | :attr('class', 'mw-collapsible mw-collapsed') |
|
− | + | :attr('style', |
|
− | + | 'text-align:left; line-height:1.60em; width:810px;' |
|
− | + | ) |
|
− | + | :tag('th') |
|
+ | :attr('class', |
||
− | if rows['mods.mod_group'] ~= last_group or (total_mod_groups == 1 and rows['mods.mod_type'] ~= last_type) then |
||
− | + | string.format('mw-customtoggle-%s', table_index) |
|
− | + | ) |
|
− | + | :attr('style', |
|
− | + | 'text-align:left; line-height:1.40em; border-bottom:1pt solid dimgrey;' |
|
− | + | ) |
|
− | + | :attr('colspan', '3' .. #extra_fields) |
|
− | + | :wikitext(tbl_caption) |
|
− | + | :done() |
|
− | + | :done() |
|
+ | end |
||
− | if n['mods.mod_group'] == rows['mods.mod_group'] then |
||
+ | |||
− | count[n['mods.mod_type']] = 1 |
||
− | + | -- If the mod has no name then use the mod type: |
|
− | + | local mod_name = rows['mods.name'] or '' |
|
− | + | if mod_name == '' then |
|
− | + | mod_name = rows['mods.mod_type'] |
|
− | + | end |
|
+ | |||
− | local number_of_mod_types = 0 |
||
− | + | -- Check if there are any extra properties to show in |
|
− | + | -- the drop down list and then add a cell for that, |
|
− | + | -- add this node at the end of the table row: |
|
− | + | local td = mw.html.create('td') |
|
+ | if extra_fields ~= nil then |
||
− | -- If there are multiple unique mod types with the |
||
+ | for _, extra_field in ipairs(extra_fields) do |
||
− | -- same mod group then change the style of the drop |
||
− | + | td |
|
− | + | :attr('width', '*') |
|
− | + | :wikitext(string.format( |
|
− | + | '%s: %s ', |
|
− | + | extra_field, |
|
− | + | rows[extra_field] or '' |
|
− | 'mod', |
||
− | string.format( |
||
− | '%s %s', |
||
− | i18n.drop_down_table.mod_group, |
||
− | rows['mods.mod_group'] |
||
− | ) |
||
− | ) or '' |
||
) |
) |
||
+ | ) |
||
+ | :done() |
||
+ | end |
||
+ | end |
||
− | + | -- Style mods.tags: |
|
− | + | local mods_tags = table.concat( |
|
− | + | m_util.string.split_args(rows['mods.tags'], {sep=',%s*'}), |
|
− | + | ', ' |
|
− | + | ) |
|
− | + | if mods_tags ~= '' then |
|
− | + | mods_tags = m_util.html.tooltip('*', mods_tags) |
|
− | + | end |
|
+ | |||
+ | -- Add a table row with the interesting properties that |
||
+ | -- modifier has: |
||
+ | tbl |
||
+ | :tag('tr') |
||
+ | :attr('class', 'mw-collapsible mw-collapsed') |
||
+ | :attr( |
||
+ | 'id', |
||
+ | string.format('mw-customcollapsible-%s', table_index) |
||
+ | ) |
||
+ | :tag('td') |
||
+ | :attr('width', '160') |
||
+ | :wikitext( |
||
+ | string.format( |
||
+ | ' [[%s|%s]]', |
||
+ | rows['mods._pageName'], |
||
+ | mod_name:gsub('%s', ' ') |
||
) |
) |
||
− | + | ) |
|
− | + | :done() |
|
− | + | :tag('td') |
|
− | + | :attr('width', '1') |
|
− | + | :wikitext( |
|
− | + | string.format( |
|
− | + | '%s %s', |
|
− | + | m_game.level_requirement['short_upper'] |
|
− | + | :gsub('%s', ' '), |
|
+ | rows['mods.required_level'] |
||
) |
) |
||
− | + | ) |
|
− | + | :done() |
|
− | + | :tag('td') |
|
− | + | :attr('width', '*') |
|
− | + | :wikitext( |
|
− | + | string.format( |
|
− | + | '%s%s', |
|
− | + | m_util.html.poe_color( |
|
− | ' |
+ | 'mod', |
− | + | rows['mods.stat_text'] |
|
− | : |
+ | :gsub('<br>', ', ') |
− | : |
+ | :gsub('<br />', ' ') |
− | + | ) or '', |
|
− | + | mods_tags |
|
− | end |
||
− | |||
− | -- If the mod has no name then use the mod type: |
||
− | local mod_name = rows['mods.name'] |
||
− | if mod_name == '' or mod_name == nil then |
||
− | mod_name = rows['mods.mod_type'] |
||
− | end |
||
− | |||
− | -- Check if there are any extra properties to show in |
||
− | -- the drop down list and then add a cell for that, |
||
− | -- add this node at the end of the table row: |
||
− | local td = mw.html.create('td') |
||
− | if extra_fields ~= nil then |
||
− | for _, extra_field in ipairs(extra_fields) do |
||
− | td |
||
− | :attr('width', '*') |
||
− | :wikitext(string.format( |
||
− | '%s: %s ', |
||
− | extra_field, |
||
− | rows[extra_field] |
||
− | ) |
||
− | ) |
||
− | :done() |
||
− | end |
||
− | end |
||
− | |||
− | -- Style mods.tags: |
||
− | local mods_tags = table.concat(m_util.string.split(rows['mods.tags'], ','), ', ') |
||
− | if mods_tags ~= '' then |
||
− | mods_tags = m_util.html.tooltip('*', mods_tags, class) |
||
− | end |
||
− | |||
− | -- Add a table row with the interesting properties that |
||
− | -- modifier has: |
||
− | tbl |
||
− | :tag('tr') |
||
− | :attr('class', 'mw-collapsible mw-collapsed') |
||
− | :attr( |
||
− | 'id', |
||
− | string.format( |
||
− | 'mw-customcollapsible-%s', |
||
− | tableIndex |
||
− | ) |
||
) |
) |
||
− | + | ) |
|
− | :attr('width', '160') |
||
− | :wikitext( |
||
− | string.format( |
||
− | ' [[%s|%s]]', |
||
− | rows['mods._pageName'], |
||
− | mod_name:gsub('%s', ' ') |
||
− | ) |
||
− | ) |
||
− | :done() |
||
− | :tag('td') |
||
− | :attr('width', '1') |
||
− | :wikitext( |
||
− | string.format( |
||
− | '%s %s', |
||
− | m_game.level_requirement['short_upper'] |
||
− | :gsub('%s', ' '), |
||
− | rows['mods.required_level'] |
||
− | ) |
||
− | ) |
||
− | :done() |
||
− | :tag('td') |
||
− | :attr('width', '*') |
||
− | :wikitext( |
||
− | string.format( |
||
− | '%s%s', |
||
− | m_util.html.poe_color( |
||
− | 'mod', |
||
− | rows['mods.stat_text'] |
||
− | :gsub('<br>', ', ') |
||
− | :gsub('<br />', ' ') |
||
− | ) or '', |
||
− | mods_tags |
||
− | ) |
||
− | ) |
||
− | :done() |
||
− | :node(td) |
||
− | :done() |
||
:done() |
:done() |
||
− | + | :node(td) |
|
− | + | :done() |
|
− | + | :done() |
|
+ | |||
− | last_type = rows['mods.mod_type'] |
||
− | + | -- Save the last mod group for later comparison: |
|
− | + | last_group = rows['mods.mod_group'] |
|
− | + | last_type = rows['mods.mod_type'] |
|
− | out[#out+1] = tostring(container) |
||
end |
end |
||
+ | out[#out+1] = tostring(container) |
||
end |
end |
||
+ | |||
− | |||
+ | -- Outro text: |
||
+ | out[#out+1] = '<br>' |
||
+ | out[#out+1] = m_util.html.poe_color( |
||
+ | 'normal', |
||
+ | string.format('[[#Top|%s]]', i18n.drop_down_table.back_to_top) |
||
+ | ) |
||
+ | |||
return table.concat(out,'') |
return table.concat(out,'') |
||
end |
end |
||
-- ---------------------------------------------------------------------------- |
-- ---------------------------------------------------------------------------- |
||
− | -- |
+ | -- Exported functions |
-- ---------------------------------------------------------------------------- |
-- ---------------------------------------------------------------------------- |
||
+ | local p = {} |
||
+ | |||
+ | -- |
||
+ | -- Template:Modifier table |
||
+ | -- |
||
+ | p.mod_table = m_util.misc.invoker_factory(_mod_table, { |
||
+ | parentFirst = true, |
||
+ | }) |
||
+ | |||
+ | -- |
||
+ | -- Template:Item modifiers |
||
+ | -- |
||
+ | p.drop_down_table = m_util.misc.invoker_factory(_drop_down_table, { |
||
+ | parentFirst = true, |
||
+ | }) |
||
+ | |||
+ | -- |
||
+ | -- Debug |
||
+ | -- |
||
p.debug = {} |
p.debug = {} |
||
function p.debug.tbl_data(tbl) |
function p.debug.tbl_data(tbl) |
||
keys = {} |
keys = {} |
||
for _, data in ipairs(mod_table.data) do |
for _, data in ipairs(mod_table.data) do |
||
− | if type(data.arg) == 'string' then |
+ | if type(data.arg) == 'string' then |
keys[data.arg] = 1 |
keys[data.arg] = 1 |
||
elseif type(data.arg) == 'table' then |
elseif type(data.arg) == 'table' then |
||
Строка 1628: | Строка 1642: | ||
end |
end |
||
end |
end |
||
+ | |||
− | |||
for _, key in ipairs(mod_table.weights) do |
for _, key in ipairs(mod_table.weights) do |
||
keys[key] = 1 |
keys[key] = 1 |
||
end |
end |
||
+ | |||
− | |||
local out = {} |
local out = {} |
||
for key, _ in pairs(keys) do |
for key, _ in pairs(keys) do |
||
out[#out+1] = string.format("['%s'] = '1'", key) |
out[#out+1] = string.format("['%s'] = '1'", key) |
||
end |
end |
||
+ | |||
− | |||
return table.concat(out, ', ') |
return table.concat(out, ', ') |
||
end |
end |
||
− | |||
− | -- ---------------------------------------------------------------------------- |
||
− | -- |
||
− | -- ---------------------------------------------------------------------------- |
||
return p |
return p |
Версия от 16:09, 24 января 2022
Этот модуль используется на очень большом количестве страниц. Чтобы избежать крупномасштабных сбоев и ненужной нагрузки на сервер, любые изменения в этом модуле должны быть сначала протестированы на его подстраницах /песочница или /testcases. Протестированные изменения могут быть добавлены на эту страницу за одну правку. Пожалуйста, обсудите любые изменения на странице обсуждения перед их внедрением. |
Этот модуль зависит от следующих других модулей: |
Реализует {{Modifier table}} и {{Item modifiers}}.
Вышеприведенная документация извлекается из Модуль:Modifier table/doc.
Редакторы могут экспериментировать в sandbox этого модуля и в testcases страницах.
Подстраницы этого модуля.
Редакторы могут экспериментировать в sandbox этого модуля и в testcases страницах.
Подстраницы этого модуля.
-------------------------------------------------------------------------------
--
-- Module:Modifier table
--
-- Module responsible for displaying modifiers in various ways. Implements
-- Template:Modifier table and Template:Item modifiers
-------------------------------------------------------------------------------
require('Module:No globals')
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
-- Should we use the sandbox version of our submodules?
local use_sandbox = m_util.misc.maybe_sandbox('Modifier table')
local m_game = mw.loadData('Module:Game')
-- Lazy loading
local f_item_link -- require('Module:Item link').item_link
-- The cfg table contains all localisable strings and configuration, to make it
-- easier to port this module to another wiki.
local cfg = use_sandbox and mw.loadData('Module:Modifier table/config/sandbox') or mw.loadData('Module:Modifier table/config')
local i18n = cfg.i18n
-- ----------------------------------------------------------------------------
-- Helper functions
-- ----------------------------------------------------------------------------
local h = {}
-- Lazy loading for Module:Item link
function h.item_link(args)
if not f_item_link then
f_item_link = require('Module:Item link').item_link
end
return f_item_link(args)
end
function h.header(str)
--[[
This function replaces specific numbers with a generic #.
]]
local s = table.concat(m_util.string.split(str, '%(%d+%.*%d*%-%d+%.*%d*%)'), '#')
s = table.concat(m_util.string.split(s, '%d+%.*%d*'), '#')
s = table.concat(m_util.string.split(s, '<br>'), ', ')
s = table.concat(m_util.string.split(s, '<br />'), ' ')
return s
end
function h.query_weights(table_name, page_ids)
return m_cargo.map_results_to_id{
results=m_cargo.query(
{'mods', table_name},
{
'mods._pageID',
table_name .. '.tag',
table_name .. '.weight'
},
{
where=page_ids,
join=string.format('mods._pageID=%s._pageID', table_name),
orderBy=string.format('mods.id ASC,%s.ordinal ASC', table_name),
}
),
field='mods._pageID',
}
end
function h.disambiguate_mod_name(results)
--[[
Disambiguates results from a mods query.
]]
local str = {}
for i,v in pairs(results) do
str[#str+1] = string.format(
'%s - %s ([[%s|page]])',
v['mods.id'] or v['mods._pageName'] or '',
string.gsub(
v['mods.stat_text_raw'] or 'N/A',
'<br>',
', '
) or '',
v['mods._pageName'] or ''
)
end
return table.concat(str, '<br>')
end
h.tbl = {}
h.tbl.display = {}
h.tbl.display.factory = {}
function h.tbl.display.factory.value(args)
-- Format options for each field:
args.options = args.options or {}
-- Separator between fields:
args.delimiter = args.delimiter or ', '
return function(tpl_args, tr, data, fields)
local values = {}
local fmt_values = {}
for index, field in ipairs(fields) do
local value = {
min=data[field],
max=data[field],
base=data[field],
}
if value.min then
values[#values+1] = value.max
local opts = args.options[index] or {}
-- Global colour is set, no overrides.
if args.color ~= nil or opts.color == nil then
opts.no_color = true
end
fmt_values[#fmt_values+1] = m_util.html.format_value(nil, value, opts)
end
end
if #values == 0 then
tr
:wikitext(m_util.html.td.na())
else
local td = tr:tag('td')
td
:attr('data-sort-value', table.concat(values, args.delimiter))
:wikitext(table.concat(fmt_values, args.delimiter))
if args.color then
td:attr('class', 'tc -' .. args.color)
end
end
end
end
function h.get_spawn_chance(args)
--[[
Calculates the spawn chance of a set of mods that all have a
spawn weight.
]]
-- Get the table:
local tbl = args['tbl']
-- Probabilities affecting the result besides the spawn weight:
local chance_multiplier = tonumber(args['chance_multiplier']) or 1
-- Total number of outcomes.
local N = 0
for i,_ in ipairs(tbl) do
N = N + tbl[i]['spawn_weights.weight']
end
for i,_ in ipairs(tbl) do
-- Number of ways it can happen:
local n = tbl[i]['spawn_weights.weight']
-- Truncated value:
tbl[i]['spawn_weights.chance'] = string.format(
"%0.2f%%",
n/N * chance_multiplier*100
)
end
return tbl
end
-- ----------------------------------------------------------------------------
-- Additional configuration
-- ----------------------------------------------------------------------------
local mod_table = {}
mod_table.data = {
{
arg = 'name',
header = i18n.mod_table.name,
fields = {'mods._pageName', 'mods.id', 'mods.name'},
options = {
[3] = {
optional=true,
},
},
display = function(tpl_args, tr, data, fields)
local name
if data['mods.name'] then
name = data['mods.name']
else
name = data['mods.id']
end
tr
:tag('td')
:wikitext(string.format('[[%s|%s]]', data['mods._pageName'], name))
end,
order = 1000,
sort_type = 'text',
},
{
arg = 'domain',
header = i18n.mod_table.domain,
fields = {'mods.domain'},
display = function(tpl_args, tr, data, fields)
local k = 'mods.domain'
local i = tonumber(data[k])
if m_game.constants.mod.domains[i] == nil then
error('Undefined Modifier Domain ['..i..'] needs to be added to Module:Game')
end
data[k] = m_game.constants.mod.domains[i]['short_upper']
h.tbl.display.factory.value({})(tpl_args, tr, data, fields)
end,
order = 2000,
sort_type = 'text',
},
{
arg = 'generation_type',
header = i18n.mod_table.generation_type,
fields = {'mods.generation_type'},
display = function(tpl_args, tr, data, fields)
local k = 'mods.generation_type'
local i = tonumber(data[k])
if m_game.constants.mod.generation_types[i] == nil then
error('Undefined Modifier Generation Type ['..i..'] needs to be added to Module:Game')
end
data[k] = m_game.constants.mod.generation_types[i]['short_upper']
h.tbl.display.factory.value{}(tpl_args, tr, data, fields)
end,
order = 2001,
sort_type = 'text',
},
{
arg = {'group', 'mod_group'},
header = i18n.mod_table.mod_group,
fields = {'mods.mod_group'},
display = h.tbl.display.factory.value{},
order = 2002,
sort_type = 'text',
},
{
arg = {'mod_type'},
header = i18n.mod_table.mod_type,
fields = {'mods.mod_type'},
display = h.tbl.display.factory.value{},
order = 2003,
sort_type = 'text',
},
{
arg = {'level', 'required_level'},
header = i18n.mod_table.required_level,
fields = {'mods.required_level'},
display = h.tbl.display.factory.value{},
order = 2004,
},
{
arg = {'enchantment', 'labyrinth'},
header = i18n.mod_table.labyrinth,
fields = {string.format([[
CONCAT(
CASE mods.required_level
WHEN 32 THEN "%s"
WHEN 53 THEN "%s"
WHEN 66 THEN "%s"
WHEN 75 THEN "%s"
END
)=labyrinth_text]],
i18n.mod_table.normal_labyrinth,
i18n.mod_table.cruel_labyrinth,
i18n.mod_table.merciless_labyrinth,
i18n.mod_table.eternal_labyrinth)
},
display = h.tbl.display.factory.value{},
order = 2005,
sort_type = 'text',
},
{
arg = {'stat_text'},
header = i18n.mod_table.stat_text,
fields = {'mods.stat_text'},
display = function(tpl_args, tr, data, fields)
local value
-- map display type shows this in another column, remove this text to avoid clogging up the list
if tpl_args.type == 'map' then
local texts = m_util.string.split(data['mods.stat_text'], '<br>')
local out = {}
local valid
for _, v in ipairs(texts) do
valid = true
for _, data in pairs(mod_table.stat_ids) do
if string.find(v, data.pattern) ~= nil then
valid = false
break
end
end
if valid then
table.insert(out, v)
end
end
value = table.concat(out, '<br>')
else
value = data['mods.stat_text']
end
data['mods.stat_text'] = value
h.tbl.display.factory.value{color='mod'}(tpl_args, tr, data, fields)
end,
order = 3000,
sort_type = 'text',
},
{
arg = 'buff',
header = i18n.mod_table.buff,
fields = {'mods.granted_buff_id', 'mods.granted_buff_value'},
display = h.tbl.display.factory.value{delimiter=' '},
order = 4000,
sort_type = 'text',
},
{
arg = {'skill', 'granted_skill'},
header = i18n.mod_table.granted_skill,
fields = {'mods.granted_skill'},
display = h.tbl.display.factory.value{},
order = 4001,
sort_type = 'text',
},
{
arg = {'tags'},
header = i18n.mod_table.tags,
fields = {'mods.tags'},
display = function(tpl_args, tr, data, fields)
local k = 'mods.tags'
data[k] = table.concat(m_util.string.split(data[k], ',%s*'), ', ')
h.tbl.display.factory.value{}(tpl_args, tr, data, fields)
end,
order = 5000,
sort_type = 'text',
},
}
mod_table.stat_ids = {
['map_item_drop_quantity_+%'] = {
header = i18n.mod_table.iiq,
pattern = '%d+%% увеличение количества найденных предметов в этой области',
},
['map_item_drop_rarity_+%'] = {
header = i18n.mod_table.iir,
pattern = '%d+%% повышение редкости найденных предметов в этой области',
},
['map_pack_size_+%'] = {
header = i18n.mod_table.pack_size,
pattern = '%+%d+%% увеличение размера групп монстров',
}
}
mod_table.weights = {'spawn_weights', 'generation_weights'}
-- ----------------------------------------------------------------------------
-- Main functions
-- ----------------------------------------------------------------------------
local function _mod_table(tpl_args)
--[[
Creates a generic table for modifiers.
Examples
--------
= p.mod_table{
q_tables='spawn_weights',
q_join='mods._pageID=spawn_weights._pageID',
q_where='mods.generation_type = 10 AND spawn_weights.tag = "boots" AND spawn_weights.weight > 0',
q_orderBy='mods.id, mods.required_level',
q_limit=100,
stat_text=1,
enchantment=1,
}
]]
-- default to enabled
tpl_args.name = tpl_args.name or true
for _, key in ipairs(mod_table.weights) do
tpl_args[key] = m_util.cast.boolean(tpl_args[key])
end
if string.find(tpl_args.q_where, '%[%[') ~= nil then
error('SMW leftover in where clause')
end
local row_infos = {}
for _, row_info in ipairs(mod_table.data) do
local enabled = false
if row_info.arg == nil then
enabled = true
elseif type(row_info.arg) == 'string' and m_util.cast.boolean(tpl_args[row_info.arg]) then
enabled = true
elseif type(row_info.arg) == 'table' then
for _, argument in ipairs(row_info.arg) do
if m_util.cast.boolean(tpl_args[argument]) then
enabled = true
break
end
end
end
if enabled then
row_info.options = row_info.options or {}
row_infos[#row_infos+1] = row_info
end
end
-- sort the rows
table.sort(row_infos, function (a, b)
return (a.order or 0) < (b.order or 0)
end)
-- Set required and extra tables:
local tables = {'mods'}
for _, v in ipairs(m_util.string.split_args(tpl_args.q_tables, {',%s*'})) do
tables[#tables+1] = v
end
-- Set required and extra fields:
local fields = {
'mods._pageID',
}
for _, row_info in ipairs(row_infos) do
if type(row_info.fields) == 'function' then
row_info.fields = row_info.fields()
end
for index, field in ipairs(row_info.fields) do
row_info.options[index] = row_info.options[index] or {}
fields[#fields+1] = field
end
end
tpl_args._extra_fields = m_util.string.split_args(tpl_args.q_fields, {',%s*'})
for _, v in ipairs(tpl_args._extra_fields) do
fields[#fields+1] = v
end
-- Parse query arguments:
local query = {
-- Workaround: fix duplicates
groupBy='mods._pageID',
}
for key, value in pairs(tpl_args) do
if string.sub(key, 0, 2) == 'q_' then
query[string.sub(key, 3)] = value
end
end
local results = m_cargo.query(tables, fields, query)
if #results == 0 then
if tpl_args.default ~= nil then
return tpl_args.default
else
return 'Результатов не найдено'
end
end
-- this might be needed in other queries, currently not checking if
-- it's actually needed because performance impact should be neglible
local page_ids = {}
for _, row in ipairs(results) do
page_ids[#page_ids+1] = string.format(
'mods._pageID="%s"',
row['mods._pageID']
)
end
page_ids = table.concat(page_ids, ' OR ')
local weights = {}
for _, key in ipairs(mod_table.weights) do
if tpl_args[key] then
weights[key] = h.query_weights(key, page_ids)
end
end
local stats
if tpl_args.type == 'map' then
local query_stat_ids = {}
for k, _ in pairs(mod_table.stat_ids) do
query_stat_ids[#query_stat_ids+1] = string.format('mod_stats.id="%s"', k)
end
stats = m_cargo.map_results_to_id{
results=m_cargo.query(
{'mods', 'mod_stats'},
{
'mods._pageID',
'mod_stats.id',
'mod_stats.min',
'mod_stats.max',
},
{
where=string.format(
'(%s) AND (%s)',
page_ids,
table.concat(query_stat_ids, ' OR ')
),
join='mods._pageID=mod_stats._pageID',
orderBy='mods.id ASC',
}
),
field='mods._pageID'
}
-- In addition map stats to stat <-> min/max pairs
for page_id, rows in pairs(stats) do
local stat_id_map = {}
for _, row in ipairs(rows) do
stat_id_map[row['mod_stats.id']] = {
min=tonumber(row['mod_stats.min']),
max=tonumber(row['mod_stats.max'])
}
end
stats[page_id] = stat_id_map
end
end
--
-- Display
--
-- Preformance optimization
for index, field in ipairs(tpl_args._extra_fields) do
field = m_util.string.split(field, '%s*=%s*')
-- field[2] will be nil if there is no alias
tpl_args._extra_fields[index] = field[2] or field[1]
end
local tbl = mw.html.create('table')
tbl:attr('class', 'wikitable sortable modifier-table')
-- Header
local tr = tbl:tag('tr')
local display_fields = {}
for i, row_info in ipairs(row_infos) do
for j, field in ipairs(row_info.fields) do
-- Aliased name is used as keys in the results:
field = m_util.string.split(field, '%s*=%s*')
field = field[2] or field[1]
-- Make a new field table since mod_table.data will remain
-- modified the 2nd time a function is run and then crash.
if j == 1 then
display_fields[i] = {}
end
display_fields[i][j] = field
end
tr
:tag('th')
:attr('data-sort-type', row_info.sort_type or 'number')
:wikitext(row_info.header)
:done()
end
if tpl_args.type == 'map' then
for stat_id, data in pairs(mod_table.stat_ids) do
tr
:tag('th')
:attr('data-sort-type', 'number')
:wikitext(data.header)
:done()
end
end
for _, key in ipairs(mod_table.weights) do
if tpl_args[key] then
tr
:tag('th')
:wikitext(i18n.mod_table[key])
end
end
for _, field in ipairs(tpl_args._extra_fields) do
tr
:tag('th')
:wikitext(field)
end
-- Body
for _, row in ipairs(results) do
tr = tbl:tag('tr')
for i, row_info in ipairs(row_infos) do
-- this has been cast from a function in an earlier step
local display = true
for j, field in ipairs(display_fields[i]) do
-- this will bet set to an empty value not nil confusingly
if row[field] == nil or row[field] == '' then
if row_info.options[j].optional ~= true then
display = false
break
else
row[field] = nil
end
end
end
if display then
row_info.display(tpl_args, tr, row, display_fields[i])
else
tr:wikitext(m_util.html.td.na())
end
end
if tpl_args.type == 'map' then
for stat_id, data in pairs(mod_table.stat_ids) do
local stat_data = stats[row['mods._pageID']]
if stat_data and stat_data[stat_id] then
local v = stat_data[stat_id]
local text
if v.min == v.max then
text = v.min
else
text = string.format('(%s to %s)', v.min, v.max)
end
tr
:tag('td')
:attr('data-sort-value', (v.min+v.max)/2)
:wikitext(string.format('%s%%', text))
:done()
else
tr:wikitext(m_util.html.td.na())
end
end
end
for _, key in ipairs(mod_table.weights) do
if tpl_args[key] then
local weight_out = {}
for _, wrow in ipairs(weights[key][row['mods._pageID']]) do
if wrow[key .. '.tag'] and wrow[key .. '.weight'] then
weight_out[#weight_out+1] = string.format(
'%s %s',
wrow[key .. '.tag'],
wrow[key .. '.weight']
)
end
end
if #weight_out > 0 then
tr
:tag('td')
:wikitext(table.concat(weight_out, '<br>'))
:done()
else
tr:wikitext(m_util.html.td.na())
end
end
end
for _, field in ipairs(tpl_args._extra_fields) do
if row[field] then
tr
:tag('td')
:wikitext(row[field])
else
tr:wikitext(m_util.html.td.na())
end
end
end
return tostring(tbl)
end
local function _drop_down_table(tpl_args)
--[[
This function queries mods that can spawn on an item. It compares
the item tags and the spawn weight tags. If there's a match and
the spawn weight is larger than zero, then that mod is added to a
drop down list.
To Do:
* Add support to:
* Forsaken masters
* Bestiary
* Add a proper expand/collapse toggle for the entire header row so
it reacts together with mw-collapsible.
* Show Mod group in a better way perhaps:
Mod group [Collapsible, default=Expanded]
# to Damage [Collapsible, default=Collapsed]
3 to Damage
5 to Damage
* Add a where condition that somehow filters out mods that obviously
wont match with the item. spawn_weights.weight>0 isn't enough due
to possible edge cases.
Examples:
Weapons
= p.drop_down_table{item='Rusted Hatchet', header='One Handed Axes'}
= p.drop_down_table{item='Stone Axe', header='Two Handed Axes'}
Accessories
= p.drop_down_table{item='Amber Amulet', header='Amulets'}
Jewels
= p.drop_down_table{item='Cobalt Jewel', header='Jewels'}
Armour
= p.drop_down_table{item='Plate Vest', header='Body armours'}
Boots
= p.drop_down_table{item='Iron Greaves', header='Boots'}
= p.drop_down_table{
item='Fishing Rod',
header='FISH PLEASE',
item_tags='fishing_rod',
extra_fields='mods.tags'
}
= p.drop_down_table{
item='Fishing Rod',
item_tags='axe, one_hand_weapon, onehand, weapon, default',
extra_item_tags='fishing_rod'
}
= p.drop_down_table{
item='Vaal Blade',
}
]]
-- Format the cargo query:
local where
for _,v in ipairs({
{tpl_args.page, 'items._pageName = "%s"'},
{tpl_args.item, 'items.name = "%s"'},
}) do
if v[1] ~= nil then
where = string.format(v[2], v[1])
break
end
end
local item_info = m_cargo.query(
{'items'},
{
'items.name',
'items.tags',
'items.class_id',
'items.inventory_icon',
'items.html',
'items.release_version',
'items._pageName'
},
{
where=where,
groupBy='items._pageName',
orderBy='items.name, items.release_version DESC',
}
)[1]
-- Set the item class as key and the corresponding mod domain as
-- value:
local value
local class_to_domain = {
['LifeFlask']=2,
['ManaFlask']=2,
['HybridFlask']=2,
['UtilityFlask']=2,
['UtilityFlaskCritical']=2,
['Map']=5,
['Jewel']=10,
['Leaguestone']=12,
['AbyssJewel']=13,
}
-- Get the domain, if it's not defined in the table assume it's
-- in the item domain.
item_info['items.domain'] = tonumber(tpl_args.domain) or class_to_domain[item_info['items.class_id']] or 1
-- Convert the mod domain number to understandable text:
item_info['items.domain_text'] = m_game.constants.mod.domains[item_info['items.domain']]['short_lower']
-- Format item tags:
tpl_args.item_tags = m_util.string.split_args(
tpl_args.item_tags or item_info['items.tags'],
{sep=',%s*'}
)
for _,v in ipairs(m_util.string.split_args(tpl_args.extra_item_tags, {sep=',%s*'})) do
tpl_args.item_tags[#tpl_args.item_tags+1] = v
end
-- Format extra fields:
local extra_fields = m_util.string.split_args(tpl_args.extra_fields, {sep=',%s*'})
-- Get tags that are appended to special items:
local tags_cfg = m_game.constants.item.classes[item_info['items.class_id']].tags or {}
-- Create drop down lists in these sections and query in these
-- generation types.
local section = {
{
header = i18n.drop_down_table.prefix,
where = function(tpl_args, value)
local where = {}
for _, item_tag in ipairs(tpl_args.item_tags) do
where[#where+1] = string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
item_tag,
1,
item_info['items.domain']
)
end
return table.concat(where, ' OR ')
end,
},
{
header = i18n.drop_down_table.suffix,
where = function(tpl_args, value)
local where = {}
for _, item_tag in ipairs(tpl_args.item_tags) do
where[#where+1] = string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
item_tag,
2,
item_info['items.domain']
)
end
return table.concat(where, ' OR ')
end,
},
{
tags = {tags_cfg.elder},
header = i18n.drop_down_table.elder_prefix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.elder,
1,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.elder},
header = i18n.drop_down_table.elder_suffix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.elder,
2,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.shaper},
header = i18n.drop_down_table.shaper_prefix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.shaper,
1,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.shaper},
header = i18n.drop_down_table.shaper_suffix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.shaper,
2,
item_info['items.domain']
)
end,
},
{
header = i18n.drop_down_table.delve_prefix,
where = function(tpl_args, value)
local where = {}
for _, item_tag in ipairs(tpl_args.item_tags) do
where[#where+1] = string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
item_tag,
1,
16
)
end
return table.concat(where, ' OR ')
end,
},
{
header = i18n.drop_down_table.delve_suffix,
where = function(tpl_args, value)
local where = {}
for _, item_tag in ipairs(tpl_args.item_tags) do
where[#where+1] = string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
item_tag,
2,
16
)
end
return table.concat(where, ' OR ')
end,
},
{
tags = {tags_cfg.crusader},
header = i18n.drop_down_table.crusader_prefix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.crusader,
1,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.crusader},
header = i18n.drop_down_table.crusader_suffix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.crusader,
2,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.eyrie},
header = i18n.drop_down_table.eyrie_prefix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.eyrie,
1,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.eyrie},
header = i18n.drop_down_table.eyrie_suffix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.eyrie,
2,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.basilisk},
header = i18n.drop_down_table.basilisk_prefix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.basilisk,
1,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.basilisk},
header = i18n.drop_down_table.basilisk_suffix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.basilisk,
2,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.adjudicator},
header = i18n.drop_down_table.adjudicator_prefix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.adjudicator,
1,
item_info['items.domain']
)
end,
},
{
tags = {tags_cfg.adjudicator},
header = i18n.drop_down_table.adjudicator_suffix,
where = function(tpl_args, value)
return string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
tags_cfg.adjudicator,
2,
item_info['items.domain']
)
end,
},
{
header = i18n.drop_down_table.veiled_prefix,
where = function(tpl_args, value)
local where = {}
for _, item_tag in ipairs(tpl_args.item_tags) do
where[#where+1] = string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > ''
AND mods.id LIKE "%%Master%%")
]],
item_tag,
1,
9
)
end
return table.concat(where, ' OR ')
end,
},
{
header = i18n.drop_down_table.veiled_suffix,
where = function(tpl_args, value)
local where = {}
for _, item_tag in ipairs(tpl_args.item_tags) do
where[#where+1] = string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > ''
AND mods.id LIKE "%%Master%%")
]],
item_tag,
2,
9
)
end
return table.concat(where, ' OR ')
end,
},
{
header = i18n.drop_down_table.corrupted,
where = function(tpl_args, value)
local where = {}
for _, item_tag in ipairs(tpl_args.item_tags) do
where[#where+1] = string.format(
[[
(spawn_weights.tag="%s"
AND mods.generation_type=%s
AND mods.domain=%s
AND mods.stat_text > '')
]],
item_tag,
5,
item_info['items.domain']
)
end
return table.concat(where, ' OR ')
end,
chance_multiplier = 1/4, -- See Vaal orb, for the 4 possible events.
is_implicit = true,
},
-- Reduce template expansion size by disabling enchantments, there are
-- other good pages with enchantment lists:
-- {
-- header = i18n.drop_down_table.enchant,
-- where = function(tpl_args, value)
-- local where = {}
-- for _, item_tag in ipairs(tpl_args.item_tags) do
-- where[#where+1] = string.format(
-- [[
-- (spawn_weights.tag="%s"
-- AND mods.generation_type=%s
-- AND mods.domain=%s
-- AND mods.stat_text > '')
-- ]],
-- item_tag,
-- 10,
-- item_info['items.domain']
-- )
-- end
-- return table.concat(where, ' OR ')
-- end,
-- is_implicit = true,
-- },
}
-- Save the original tag format:
local item_tags_orig = {}
for i,v in ipairs(tpl_args.item_tags) do
item_tags_orig[i] = v
end
local item_mods = {}
local mod_group_counter = {}
mod_group_counter['all'] = {}
local extra_fieldss = {}
local table_index_base = -1
for _, sctn in ipairs(section) do
item_mods[sctn['header']] = {}
-- Preallocate the mod group counter, implicit and explicit mods
-- are counted separetely because they can spawn together:
mod_group_counter[sctn['header']] = {}
local adj = 'explicit'
if sctn['is_implicit'] then
adj = 'implicit'
end
for _, header in ipairs({sctn['header'], 'all'}) do
if mod_group_counter[header][adj] == nil then
mod_group_counter[header][adj] = {}
end
end
local continue = true
local current_tags
if sctn['tags'] then
-- some item classes do not have shaper/elder items, so the table
-- will not contain any tags:
if #sctn['tags'] == 0 then
continue = false
else
current_tags = sctn['tags']
end
else
current_tags = {}
-- Reset to original tags:
for i,v in ipairs(item_tags_orig) do
current_tags[i] = v
end
end
if continue then
-- Cargo preparation:
local q_fields = {
'mods._pageName',
'mods.name',
'mods.id',
'mods.required_level',
'mods.generation_type',
'mods.domain',
'mods.mod_group',
'mods.mod_type',
'mods.stat_text',
'mods.stat_text_raw',
'mods.tags',
'mod_stats.id',
'spawn_weights.tag',
'spawn_weights.weight',
'spawn_weights.ordinal',
'spawn_weights._pageName'
}
for i, v in ipairs(extra_fields) do
q_fields[#q_fields+1] = v
end
-- Query mods and map the results to the pagename:
local results = m_cargo.map_results_to_id{
results=m_cargo.query(
{'mods', 'spawn_weights', 'mod_stats'},
q_fields,
{
join = [[
mods._pageName=spawn_weights._pageName,
mods._pageName=mod_stats._pageName
]],
where = sctn['where'](tpl_args, value),
groupBy = [[
mods._pageName,
spawn_weights.tag,
spawn_weights.weight
]],
orderBy = [[
mods.generation_type,
mods.mod_group,
mods.mod_type,
mods.required_level,
mods._pageName,
spawn_weights.ordinal
]],
}
),
field='mods._pageName',
keep_id_field=true,
append_id_field=true,
}
if #results > 0 then
-- Loop through all found modifiers:
local last
for _, id in ipairs(results) do
-- Loop through all the modifier tags until they match
-- the item tags:
local j = 0
local tag_match_stop
repeat
j = j+1
local mod_tag = results[id][j]['spawn_weights.tag']
local mod_tag_weight = tonumber(
results[id][j]['spawn_weights.weight']
)
-- Loop through the item tags until it matches the
-- spawn weight tag and the mod tag has a value larger than
-- zero:
local y = 0
local tag_match_add = false
repeat
y = y+1
tag_match_stop = ((mod_tag == current_tags[y]) and ((mod_tag_weight or -1) >= 0)) or (results[id][j] == nil)
tag_match_add = (mod_tag == current_tags[y]) and ((mod_tag_weight or -1) > 0)
until tag_match_stop or y == #current_tags
-- If there's a match then save that mod and other
-- interesting information:
if tag_match_add then
-- Assume that the mod is global then go through
-- all the stat ids and check if any of the
-- stats are local:
local mod_scope = 'Глобальный'
for _, vv in ipairs(results[id]) do
if vv['mod_stats.id']:find('.*local.*') ~= nil then
mod_scope = 'Локальный'
end
end
-- Save the matching modifier tag:
local a = #item_mods[sctn['header']]
item_mods[sctn['header']][a+1] = results[id][j]
-- Save other interesting fields:
item_mods[sctn['header']][a+1]['mods.scope'] = mod_scope
item_mods[sctn['header']][a+1]['spawn_weight.idx_match'] = j
item_mods[sctn['header']][a+1]['mods.add'] = tag_match_add
item_mods[sctn['header']][a+1]['mods.stop'] = tag_match_stop
-- Count the mod groups:
local group = item_mods[sctn['header']][a+1]['mods.mod_group'] or 'nil_group'
for _, header in ipairs({sctn['header'], 'all'}) do
if mod_group_counter[header][adj][group] == nil then
mod_group_counter[header][adj][group] = {}
end
local tp = results[id][j]['mods.mod_type']
local bef = mod_group_counter[header][adj][group][tp] or 0
mod_group_counter[header][adj][group][tp] = 1 + bef
end
end
until tag_match_stop
end
-- If the user wants to see the spawn chance then do the
-- calculations and save that result as well:
if tpl_args.spawn_chance ~= nil then
extra_fields[#extra_fields+1] = 'spawn_weights.chance'
item_mods[sctn['header']] = h.get_spawn_chance{
tbl = item_mods[sctn['header']],
chance_multiplier = sctn['chance_multiplier']
}
end
extra_fieldss[sctn['header']] = extra_fields
end
end
end
--
-- Display the item mods
--
-- Introductory text:
local out = {}
out[#out+1] = string.format(
'==%s== \n',
tpl_args['header'] or table.concat(tpl_args.item_tags, ', ')
)
local expand_button = string.format(
'<div style="float: right; text-align:center"><div class="mw-collapsible-collapse-all" style="cursor:pointer;">[%s]</div><hr><div class="mw-collapsible-expand-all" style="cursor:pointer;">[%s]</div></div>',
i18n.drop_down_table.collapse_all,
i18n.drop_down_table.expand_all
)
out[#out+1] = expand_button
out[#out+1] = string.format('%s %s.<br><br><br>',
i18n.drop_down_table.table_intro,
h.item_link{
page=item_info['items._pageName'],
name=item_info['items.name'],
inventory_icon=item_info['items.inventory_icon'] or '',
html=item_info['items.html'] or '',
skip_query=true
}
)
-- Loop through the sections:
for _, sctn in ipairs(section) do
local extra_fields = extra_fieldss[sctn['header']]
local adj = 'explicit'
if sctn['is_implicit'] then
adj = 'implicit'
end
-- Create html container:
local container = mw.html.create('div')
:attr('style', 'vertical-align:top; display:inline-block;')
-- Create the drop down table with <table></table>:
local headers = container
if #item_mods[sctn['header']] > 0 then
headers
:tag('h3')
:wikitext(string.format('%s', sctn['header']))
:done()
:done()
end
local total_mod_groups = 0
for _ in pairs(mod_group_counter[sctn['header']][adj]) do
total_mod_groups = 1+total_mod_groups
end
-- Loop through and add all matching mods to the <table>.
local tbl, last_group, last_type, table_index
for _, rows in ipairs(item_mods[sctn['header']]) do
-- If the last mod group is different to the current
-- mod group then assume the mod isn't related and start
-- a new drop down list, if there's only one mod group
-- then use mod type instead:
if rows['mods.mod_group'] ~= last_group or (total_mod_groups == 1 and rows['mods.mod_type'] ~= last_type) then
-- Check through all the mods and see if there are
-- multiple mod types within the same mod group:
local count = {}
for _, n in ipairs(item_mods[sctn['header']]) do
-- If the mod has the same mod group, then add
-- the mod type to the counter. Only unique mod
-- types matter so the number is just a dummy
-- value:
if n['mods.mod_group'] == rows['mods.mod_group'] then
count[n['mods.mod_type']] = 1
end
end
-- Calculate how many unique mod types with the
-- same mod group there are for all explicit or implicit
-- sections since a mod with the same mod group can't
-- spawn. Doesn't matter if it's prefix or suffix.
local number_of_mod_types = 0
for _ in pairs(mod_group_counter['all'][adj][rows['mods.mod_group']]) do
number_of_mod_types = 1 + number_of_mod_types
end
-- If there are multiple unique mod types with the
-- same mod group then change the style of the drop
-- down list to indicate it, if there's only one
-- mod group in the generation type then ignore it:
local table_index_mod_group
local tbl_caption
if number_of_mod_types > 1 and total_mod_groups > 1 then
table_index_mod_group = table.concat(
{string.byte(rows['mods.mod_group'], 1, #rows['mods.mod_group'])},
''
)
tbl_caption = string.format(
'%s',
m_util.html.poe_color(
'stat',
string.format(
'%s %s',
i18n.drop_down_table.mod_group,
rows['mods.mod_group']
)
) or ''
)
else
tbl_caption = string.format(
'%s (%s)',
m_util.html.poe_color(
'mod',
h.header(rows['mods.stat_text_raw'])
) or '',
rows['mods.scope']
)
end
-- Create a table index for handling the collapsible:
table_index_base = table_index_base+1
if table_index_mod_group ~= nil then
table_index = table_index_mod_group
else
table_index = table_index_base
end
-- Add class and style to the <table>:
tbl = container:tag('table')
tbl
:attr('class', 'mw-collapsible mw-collapsed')
:attr('style',
'text-align:left; line-height:1.60em; width:810px;'
)
:tag('th')
:attr('class',
string.format('mw-customtoggle-%s', table_index)
)
:attr('style',
'text-align:left; line-height:1.40em; border-bottom:1pt solid dimgrey;'
)
:attr('colspan', '3' .. #extra_fields)
:wikitext(tbl_caption)
:done()
:done()
end
-- If the mod has no name then use the mod type:
local mod_name = rows['mods.name'] or ''
if mod_name == '' then
mod_name = rows['mods.mod_type']
end
-- Check if there are any extra properties to show in
-- the drop down list and then add a cell for that,
-- add this node at the end of the table row:
local td = mw.html.create('td')
if extra_fields ~= nil then
for _, extra_field in ipairs(extra_fields) do
td
:attr('width', '*')
:wikitext(string.format(
'%s: %s ',
extra_field,
rows[extra_field] or ''
)
)
:done()
end
end
-- Style mods.tags:
local mods_tags = table.concat(
m_util.string.split_args(rows['mods.tags'], {sep=',%s*'}),
', '
)
if mods_tags ~= '' then
mods_tags = m_util.html.tooltip('*', mods_tags)
end
-- Add a table row with the interesting properties that
-- modifier has:
tbl
:tag('tr')
:attr('class', 'mw-collapsible mw-collapsed')
:attr(
'id',
string.format('mw-customcollapsible-%s', table_index)
)
:tag('td')
:attr('width', '160')
:wikitext(
string.format(
' [[%s|%s]]',
rows['mods._pageName'],
mod_name:gsub('%s', ' ')
)
)
:done()
:tag('td')
:attr('width', '1')
:wikitext(
string.format(
'%s %s',
m_game.level_requirement['short_upper']
:gsub('%s', ' '),
rows['mods.required_level']
)
)
:done()
:tag('td')
:attr('width', '*')
:wikitext(
string.format(
'%s%s',
m_util.html.poe_color(
'mod',
rows['mods.stat_text']
:gsub('<br>', ', ')
:gsub('<br />', ' ')
) or '',
mods_tags
)
)
:done()
:node(td)
:done()
:done()
-- Save the last mod group for later comparison:
last_group = rows['mods.mod_group']
last_type = rows['mods.mod_type']
end
out[#out+1] = tostring(container)
end
-- Outro text:
out[#out+1] = '<br>'
out[#out+1] = m_util.html.poe_color(
'normal',
string.format('[[#Top|%s]]', i18n.drop_down_table.back_to_top)
)
return table.concat(out,'')
end
-- ----------------------------------------------------------------------------
-- Exported functions
-- ----------------------------------------------------------------------------
local p = {}
--
-- Template:Modifier table
--
p.mod_table = m_util.misc.invoker_factory(_mod_table, {
parentFirst = true,
})
--
-- Template:Item modifiers
--
p.drop_down_table = m_util.misc.invoker_factory(_drop_down_table, {
parentFirst = true,
})
--
-- Debug
--
p.debug = {}
function p.debug.tbl_data(tbl)
keys = {}
for _, data in ipairs(mod_table.data) do
if type(data.arg) == 'string' then
keys[data.arg] = 1
elseif type(data.arg) == 'table' then
for _, arg in ipairs(data.arg) do
keys[arg] = 1
end
end
end
for _, key in ipairs(mod_table.weights) do
keys[key] = 1
end
local out = {}
for key, _ in pairs(keys) do
out[#out+1] = string.format("['%s'] = '1'", key)
end
return table.concat(out, ', ')
end
return p