(Separated the filtering part and display part.) |
(Module:Cargo contains the most up-to-date cargo functions. Also DRY principle...) |
||
(39 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
-- |
-- |
||
− | local util = require('Module:Util') |
||
local getArgs = require('Module:Arguments').getArgs |
local getArgs = require('Module:Arguments').getArgs |
||
− | local |
+ | local m_util = require('Module:Util') |
− | local |
+ | local m_cargo = require('Module:Cargo') |
+ | local m_game = require('Module:Game') |
||
+ | local f_item_link = require('Module:Item link').item_link |
||
local p = {} |
local p = {} |
||
-- ---------------------------------------------------------------------------- |
-- ---------------------------------------------------------------------------- |
||
+ | -- Strings |
||
− | -- Utility / Helper functions |
||
-- ---------------------------------------------------------------------------- |
-- ---------------------------------------------------------------------------- |
||
+ | -- 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. |
||
− | local |
+ | local i18n = { |
+ | categories = { |
||
− | |||
+ | mods = 'Mods', |
||
− | -- Validate single value properties and set them |
||
+ | }, |
||
− | |||
− | h.validate = {} |
||
− | |||
− | function h.validate.not_nil (args) |
||
− | return function (arg) |
||
− | if g_args[arg] == nil then |
||
− | error(string.format('%s must not be nil', arg)) |
||
− | end |
||
− | end |
||
− | end |
||
− | |||
− | function h.validate.number (args) |
||
− | return function (arg) |
||
− | g_args[arg] = util.cast.number(g_args[arg], args) |
||
− | return g_args[arg] |
||
− | end |
||
− | end |
||
− | |||
− | |||
− | function h.handle_mapped_property_args (map) |
||
− | local properties = {} |
||
+ | tooltips = { |
||
− | for _, data in ipairs(map) do |
||
− | + | -- intro texts |
|
+ | intro_named_id = "'''%s''' is the internal id of [[modifier]] '''%s'''.\n", |
||
− | data.func(data.name) |
||
+ | intro_unnamed_id = "'''%s''' is the internal id of an unnamed [[modifier]].\n", |
||
− | end |
||
− | + | -- core data |
|
+ | id = 'Mod Id', |
||
− | properties[data.property] = g_args[data.name] |
||
− | + | name = 'Name', |
|
+ | mod_group = 'Group', |
||
− | end |
||
+ | mod_type = 'Mod type', |
||
− | |||
+ | domain = 'Domain', |
||
− | g_frame:callParserFunction('#set:', properties) |
||
+ | domain_fmt = '%s (Id: %s)', |
||
− | end |
||
+ | generation_type = 'Generation type', |
||
− | |||
+ | generation_type_fmt = '%s (Id: %s)', |
||
− | function h.create_header(row) |
||
+ | required_level = 'Req. Level', |
||
− | local stat = mw.html.create('span') |
||
+ | stat_text = 'Effect', |
||
− | local text, nsub = mw.ustring.gsub(row['Has stat text'], '%d+', '?') |
||
+ | granted_buff_id = 'Granted Buff Id', |
||
− | stat |
||
+ | granted_buff_value = 'Granted Buff Value', |
||
− | :attr('class', 'mod-table-header-stat') |
||
+ | granted_skill = 'Granted Skill', |
||
− | :wikitext(text) |
||
− | + | tags = 'Tags', |
|
+ | tier_text = 'Tier Text', |
||
+ | -- shared |
||
− | local mgroup = mw.html.create('span') |
||
+ | ordinal = '#', |
||
− | mgroup |
||
+ | |||
− | :attr('class', 'mod-table-header-modgroup') |
||
− | + | -- stats |
|
− | + | stats = 'Stats', |
|
+ | stat_id = 'Stat Id', |
||
+ | min = 'Minimum', |
||
+ | max = 'Maximum', |
||
+ | -- weights |
||
− | local tbl = mw.html.create('table') |
||
+ | spawn_weights = 'Spawn weights', |
||
− | tbl |
||
+ | generation_weights = 'Generation weights', |
||
− | :attr('class', 'wikitable mw-collapsible mw-collapsed mod-table') |
||
− | + | tag = 'Tag', |
|
− | + | weight = 'Weight', |
|
+ | |||
− | :attr('class', 'mod-table-header') |
||
+ | -- sell price |
||
− | :attr('colspan', g_args.colspan) |
||
− | + | sell_price = 'Modifier sell price', |
|
+ | item = 'Item', |
||
− | :attr('class', 'mod-table-header-container') |
||
+ | }, |
||
− | :wikitext(tostring(stat) .. tostring(mgroup)) |
||
+ | |||
− | :done() |
||
− | + | errors = { |
|
− | + | -- |
|
+ | -- Mod template |
||
− | end |
||
+ | -- |
||
+ | 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', |
||
+ | }, |
||
+ | } |
||
− | function h.format_mod(tbl, row, tags) |
||
− | local tr = tbl:tag('tr') |
||
− | tr |
||
− | :tag('td') |
||
− | :wikitext(string.format('[[%s|%s]]', row[1], row['Has name'])) |
||
− | :attr('class', 'mod-table-cell-name') |
||
− | :done() |
||
− | :tag('td') |
||
− | :wikitext(row['Has level requirement']) |
||
− | :attr('class', 'mod-table-cell-level') |
||
− | :done() |
||
− | :tag('td') |
||
− | :wikitext(row['Has stat text']) |
||
− | :attr('class', 'mod-table-cell-stat') |
||
− | :done() |
||
− | :tag('td') |
||
− | :wikitext(table.concat(tags, ', ')) |
||
− | :attr('class', 'mod-table-cell-tags') |
||
− | :done() |
||
− | end |
||
+ | -- ---------------------------------------------------------------------------- |
||
+ | -- utility / Helper functions |
||
+ | -- ---------------------------------------------------------------------------- |
||
+ | |||
+ | local h = {} |
||
-- ---------------------------------------------------------------------------- |
-- ---------------------------------------------------------------------------- |
||
Line 110: | Line 89: | ||
-- Template: Mod |
-- Template: Mod |
||
-- |
-- |
||
+ | |||
+ | local mod_map = { |
||
+ | main = { |
||
+ | table = 'mods', |
||
+ | display_order = {'id', 'name', 'mod_group', 'mod_type', 'domain', 'generation_type', 'required_level', 'stat_text', 'granted_buff_id', 'granted_buff_value', 'granted_skill', 'tags', 'tier_text'}, |
||
+ | order = {'id', 'name', 'mod_group', 'mod_type', 'domain', 'generation_type', 'required_level', 'stat_text', 'stat_text_raw', 'granted_buff_id', 'granted_buff_value', 'granted_skill', 'tags', 'tier_text'}, |
||
+ | fields = { |
||
+ | id = { |
||
+ | name = 'id', |
||
+ | field = 'id', |
||
+ | type = 'String', |
||
+ | wikitext = i18n.tooltips.id, |
||
+ | }, |
||
+ | name = { |
||
+ | name = 'name', |
||
+ | field = 'name', |
||
+ | type = 'String', |
||
+ | wikitext = i18n.tooltips.name, |
||
+ | }, |
||
+ | mod_group = { |
||
+ | name = 'mod_group', |
||
+ | field = 'mod_group', |
||
+ | type = 'String', |
||
+ | wikitext = i18n.tooltips.mod_group, |
||
+ | }, |
||
+ | mod_type = { |
||
+ | name = 'mod_type', |
||
+ | field = 'mod_type', |
||
+ | type = 'String', |
||
+ | wikitext = i18n.tooltips.mod_type, |
||
+ | }, |
||
+ | domain = { |
||
+ | name = 'domain', |
||
+ | field = 'domain', |
||
+ | type = 'Integer', |
||
+ | wikitext = 'Mod domain', |
||
+ | display = function (value) |
||
+ | return string.format(i18n.tooltips.domain_fmt, m_game.constants.mod.domains[value]['short_upper'], value) |
||
+ | end, |
||
+ | }, |
||
+ | generation_type = { |
||
+ | name = 'generation_type', |
||
+ | field = 'generation_type', |
||
+ | type = 'Integer', |
||
+ | wikitext = i18n.tooltips.generation_type, |
||
+ | display = function (value) |
||
+ | return string.format(i18n.tooltips.generation_type_fmt, m_game.constants.mod.generation_types[value]['short_upper'], value) |
||
+ | end, |
||
+ | }, |
||
+ | required_level = { |
||
+ | name = 'required_level', |
||
+ | field = 'required_level', |
||
+ | type = 'Integer', |
||
+ | wikitext = i18n.tooltips.required_level, |
||
+ | }, |
||
+ | stat_text = { |
||
+ | name = 'stat_text', |
||
+ | field = 'stat_text', |
||
+ | type = 'Text', |
||
+ | wikitext = i18n.tooltips.stat_text, |
||
+ | }, |
||
+ | stat_text_raw = { |
||
+ | name = nil, |
||
+ | field = 'stat_text_raw', |
||
+ | type = 'Text', |
||
+ | func = function(tpl_args, frame) |
||
+ | if tpl_args.stat_text then |
||
+ | tpl_args.stat_text_raw = string.gsub( |
||
+ | -- [[x]] -> x |
||
+ | string.gsub( |
||
+ | tpl_args.stat_text, '%[%[([^%]|]+)%]%]', '%1' |
||
+ | ), |
||
+ | -- [[x|y]] -> y |
||
+ | '%[%[[^|]+|([^%]|]+)%]%]', '%1' |
||
+ | ) |
||
+ | end |
||
+ | return tpl_args.stat_text_raw |
||
+ | end |
||
+ | }, |
||
+ | granted_buff_id = { |
||
+ | name = 'granted_buff_id', |
||
+ | field = 'granted_buff_id', |
||
+ | type = 'String', |
||
+ | wikitext = i18n.tooltips.granted_buff_id, |
||
+ | }, |
||
+ | granted_buff_value = { |
||
+ | name = 'granted_buff_value', |
||
+ | field = 'granted_buff_value', |
||
+ | type = 'Integer', |
||
+ | wikitext = i18n.tooltips.granted_buff_value, |
||
+ | }, |
||
+ | granted_skill = { |
||
+ | name = 'granted_skill', |
||
+ | field = 'granted_skill', |
||
+ | type = 'String', |
||
+ | wikitext = i18n.tooltips.granted_skill, |
||
+ | }, |
||
+ | tags = { |
||
+ | name = 'tags', |
||
+ | field = 'tags', |
||
+ | type = 'List (,) of String', |
||
+ | wikitext = 'Tags', |
||
+ | display = function(value) |
||
+ | return table.concat(value, ', ') |
||
+ | end, |
||
+ | default = {}, |
||
+ | }, |
||
+ | tier_text = { |
||
+ | name = 'tier_text', |
||
+ | field = 'tier_text', |
||
+ | type = 'Text', |
||
+ | wikitext = i18n.tooltips.tier_text, |
||
+ | }, |
||
+ | }, |
||
+ | }, |
||
+ | mod_sell_prices = { |
||
+ | table = 'mod_sell_prices', |
||
+ | order = {'name', 'amount'}, |
||
+ | fields = { |
||
+ | name = { |
||
+ | name = 'name', |
||
+ | field = 'name', |
||
+ | type = 'String', |
||
+ | func = function (value) return value end, |
||
+ | }, |
||
+ | amount = { |
||
+ | name = 'amount', |
||
+ | field = 'amount', |
||
+ | type = 'Integer', |
||
+ | func = tonumber, |
||
+ | }, |
||
+ | }, |
||
+ | }, |
||
+ | } |
||
+ | |||
+ | p.table_main = m_cargo.declare_factory{data=mod_map.main} |
||
+ | p.table_mod_sell_prices = m_cargo.declare_factory{data=mod_map.mod_sell_prices} |
||
+ | |||
+ | function p.table_mod_stats(frame) |
||
+ | m_cargo.declare(frame, { |
||
+ | _table = 'mod_stats', |
||
+ | id = 'String', |
||
+ | min = 'Integer', |
||
+ | max = 'Integer', |
||
+ | }) |
||
+ | end |
||
+ | |||
-- p.mod{id = "LocalIncreasedPhysicalDamagePercentUniqueOneHandSword2", name = "", mod_group = "LocalPhysicalDamagePercent", domain = "1", generation_type = "3", required_level = "1", mod_type = "LocalPhysicalDamagePercent", stat_text = "150% increased Physical Damage", stat1_id = "local_physical_damage_+%", stat1_min = "150", stat1_max = "150"} |
-- p.mod{id = "LocalIncreasedPhysicalDamagePercentUniqueOneHandSword2", name = "", mod_group = "LocalPhysicalDamagePercent", domain = "1", generation_type = "3", required_level = "1", mod_type = "LocalPhysicalDamagePercent", stat_text = "150% increased Physical Damage", stat1_id = "local_physical_damage_+%", stat1_min = "150", stat1_max = "150"} |
||
function p.mod(frame) |
function p.mod(frame) |
||
-- Get args |
-- Get args |
||
− | + | tpl_args = getArgs(frame, { |
|
parentFirst = true |
parentFirst = true |
||
}) |
}) |
||
− | + | frame = m_util.misc.get_frame(frame) |
|
-- |
-- |
||
Line 125: | Line 251: | ||
-- Validate single value properties and set them |
-- Validate single value properties and set them |
||
+ | m_util.args.from_cargo_map{ |
||
− | local map = { |
||
− | + | tpl_args=tpl_args, |
|
− | + | frame=frame, |
|
− | + | table_map=mod_map.main, |
|
− | wikitext = 'Mod Id', |
||
− | }, |
||
− | { |
||
− | name = 'name', |
||
− | property = 'Has name', |
||
− | wikitext = 'Name', |
||
− | }, |
||
− | { |
||
− | name = 'mod_group', |
||
− | property = 'Has mod group', |
||
− | wikitext = 'Group', |
||
− | }, |
||
− | { |
||
− | name = 'mod_type', |
||
− | property = 'Has mod type', |
||
− | wikitext = 'Mod type', |
||
− | }, |
||
− | { |
||
− | name = 'domain', |
||
− | property = 'Has mod domain', |
||
− | func = h.validate.number{min=1, max=13}, |
||
− | wikitext = 'Mod domain', |
||
− | display = function (value) |
||
− | return game.constants.mod.domains[value]['short_upper'] .. ' (Id: ' .. value .. ')' |
||
− | end, |
||
− | }, |
||
− | { |
||
− | name = 'generation_type', |
||
− | property = 'Has mod generation type', |
||
− | func = h.validate.number{min=1, max=12}, |
||
− | wikitext = 'Generation type', |
||
− | display = function (value) |
||
− | return game.constants.mod.generation_types[value]['short_upper'] .. ' (Id: ' .. value .. ')' |
||
− | end, |
||
− | }, |
||
− | { |
||
− | name = 'required_level', |
||
− | property = 'Has level requirement', |
||
− | func = h.validate.number{min=0, max=100}, |
||
− | wikitext = 'Req. level', |
||
− | }, |
||
− | { |
||
− | name = 'stat_text', |
||
− | property = 'Has stat text', |
||
− | wikitext = 'Effect', |
||
− | }, |
||
− | { |
||
− | name = 'granted_buff_id', |
||
− | property = 'Has granted buff id', |
||
− | wikitext = 'Granted Buff Id', |
||
− | }, |
||
− | { |
||
− | name = 'granted_buff_value', |
||
− | property = 'Has granted buff value', |
||
− | wikitext = 'Granted Buff Value', |
||
− | }, |
||
− | { |
||
− | name = 'granted_skill', |
||
− | property = 'Has granted skill id', |
||
− | wikitext = 'Granted Skill', |
||
− | }, |
||
} |
} |
||
+ | -- Validate % set the stat subobjects |
||
− | h.handle_mapped_property_args(map) |
||
+ | m_util.args.stats(tpl_args, {frame=frame}) |
||
− | |||
+ | for _, stat_data in pairs(tpl_args.stats) do |
||
− | -- Validate & set multi value property |
||
+ | m_cargo.store(frame, { |
||
− | |||
+ | _table = 'mod_stats', |
||
− | if g_args['tags'] == nil then |
||
− | + | id = stat_data.id, |
|
+ | min = stat_data.min, |
||
− | else |
||
− | + | max = stat_data.max, |
|
− | + | }) |
|
− | g_args['tags'] = tags |
||
− | |||
− | properties = {} |
||
− | properties['Has tag'] = table.concat(tags, ';') |
||
− | properties['+sep'] = ';' |
||
− | util.smw.set(g_frame, properties) |
||
end |
end |
||
− | |||
− | -- Validate % set the stat subobjects |
||
− | util.args.stats(g_args, {frame=g_frame}) |
||
-- Validate & set spawn weight subobjects |
-- Validate & set spawn weight subobjects |
||
+ | m_util.args.spawn_weight_list(tpl_args, { |
||
− | local i = 0 |
||
− | + | frame=frame, |
|
+ | }) |
||
− | local value = nil |
||
− | |||
− | repeat |
||
− | i = i + 1 |
||
− | id = { |
||
− | tag = string.format('spawn_weight%s_tag', i), |
||
− | value = string.format('spawn_weight%s_value', i), |
||
− | } |
||
− | |||
− | value = { |
||
− | tag = g_args[id.tag], |
||
− | value = g_args[id.value], |
||
− | } |
||
− | |||
− | if value.tag ~= nil and value.value ~= nil then |
||
− | properties = {} |
||
− | properties['Is tag number'] = i |
||
− | properties['Has tag'] = value.tag |
||
− | properties['Has spawn weight'] = h.validate.number({min=0})(id.value) |
||
− | |||
− | util.smw.subobject(g_frame, string.format('spawn weight %s', i), properties) |
||
− | |||
− | elseif not (value.tag == nil and value.value == nil) then |
||
− | error ('Both ' .. id.tag .. ' and ' .. id.value .. ' must be specified') |
||
− | end |
||
− | until value.tag == nil |
||
-- Validate & set generation weight subobjects |
-- Validate & set generation weight subobjects |
||
+ | m_util.args.generation_weight_list(tpl_args, { |
||
− | i = 0 |
||
− | + | frame=frame, |
|
− | + | }) |
|
− | |||
− | repeat |
||
− | i = i + 1 |
||
− | id = { |
||
− | tag = string.format('generation_weight%s_tag', i), |
||
− | value = string.format('generation_weight%s_value', i), |
||
− | } |
||
− | |||
− | value = { |
||
− | tag = g_args[id.tag], |
||
− | value = g_args[id.value], |
||
− | } |
||
− | |||
− | if value.tag ~= nil and value.value ~= nil then |
||
− | properties = {} |
||
− | properties['Is tag number'] = i |
||
− | properties['Has tag'] = value.tag |
||
− | properties['Has generation weight'] = h.validate.number({min=0})(id.value) |
||
− | |||
− | |||
− | util.smw.subobject(g_frame, string.format('generation weight %s', i), properties) |
||
− | |||
− | elseif not (value.tag == nil and value.value == nil) then |
||
− | error ('Both ' .. id.tag .. ' and ' .. id.value .. ' must be specified') |
||
− | end |
||
− | until value.tag == nil |
||
-- Validate & set mod sell values |
-- Validate & set mod sell values |
||
Line 279: | Line 284: | ||
repeat |
repeat |
||
i = i + 1 |
i = i + 1 |
||
− | + | ||
+ | local id = {} |
||
− | name = string.format('sell_price%s_name', i), |
||
+ | value = {} |
||
− | amount = string.format('sell_price%s_amount', i), |
||
+ | for key, data in pairs(mod_map.mod_sell_prices.fields) do |
||
− | } |
||
+ | id[key] = string.format('%s%s_%s', 'sell_price', i, data.name) |
||
− | |||
− | value = |
+ | value[key] = data.func(tpl_args[id[key]]) |
− | + | end |
|
− | amount = tonumber(g_args[id.amount]), |
||
− | } |
||
if value.name == nil and value.amount == nil then |
if value.name == nil and value.amount == nil then |
||
Line 293: | Line 296: | ||
elseif value.name ~= nil and value.amount ~= nil then |
elseif value.name ~= nil and value.amount ~= nil then |
||
if names[value.name] then |
if names[value.name] then |
||
− | error( |
+ | error(i18n.errors.sell_price_duplicate_name) |
else |
else |
||
names[value.name] = true |
names[value.name] = true |
||
end |
end |
||
+ | |||
− | |||
− | + | local cargo_data = { |
|
− | + | _table = mod_map.mod_sell_prices.table, |
|
+ | } |
||
− | properties['Has sell price amount'] = value.amount |
||
+ | for key, data in pairs(mod_map.mod_sell_prices.fields) do |
||
− | |||
− | + | cargo_data[data.field] = value[key] |
|
+ | end |
||
+ | m_cargo.store(frame, cargo_data) |
||
sell_prices[#sell_prices+1] = value |
sell_prices[#sell_prices+1] = value |
||
else |
else |
||
− | error ( |
+ | error (string.format(i18n.errors.sell_price_missing_arguments, id.name, id.amount)) |
end |
end |
||
Line 325: | Line 330: | ||
:attr('class', 'wikitable') |
:attr('class', 'wikitable') |
||
− | for _, |
+ | for _, key in ipairs(mod_map.main.display_order) do |
+ | local data = mod_map.main.fields[key] |
||
local text |
local text |
||
if data.display == nil then |
if data.display == nil then |
||
− | text = |
+ | text = tpl_args[key] |
else |
else |
||
− | text = data.display( |
+ | text = data.display(tpl_args[key]) |
end |
end |
||
Line 336: | Line 342: | ||
:tag('tr') |
:tag('tr') |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(data.wikitext) |
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
Line 344: | Line 350: | ||
:done() |
:done() |
||
end |
end |
||
− | |||
− | tbl |
||
− | :tag('tr') |
||
− | :tag('th') |
||
− | :wikitext('[[Property:Has tag|Tags]]') |
||
− | :done() |
||
− | :tag('td') |
||
− | :wikitext(table.concat(g_args['tags'], ', ')) |
||
− | :done() |
||
− | :done() |
||
− | :done() |
||
-- stat table |
-- stat table |
||
Line 364: | Line 359: | ||
:tag('th') |
:tag('th') |
||
:attr('colspan', 4) |
:attr('colspan', 4) |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.stats) |
:done() |
:done() |
||
:done() |
:done() |
||
:tag('tr') |
:tag('tr') |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.ordinal) |
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.stat_id) |
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.min) |
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.max) |
:done() |
:done() |
||
:done() |
:done() |
||
:done() |
:done() |
||
− | for i=1, |
+ | for i=1, #tpl_args.stats do |
local value = { |
local value = { |
||
− | id = |
+ | id = tpl_args['stat' .. i .. '_id'], |
− | min = |
+ | min = tpl_args['stat' .. i .. '_min'], |
− | max = |
+ | max = tpl_args['stat' .. i .. '_max'], |
} |
} |
||
Line 418: | Line 413: | ||
:tag('th') |
:tag('th') |
||
:attr('colspan', 3) |
:attr('colspan', 3) |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.spawn_weights) |
:done() |
:done() |
||
:done() |
:done() |
||
:tag('tr') |
:tag('tr') |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.ordinal) |
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.tag) |
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.weight) |
:done() |
:done() |
||
:done() |
:done() |
||
Line 439: | Line 434: | ||
i = i + 1 |
i = i + 1 |
||
value = { |
value = { |
||
− | tag = |
+ | tag = tpl_args[string.format('spawn_weight%s_tag', i)], |
− | value = |
+ | value = tpl_args[string.format('spawn_weight%s_value', i)], |
} |
} |
||
Line 468: | Line 463: | ||
:tag('th') |
:tag('th') |
||
:attr('colspan', 3) |
:attr('colspan', 3) |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.generation_weights) |
:done() |
:done() |
||
:done() |
:done() |
||
:tag('tr') |
:tag('tr') |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.ordinal) |
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.tag) |
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.weight) |
:done() |
:done() |
||
:done() |
:done() |
||
Line 489: | Line 484: | ||
i = i + 1 |
i = i + 1 |
||
value = { |
value = { |
||
− | tag = |
+ | tag = tpl_args[string.format('generation_weight%s_tag', i)], |
− | value = |
+ | value = tpl_args[string.format('generation_weight%s_value', i)], |
} |
} |
||
Line 517: | Line 512: | ||
:tag('th') |
:tag('th') |
||
:attr('colspan', 2) |
:attr('colspan', 2) |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.sell_price) |
:done() |
:done() |
||
:done() |
:done() |
||
:tag('tr') |
:tag('tr') |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.ordinal) |
:done() |
:done() |
||
:tag('th') |
:tag('th') |
||
− | :wikitext( |
+ | :wikitext(i18n.tooltips.item) |
:done() |
:done() |
||
:done() |
:done() |
||
Line 537: | Line 532: | ||
:done() |
:done() |
||
:tag('td') |
:tag('td') |
||
− | :wikitext( |
+ | :wikitext(string.format('[[%s]]', value.name)) |
:done() |
:done() |
||
:done() |
:done() |
||
Line 546: | Line 541: | ||
out = {} |
out = {} |
||
− | if mw.ustring.find( |
+ | if mw.ustring.find(tpl_args['id'], '_') then |
− | out[#out+1] = |
+ | out[#out+1] = frame:expandTemplate{ title = 'Incorrect title', args = { title=tpl_args['id'] } } .. '\n\n\n' |
end |
end |
||
− | if |
+ | if tpl_args['name'] then |
+ | |||
− | out[#out+1] = string.format("'''%s''' is the internal id of modifier '''%s'''.\n", g_args['id'], g_args['name']) |
||
+ | out[#out+1] = string.format(i18n.tooltips.intro_named_id, tpl_args['id'], tpl_args['name']) |
||
else |
else |
||
− | out[#out+1] = string.format( |
+ | out[#out+1] = string.format(i18n.tooltips.intro_unnamed_id, tpl_args['id']) |
end |
end |
||
-- Categories |
-- Categories |
||
− | cats = { |
+ | cats = {i18n.categories.mods} |
-- Done -> output |
-- Done -> output |
||
− | return tostring(container) .. |
+ | return tostring(container) .. m_util.misc.add_category(cats) .. '\n' .. table.concat(out) |
− | end |
||
− | |||
− | -- |
||
− | -- Template: SMW query mods |
||
− | -- |
||
− | |||
− | function p.query_mods(frame) |
||
− | -- Args |
||
− | g_args = getArgs(frame, { |
||
− | parentFirst = true |
||
− | }) |
||
− | g_frame = util.misc.get_frame(frame) |
||
− | |||
− | g_args.colspan = 4 |
||
− | |||
− | local conditions = {} |
||
− | conditions[#conditions+1] = 'concept' |
||
− | if g_args.tag then |
||
− | conditions[#conditions+1] = string.format('[[Has subobject::<q>[[-Has subobject::+]] [[Has spawn weight::>>0]] [[Has tag::%s]]</q>]]', g_args.tag) |
||
− | end |
||
− | |||
− | g_args.header_level = g_args.header_level or 2 |
||
− | |||
− | -- Fields |
||
− | local fields = {} |
||
− | fields[#fields+1] = '?Is mod' |
||
− | fields[#fields+1] = '?Has name' |
||
− | fields[#fields+1] = '?Has level requirement' |
||
− | fields[#fields+1] = '?Has mod group' |
||
− | fields[#fields+1] = '?Has stat text' |
||
− | -- parameters |
||
− | local parameters = {} |
||
− | parameters.sort = 'Has mod group, ' |
||
− | parameters.limit = 1000 -- lets see |
||
− | |||
− | local data = {} |
||
− | data.header = { |
||
− | prefix = 'Prefix', |
||
− | suffix = 'Suffix', |
||
− | } |
||
− | |||
− | local out = {} |
||
− | for _, v in ipairs({'prefix', 'suffix'}) do |
||
− | out[#out+1] = string.format('<h%i>%s</h%i>', g_args.header_level, data.header[v], g_args.header_level) |
||
− | conditions[1] = string.format('[[Concept:Spawnable named %s item mods]]', v) |
||
− | |||
− | local query |
||
− | local results |
||
− | -- |
||
− | -- Query tags |
||
− | -- |
||
− | query = {} |
||
− | query[#query+1] = string.format('[[-Has subobject::<q>%s</q>]]', table.concat(conditions, ' ')) |
||
− | query[#query+1] = '[[Has tag::+]]' |
||
− | query[#query+1] = '[[Has spawn weight::+]]' |
||
− | --query[#query+1] = '[[Has spawn weight::>>0]]' |
||
− | query[#query+1] = '?Has tag' |
||
− | query[#query+1] = '?Has spawn weight#' -- need native number |
||
− | query.limit = 1000 |
||
− | query.offset = 0 |
||
− | -- Tag order is very important |
||
− | query.sort = ', Is tag number' |
||
− | |||
− | local tags = {} |
||
− | -- this works because lua only considers nil to be false >_> |
||
− | while query.offset do |
||
− | results = util.smw.query(query, g_frame) |
||
− | query.offset = query.offset + #results |
||
− | -- terminates the while if enough reuslts have been fetched |
||
− | if query.offset % 1000 ~= 0 then |
||
− | query.offset = nil |
||
− | end |
||
− | |||
− | for _, row in ipairs(results) do |
||
− | local page, _ = string.gsub(row[1], '#_[%x]+', '') |
||
− | if tags[page] == nil then |
||
− | tags[page] = {} |
||
− | end |
||
− | |||
− | local text |
||
− | if tonumber(row['Has spawn weight']) > 0 then |
||
− | text = '[[File:Yes.png|yes|link=]]' |
||
− | else |
||
− | text = '[[File:No.png|no|link=]]' |
||
− | end |
||
− | |||
− | tags[page][#tags[page]+1] = string.format('%s %s', row['Has tag'], text) |
||
− | end |
||
− | end |
||
− | |||
− | -- |
||
− | -- Query mods |
||
− | -- |
||
− | query = {} |
||
− | for _, v in ipairs(conditions) do |
||
− | query[#query+1] = v |
||
− | end |
||
− | for _, v in ipairs(fields) do |
||
− | query[#query+1] = v |
||
− | end |
||
− | for k, v in pairs(parameters) do |
||
− | query[k] = v |
||
− | end |
||
− | |||
− | results = util.smw.query(query, g_frame) |
||
− | |||
− | local last = '' |
||
− | local tbl = '' |
||
− | for _, row in ipairs(results) do |
||
− | local current = string.gsub(row['Is mod'], '%d+.*', '%%d.*') |
||
− | if string.match(last, current) then |
||
− | h.format_mod(tbl, row, tags[row[1]]) |
||
− | else |
||
− | out[#out+1] = tostring(tbl) |
||
− | tbl = h.create_header(row) |
||
− | h.format_mod(tbl, row, tags[row[1]]) |
||
− | end |
||
− | last = row['Is mod'] |
||
− | end |
||
− | |||
− | -- add the last table |
||
− | out[#out+1] = tostring(tbl) |
||
− | end |
||
− | |||
− | return table.concat(out, '') |
||
− | end |
||
− | |||
− | -- |
||
− | -- Template: SMW mod table |
||
− | -- |
||
− | |||
− | -- =p.mod_list{'Strength1', 'shitty name', 'test', 'test2', userparam='extra_rows=2, show_jewels=1'} |
||
− | -- =p.mod_list{'ColdCritMultiplier', 'shitty name', 'test', 'test2', userparam='extra_rows=2, show_jewels=1'} |
||
− | -- =p.mod_list{'MapMultipleExilesMap2Tier', 'asdasda', 'Area yields 15% more Items<br>8% increased Rarity of Items found in this Area<br>Area is inhabited by 2 additional Rogue Exiles<br>Extra monsters ignore rarity bias (Hidden)<br>+14% Monster pack size', userparam='extra_rows=1, type=map, effect_rowid=2'} |
||
− | |||
− | function p.mod_list(frame) |
||
− | local types = {'map', 'jewel'} |
||
− | |||
− | -- Args |
||
− | g_args = getArgs(frame, { |
||
− | parentFirst = true |
||
− | }) |
||
− | g_frame = util.misc.get_frame(frame) |
||
− | |||
− | -- |
||
− | local args = util.string.split_args(g_args.userparam, {sep=', '}) |
||
− | g_args.userparam = args |
||
− | |||
− | args.extra_rows = (tonumber(args.extra_rows) or 0) |
||
− | if args.show_tags == nil then |
||
− | args.show_tags = true |
||
− | else |
||
− | args.show_tags = util.cast.boolean(args.show_tags) |
||
− | end |
||
− | args.effect_rowid = (tonumber(args.effect_rowid) or 0) + 1 |
||
− | |||
− | tr = mw.html.create('tr') |
||
− | tr |
||
− | :tag('td') |
||
− | :attr('data-sort-value', g_args[2] or g_args[1]) |
||
− | :wikitext(string.format('[[%s|%s]]', g_args[1], g_args[2] or g_args[1])) |
||
− | :done() |
||
− | |||
− | local i = 2 |
||
− | local row_max = i + args.extra_rows |
||
− | local text |
||
− | while i < row_max do |
||
− | i = i + 1 |
||
− | text = g_args[i] or '' |
||
− | text = table.concat(mw.text.split(text, ';', true), '<br>') |
||
− | |||
− | if args.type == 'map' and i == args.effect_rowid then |
||
− | text = mw.text.split(text, '<br>', true) |
||
− | |||
− | local map = { |
||
− | '%d+%% increased Quantity of Items found in this Area', |
||
− | '%d+%% increased Rarity of Items found in this Area', |
||
− | '%+%d+%% Monster pack size', |
||
− | } |
||
− | out = {} |
||
− | |||
− | local valid |
||
− | for k, v in pairs(text) do |
||
− | valid = true |
||
− | for _, pattern in ipairs(map) do |
||
− | if mw.ustring.find(v, pattern) ~= nil then |
||
− | valid = false |
||
− | break |
||
− | end |
||
− | end |
||
− | |||
− | if valid then |
||
− | table.insert(out, v) |
||
− | end |
||
− | end |
||
− | |||
− | text = table.concat(out, '<br>') |
||
− | end |
||
− | |||
− | tr |
||
− | :tag('td') |
||
− | :wikitext(text) |
||
− | :done() |
||
− | end |
||
− | |||
− | |||
− | local query |
||
− | local result |
||
− | |||
− | if args.type == 'map' then |
||
− | query = { |
||
− | string.format('[[-Has subobject::%s]]', g_args[1]), |
||
− | '[[Has stat id::+]]', |
||
− | '?Has stat id', |
||
− | '?Has minimum stat value', |
||
− | '?Has maximum stat value', |
||
− | } |
||
− | |||
− | result = util.smw.query(query, g_frame) |
||
− | |||
− | local stat_map = { |
||
− | ['map_item_drop_quantity_+%'] = {disp=0, sort=0}, |
||
− | ['map_item_drop_rarity_+%'] = {disp=0, sort=0}, |
||
− | ['map_pack_size_+%'] = {disp=0, sort=0}, |
||
− | } |
||
− | |||
− | local stat |
||
− | for _, row in ipairs(result) do |
||
− | stat = stat_map[row['Has stat id']] |
||
− | if stat ~= nil then |
||
− | stat.sort = (row['Has minimum stat value'] + row['Has maximum stat value']) / 2 |
||
− | if row['Has minimum stat value'] ~= row['Has minimum stat value'] then |
||
− | stat.disp = string.format('(%s%-%s)', row['Has minimum stat value'], row['Has maximum stat value']) |
||
− | else |
||
− | stat.disp = row['Has minimum stat value'] |
||
− | end |
||
− | end |
||
− | end |
||
− | |||
− | for _, k in ipairs({'map_item_drop_quantity_+%', 'map_item_drop_rarity_+%', 'map_pack_size_+%'}) do |
||
− | stat = stat_map[k] |
||
− | tr |
||
− | :tag('td') |
||
− | :attr('data-sort-value', stat.sort) |
||
− | :wikitext(stat.disp) |
||
− | :done() |
||
− | :done() |
||
− | end |
||
− | end |
||
− | |||
− | local tags |
||
− | if args.show_tags or args.type == 'jewel' then |
||
− | query = { |
||
− | string.format('[[-Has subobject::%s]]', g_args[1]), |
||
− | '[[Has tag::+]]', |
||
− | '?Has tag', |
||
− | '?Has spawn weight', |
||
− | sort='Is tag number', |
||
− | } |
||
− | |||
− | tags = {} |
||
− | result = util.smw.query(query, g_frame) |
||
− | end |
||
− | |||
− | if args.type == 'jewel' then |
||
− | local jewels = { |
||
− | dex=0, |
||
− | str=0, |
||
− | int=0, |
||
− | pris=0, |
||
− | } |
||
− | |||
− | local cast_tbl = { |
||
− | not_dex={'str', 'int'}, |
||
− | not_int={'str', 'dex'}, |
||
− | not_str={'int', 'dex'}, |
||
− | default={'str','int','dex','pris'}, |
||
− | } |
||
− | |||
− | local i = #result |
||
− | local row |
||
− | local cast |
||
− | while i > 0 do |
||
− | row = result[i] |
||
− | cast = cast_tbl[row['Has tag']] |
||
− | if cast ~= nil then |
||
− | for _, k in ipairs(cast) do |
||
− | jewels[k] = row['Has spawn weight'] |
||
− | end |
||
− | end |
||
− | |||
− | i = i - 1 |
||
− | end |
||
− | |||
− | tr |
||
− | :tag('td') |
||
− | :attr('class', 'table-cell-dex') |
||
− | :wikitext(jewels.dex) |
||
− | :done() |
||
− | :tag('td') |
||
− | :attr('class', 'table-cell-int') |
||
− | :wikitext(jewels.int) |
||
− | :done() |
||
− | :tag('td') |
||
− | :attr('class', 'table-cell-str') |
||
− | :wikitext(jewels.str) |
||
− | :done() |
||
− | :tag('td') |
||
− | :attr('class', 'table-cell-prismatic') |
||
− | :wikitext(jewels.pris) |
||
− | :done() |
||
− | :done() |
||
− | end |
||
− | |||
− | if args.show_tags then |
||
− | for _, row in ipairs(result) do |
||
− | tags[#tags+1] = string.format('%s %s', row['Has tag'], row['Has spawn weight']) |
||
− | end |
||
− | |||
− | tr |
||
− | :tag('td') |
||
− | :wikitext(table.concat(tags, '<br>')) |
||
− | :done() |
||
− | :done() |
||
− | end |
||
− | |||
− | return tostring(tr) |
||
− | end |
||
− | |||
− | function p.item_sell_price(frame) |
||
− | -- Query and sum the vendor prices for an item. |
||
− | -- Unidentified items won't currently show the correct vendor price. Not sure how that is specified, nor is it used at all. |
||
− | -- Expanding {{il}} seems to give a nil /n the first time a new command is run. Doesn't always happen. |
||
− | |||
− | -- = p.item_sell_price{page="Voideye"} |
||
− | -- = p.item_sell_price{page="Pyre"} |
||
− | -- = p.item_sell_price{page="Vessel of Vinktar (Lightning Penetration)"} |
||
− | |||
− | -- Args |
||
− | local g_args = getArgs(frame, { |
||
− | parentFirst = true |
||
− | }) |
||
− | local g_frame = util.misc.get_frame(frame) |
||
− | |||
− | -- Only the explicit modifiers are counted when vendors calculates the price. |
||
− | local condition = string.format('[[%s]]', g_args['page']) |
||
− | local query_item_mods = { |
||
− | condition, |
||
− | '?Has explicit mod ids', |
||
− | '?Has rarity', |
||
− | } |
||
− | local results_query_item_mods = util.smw.query(query_item_mods, g_frame) |
||
− | local item_mods = util.string.split(results_query_item_mods[1]['Has explicit mod ids'], '<MANY>') |
||
− | |||
− | -- If the item has a Normal rarity then the sell price would be a fixed price. |
||
− | if results_query_item_mods[1]['Has rarity'] == 'Normal' then |
||
− | local amount_normal = 1 |
||
− | local currency_normal = 'Scroll Fragment' |
||
− | return string.format('%s %s', amount_normal, g_frame:expandTemplate{title = 'il', args = {currency_normal, currency_normal .. 's'}}) |
||
− | |||
− | -- return string.format('%s %s', amount_normal, currency_normal) |
||
− | end |
||
− | |||
− | local mods_sell_price = {} |
||
− | for _, modid in ipairs(item_mods) do |
||
− | local query_mod_page = { |
||
− | string.format('[[Is mod::%s]]', modid), |
||
− | } |
||
− | local mod_page = util.smw.query(query_mod_page, g_frame) |
||
− | |||
− | local query_mod_sell_price = { |
||
− | string.format('[[-Has subobject::%s]]', mod_page[1][1]), |
||
− | '?Has sell price amount#', |
||
− | '?Has sell price item name', |
||
− | } |
||
− | local results = util.smw.query(query_mod_sell_price, g_frame) |
||
− | |||
− | for _, k in ipairs(results) do |
||
− | if k['Has sell price amount'] ~= '' then |
||
− | if mods_sell_price[k['Has sell price item name']] == nil then |
||
− | mods_sell_price[k['Has sell price item name']] = k['Has sell price amount'] |
||
− | else |
||
− | mods_sell_price[k['Has sell price item name']] = k['Has sell price amount'] + mods_sell_price[k['Has sell price item name']] |
||
− | end |
||
− | end |
||
− | end |
||
− | end |
||
− | |||
− | local out = {} |
||
− | for currency, amount in pairs(mods_sell_price) do |
||
− | out[#out+1] = string.format('%s %s', amount, g_frame:expandTemplate{title = 'il', args = {currency, currency .. 's'}}) |
||
− | end |
||
− | |||
− | return table.concat(out, ', ') |
||
− | end |
||
− | |||
− | |||
− | function p.find_mod_domain(input) |
||
− | -- Find the mod domain based on the item class. |
||
− | local out = input |
||
− | local mod_domains = game.constants.mod.domains |
||
− | |||
− | for i,_ in ipairs(out) do |
||
− | out[i]['Has mod domain'] = 1 |
||
− | for j, row in pairs(mod_domains) do |
||
− | if out[i]['Has item class']:gsub('Map', 'Area'):match(mod_domains[j]['short_upper']) then -- This may need updating if an area item class doesn't have 'Map' in the string, or if the mod domain descriptions doesn't match the item class. |
||
− | out[i]['Has mod domain'] = j |
||
− | end |
||
− | end |
||
− | |||
− | out[i]['Has mod domain text'] = mod_domains[out[i]['Has mod domain']]['short_lower'] |
||
− | end |
||
− | |||
− | -- out[1]['Has mod domain'] = 1 |
||
− | -- out[1]['Has mod domain text'] = 'item' |
||
− | |||
− | return out |
||
− | end |
||
− | |||
− | function p.get_item_tags(frame) |
||
− | -- This function queries for the tags for a specific item. |
||
− | |||
− | -- Args |
||
− | local g_args = getArgs(frame, { |
||
− | parentFirst = true |
||
− | }) |
||
− | local g_frame = util.misc.get_frame(frame) |
||
− | |||
− | local item_name = g_args[1] |
||
− | |||
− | local query = { |
||
− | string.format('[[Has name::%s]]', item_name), |
||
− | '?Has tags', |
||
− | '?Has base strength requirement', |
||
− | '?Has base intelligence requirement', |
||
− | '?Has base dexterity requirement', |
||
− | '?Has item class' |
||
− | } |
||
− | local results = util.smw.query(query, g_frame) |
||
− | |||
− | for i,_ in ipairs(results) do |
||
− | results[i]['Has tags'] = results[i]['Has tags']:gsub('(<MANY>)', ', ') -- Remove unnecessary symbols. |
||
− | |||
− | function table.reverse(a) -- Reverse order. Item tags are often sorted from lowest to highest priority. Therefore reversing order should lead to finding a match faster most of the time. |
||
− | local res = {} |
||
− | for i = #a, 1, -1 do |
||
− | res[#res+1] = a[i] |
||
− | end |
||
− | return res |
||
− | end |
||
− | results[i]['Has tags'] = table.concat(table.reverse(util.string.split(results[i]['Has tags'], ', ')), ', ') |
||
− | end |
||
− | |||
− | results = p.find_mod_domain(results) |
||
− | |||
− | return results |
||
− | end |
||
− | |||
− | function p.header(str) |
||
− | -- Replace specific numbers with a generic #. |
||
− | local s = table.concat(util.string.split(str, '%(%d+%.*%d*%-%d+%.*%d*%)'), '#') |
||
− | s = table.concat(util.string.split(s, '%d+%.*%d*'), '#') |
||
− | s = table.concat(util.string.split(s, '<br>'), ', ') |
||
− | |||
− | return s |
||
− | end |
||
− | |||
− | function p.drop_down_table(frame) |
||
− | -- Misses forsaken masters currently. |
||
− | -- Add a proper expand/collapse toggle for the entire header row so it reacts together with mw-collapsible. |
||
− | -- Add a better solution for properties inside subobjects, for extra_properties. Note that properties already queried for should not be added with this solution. |
||
− | |||
− | -- 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 = 'Armour body armours'} |
||
− | -- p.drop_down_table{item = 'Iron Greaves', header = 'Armour boots'} |
||
− | -- p.drop_down_table{item = 'Iron Gauntlets', header = 'Armour gloves'} |
||
− | -- p.drop_down_table{item = 'Iron Hat', header = 'Armour helmets'} |
||
− | -- p.drop_down_table{item = 'Splintered Tower Shield', header = 'Armour shields'} |
||
− | |||
− | |||
− | -- Args |
||
− | local g_args = getArgs(frame, { |
||
− | parentFirst = true |
||
− | }) |
||
− | local g_frame = util.misc.get_frame(frame) |
||
− | |||
− | local get_item_tags = p.get_item_tags{g_args.item}[1] |
||
− | local item_tags = {} |
||
− | if g_args.item_tags ~= nil then |
||
− | item_tags = util.string.split(g_args.item_tags, ', ') |
||
− | else |
||
− | item_tags = util.string.split(get_item_tags['Has tags'], ', ') |
||
− | end |
||
− | |||
− | local header = g_args['header'] |
||
− | if header == nil then |
||
− | header = table.concat(item_tags, ', ') |
||
− | end |
||
− | |||
− | -- Conditions |
||
− | local conditions = {} |
||
− | conditions[1] = 'concept' -- Reserve for Concepts. |
||
− | conditions[#conditions+1] = string.format('[[Has subobject::<q> [[Has spawn weight::>>0]] [[Has tag::%s]] </q>]]', table.concat(item_tags, ' || ')) |
||
− | |||
− | -- Fields |
||
− | local all_fields = { |
||
− | 1, |
||
− | 'Is mod', |
||
− | 'Has name', |
||
− | 'Has level requirement', |
||
− | 'Has mod group', |
||
− | 'Has mod type', |
||
− | 'Has stat text', |
||
− | } |
||
− | |||
− | local extra_properties = {} |
||
− | if g_args.extra_properties ~= nil then |
||
− | extra_properties = util.string.split(g_args.extra_properties, ', ') |
||
− | local a = #all_fields |
||
− | for _,v in ipairs(extra_properties) do |
||
− | table.insert(all_fields, a+1, v) |
||
− | end |
||
− | end |
||
− | |||
− | local fields = {} |
||
− | for _,v in ipairs(all_fields) do |
||
− | fields[#fields+1] = string.format('?%s', v) |
||
− | end |
||
− | |||
− | -- Parameters |
||
− | local parameters = { |
||
− | sort = 'Has mod group, Has mod type, Has level requirement', |
||
− | limit = 1000 -- lets see |
||
− | } |
||
− | |||
− | local data = {} |
||
− | data = { |
||
− | [1] = { |
||
− | header = 'Prefix', |
||
− | generation_type = 'prefix', |
||
− | condition = string.format('[[Concept:Spawnable named prefix %s mods]]', get_item_tags['Has mod domain text']), |
||
− | }, |
||
− | [2] = { |
||
− | header = 'Suffix', |
||
− | generation_type = 'suffix', |
||
− | condition = string.format('[[Concept:Spawnable named suffix %s mods]]', get_item_tags['Has mod domain text']), |
||
− | }, |
||
− | [3] = { |
||
− | header = 'Corrupted', |
||
− | generation_type = 'corrupted', |
||
− | condition = string.format('[[Concept:Spawnable corrupted %s mods]]', get_item_tags['Has mod domain text']), |
||
− | }, |
||
− | -- [4] = { |
||
− | -- header = 'Forsaken masters', |
||
− | -- generation_type = 'master', |
||
− | -- condition = '[[Concept:AAAAAAAAAAAAAAAAAAAA]]', |
||
− | -- }, |
||
− | } |
||
− | |||
− | -- Define the output. |
||
− | local out = {} |
||
− | out[#out+1] = string.format('==%s== \n', header) |
||
− | out[#out+1] = '<div style="float: right; text-align:center"><div class="mw-collapsible-collapse-all" style="cursor:pointer;">[Collapse All]</div><hr><div class="mw-collapsible-expand-all" style="cursor:pointer;">[Expand All]</div></div>' |
||
− | out[#out+1] = string.format('The table below displays the available [[modifiers]] for [[item]]s such as %s.<br><br><br>', g_frame:expandTemplate{title = 'Item link', args = {get_item_tags[1]}}) |
||
− | |||
− | local results = {} |
||
− | local item_mods = {} |
||
− | local tableIndex = -1 |
||
− | |||
− | for i_type,_ in ipairs(data) do |
||
− | local generation_type = data[i_type]['generation_type'] |
||
− | |||
− | -- |
||
− | -- Query mods |
||
− | -- |
||
− | |||
− | conditions[1] = data[i_type]['condition'] |
||
− | local query = {} |
||
− | for _, v in ipairs(conditions) do |
||
− | query[#query+1] = v |
||
− | end |
||
− | for _, v in ipairs(fields) do |
||
− | query[#query+1] = v |
||
− | end |
||
− | for k, v in pairs(parameters) do |
||
− | query[k] = v |
||
− | end |
||
− | results[generation_type] = util.smw.query(query, g_frame) |
||
− | |||
− | item_mods[generation_type] = {} |
||
− | |||
− | if #results[generation_type] > 0 then |
||
− | |||
− | local results_mod_tags = {} |
||
− | local mod_tags_weighting = {} |
||
− | |||
− | local last |
||
− | for i, v in ipairs(results[generation_type]) do -- Loop through all the results from the smw query. |
||
− | -- Query mod_tags |
||
− | local pagename = results[generation_type][i][1] |
||
− | query_mod_tags = { |
||
− | string.format('[[-Has subobject::%s]]', pagename), |
||
− | '?Has tag#', |
||
− | '?Has spawn weight#', |
||
− | '?Is tag number#', |
||
− | sort='Is tag number', |
||
− | } |
||
− | results_mod_tags[i] = util.smw.query(query_mod_tags, g_frame) |
||
− | |||
− | local j = 0 |
||
− | local tag_match_stop |
||
− | repeat -- Loop through the mod tags until a match is found. |
||
− | j = j+1 |
||
− | local mod_tag = results_mod_tags[i][j]['Has tag'] |
||
− | local mod_tag_weight = tonumber(results_mod_tags[i][j]['Has spawn weight']) |
||
− | |||
− | local y = 0 |
||
− | local tag_match_add |
||
− | repeat -- Loop through the item tags until it matches the mod tag and the mod tag has a value. |
||
− | y = y+1 |
||
− | tag_match_stop = (mod_tag == item_tags[y]) and ((mod_tag_weight or -1) >= 0) |
||
− | tag_match_add = (mod_tag == item_tags[y]) and ((mod_tag_weight or -1) > 0) |
||
− | until tag_match_stop or y == #item_tags |
||
− | |||
− | if tag_match_add then |
||
− | -- Complement the useful properties for the subobject. |
||
− | for q,w in pairs(results_mod_tags[i][j]) do |
||
− | results[generation_type][i][q] = w |
||
− | end |
||
− | |||
− | -- Filtered item modifier table: |
||
− | local a = #item_mods[generation_type] |
||
− | item_mods[generation_type][a+1] = {} |
||
− | for _,property in ipairs(all_fields) do |
||
− | item_mods[generation_type][a+1][property] = results[generation_type][i][property] |
||
− | end |
||
− | end |
||
− | until tag_match_stop or j == #results_mod_tags[i] |
||
− | end |
||
− | end |
||
− | |||
− | -- Display in table: |
||
− | |||
− | local container = mw.html.create('div') |
||
− | :attr('style', 'vertical-align:top; display:inline-block;') |
||
− | |||
− | local headers = container |
||
− | headers |
||
− | :tag('h3') |
||
− | :wikitext(string.format('%s', data[i_type]['header'])) |
||
− | :done() |
||
− | :done() |
||
− | |||
− | local last = '' |
||
− | for _, mod_properties in ipairs(item_mods[generation_type]) do |
||
− | if mod_properties['Has mod group'] ~= last then |
||
− | |||
− | -- Check if there are multiple mod types in the same mod group: |
||
− | local count = {} |
||
− | for _,n in ipairs(item_mods[generation_type]) do |
||
− | if n['Has mod group'] == mod_properties['Has mod group'] then |
||
− | count[n['Has mod type']] = 1 |
||
− | end |
||
− | end |
||
− | |||
− | local number_of_mod_types = 0 |
||
− | for _ in pairs(count) do |
||
− | number_of_mod_types = number_of_mod_types + 1 |
||
− | end |
||
− | |||
− | if number_of_mod_types > 1 then |
||
− | tbl_caption = string.format('%s', g_frame:expandTemplate{title = 'c', args = {'mod', mod_properties['Has mod group']}}) |
||
− | else |
||
− | local mod_appl = 'Global' -- Assume the mod is global if local isn't specified in the mod id. |
||
− | if mod_properties['Is mod']:find('Local') ~= nil then |
||
− | mod_appl = 'Local' |
||
− | end |
||
− | |||
− | tbl_caption = string.format('%s (%s)', g_frame:expandTemplate{title = 'c', args = {'mod', p.header(mod_properties['Has stat text'])}}, mod_appl) |
||
− | end |
||
− | |||
− | tableIndex = tableIndex+1 |
||
− | 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', tableIndex)) |
||
− | :attr('style', 'text-align:left; line-height:1.40em; border-bottom:1pt solid dimgrey;') |
||
− | :attr('colspan', '3' .. #extra_properties) |
||
− | :wikitext(tbl_caption) |
||
− | :done() |
||
− | :done() |
||
− | end |
||
− | |||
− | local mod_name = mod_properties['Has name'] |
||
− | if mod_name == '' then |
||
− | mod_name = mod_properties['Is mod'] |
||
− | end |
||
− | |||
− | local td = mw.html.create('td') |
||
− | if extra_properties ~= nil then |
||
− | for _, extra_property in ipairs(extra_properties) do |
||
− | td |
||
− | :attr('width', '*') |
||
− | :wikitext(string.format('%s: %s ', extra_property, mod_properties[extra_property])) |
||
− | :done() |
||
− | end |
||
− | end |
||
− | |||
− | tbl |
||
− | :tag('tr') |
||
− | :attr('class', 'mw-collapsible mw-collapsed') |
||
− | :attr('id', string.format('mw-customcollapsible-%s', tableIndex)) |
||
− | :tag('td') |
||
− | :attr('width', '160') |
||
− | :wikitext(string.format(' [[%s|%s]]', mod_properties[1], mod_name:gsub('%s', ' '))) |
||
− | :done() |
||
− | :tag('td') |
||
− | :attr('width', '1') |
||
− | :wikitext(string.format('%s %s',game.level_requirement['short_upper']:gsub('%s', ' '), mod_properties['Has level requirement'])) |
||
− | :done() |
||
− | :tag('td') |
||
− | :attr('width', '*') |
||
− | :wikitext(string.format('%s', g_frame:expandTemplate{title = 'c', args = {'mod', mod_properties['Has stat text']:gsub('<br>', ', ')}})) |
||
− | :done() |
||
− | :node(td) |
||
− | :done() |
||
− | :done() |
||
− | |||
− | last = mod_properties['Has mod group'] |
||
− | end |
||
− | |||
− | out[#out+1] = tostring(container) |
||
− | end |
||
− | |||
− | return table.concat(out,'') |
||
end |
end |
||
Latest revision as of 04:06, 2 May 2021
This Lua module is used on a very large number of pages. To avoid large-scale disruption and unnecessary server load, any changes to this module should first be tested in its /sandbox or /testcases subpages. The tested changes can then be added to this page in one single edit. Please consider discussing any changes on the talk page before implementing them. |
This module depends on the following other modules: |
Module for handling for Mods with Semantic MediaWiki support.
List of currently implemented templates
The above documentation is transcluded from Module:Mod/doc.
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
Editors can experiment in this module's sandbox and testcases pages.
Subpages of this module.
--
-- Module for mod related templates
--
local getArgs = require('Module:Arguments').getArgs
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
local m_game = require('Module:Game')
local f_item_link = require('Module:Item link').item_link
local p = {}
-- ----------------------------------------------------------------------------
-- 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.
local i18n = {
categories = {
mods = 'Mods',
},
tooltips = {
-- intro texts
intro_named_id = "'''%s''' is the internal id of [[modifier]] '''%s'''.\n",
intro_unnamed_id = "'''%s''' is the internal id of an unnamed [[modifier]].\n",
-- core data
id = 'Mod Id',
name = 'Name',
mod_group = 'Group',
mod_type = 'Mod type',
domain = 'Domain',
domain_fmt = '%s (Id: %s)',
generation_type = 'Generation type',
generation_type_fmt = '%s (Id: %s)',
required_level = 'Req. Level',
stat_text = 'Effect',
granted_buff_id = 'Granted Buff Id',
granted_buff_value = 'Granted Buff Value',
granted_skill = 'Granted Skill',
tags = 'Tags',
tier_text = 'Tier Text',
-- shared
ordinal = '#',
-- stats
stats = 'Stats',
stat_id = 'Stat Id',
min = 'Minimum',
max = 'Maximum',
-- weights
spawn_weights = 'Spawn weights',
generation_weights = 'Generation weights',
tag = 'Tag',
weight = 'Weight',
-- sell price
sell_price = 'Modifier sell price',
item = 'Item',
},
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',
},
}
-- ----------------------------------------------------------------------------
-- utility / Helper functions
-- ----------------------------------------------------------------------------
local h = {}
-- ----------------------------------------------------------------------------
-- Templates
-- ----------------------------------------------------------------------------
--
-- Template: Mod
--
local mod_map = {
main = {
table = 'mods',
display_order = {'id', 'name', 'mod_group', 'mod_type', 'domain', 'generation_type', 'required_level', 'stat_text', 'granted_buff_id', 'granted_buff_value', 'granted_skill', 'tags', 'tier_text'},
order = {'id', 'name', 'mod_group', 'mod_type', 'domain', 'generation_type', 'required_level', 'stat_text', 'stat_text_raw', 'granted_buff_id', 'granted_buff_value', 'granted_skill', 'tags', 'tier_text'},
fields = {
id = {
name = 'id',
field = 'id',
type = 'String',
wikitext = i18n.tooltips.id,
},
name = {
name = 'name',
field = 'name',
type = 'String',
wikitext = i18n.tooltips.name,
},
mod_group = {
name = 'mod_group',
field = 'mod_group',
type = 'String',
wikitext = i18n.tooltips.mod_group,
},
mod_type = {
name = 'mod_type',
field = 'mod_type',
type = 'String',
wikitext = i18n.tooltips.mod_type,
},
domain = {
name = 'domain',
field = 'domain',
type = 'Integer',
wikitext = 'Mod domain',
display = function (value)
return string.format(i18n.tooltips.domain_fmt, m_game.constants.mod.domains[value]['short_upper'], value)
end,
},
generation_type = {
name = 'generation_type',
field = 'generation_type',
type = 'Integer',
wikitext = i18n.tooltips.generation_type,
display = function (value)
return string.format(i18n.tooltips.generation_type_fmt, m_game.constants.mod.generation_types[value]['short_upper'], value)
end,
},
required_level = {
name = 'required_level',
field = 'required_level',
type = 'Integer',
wikitext = i18n.tooltips.required_level,
},
stat_text = {
name = 'stat_text',
field = 'stat_text',
type = 'Text',
wikitext = i18n.tooltips.stat_text,
},
stat_text_raw = {
name = nil,
field = 'stat_text_raw',
type = 'Text',
func = function(tpl_args, frame)
if tpl_args.stat_text then
tpl_args.stat_text_raw = string.gsub(
-- [[x]] -> x
string.gsub(
tpl_args.stat_text, '%[%[([^%]|]+)%]%]', '%1'
),
-- [[x|y]] -> y
'%[%[[^|]+|([^%]|]+)%]%]', '%1'
)
end
return tpl_args.stat_text_raw
end
},
granted_buff_id = {
name = 'granted_buff_id',
field = 'granted_buff_id',
type = 'String',
wikitext = i18n.tooltips.granted_buff_id,
},
granted_buff_value = {
name = 'granted_buff_value',
field = 'granted_buff_value',
type = 'Integer',
wikitext = i18n.tooltips.granted_buff_value,
},
granted_skill = {
name = 'granted_skill',
field = 'granted_skill',
type = 'String',
wikitext = i18n.tooltips.granted_skill,
},
tags = {
name = 'tags',
field = 'tags',
type = 'List (,) of String',
wikitext = 'Tags',
display = function(value)
return table.concat(value, ', ')
end,
default = {},
},
tier_text = {
name = 'tier_text',
field = 'tier_text',
type = 'Text',
wikitext = i18n.tooltips.tier_text,
},
},
},
mod_sell_prices = {
table = 'mod_sell_prices',
order = {'name', 'amount'},
fields = {
name = {
name = 'name',
field = 'name',
type = 'String',
func = function (value) return value end,
},
amount = {
name = 'amount',
field = 'amount',
type = 'Integer',
func = tonumber,
},
},
},
}
p.table_main = m_cargo.declare_factory{data=mod_map.main}
p.table_mod_sell_prices = m_cargo.declare_factory{data=mod_map.mod_sell_prices}
function p.table_mod_stats(frame)
m_cargo.declare(frame, {
_table = 'mod_stats',
id = 'String',
min = 'Integer',
max = 'Integer',
})
end
-- p.mod{id = "LocalIncreasedPhysicalDamagePercentUniqueOneHandSword2", name = "", mod_group = "LocalPhysicalDamagePercent", domain = "1", generation_type = "3", required_level = "1", mod_type = "LocalPhysicalDamagePercent", stat_text = "150% increased Physical Damage", stat1_id = "local_physical_damage_+%", stat1_min = "150", stat1_max = "150"}
function p.mod(frame)
-- Get args
tpl_args = getArgs(frame, {
parentFirst = true
})
frame = m_util.misc.get_frame(frame)
--
-- Validation & semantic properties
--
-- Validate single value properties and set them
m_util.args.from_cargo_map{
tpl_args=tpl_args,
frame=frame,
table_map=mod_map.main,
}
-- Validate % set the stat subobjects
m_util.args.stats(tpl_args, {frame=frame})
for _, stat_data in pairs(tpl_args.stats) do
m_cargo.store(frame, {
_table = 'mod_stats',
id = stat_data.id,
min = stat_data.min,
max = stat_data.max,
})
end
-- Validate & set spawn weight subobjects
m_util.args.spawn_weight_list(tpl_args, {
frame=frame,
})
-- Validate & set generation weight subobjects
m_util.args.generation_weight_list(tpl_args, {
frame=frame,
})
-- Validate & set mod sell values
i = 0
local names = {}
local sell_prices = {}
repeat
i = i + 1
local id = {}
value = {}
for key, data in pairs(mod_map.mod_sell_prices.fields) do
id[key] = string.format('%s%s_%s', 'sell_price', i, data.name)
value[key] = data.func(tpl_args[id[key]])
end
if value.name == nil and value.amount == nil then
value = nil
elseif value.name ~= nil and value.amount ~= nil then
if names[value.name] then
error(i18n.errors.sell_price_duplicate_name)
else
names[value.name] = true
end
local cargo_data = {
_table = mod_map.mod_sell_prices.table,
}
for key, data in pairs(mod_map.mod_sell_prices.fields) do
cargo_data[data.field] = value[key]
end
m_cargo.store(frame, cargo_data)
sell_prices[#sell_prices+1] = value
else
error (string.format(i18n.errors.sell_price_missing_arguments, id.name, id.amount))
end
until value == nil
--
-- Display
--
local container = mw.html.create('div')
container
:attr('class', 'modbox')
-- core stats
local tbl = container:tag('table')
tbl
:attr('class', 'wikitable')
for _, key in ipairs(mod_map.main.display_order) do
local data = mod_map.main.fields[key]
local text
if data.display == nil then
text = tpl_args[key]
else
text = data.display(tpl_args[key])
end
tbl
:tag('tr')
:tag('th')
:wikitext(data.wikitext)
:done()
:tag('td')
:wikitext(text)
:done()
:done()
:done()
end
-- stat table
tbl = container:tag('table')
tbl
:attr('class', 'wikitable sortable')
:tag('tr')
:tag('th')
:attr('colspan', 4)
:wikitext(i18n.tooltips.stats)
:done()
:done()
:tag('tr')
:tag('th')
:wikitext(i18n.tooltips.ordinal)
:done()
:tag('th')
:wikitext(i18n.tooltips.stat_id)
:done()
:tag('th')
:wikitext(i18n.tooltips.min)
:done()
:tag('th')
:wikitext(i18n.tooltips.max)
:done()
:done()
:done()
for i=1, #tpl_args.stats do
local value = {
id = tpl_args['stat' .. i .. '_id'],
min = tpl_args['stat' .. i .. '_min'],
max = tpl_args['stat' .. i .. '_max'],
}
if value.id then
tbl
:tag('tr')
:tag('td')
:wikitext(i)
:done()
:tag('td')
:wikitext(value.id)
:done()
:tag('td')
:wikitext(value.min)
:done()
:tag('td')
:wikitext(value.max)
:done()
:done()
:done()
end
end
-- spawn weight table
tbl = container:tag('table')
tbl
:attr('class', 'wikitable sortable')
:tag('tr')
:tag('th')
:attr('colspan', 3)
:wikitext(i18n.tooltips.spawn_weights)
:done()
:done()
:tag('tr')
:tag('th')
:wikitext(i18n.tooltips.ordinal)
:done()
:tag('th')
:wikitext(i18n.tooltips.tag)
:done()
:tag('th')
:wikitext(i18n.tooltips.weight)
:done()
:done()
:done()
i = 0
value = nil
repeat
i = i + 1
value = {
tag = tpl_args[string.format('spawn_weight%s_tag', i)],
value = tpl_args[string.format('spawn_weight%s_value', i)],
}
if value.tag then
tbl
:tag('tr')
:tag('td')
:wikitext(i)
:done()
:tag('td')
:wikitext(value.tag)
:done()
:tag('td')
:wikitext(value.value)
:done()
:done()
:done()
end
until value.tag == nil
-- generation weight table
tbl = container:tag('table')
tbl
:attr('class', 'wikitable sortable')
:tag('tr')
:tag('th')
:attr('colspan', 3)
:wikitext(i18n.tooltips.generation_weights)
:done()
:done()
:tag('tr')
:tag('th')
:wikitext(i18n.tooltips.ordinal)
:done()
:tag('th')
:wikitext(i18n.tooltips.tag)
:done()
:tag('th')
:wikitext(i18n.tooltips.weight)
:done()
:done()
:done()
i = 0
value = nil
repeat
i = i + 1
value = {
tag = tpl_args[string.format('generation_weight%s_tag', i)],
value = tpl_args[string.format('generation_weight%s_value', i)],
}
if value.tag then
tbl
:tag('tr')
:tag('td')
:wikitext(i)
:done()
:tag('td')
:wikitext(value.tag)
:done()
:tag('td')
:wikitext(value.value)
:done()
:done()
:done()
end
until value.tag == nil
-- Sell prices
tbl = container:tag('table')
tbl
:attr('class', 'wikitable sortable')
:tag('tr')
:tag('th')
:attr('colspan', 2)
:wikitext(i18n.tooltips.sell_price)
:done()
:done()
:tag('tr')
:tag('th')
:wikitext(i18n.tooltips.ordinal)
:done()
:tag('th')
:wikitext(i18n.tooltips.item)
:done()
:done()
:done()
for i, value in ipairs(sell_prices) do
tbl
:tag('tr')
:tag('td')
:wikitext(value.amount)
:done()
:tag('td')
:wikitext(string.format('[[%s]]', value.name))
:done()
:done()
end
-- Generic messages on the page
out = {}
if mw.ustring.find(tpl_args['id'], '_') then
out[#out+1] = frame:expandTemplate{ title = 'Incorrect title', args = { title=tpl_args['id'] } } .. '\n\n\n'
end
if tpl_args['name'] then
out[#out+1] = string.format(i18n.tooltips.intro_named_id, tpl_args['id'], tpl_args['name'])
else
out[#out+1] = string.format(i18n.tooltips.intro_unnamed_id, tpl_args['id'])
end
-- Categories
cats = {i18n.categories.mods}
-- Done -> output
return tostring(container) .. m_util.misc.add_category(cats) .. '\n' .. table.concat(out)
end
return p