Module:Mod: Difference between revisions
Jump to navigation
Jump to search
>Illviljan (Modifier drop down list moved to module:modifier table. Removed old mod list.) |
m (88 revisions imported) |
||
(26 intermediate revisions by 6 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_util = require('Module:Util') | ||
local | local m_cargo = require('Module:Cargo') | ||
local | -- Should we use the sandbox version of our submodules? | ||
local use_sandbox = m_util.misc.maybe_sandbox('Mod') | |||
local | 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 = {} | 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 | |||
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 | |||
error(string.format( | 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 | 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 | ||
end | end | ||
-- ---------------------------------------------------------------------------- | -- ---------------------------------------------------------------------------- | ||
Line 142: | Line 86: | ||
main = { | main = { | ||
table = 'mods', | 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 = { | fields = { | ||
id = { | id = { | ||
name = | name = 'id', | ||
field = | field = 'id', | ||
type = 'String', | type = 'String', | ||
wikitext = ' | 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 = | name = 'name', | ||
field = | field = 'name', | ||
type = 'String', | type = 'String', | ||
wikitext = | wikitext = i18n.data_sheet.name, | ||
}, | }, | ||
mod_groups = { | |||
name = | name = 'mod_groups', | ||
field = | field = 'mod_groups', | ||
type = 'String', | type = 'List (,) of String', | ||
wikitext = ' | wikitext = i18n.data_sheet.mod_groups, | ||
display = function (value) | |||
return table.concat(value, ', ') | |||
end, | |||
default = {}, | |||
}, | }, | ||
mod_type = { | mod_type = { | ||
name = | name = 'mod_type', | ||
field = | field = 'mod_type', | ||
type = 'String', | type = 'String', | ||
wikitext = | wikitext = i18n.data_sheet.mod_type, | ||
}, | }, | ||
domain = { | domain = { | ||
name = | name = 'domain', | ||
field = | field = 'domain', | ||
type = 'Integer', | type = 'Integer', | ||
wikitext = 'Mod domain', | wikitext = 'Mod domain', | ||
display = function (value) | display = function (value) | ||
return | return string.format(i18n.data_sheet.domain_fmt, m_game.constants.mod.domains[value]['short_upper'], value) | ||
end, | end, | ||
}, | }, | ||
generation_type = { | generation_type = { | ||
name = | name = 'generation_type', | ||
field = | field = 'generation_type', | ||
type = 'Integer', | type = 'Integer', | ||
wikitext = i18n.data_sheet.generation_type, | |||
display = function (value) | display = function (value) | ||
return | return string.format(i18n.data_sheet.generation_type_fmt, m_game.constants.mod.generation_types[value]['short_upper'], value) | ||
end, | end, | ||
}, | }, | ||
required_level = { | required_level = { | ||
name = | name = 'required_level', | ||
field = | field = 'required_level', | ||
type = 'Integer', | type = 'Integer', | ||
wikitext = i18n.data_sheet.required_level, | |||
}, | }, | ||
stat_text = { | stat_text = { | ||
name = | name = 'stat_text', | ||
field = | field = 'stat_text', | ||
type = 'Text', | type = 'Text', | ||
wikitext = | wikitext = i18n.data_sheet.stat_text, | ||
}, | }, | ||
stat_text_raw = { | stat_text_raw = { | ||
Line 206: | Line 169: | ||
field = 'stat_text_raw', | field = 'stat_text_raw', | ||
type = 'Text', | type = 'Text', | ||
func = function(tpl_args, | func = function (tpl_args, value) | ||
if tpl_args.stat_text then | 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 | end | ||
return | return value | ||
end | end | ||
}, | }, | ||
granted_buff_id = { | granted_buff_id = { | ||
name = | name = 'granted_buff_id', | ||
field = | field = 'granted_buff_id', | ||
type = 'String', | type = 'String', | ||
wikitext = | wikitext = i18n.data_sheet.granted_buff_id, | ||
}, | }, | ||
granted_buff_value = { | granted_buff_value = { | ||
name = | name = 'granted_buff_value', | ||
field = | field = 'granted_buff_value', | ||
type = 'Integer', | type = 'Integer', | ||
wikitext = | wikitext = i18n.data_sheet.granted_buff_value, | ||
}, | }, | ||
granted_skill = { | granted_skill = { | ||
name = | name = 'granted_skill', | ||
field = | field = 'granted_skill', | ||
type = 'String', | type = 'String', | ||
wikitext = | wikitext = i18n.data_sheet.granted_skill, | ||
}, | }, | ||
tags = { | tags = { | ||
name = | name = 'tags', | ||
field = | field = 'tags', | ||
type = 'List (,) of String', | type = 'List (,) of String', | ||
wikitext = 'Tags', | wikitext = 'Tags', | ||
display = function (value) | |||
return table.concat(value, ', ') | |||
end, | 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', | |||
}, | }, | ||
}, | }, | ||
Line 264: | Line 272: | ||
fields = { | fields = { | ||
name = { | name = { | ||
name = | name = 'name', | ||
field = | field = 'name', | ||
type = 'String', | type = 'String', | ||
func = function (value) return value end, | func = function (value) return value end, | ||
}, | }, | ||
amount = { | amount = { | ||
name = | name = 'amount', | ||
field = | field = 'amount', | ||
type = 'Integer', | type = 'Integer', | ||
func = tonumber, | func = tonumber, | ||
Line 279: | Line 287: | ||
} | } | ||
-- ---------------------------------------------------------------------------- | |||
-- Main functions | |||
-- ---------------------------------------------------------------------------- | |||
-- p.mod{id = "LocalIncreasedPhysicalDamagePercentUniqueOneHandSword2", name = "", | 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 | -- 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 | |||
m_util.args.stats(tpl_args | |||
for _, stat_data in pairs(tpl_args.stats) do | for _, stat_data in pairs(tpl_args.stats) do | ||
m_cargo.store({ | |||
_table = 'mod_stats', | _table = 'mod_stats', | ||
id = stat_data.id, | id = stat_data.id, | ||
Line 347: | Line 315: | ||
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 = {} | ||
Line 365: | Line 335: | ||
local id = {} | local id = {} | ||
value = {} | local value = {} | ||
for key, data in pairs(mod_map.mod_sell_prices.fields) do | for key, data in pairs(mod_map.mod_sell_prices.fields) do | ||
id[key] = string.format('%s%s_%s', | id[key] = string.format('%s%s_%s', 'sell_price', i, data.name) | ||
value[key] = data.func(tpl_args[id[key]]) | value[key] = data.func(tpl_args[id[key]]) | ||
end | end | ||
Line 386: | Line 356: | ||
cargo_data[data.field] = value[key] | cargo_data[data.field] = value[key] | ||
end | end | ||
m_cargo.store(cargo_data) | |||
sell_prices[#sell_prices+1] = value | sell_prices[#sell_prices+1] = value | ||
Line 394: | Line 364: | ||
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 400: | 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 _, key in ipairs(mod_map.main. | for _, key in ipairs(mod_map.main.display_order) do | ||
local data = mod_map.main.fields[key] | local data = mod_map.main.fields[key] | ||
local text | local text = tpl_args[key] | ||
if data.display == | if type(data.display) == 'function' then | ||
text = data.display(text) | |||
text = data.display( | |||
end | end | ||
tbl | tbl | ||
:tag('tr') | :tag('tr') | ||
Line 429: | Line 401: | ||
:done() | :done() | ||
end | end | ||
-- stat table | -- stat table | ||
Line 445: | 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() | ||
Line 499: | 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 520: | Line 481: | ||
i = 0 | i = 0 | ||
value = nil | local value = nil | ||
repeat | repeat | ||
i = i + 1 | i = i + 1 | ||
Line 549: | 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 598: | 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 629: | Line 590: | ||
-- Generic messages on the page | -- Generic messages on the page | ||
out = {} | local out = {} | ||
if mw.ustring.find(tpl_args['id'], '_') then | 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 tpl_args['name'] then | 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 | |||
-- 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 | end | ||
-- Categories | -- Categories | ||
cats = { | local cats = {i18n.categories.mods} | ||
-- Done -> output | -- Done -> output | ||
return tostring(container) .. m_util.misc.add_category(cats) .. '\n' .. table.concat(out) | 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
This module is used on 34000+ pages.
To avoid major disruption and server load, do not make unnecessary edits to this module. Test changes to this module first using its /sandbox and /testcases subpages or your user space. All of the changes can then be applied to this module in a single edit.
Consider discussing changes on the talk page or on Discord before implementing them.
Module for handling for modifiers with Cargo support.
List of currently implemented templates
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