Module:Mod: Difference between revisions
Jump to navigation
Jump to search
>Illviljan (Item tags order seems to be reversed now in the item template after 3.0.0. Therefore there's no need for this reversing function anymore. It was mainly there to possibly improve performance.) |
m (88 revisions imported) |
||
(47 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 | |||
-- easier to port this module to another wiki. | |||
local | 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 111: | 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) | |||
-- Validate | 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 | end | ||
-- Validate | -- Validate and store spawn weights | ||
h.set_weights(tpl_args, { | |||
prefix = 'spawn_weight', | |||
table_map = mod_map.mod_spawn_weights | |||
}) | }) | ||
-- Validate | -- Validate and store generation weights | ||
h.set_weights(tpl_args, { | |||
prefix = 'generation_weight', | |||
table_map = mod_map.mod_generation_weights | |||
}) | }) | ||
-- Validate | -- Validate and store mod sell values | ||
i = 0 | local i = 0 | ||
local names = {} | local names = {} | ||
local sell_prices = {} | local sell_prices = {} | ||
repeat | repeat | ||
i = i + 1 | i = i + 1 | ||
id = { | |||
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 | if value.name == nil and value.amount == nil then | ||
Line 247: | Line 345: | ||
elseif value.name ~= nil and value.amount ~= nil then | elseif value.name ~= nil and value.amount ~= nil then | ||
if names[value.name] then | if names[value.name] then | ||
error( | error(i18n.errors.sell_price_duplicate_name) | ||
else | else | ||
names[value.name] = true | names[value.name] = true | ||
end | end | ||
local cargo_data = { | |||
_table = mod_map.mod_sell_prices.table, | |||
} | |||
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 | sell_prices[#sell_prices+1] = value | ||
else | else | ||
error ( | error (string.format(i18n.errors.sell_price_missing_arguments, id.name, id.amount)) | ||
end | end | ||
until value == nil | 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'} | |||
-- | -- | ||
Line 270: | 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 298: | Line 401: | ||
:done() | :done() | ||
end | end | ||
-- stat table | -- stat table | ||
Line 314: | 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 368: | 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 389: | 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 418: | 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 443: | 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 467: | Line 559: | ||
tbl = container:tag('table') | tbl = container:tag('table') | ||
tbl | tbl | ||
: | :addClass('wikitable sortable') | ||
:tag('tr') | :tag('tr') | ||
:tag('th') | :tag('th') | ||
:attr('colspan', 2) | :attr('colspan', 2) | ||
:wikitext( | :wikitext(i18n.data_sheet.sell_price) | ||
: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.item) | ||
:done() | :done() | ||
:done() | :done() | ||
Line 491: | Line 583: | ||
:done() | :done() | ||
:tag('td') | :tag('td') | ||
:wikitext( | :wikitext(string.format('[[%s]]', value.name)) | ||
:done() | :done() | ||
:done() | :done() | ||
Line 498: | Line 590: | ||
-- Generic messages on the page | -- Generic messages on the page | ||
out = {} | local out = {} | ||
if mw.ustring.find( | if mw.ustring.find(tpl_args['id'], '_') then | ||
out[#out+1] = | out[#out+1] = mw.getCurrentFrame():expandTemplate{ title = 'Incorrect title', args = { title=tpl_args['id'] } } .. '\n\n\n' | ||
end | end | ||
if | if tpl_args['name'] then | ||
out[#out+1] = string.format( | out[#out+1] = string.format(i18n.sections.intro_named_id, tpl_args['id'], tpl_args['name']) | ||
else | else | ||
out[#out+1] = string.format( | 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