Module:Mod: Difference between revisions
Jump to navigation
Jump to search
>Illviljan (Tags on items don't have any priority order anymore, to fix issue with bow mods. Tags on modifiers still have.) |
m (88 revisions imported) |
||
(78 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
-- | ------------------------------------------------------------------------------- | ||
-- 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 | |||
local | -- 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 | local i18n = cfg.i18n | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
-- | -- Helper functions | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
local h = {} | 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 | |||
function h. | |||
end | end | ||
return f_item_table(args) | |||
end | end | ||
function h. | 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, | |||
if | [args.table_map.fields.ordinal.field] = i, | ||
[args.table_map.fields.tag.field] = tag, | |||
[args.table_map.fields.value.field] = value, | |||
}) | |||
end | end | ||
end | end | ||
end | end | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Line 110: | Line 83: | ||
-- | -- | ||
-- | local mod_map = { | ||
function | 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'}, | |||
name = ' | { | ||
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, | ||
name = | }, | ||
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 | -- 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 | |||
-- Validate | |||
local i | |||
local | |||
local | |||
local value = { | local id = {} | ||
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 | 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 | 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 | 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 | end | ||
until value == nil | |||
until value | |||
-- 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'} | |||
-- | -- | ||
Line 313: | Line 377: | ||
local container = mw.html.create('div') | local container = mw.html.create('div') | ||
:addClass('modbox') | |||
: | |||
-- core stats | -- core stats | ||
local tbl = container:tag('table') | local tbl = container:tag('table') | ||
:addClass('wikitable') | |||
: | |||
for _, | for _, key in ipairs(mod_map.main.display_order) do | ||
local text | local data = mod_map.main.fields[key] | ||
if data.display == | local text = tpl_args[key] | ||
if type(data.display) == 'function' then | |||
text = data.display(text) | |||
text = data.display( | |||
end | end | ||
tbl | tbl | ||
:tag('tr') | :tag('tr') | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(data.wikitext) | ||
:done() | :done() | ||
:tag('td') | :tag('td') | ||
Line 341: | Line 401: | ||
:done() | :done() | ||
end | end | ||
-- stat table | -- stat table | ||
Line 357: | Line 406: | ||
tbl = container:tag('table') | tbl = container:tag('table') | ||
tbl | tbl | ||
: | :addClass('wikitable sortable') | ||
:tag('tr') | :tag('tr') | ||
:tag('th') | :tag('th') | ||
:attr('colspan', 4) | :attr('colspan', 4) | ||
:wikitext( | :wikitext(i18n.data_sheet.stats) | ||
:done() | :done() | ||
:done() | :done() | ||
:tag('tr') | :tag('tr') | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.ordinal) | ||
:done() | :done() | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.stat_id) | ||
:done() | :done() | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.min) | ||
:done() | :done() | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.max) | ||
:done() | :done() | ||
:done() | :done() | ||
:done() | :done() | ||
for i=1, | for i=1, #tpl_args.stats do | ||
local value = { | local value = { | ||
id = | id = tpl_args['stat' .. i .. '_id'], | ||
min = | min = tpl_args['stat' .. i .. '_min'], | ||
max = | max = tpl_args['stat' .. i .. '_max'], | ||
} | } | ||
Line 411: | Line 460: | ||
tbl = container:tag('table') | tbl = container:tag('table') | ||
tbl | tbl | ||
: | :addClass('wikitable sortable') | ||
:tag('tr') | :tag('tr') | ||
:tag('th') | :tag('th') | ||
:attr('colspan', 3) | :attr('colspan', 3) | ||
:wikitext( | :wikitext(i18n.data_sheet.spawn_weights) | ||
:done() | :done() | ||
:done() | :done() | ||
:tag('tr') | :tag('tr') | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.ordinal) | ||
:done() | :done() | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.tag) | ||
:done() | :done() | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.weight) | ||
:done() | :done() | ||
:done() | :done() | ||
Line 432: | Line 481: | ||
i = 0 | i = 0 | ||
value = nil | local value = nil | ||
repeat | repeat | ||
i = i + 1 | i = i + 1 | ||
value = { | value = { | ||
tag = | tag = tpl_args[string.format('spawn_weight%s_tag', i)], | ||
value = | value = tpl_args[string.format('spawn_weight%s_value', i)], | ||
} | } | ||
Line 461: | Line 510: | ||
tbl = container:tag('table') | tbl = container:tag('table') | ||
tbl | tbl | ||
: | :addClass('wikitable sortable') | ||
:tag('tr') | :tag('tr') | ||
:tag('th') | :tag('th') | ||
:attr('colspan', 3) | :attr('colspan', 3) | ||
:wikitext( | :wikitext(i18n.data_sheet.generation_weights) | ||
:done() | :done() | ||
:done() | :done() | ||
:tag('tr') | :tag('tr') | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.ordinal) | ||
:done() | :done() | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.tag) | ||
:done() | :done() | ||
:tag('th') | :tag('th') | ||
:wikitext( | :wikitext(i18n.data_sheet.weight) | ||
:done() | :done() | ||
:done() | :done() | ||
Line 486: | Line 535: | ||
i = i + 1 | i = i + 1 | ||
value = { | value = { | ||
tag = | tag = tpl_args[string.format('generation_weight%s_tag', i)], | ||
value = | value = tpl_args[string.format('generation_weight%s_value', i)], | ||
} | } | ||
Line 507: | Line 556: | ||
until value.tag == nil | 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 | 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' | |||
if | |||
out[#out+1] = | |||
end | end | ||
if tpl_args['name'] then | |||
out[#out+1] = string.format(i18n.sections.intro_named_id, tpl_args['id'], tpl_args['name']) | |||
else | else | ||
out[#out+1] = string.format(i18n.sections.intro_unnamed_id, tpl_args['id']) | |||
end | 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) | |||
:tag(' | |||
:wikitext( | |||
:done() | :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 | end | ||
-- Categories | |||
local cats = {i18n.categories.mods} | |||
-- Done -> output | |||
return tostring( | return tostring(container) .. m_util.misc.add_category(cats) .. '\n' .. table.concat(out) | ||
end | 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 | return p |
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