Path of Exile Wiki

Please consider helping keep the wiki up to date. Check the to-do list of updates needed for version 3.14.0.

Game data exports will becoming later as the technical changes in addition to regular changes take some more time.

READ MORE

Path of Exile Wiki
(Added support for Has spawn chance, mainly for comparisons with poedb. Basically it is the specific modifiers spawn weight divided with the sum of all modifiers spawn weighting in that specific generation type.)
(Module:Cargo contains the most up-to-date cargo functions. Also DRY principle...)
 
(30 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 game = require('Module:Game')
+
local m_util = require('Module:Util')
local m_item = require('Module:Item2')
+
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 h = {}
+
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
 
if data.func ~= nil then
+
-- 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
 
 
 
if data.property ~= nil then
+
-- core data
  +
id = 'Mod Id',
properties[data.property] = g_args[data.name]
 
end
+
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)
 
:done()
+
tags = 'Tags',
  +
tier_text = 'Tier Text',
 
 
  +
-- shared
local mgroup = mw.html.create('span')
 
  +
ordinal = '#',
mgroup
 
  +
:attr('class', 'mod-table-header-modgroup')
 
:wikitext(row['Has mod group'])
+
-- stats
:done()
+
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('tr')
+
tag = 'Tag',
:tag('th')
+
weight = 'Weight',
  +
:attr('class', 'mod-table-header')
 
  +
-- sell price
:attr('colspan', g_args.colspan)
 
:tag('span')
+
sell_price = 'Modifier sell price',
  +
item = 'Item',
:attr('class', 'mod-table-header-container')
 
  +
},
:wikitext(tostring(stat) .. tostring(mgroup))
 
  +
:done()
 
:done()
+
errors = {
return tbl
+
--
  +
-- 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
g_args = getArgs(frame, {
+
tpl_args = getArgs(frame, {
 
parentFirst = true
 
parentFirst = true
 
})
 
})
g_frame = util.misc.get_frame(frame)
+
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,
name = 'id',
+
frame=frame,
property = 'Is mod',
+
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
 
g_args['tags'] = {}
+
id = stat_data.id,
  +
min = stat_data.min,
else
 
local tags = mw.text.split(g_args['tags'], ', ')
+
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
 
local id = nil
+
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
 
id = nil
+
frame=frame,
value = nil
+
})
 
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
id = {
+
  +
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]])
name = g_args[id.name],
+
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('Do not specify a sell price item name multiple times. Instead adjust the amount')
+
error(i18n.errors.sell_price_duplicate_name)
 
else
 
else
 
names[value.name] = true
 
names[value.name] = true
 
end
 
end
  +
 
properties = {}
+
local cargo_data = {
properties['Has sell price item name'] = value.name
+
_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
 
util.smw.subobject(g_frame, 'sell price ' .. value.name, properties)
+
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 ('Both ' .. id.name .. ' and ' .. id.amount .. ' must be specified')
+
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 _, data in ipairs(map) do
+
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 = g_args[data.name]
+
text = tpl_args[key]
 
else
 
else
text = data.display(g_args[data.name])
+
text = data.display(tpl_args[key])
 
end
 
end
 
 
Line 336: Line 342:
 
:tag('tr')
 
:tag('tr')
 
:tag('th')
 
:tag('th')
:wikitext(string.format('[[Property:%s|%s]]', data.property, data.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('Stats')
+
:wikitext(i18n.tooltips.stats)
 
:done()
 
:done()
 
:done()
 
:done()
 
:tag('tr')
 
:tag('tr')
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Is stat number|#]]')
+
:wikitext(i18n.tooltips.ordinal)
 
:done()
 
:done()
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Has stat id|Stat Id]]')
+
:wikitext(i18n.tooltips.stat_id)
 
:done()
 
:done()
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Has minimum stat value|Minimum]]')
+
:wikitext(i18n.tooltips.min)
 
:done()
 
