Module:Mod: Difference between revisions
Jump to navigation
Jump to search
>Illviljan mNo edit summary |
>Illviljan (Using subobjects to check if a mod is local or global. Which should fix issues with flasks.) |
||
Line 1,181: | Line 1,181: | ||
if #results[generation_type] > 0 then | if #results[generation_type] > 0 then | ||
query_mod_tags = { | query_mod_tags = { | ||
string.format('[[-Has subobject::<q>%s</q>]]', table.concat(conditions, ' ')), | string.format('[[-Has subobject::<q>%s</q>]]', table.concat(conditions, ' ')), | ||
Line 1,214: | Line 1,213: | ||
local j = 0 | local j = 0 | ||
local tag_match_stop | local tag_match_stop | ||
repeat -- Loop through the mod tags until a match is found. | repeat -- Loop through the mod tags until a match is found. | ||
j = j+1 | j = j+1 | ||
Line 1,230: | Line 1,228: | ||
if tag_match_add then | if tag_match_add then | ||
for | local mod_scope = 'Global' | ||
for subobject, subobject_val in pairs(mod_data_subobject[pagename]) do | |||
end | 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] | local a = #item_mods[generation_type] | ||
Line 1,239: | Line 1,250: | ||
item_mods[generation_type][a+1][property] = results[generation_type][i][property] | item_mods[generation_type][a+1][property] = results[generation_type][i][property] | ||
end | end | ||
item_mods[generation_type][a+1]['Has mod scope'] = mod_scope | |||
end | end | ||
until tag_match_stop | until tag_match_stop | ||
Line 1,246: | Line 1,258: | ||
-- Display in table: | -- Display in table: | ||
-- | -- | ||
local headers = container | local headers = container | ||
headers | headers | ||
Line 1,257: | Line 1,268: | ||
for _, mod_properties in ipairs(item_mods[generation_type]) do | for _, mod_properties in ipairs(item_mods[generation_type]) do | ||
if mod_properties['Has mod group'] ~= last then | if mod_properties['Has mod group'] ~= last then | ||
local count = {} | local count = {} | ||
for _,n in ipairs(item_mods[generation_type]) do -- Check if there are multiple mod types in the same mod group: | for _,n in ipairs(item_mods[generation_type]) do -- Check if there are multiple mod types in the same mod group: | ||
Line 1,274: | Line 1,284: | ||
tbl_caption = string.format('%s',g_frame:expandTemplate{title = 'c', args = {'mod', 'Mod group: ' .. mod_properties['Has mod group']}}) | tbl_caption = string.format('%s',g_frame:expandTemplate{title = 'c', args = {'mod', 'Mod group: ' .. mod_properties['Has mod group']}}) | ||
else | else | ||
tbl_caption = string.format('%s (%s)', g_frame:expandTemplate{title = 'c', args = {'mod', p.header(mod_properties['Has stat text'])}}, mod_properties['Has mod scope']) | |||
tbl_caption = string.format('%s (%s)', g_frame:expandTemplate{title = 'c', args = {'mod', p.header(mod_properties['Has stat text'])}}, | |||
end | end | ||
Revision as of 22:34, 19 October 2016
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 util = require('Module:Util')
local getArgs = require('Module:Arguments').getArgs
local game = require('Module:Game')
local m_item = require('Module:Item2')
local p = {}
-- ----------------------------------------------------------------------------
-- Utility / Helper functions
-- ----------------------------------------------------------------------------
local h = {}
-- 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 = {}
for _, data in ipairs(map) do
if data.func ~= nil then
data.func(data.name)
end
if data.property ~= nil then
properties[data.property] = g_args[data.name]
end
end
g_frame:callParserFunction('#set:', properties)
end
function h.create_header(row)
local stat = mw.html.create('span')
local text, nsub = mw.ustring.gsub(row['Has stat text'], '%d+', '?')
stat
:attr('class', 'mod-table-header-stat')
:wikitext(text)
:done()
local mgroup = mw.html.create('span')
mgroup
:attr('class', 'mod-table-header-modgroup')
:wikitext(row['Has mod group'])
:done()
local tbl = mw.html.create('table')
tbl
:attr('class', 'wikitable mw-collapsible mw-collapsed mod-table')
:tag('tr')
:tag('th')
:attr('class', 'mod-table-header')
:attr('colspan', g_args.colspan)
:tag('span')
:attr('class', 'mod-table-header-container')
:wikitext(tostring(stat) .. tostring(mgroup))
:done()
:done()
return tbl
end
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
-- ----------------------------------------------------------------------------
-- Templates
-- ----------------------------------------------------------------------------
--
-- Template: Mod
--
-- 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
g_args = getArgs(frame, {
parentFirst = true
})
g_frame = util.misc.get_frame(frame)
--
-- Validation & semantic properties
--
-- Validate single value properties and set them
local map = {
{
name = 'id',
property = 'Is mod',
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',
},
}
h.handle_mapped_property_args(map)
-- Validate & set multi value property
if g_args['tags'] == nil then
g_args['tags'] = {}
else
local tags = mw.text.split(g_args['tags'], ', ')
g_args['tags'] = tags
properties = {}
properties['Has tag'] = table.concat(tags, ';')
properties['+sep'] = ';'
util.smw.set(g_frame, properties)
end
-- Validate % set the stat subobjects
util.args.stats(g_args, {frame=g_frame})
-- Validate & set spawn weight subobjects
local i = 0
local id = nil
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
i = 0
id = nil
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
i = 0
local names = {}
local sell_prices = {}
repeat
i = i + 1
id = {
name = string.format('sell_price%s_name', i),
amount = string.format('sell_price%s_amount', i),
}
value = {
name = g_args[id.name],
amount = tonumber(g_args[id.amount]),
}
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('Do not specify a sell price item name multiple times. Instead adjust the amount')
else
names[value.name] = true
end
properties = {}
properties['Has sell price item name'] = value.name
properties['Has sell price amount'] = value.amount
util.smw.subobject(g_frame, 'sell price ' .. value.name, properties)
sell_prices[#sell_prices+1] = value
else
error ('Both ' .. id.name .. ' and ' .. id.amount .. ' must be specified')
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 _, data in ipairs(map) do
local text
if data.display == nil then
text = g_args[data.name]
else
text = data.display(g_args[data.name])
end
tbl
:tag('tr')
:tag('th')
:wikitext(string.format('[[Property:%s|%s]]', data.property, data.wikitext))
:done()
:tag('td')
:wikitext(text)
:done()
:done()
:done()
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
tbl = container:tag('table')
tbl
:attr('class', 'wikitable sortable')
:tag('tr')
:tag('th')
:attr('colspan', 4)
:wikitext('Stats')
:done()
:done()
:tag('tr')
:tag('th')
:wikitext('[[Property:Is stat number|#]]')
:done()
:tag('th')
:wikitext('[[Property:Has stat id|Stat Id]]')
:done()
:tag('th')
:wikitext('[[Property:Has minimum stat value|Minimum]]')
:done()
:tag('th')
:wikitext('[[Property:Has maximum stat value|Maximum]]')
:done()
:done()
:done()
for i=1, 5 do
local value = {
id = g_args['stat' .. i .. '_id'],
min = g_args['stat' .. i .. '_min'],
max = g_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('Spawn Weights')
:done()
:done()
:tag('tr')
:tag('th')
:wikitext('[[Property:Is tag number|#]]')
:done()
:tag('th')
:wikitext('[[Property:Has tag|Tag]]')
:done()
:tag('th')
:wikitext('[[Property:Has spawn weight|Weight]]')
:done()
:done()
:done()
i = 0
value = nil
repeat
i = i + 1
value = {
tag = g_args[string.format('spawn_weight%s_tag', i)],
value = g_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('Generation Weights')
:done()
:done()
:tag('tr')
:tag('th')
:wikitext('[[Property:Is tag number|#]]')
:done()
:tag('th')
:wikitext('[[Property:Has tag|Tag]]')
:done()
:tag('th')
:wikitext('[[Property:Has generation weight|Weight]]')
:done()
:done()
:done()
i = 0
value = nil
repeat
i = i + 1
value = {
tag = g_args[string.format('generation_weight%s_tag', i)],
value = g_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('Modifier sell price')
:done()
:done()
:tag('tr')
:tag('th')
:wikitext('[[Property:Has sell price amount|#]]')
:done()
:tag('th')
:wikitext('[[Property:Has sell price item name|Item]]')
:done()
:done()
:done()
for i, value in ipairs(sell_prices) do
tbl
:tag('tr')
:tag('td')
:wikitext(value.amount)
:done()
:tag('td')
:wikitext(m_item.item_link{item_name_exact=value.name})
:done()
:done()
end
-- Generic messages on the page
out = {}
if mw.ustring.find(g_args['id'], '_') then
out[#out+1] = g_frame:expandTemplate{ title = 'Incorrect title', args = { title=g_args['id'] } } .. '\n\n\n'
end
if g_args['name'] then
out[#out+1] = string.format("'''%s''' is the internal id of modifier '''%s'''.\n", g_args['id'], g_args['name'])
else
out[#out+1] = string.format("'''%s''' is the internal id of an unnamed modifier.\n", g_args['id'], g_args['name'])
end
-- Categories
cats = {'Mods'}
-- Done -> output
return tostring(container) .. 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.
-- 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'}
-- 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']),
},
-- [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']
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
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
--
-- Display in table:
--
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
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',g_frame:expandTemplate{title = 'c', args = {'mod', 'Mod group: ' .. mod_properties['Has mod group']}})
else
tbl_caption = string.format('%s (%s)', g_frame:expandTemplate{title = 'c', args = {'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: %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
end
out[#out+1] = tostring(container)
end
return table.concat(out,'')
end
return p