Module:Mod: Difference between revisions
Jump to navigation
Jump to search
(Strip html tags from `stat_text_raw` field) |
m (88 revisions imported) |
||
(One intermediate revision by the same user not shown) | |||
Line 171: | Line 171: | ||
func = function (tpl_args, value) | func = function (tpl_args, value) | ||
if tpl_args.stat_text then | if tpl_args.stat_text then | ||
value = m_util.string. | -- Strip wikilinks and html, but keep any line break tags | ||
value = m_util.string.strip_wikilinks(tpl_args.stat_text) | |||
value = mw.ustring.gsub(value, '<br */?>', '�') | |||
value = m_util.string.strip_html(value) | |||
) | value = mw.ustring.gsub(value, '�', '<br>') | ||
end | end | ||
return value | return value |
Latest revision as of 20:25, 25 September 2024
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:Mod
--
-- This module implements Template:Mod
-------------------------------------------------------------------------------
require('Module:No globals')
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')
-- Should we use the sandbox version of our submodules?
local use_sandbox = m_util.misc.maybe_sandbox('Mod')
local m_game = use_sandbox and mw.loadData('Module:Game/sandbox') or mw.loadData('Module:Game')
-- Lazy loading
local f_item_table -- require('Module:Item table').item_table
-- The cfg table contains all localisable strings and configuration, to make it
-- easier to port this module to another wiki.
local cfg = use_sandbox and mw.loadData('Module:Mod/config/sandbox') or mw.loadData('Module:Mod/config')
local i18n = cfg.i18n
-- ----------------------------------------------------------------------------
-- Helper functions
-- ----------------------------------------------------------------------------
local h = {}
-- Lazy loading for Module:Item table
function h.item_table(args)
if not f_item_table then
f_item_table = require('Module:Item table').item_table
end
return f_item_table(args)
end
function h.set_weights(tpl_args, args)
-- Parses a weighted pair of lists and sets properties
--
-- tpl_args: argument table to work with
-- args:
-- prefix - input prefix for parsing the arguments from tpl_args
-- table_map - cargo table map
args = args or {}
for i=1, math.huge do -- repeat until no more weights are found
local prefix = args.prefix .. i
local params = {
tag = string.format('%s_tag', prefix),
value = string.format('%s_value', prefix),
}
local tag = tpl_args[params.tag]
local value = tpl_args[params.value]
if tag == nil and value == nil then
break
end
if tag == nil or value == nil then
error(string.format(i18n.errors.invalid_weight, params.tag, params.value))
end
value = m_util.cast.number(value, {min = 0})
-- Store to cargo table unless tag = default and value = 0
if tag ~= 'default' or value ~= 0 then
m_cargo.store({
_table = args.table_map.table,
[args.table_map.fields.ordinal.field] = i,
[args.table_map.fields.tag.field] = tag,
[args.table_map.fields.value.field] = value,
})
end
end
end
-- ----------------------------------------------------------------------------
-- Templates
-- ----------------------------------------------------------------------------
--
-- Template: Mod
--
local mod_map = {
main = {
table = 'mods',
display_order = {'id', 'name', 'mod_groups', 'mod_type', 'domain', 'generation_type', 'required_level', 'stat_text', 'granted_buff_id', 'granted_buff_value', 'granted_skill', 'tags', 'tier_text'},
order = {'id', 'name', 'mod_groups', '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.data_sheet.id,
func = function (tpl_args, value)
-- Validate that the id is unique
local results = m_cargo.query(
{'mods'},
{'mods._pageName'},
{
where = string.format(
'mods.id = "%s" AND mods._pageName != "%s"',
value,
m_cargo.addslashes(mw.title.getCurrentTitle().prefixedText)
)
}
)
if #results > 0 then
error(string.format(i18n.errors.duplicate_mod_id, results[1]['mods._pageName']))
end
return value
end
},
name = {
name = 'name',
field = 'name',
type = 'String',
wikitext = i18n.data_sheet.name,
},
mod_groups = {
name = 'mod_groups',
field = 'mod_groups',
type = 'List (,) of String',
wikitext = i18n.data_sheet.mod_groups,
display = function (value)
return table.concat(value, ', ')
end,
default = {},
},
mod_type = {
name = 'mod_type',
field = 'mod_type',
type = 'String',
wikitext = i18n.data_sheet.mod_type,
},
domain = {
name = 'domain',
field = 'domain',
type = 'Integer',
wikitext = 'Mod domain',
display = function (value)
return string.format(i18n.data_sheet.domain_fmt, m_game.constants.mod.domains[value]['short_upper'], value)
end,
},
generation_type = {
name = 'generation_type',
field = 'generation_type',
type = 'Integer',
wikitext = i18n.data_sheet.generation_type,
display = function (value)
return string.format(i18n.data_sheet.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.data_sheet.required_level,
},
stat_text = {
name = 'stat_text',
field = 'stat_text',
type = 'Text',
wikitext = i18n.data_sheet.stat_text,
},
stat_text_raw = {
name = nil,
field = 'stat_text_raw',
type = 'Text',
func = function (tpl_args, value)
if tpl_args.stat_text then
-- Strip wikilinks and html, but keep any line break tags
value = m_util.string.strip_wikilinks(tpl_args.stat_text)
value = mw.ustring.gsub(value, '<br */?>', '�')
value = m_util.string.strip_html(value)
value = mw.ustring.gsub(value, '�', '<br>')
end
return value
end
},
granted_buff_id = {
name = 'granted_buff_id',
field = 'granted_buff_id',
type = 'String',
wikitext = i18n.data_sheet.granted_buff_id,
},
granted_buff_value = {
name = 'granted_buff_value',
field = 'granted_buff_value',
type = 'Integer',
wikitext = i18n.data_sheet.granted_buff_value,
},
granted_skill = {
name = 'granted_skill',
field = 'granted_skill',
type = 'String',
wikitext = i18n.data_sheet.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.data_sheet.tier_text,
},
},
},
mod_stats = {
table = 'mod_stats',
fields = {
id = {
field = 'id',
type = 'String',
},
min = {
field = 'min',
type = 'Integer',
},
max = {
field = 'max',
type = 'Integer',
},
},
},
mod_spawn_weights = {
table = 'mod_spawn_weights',
fields = {
ordinal = {
field = 'ordinal',
type = 'Integer',
},
tag = {
field = 'tag',
type = 'String',
},
value = {
field = 'value',
type = 'Integer',
},
},
},
mod_generation_weights = {
table = 'mod_generation_weights',
fields = {
ordinal = {
field = 'ordinal',
type = 'Integer',
},
tag = {
field = 'tag',
type = 'String',
},
value = {
field = 'value',
type = 'Integer',
},
},
},
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,
},
},
},
}
-- ----------------------------------------------------------------------------
-- Main functions
-- ----------------------------------------------------------------------------
local function _mod(tpl_args)
-- p.mod{id = "LocalIncreasedPhysicalDamagePercentUniqueOneHandSword2", name = "", mod_groups = "LocalPhysicalDamagePercent, Dexterity", 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"}
--
-- Validate and store
--
-- Validate single value properties and set them
m_cargo.store_mapped_args{
tpl_args = tpl_args,
table_map = mod_map.main,
}
-- Validate and store stats
m_util.args.stats(tpl_args)
for _, stat_data in pairs(tpl_args.stats) do
m_cargo.store({
_table = 'mod_stats',
id = stat_data.id,
min = stat_data.min,
max = stat_data.max,
})
end
-- Validate and store spawn weights
h.set_weights(tpl_args, {
prefix = 'spawn_weight',
table_map = mod_map.mod_spawn_weights
})
-- Validate and store generation weights
h.set_weights(tpl_args, {
prefix = 'generation_weight',
table_map = mod_map.mod_generation_weights
})
-- Validate and store mod sell values
local i = 0
local names = {}
local sell_prices = {}
repeat
i = i + 1
local id = {}
local 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(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
-- Attach to tables
mw.getCurrentFrame():expandTemplate{title = 'Template:Mod/cargo/mods/attach'}
mw.getCurrentFrame():expandTemplate{title = 'Template:Mod/cargo/mod stats/attach'}
mw.getCurrentFrame():expandTemplate{title = 'Template:Mod/cargo/mod spawn weights/attach'}
mw.getCurrentFrame():expandTemplate{title = 'Template:Mod/cargo/mod generation weights/attach'}
mw.getCurrentFrame():expandTemplate{title = 'Template:Mod/cargo/mod sell prices/attach'}
--
-- Display
--
local container = mw.html.create('div')
:addClass('modbox')
-- core stats
local tbl = container:tag('table')
:addClass('wikitable')
for _, key in ipairs(mod_map.main.display_order) do
local data = mod_map.main.fields[key]
local text = tpl_args[key]
if type(data.display) == 'function' then
text = data.display(text)
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
:addClass('wikitable sortable')
:tag('tr')
:tag('th')
:attr('colspan', 4)
:wikitext(i18n.data_sheet.stats)
:done()
:done()
:tag('tr')
:tag('th')
:wikitext(i18n.data_sheet.ordinal)
:done()
:tag('th')
:wikitext(i18n.data_sheet.stat_id)
:done()
:tag('th')
:wikitext(i18n.data_sheet.min)
:done()
:tag('th')
:wikitext(i18n.data_sheet.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
:addClass('wikitable sortable')
:tag('tr')
:tag('th')
:attr('colspan', 3)
:wikitext(i18n.data_sheet.spawn_weights)
:done()
:done()
:tag('tr')
:tag('th')
:wikitext(i18n.data_sheet.ordinal)
:done()
:tag('th')
:wikitext(i18n.data_sheet.tag)
:done()
:tag('th')
:wikitext(i18n.data_sheet.weight)
:done()
:done()
:done()
i = 0
local 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
:addClass('wikitable sortable')
:tag('tr')
:tag('th')
:attr('colspan', 3)
:wikitext(i18n.data_sheet.generation_weights)
:done()
:done()
:tag('tr')
:tag('th')
:wikitext(i18n.data_sheet.ordinal)
:done()
:tag('th')
:wikitext(i18n.data_sheet.tag)
:done()
:tag('th')
:wikitext(i18n.data_sheet.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
:addClass('wikitable sortable')
:tag('tr')
:tag('th')
:attr('colspan', 2)
:wikitext(i18n.data_sheet.sell_price)
:done()
:done()
:tag('tr')
:tag('th')
:wikitext(i18n.data_sheet.ordinal)
:done()
:tag('th')
:wikitext(i18n.data_sheet.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
local out = {}
if mw.ustring.find(tpl_args['id'], '_') then
out[#out+1] = mw.getCurrentFrame():expandTemplate{ title = 'Incorrect title', args = { title=tpl_args['id'] } } .. '\n\n\n'
end
if tpl_args['name'] then
out[#out+1] = string.format(i18n.sections.intro_named_id, tpl_args['id'], tpl_args['name'])
else
out[#out+1] = string.format(i18n.sections.intro_unnamed_id, tpl_args['id'])
end
-- Item usage
local items = m_cargo.query(
{'item_mods'},
{'item_mods._pageName=page'},
{
where = string.format(
'item_mods.id = "%s"',
tpl_args['id']
)
}
)
if #items > 0 then
local html = mw.html.create()
:tag('h2')
:wikitext(i18n.sections.items)
:done()
:tag('p')
:wikitext(i18n.sections.used_by_items)
:done()
out[#out+1] = tostring(html)
out[#out+1] = h.item_table{
q_tables = 'items',
q_where = string.format(
'items._pageName IN ("%s")',
table.concat(m_util.table.column(items, 'page'), '","')
),
q_orderBy = 'items.name ASC',
}
end
-- Categories
local cats = {i18n.categories.mods}
-- Done -> output
return tostring(container) .. m_util.misc.add_category(cats) .. '\n' .. table.concat(out)
end
-- ----------------------------------------------------------------------------
-- Exported functions
-- ----------------------------------------------------------------------------
local p = {}
p.table_main = m_cargo.declare_factory{data=mod_map.main}
p.table_mod_stats = m_cargo.declare_factory{data=mod_map.mod_stats}
p.table_mod_spawn_weights = m_cargo.declare_factory{data=mod_map.mod_spawn_weights}
p.table_mod_generation_weights = m_cargo.declare_factory{data=mod_map.mod_generation_weights}
p.table_mod_sell_prices = m_cargo.declare_factory{data=mod_map.mod_sell_prices}
--
-- Template:Mod
--
p.mod = m_util.misc.invoker_factory(_mod, {
wrappers = 'Template:Mod',
})
return p