:done()
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Has maximum stat value|Maximum]]')
+
:wikitext(i18n.tooltips.max)
 
:done()
 
:done()
 
:done()
 
:done()
 
:done()
 
:done()
 
 
for i=1, 5 do
+
for i=1, #tpl_args.stats do
 
local value = {
 
local value = {
id = g_args['stat' .. i .. '_id'],
+
id = tpl_args['stat' .. i .. '_id'],
min = g_args['stat' .. i .. '_min'],
+
min = tpl_args['stat' .. i .. '_min'],
max = g_args['stat' .. i .. '_max'],
+
max = tpl_args['stat' .. i .. '_max'],
 
}
 
}
 
 
Line 418: Line 413:
 
:tag('th')
 
:tag('th')
 
:attr('colspan', 3)
 
:attr('colspan', 3)
:wikitext('Spawn Weights')
+
:wikitext(i18n.tooltips.spawn_weights)
 
:done()
 
:done()
 
:done()
 
:done()
 
:tag('tr')
 
:tag('tr')
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Is tag number|#]]')
+
:wikitext(i18n.tooltips.ordinal)
 
:done()
 
:done()
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Has tag|Tag]]')
+
:wikitext(i18n.tooltips.tag)
 
:done()
 
:done()
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Has spawn weight|Weight]]')
+
:wikitext(i18n.tooltips.weight)
 
:done()
 
:done()
 
:done()
 
:done()
Line 439: Line 434:
 
i = i + 1
 
i = i + 1
 
value = {
 
value = {
tag = g_args[string.format('spawn_weight%s_tag', i)],
+
tag = tpl_args[string.format('spawn_weight%s_tag', i)],
value = g_args[string.format('spawn_weight%s_value', i)],
+
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('Generation Weights')
+
:wikitext(i18n.tooltips.generation_weights)
 
:done()
 
:done()
 
:done()
 
:done()
 
:tag('tr')
 
:tag('tr')
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Is tag number|#]]')
+
:wikitext(i18n.tooltips.ordinal)
 
:done()
 
:done()
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Has tag|Tag]]')
+
:wikitext(i18n.tooltips.tag)
 
:done()
 
:done()
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Has generation weight|Weight]]')
+
:wikitext(i18n.tooltips.weight)
 
:done()
 
:done()
 
:done()
 
:done()
Line 489: Line 484:
 
i = i + 1
 
i = i + 1
 
value = {
 
value = {
tag = g_args[string.format('generation_weight%s_tag', i)],
+
tag = tpl_args[string.format('generation_weight%s_tag', i)],
value = g_args[string.format('generation_weight%s_value', i)],
+
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('Modifier sell price')
+
:wikitext(i18n.tooltips.sell_price)
 
:done()
 
:done()
 
:done()
 
:done()
 
:tag('tr')
 
:tag('tr')
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Has sell price amount|#]]')
+
:wikitext(i18n.tooltips.ordinal)
 
:done()
 
:done()
 
:tag('th')
 
:tag('th')
:wikitext('[[Property:Has sell price item name|Item]]')
+
:wikitext(i18n.tooltips.item)
 
:done()
 
:done()
 
:done()
 
:done()
Line 537: Line 532:
 
:done()
 
:done()
 
:tag('td')
 
:tag('td')
:wikitext(m_item.item_link{item_name_exact=value.name})
+
:wikitext(string.format('[[%s]]', value.name))
 
:done()
 
:done()
 
:done()
 
:done()
Line 546: Line 541:
 
out = {}
 
out = {}
 
 
if mw.ustring.find(g_args['id'], '_') then
+
if mw.ustring.find(tpl_args['id'], '_') then
out[#out+1] = g_frame:expandTemplate{ title = 'Incorrect title', args = { title=g_args['id'] } } .. '\n\n\n'
+
out[#out+1] = frame:expandTemplate{ title = 'Incorrect title', args = { title=tpl_args['id'] } } .. '\n\n\n'
 
end
 
end
 
 
if g_args['name'] then
+
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("'''%s''' is the internal id of an unnamed modifier.\n", g_args['id'], g_args['name'])
+
out[#out+1] = string.format(i18n.tooltips.intro_unnamed_id, tpl_args['id'])
 
end
 
end
 
 
 
-- Categories
 
-- Categories
 
 
cats = {'Mods'}
+
cats = {i18n.categories.mods}
 
 
 
-- Done -> output
 
-- Done -> output
 
 
return tostring(container) .. util.misc.add_category(cats) .. '\n' .. table.concat(out)
+
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.get_spawn_chance(frame)
 
-- Calculates the spawn chance of a set of mods that all have a spawn weight.
 
 
-- Args
 
local g_args = getArgs(frame, {
 
parentFirst = true
 
})
 
local g_frame = util.misc.get_frame(frame)
 
 
local tbl = g_args['tbl']
 
local chance_multiplier = tonumber(g_args['chance_multiplier']) or 1 -- Probabillities affecting the result besides the spawn weight.
 
 
local N = 0
 
for i,_ in ipairs(tbl) do
 
N = N + tbl[i]['Has spawn weight'] -- Total number of outcomes.
 
end
 
 
for i,_ in ipairs(tbl) do
 
local n = tbl[i]['Has spawn weight'] -- Number of ways it can happen.
 
 
tbl[i]['Has spawn chance'] = string.format("%0.2f%%", n/N * chance_multiplier*100) -- Truncated value.
 
end
 
 
return tbl
 
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.
 
-- Show Mod group in a better way perhaps:
 
-- Mod group (expanded)
 
-- # to Damage (Collapsed)
 
-- 3 to Damage
 
-- 5 to Damage
 
-- 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'}
 
 
-- p.drop_down_table{item = 'Fishing Rod', header = 'FISH PLEASE', item_tags = 'fishing_rod', extra_properties = 'Has spawn weight, Has spawn chance'}
 
 
 
-- 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 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
 
offset = 0,
 
}
 
 
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']),
 
chance_multiplier = 1/4, -- See Vaal orb, for the 4 possible events.
 
},
 
-- [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>', m_item.item_link{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']
 
 
local query = {}
 
 
conditions[1] = data[i_type]['condition']
 
query[#query+1] = table.concat(conditions, ' ')
 
 
for _, v in ipairs(fields) do
 
query[#query+1] = v
 
end
 
for k, v in pairs(parameters) do
 
query[k] = v
 
end
 
 
if results[generation_type] == nil then
 
results[generation_type] = {}
 
end
 
repeat
 
local result = util.smw.query(query, g_frame)
 
query.offset = query.offset + #result -- Possible error source if only one mod is missing.
 
 
for _,v in ipairs(result) do
 
results[generation_type][#results[generation_type]+1] = v
 
end
 
until #result < 1000
 
 
item_mods[generation_type] = {}
 
 
local container = mw.html.create('div')
 
:attr('style', 'vertical-align:top; display:inline-block;')
 
 
if #results[generation_type] > 0 then
 
query_mod_tags = {
 
string.format('[[-Has subobject::<q>%s</q>]]', table.concat(conditions, ' ')),
 
'?Has tag#',
 
'?Has spawn weight#',
 
'?Is tag number#',
 
offset = 0,
 
}
 
 
local results_mod_tags = {}
 
local mod_data_subobject = {}
 
repeat -- Query again and add the remaining results.
 
results_mod_tags[#results_mod_tags+1] = util.smw.query(query_mod_tags, g_frame)
 
query_mod_tags.offset = query_mod_tags.offset + #results_mod_tags[#results_mod_tags]
 
 
for _,v in ipairs(results_mod_tags[#results_mod_tags]) do
 
local pagename = util.string.split(v[1], '#')[1]
 
if mod_data_subobject[pagename] == nil then
 
mod_data_subobject[pagename] = {}
 
end
 
 
local subobjectname = v[1]
 
mod_data_subobject[pagename][subobjectname] = v
 
end
 
until #results_mod_tags[#results_mod_tags] < 1000
 
 
local last
 
for i, v in ipairs(results[generation_type]) do -- Loop through all the results from the smw query.
 
local pagename = results[generation_type][i][1]
 
 
local j = 0
 
local tag_match_stop
 
repeat -- Loop through the mod tags until a match is found.
 
j = j+1
 
local subobjectname = string.format('%s#%s_%s', pagename, 'spawn_weight', j)
 
local mod_tag = mod_data_subobject[pagename][subobjectname]['Has tag']
 
local mod_tag_weight = tonumber(mod_data_subobject[pagename][subobjectname]['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)) or (mod_data_subobject[pagename][subobjectname] == nil)
 
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
 
local mod_scope = 'Global'
 
for subobject, subobject_val in pairs(mod_data_subobject[pagename]) do
 
if subobject:find('stat.*local') ~= nil then -- If at least one stat is local then change the scope of the mod to local.
 
mod_scope = 'Local'
 
end
 
 
if subobject == subobjectname then -- Complement with the properties the matching subobject has.
 
for property,w in pairs(subobject_val) do
 
if results[generation_type][i][property] == nil then
 
results[generation_type][i][property] = {}
 
end
 
 
results[generation_type][i][property] = w
 
end
 
end
 
end
 
 
local a = #item_mods[generation_type]
 
item_mods[generation_type][a+1] = {}
 
for _,property in ipairs(all_fields) do -- Filtered item modifier table:
 
item_mods[generation_type][a+1][property] = results[generation_type][i][property]
 
end
 
item_mods[generation_type][a+1]['Has mod scope'] = mod_scope
 
end
 
until tag_match_stop
 
end
 
 
 
 
for _,v in ipairs(extra_properties) do
 
if v == 'Has spawn chance' then
 
item_mods[generation_type] = p.get_spawn_chance{tbl = item_mods[generation_type], chance_multiplier = data[i_type]['chance_multiplier']}
 
break
 
end
 
end
 
 
 
 
local headers = container -- Display in <table>.
 
headers
 
:tag('h3')
 
:wikitext(string.format('%s', data[i_type]['header']))
 
:done()
 
:done()
 
local tbl, last
 
for _, mod_properties in ipairs(item_mods[generation_type]) do
 
if mod_properties['Has mod group'] ~= last then
 
 
local count = {}
 
for _,n in ipairs(item_mods[generation_type]) do -- Check if there are multiple mod types in the same mod group:
 
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', util.html.poe_color('mod', 'Mod group: ' .. mod_properties['Has mod group']))
 
else
 
tbl_caption = string.format('%s (%s)', util.html.poe_color('mod', p.header(mod_properties['Has stat text'])), mod_properties['Has mod scope'])
 
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:&nbsp;%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('&nbsp;&nbsp;&nbsp;[[%s|%s]]', mod_properties[1], mod_name:gsub('%s', '&nbsp;')))
 
:done()
 
:tag('td')
 
:attr('width', '1')
 
:wikitext(string.format('%s&nbsp;%s',game.level_requirement['short_upper']:gsub('%s', '&nbsp;'), mod_properties['Has level requirement']))
 
:done()
 
:tag('td')
 
:attr('width', '*')
 
:wikitext(string.format('%s', util.html.poe_color('mod', mod_properties['Has stat text']:gsub('<br>', ', ')) ))
 
:done()
 
:node(td)
 
:done()
 
:done()
 
 
last = mod_properties['Has mod group']
 
end
 
end
 
 
out[#out+1] = tostring(container)
 
end
 
 
return table.concat(out,'')
 
 
end
 
end
   

Latest revision as of 04:06, 2 May 2021

Template info icon Module documentation[view] [edit] [history] [purge]

Module for handling for Mods with Semantic MediaWiki support.

List of currently implemented templates

--
-- 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