(Attempt to define monster rarity. Added monster skill links. Added monster screenshot. Moved stuff around in the infobox to resemble the old infobox more. Show monster type id. Check for bosses.) |
Нет описания правки |
||
Строка 47: | Строка 47: | ||
intro = { |
intro = { |
||
− | text_with_name = "'''%s''' |
+ | text_with_name = "'''%s''' — это внутренний идентификатор [[монстр]]а [[%s|%s]]. ", |
− | text_without_name = "'''%s''' |
+ | text_without_name = "'''%s''' — это внутренний идентификатор безымянного [[монстр]]а. ", |
}, |
}, |
||
Версия от 20:00, 13 октября 2019
Этот модуль зависит от следующих других модулей: |
Модуль и его настройки связанны с монстрами.
Подстраницы
- Модуль:Monster/doc
- Модуль:Monster/monster base stats
- Модуль:Monster/monster base stats/doc
- Модуль:Monster/monster life scaling
- Модуль:Monster/monster life scaling/doc
- Модуль:Monster/monster map multipliers
- Модуль:Monster/monster map multipliers/doc
- Модуль:Monster/monster resistances
- Модуль:Monster/monster resistances/doc
- Модуль:Monster/monster types
- Модуль:Monster/monster types/doc
Вышеприведенная документация извлекается из Модуль:Monster/doc.
Редакторы могут экспериментировать в sandbox этого модуля и в testcases страницах.
Подстраницы этого модуля.
Редакторы могут экспериментировать в sandbox этого модуля и в testcases страницах.
Подстраницы этого модуля.
-- ----------------------------------------------------------------------------
-- Imports
-- ----------------------------------------------------------------------------
local m_cargo = require('Module:Cargo')
local getArgs = require('Module:Arguments').getArgs
local m_util = require('Module:Util')
local m_game = require('Module:Game')
local f_skill_link = require('Module:Skill link').skill_link
local p = {}
-- ----------------------------------------------------------------------------
-- Strings
-- ----------------------------------------------------------------------------
local i18n = {
cats = {
data = 'Monster data'
},
tooltips = {
name = 'Название',
rarity = 'Редкость',
experience_multiplier = 'Базовый множитель опыта',
health_multiplier = 'Базовый множитель здоровья',
damage_multiplier = 'Базовый множитель урона',
attack_speed = 'Базовая скорость атаки',
critical_strike_chance = 'Базовый шанс критического удара',
minimum_attack_distance = 'Минимальное расстояние атаки',
maximum_attack_distance = 'Максимальное расстояние атаки',
difficulty = 'Акт',
resistances = 'Сопротивления',
part1 = '[[Акт 1|1]]-[[Акт 5|5]]',
part2 = '[[Акт 5|5]]-[[Акт 10|10]]',
maps = '[[Акт 10|10]]-',
fire = m_game.constants.damage_types.fire.short_upper,
cold = m_game.constants.damage_types.cold.short_upper,
lightning = m_game.constants.damage_types.lightning.short_upper,
chaos = m_game.constants.damage_types.chaos.short_upper,
stat_text = 'Свойства',
size = 'Размер',
model_size_multiplier = 'Множитель размера модели',
tags = 'Внутренние метки',
metadata_id = 'Metadata id',
monster_type_id = 'Monster type id',
areas = 'Области',
},
intro = {
text_with_name = "'''%s''' — это внутренний идентификатор [[монстр]]а [[%s|%s]]. ",
text_without_name = "'''%s''' — это внутренний идентификатор безымянного [[монстр]]а. ",
},
errors = {
invalid_rarity_id = 'The rarity id "%s" is invalid. Acceptable values are "normal", "magic", "rare" and "unique".',
},
}
-- ----------------------------------------------------------------------------
-- Helpers
-- ----------------------------------------------------------------------------
local h = {}
function h.add_mod_id(tpl_args, frame, value)
for _, id in ipairs(value or {}) do
if tpl_args._mods[id] == nil then
tpl_args._mods[id] = true
tpl_args._mods[#tpl_args._mods+1] = id
end
end
return value
end
function h.stat_calc(stats)
--[[
Calculates a modified stat.
Parameters
----------
stats : List
Associated List with added, increased and more
as keys.
Examples
--------
stats = {
added={6,4},
increased={100, 50}, -- [%]
more={20, 30}, -- [%]
}
= h.stat_calc(stats)
]]
local funcs = {
added=function(stats)
--[[
Sum the added terms.
]]
local out = 0
for _, v in ipairs(stats['added']) do
out = v + out
end
return out
end,
increased=function(stats)
--[[
Sum the increased terms.
Values should be in percent.
]]
local out = 1
for _, v in ipairs(stats['increased']) do
out = v/100 + out
end
return out
end,
more=function(stats)
--[[
Calculate the product of the more terms.
Values should be in percent.
]]
local out = 1
for _, v in ipairs(stats['more']) do
out = (1 + v/100) * out
end
return out
end,
}
local out = 1
for k, v in pairs(stats) do
if type(funcs[k]) == 'function' then
out = funcs[k](stats) * out
else
out = v * out
end
end
return out
end
h.stat_calc_verbose = function(stats)
--[[
Show how the stats list is calculated.
]]
local verbose_funcs = {
added = function(stats)
local st = {}
for _, v in ipairs(stats['added']) do
st[#st+1] = v/1
end
return string.format('(%s)', table.concat(st, ' + '))
end,
increased = function(stats)
local st = {}
for _, v in ipairs(stats['increased']) do
st[#st+1] = v/100
end
return string.format('(1 + %s)', table.concat(st, ' + '))
end,
more = function(stats)
local st = {}
for _, v in ipairs(stats['more']) do
st[#st+1] = string.format('(1 + %s)', v/100)
end
return string.format('(%s)', table.concat(st, ' * '))
end,
}
local out = {}
for k, v in pairs(stats) do
if type(verbose_funcs[k]) == 'function' then
out[#out+1] = verbose_funcs[k](stats)
else
out[#out+1] = string.format('%s', v)
end
end
return table.concat(out, ' * ')
end
function h.intro_text(tpl_args, frame)
--[[
Display an introductory text about the monster.
]]
local out = {}
if mw.ustring.find(tpl_args['metadata_id'], '_') then
out[#out+1] = frame:expandTemplate{
title='Incorrect title',
args = {title=tpl_args['id']}
}
end
if tpl_args['name'] then
out[#out+1] = string.format(
i18n.intro.text_with_name,
tpl_args['metadata_id'],
tpl_args['main_page'] or tostring(mw.title.getCurrentTitle()),
tpl_args['name']
)
else
out[#out+1] = string.format(
i18n.intro.text_without_name,
tpl_args['metadata_id']
)
end
return table.concat(out)
end
-- ----------------------------------------------------------------------------
-- Tables
-- ----------------------------------------------------------------------------
local tables = {}
tables.monsters = {
table = 'monsters',
order = {'metadata_id', 'tags', 'monster_type_id', 'mod_ids', 'part1_mod_ids', 'part2_mod_ids', 'endgame_mod_ids', 'skill_ids', 'name', 'size', 'minimum_attack_distance', 'maximum_attack_distance', 'model_size_multiplier', 'experience_multiplier', 'damage_multiplier', 'health_multiplier', 'critical_strike_chance', 'attack_speed', 'mods', 'is_boss', 'rarity_id', 'rarity'},
fields = {
metadata_id = {
field = 'metadata_id',
type = 'String',
func = function (tpl_args, frame, value)
tpl_args.monster_usages = m_cargo.query(
{'areas', 'maps'},
{
'areas.name',
'areas.id',
'areas.area_level',
'areas.boss_monster_ids',
'areas.main_page',
'areas._pageName',
'maps.area_level',
},
{
join='areas.id=maps.area_id',
where=string.format('areas.boss_monster_ids HOLDS "%s"', value),
}
)
return value
end,
},
monster_type_id = {
field = 'monster_type_id',
type = 'String',
func = function (tpl_args, frame, value)
tpl_args.monster_type = m_cargo.query(
{'monster_types', 'monster_resistances'},
{
'monster_types.tags',
'monster_types.armour_multiplier',
'monster_types.evasion_multiplier',
'monster_types.energy_shield_multiplier',
'monster_types.damage_spread',
'monster_resistances.part1_fire',
'monster_resistances.part1_cold',
'monster_resistances.part1_lightning',
'monster_resistances.part1_chaos',
'monster_resistances.part2_fire',
'monster_resistances.part2_cold',
'monster_resistances.part2_lightning',
'monster_resistances.part2_chaos',
'monster_resistances.maps_fire',
'monster_resistances.maps_cold',
'monster_resistances.maps_lightning',
'monster_resistances.maps_chaos'
},
{
join='monster_types.monster_resistance_id = monster_resistances.id',
where=string.format('monster_types.id = "%s"', value),
}
)[1]
if tpl_args.monster_type['monster_types.tags'] then
local tags = m_util.string.split(
tpl_args.monster_type['monster_types.tags'],
',%s+'
)
-- TODO: Maybe this can be fixed earlier?
if tpl_args.tags == nil then
tpl_args.tags = {}
end
for _, tag in ipairs(tags) do
tpl_args.tags[#tpl_args.tags+1] = tag
end
end
return value
end,
},
mod_ids = {
field = 'mod_ids',
type = 'List (,) of String',
func = h.add_mod_id,
},
part1_mod_ids = {
field = 'part1_mod_ids',
type = 'List (,) of String',
func = h.add_mod_id,
},
part2_mod_ids = {
field = 'part2_mod_ids',
type = 'List (,) of String',
func = h.add_mod_id,
},
endgame_mod_ids = {
field = 'endgame_mod_ids',
type = 'List (,) of String',
func = h.add_mod_id,
},
tags = {
field = 'tags',
type = 'List (,) of String',
},
skill_ids = {
field = 'skill_ids',
type = 'List (,) of String',
--TODO
},
-- add base type info or just parse it?
name = {
field = 'name',
type = 'String',
},
size = {
field = 'size',
type = 'Integer',
},
minimum_attack_distance = {
field = 'minimum_attack_distance',
type = 'Integer',
},
maximum_attack_distance = {
field = 'maximum_attack_distance',
type = 'Integer',
},
model_size_multiplier = {
field = 'model_size_multiplier',
type = 'Float',
},
experience_multiplier = {
field = 'experience_multiplier',
type = 'Float',
},
damage_multiplier = {
field = 'damage_multiplier',
type = 'Float',
},
health_multiplier = {
field = 'health_multiplier',
type = 'Float',
},
critical_strike_chance = {
field = 'critical_strike_chance',
type = 'Float',
},
attack_speed = {
field = 'attack_speed',
type = 'Float',
},
is_boss = {
field = 'is_boss',
type = 'Boolean',
func = function (tpl_args, frame)
-- If the monster is used in some area it's most likely
-- an unique boss:
if #tpl_args.monster_usages > 0 then
tpl_args.is_boss = true
else
tpl_args.is_boss = false
end
return tpl_args.is_boss
end,
},
rarity_id = {
field = 'rarity_id',
type = 'String',
func = function (tpl_args, frame)
--[[
Define the rarity of the monster. There's no obvious
parameter that can be datamined for this so this will
be mostly guess work.
]]
-- User defined rarity takes priority:
if tpl_args.rarity_id ~= nil then
if m_game.constants.rarities[tpl_args.rarity_id] == nil then
error(string.format(i18n.errors.invalid_rarity_id,
tostring(tpl_args.rarity_id)))
end
return tpl_args.rarity_id
end
-- If the monster is used in some area it's most likely
-- an unique boss:
if tpl_args.is_boss then
tpl_args.rarity_id = 'unique'
return tpl_args.rarity_id
end
-- If there are no mods it's probably a normal monster:
if #tpl_args._mods == 0 then
tpl_args.rarity_id = 'normal'
return tpl_args.rarity_id
end
-- Try to determine rarity from mods:
for _, modid in ipairs(tpl_args._mods) do
local mod = tpl_args._mod_data[modid]
-- Check if the mod contains the monster rarity stat:
for _, v in ipairs(mod) do
if v['mod_stats.id'] == 'monster_rarity' then
-- TODO: m_game rarity id does not match the stat:
local int_id = tonumber(v['mod_stats.max']) + 1
for k, row in pairs(m_game.constants.rarities) do
if int_id == row['id'] then
tpl_args.rarity_id = k
return tpl_args.rarity_id
end
end
end
end
end
-- If none of the mods contains the monster rarity
-- stat then it might be an unique:
if tpl_args.rarity_id == nil then
tpl_args.rarity_id = 'unique'
return tpl_args.rarity_id
end
end,
},
rarity = {
field = 'rarity',
type = 'String',
func = function (tpl_args, frame)
return m_game.constants.rarities[tpl_args.rarity_id]['full']
end
},
--
-- Processing fields
--
mods = {
func = function (tpl_args, frame)
-- Format the mod ids for cargo queries:
local mlist = {}
for _, key in ipairs(tpl_args._mods) do
mlist[#mlist+1] = string.format('"%s"', key)
end
if #mlist == 0 then
return
end
-- tpl_args._mods = m_cargo.array_query{
-- tables={'mods', 'mod_stats'},
-- fields={'mods.stat_text', 'mods.generation_type',
-- 'mod_stats.id', 'mod_stats.max'},
-- id_field='mods.id',
-- query={join='mods._pageID=mod_stats._pageID'},
-- id_array=mlist,
-- }
tpl_args._mod_data = m_cargo.map_results_to_id{
results=m_cargo.query(
{
'mods',
'mod_stats',
},
{
'mods.id',
'mods.stat_text',
'mods.generation_type',
'mod_stats.id',
'mod_stats.max',
},
{
join=[[
mods._pageID=mod_stats._pageID
]],
where=string.format([[
mods.id IN (%s)
]], table.concat(mlist, ',')),
}
),
field='mods.id',
keep_id_field=false,
}
end,
},
}
}
tables.monster_types = {
table = 'monster_types',
order = {'id', 'tags', 'monster_resistance_id'},
fields = {
id = {
field = 'id',
type = 'String',
},
tags = {
field = 'tags',
type = 'List (,) of String',
},
monster_resistance_id = {
field = 'monster_resistance_id',
type = 'String',
},
armour_multiplier = {
field = 'armour_multiplier',
type = 'Float',
},
evasion_multiplier = {
field = 'evasion_multiplier',
type = 'Float',
},
energy_shield_multiplier = {
field = 'energy_shield_multiplier',
type = 'Float',
},
damage_spread = {
field = 'damage_spread',
type = 'Float',
},
}
}
tables.monster_resistances = {
table = 'monster_resistances',
order = {'id', 'part1_fire', 'part1_cold', 'part1_lightning',
'part1_chaos', 'part2_fire', 'part2_cold', 'part2_lightning',
'part2_chaos', 'maps_fire', 'maps_cold', 'maps_lightning',
'maps_chaos'},
fields = {
id = {
field = 'id',
type = 'String',
},
part1_fire = {
field = 'part1_fire',
type = 'Integer',
},
part1_cold = {
field = 'part1_cold',
type = 'Integer',
},
part1_lightning = {
field = 'part1_lightning',
type = 'Integer',
},
part1_chaos = {
field = 'part1_chaos',
type = 'Integer',
},
part2_fire = {
field = 'part2_fire',
type = 'Integer',
},
part2_cold = {
field = 'part2_cold',
type = 'Integer',
},
part2_lightning = {
field = 'part2_lightning',
type = 'Integer',
},
part2_chaos = {
field = 'part2_chaos',
type = 'Integer',
},
maps_fire = {
field = 'maps_fire',
type = 'Integer',
},
maps_cold = {
field = 'maps_cold',
type = 'Integer',
},
maps_lightning = {
field = 'maps_lightning',
type = 'Integer',
},
maps_chaos = {
field = 'maps_chaos',
type = 'Integer',
},
}
}
tables.monster_base_stats = {
table = 'monster_base_stats',
order = {'level', 'damage', 'evasion', 'accuracy', 'life', 'experience',
'summon_life'},
fields = {
level = {
field = 'level',
type = 'Integer',
},
damage = {
field = 'damage',
type = 'Float',
},
evasion = {
field = 'evasion',
type = 'Integer',
},
accuracy = {
field = 'accuracy',
type = 'Integer',
},
life = {
field = 'life',
type = 'Integer',
},
experience = {
field = 'experience',
type = 'Integer',
},
summon_life = {
field = 'summon_life',
type = 'Integer',
},
-- whole bunch of other values I have no clue about ...
}
}
tables.monster_map_multipliers = {
table = 'monster_map_multipliers',
order = {'level', 'life', 'damage', 'boss_life', 'boss_damage',
'boss_item_rarity', 'boss_item_quantity'},
fields = {
level = {
field = 'level',
type = 'Integer',
},
life = {
field = 'life',
type = 'Integer',
},
damage = {
field = 'damage',
type = 'Integer',
},
boss_life = {
field = 'boss_life',
type = 'Integer',
},
boss_damage = {
field = 'boss_damage',
type = 'Integer',
},
boss_item_rarity = {
field = 'boss_item_rarity',
type = 'Integer',
},
boss_item_quantity = {
field = 'boss_item_quantity',
type = 'Integer',
},
}
}
tables.monster_life_scaling = {
table = 'monster_life_scaling',
order = {'level', 'magic', 'rare'},
fields = {
level = {
field = 'level',
type = 'Integer',
},
magic = {
field = 'magic',
type = 'Integer',
},
rare = {
field = 'rare',
type = 'Integer',
},
}
}
-- ----------------------------------------------------------------------------
-- Monster box sections
-- ----------------------------------------------------------------------------
local display = {}
function display.value (args)
return function (tpl_args, frame)
local v
if args.sub then
v = tpl_args[args.sub][args.arg]
else
v = tpl_args[args.arg]
end
if v and args.fmt then
return string.format(args.fmt, v)
else
return v
end
end
end
function display.sub_value (args)
return function (tpl_args, frame)
return tpl_args[args.sub][args.arg]
end
end
local tbl_view = {
{
-- header = i18n.tooltips.name,
func = function (tpl_args, frame)
if tpl_args.name == nil then
return
end
local linked_name = string.format(
'[[Monster:%s|%s]]',
string.gsub(tpl_args.metadata_id, '_', '~'),
tpl_args.name
)
return m_util.html.poe_color(tpl_args.rarity_id, linked_name)
end,
},
{
-- header = i18n.tooltips.image,
func = function (tpl_args, frame)
return string.format(
'[[File:%s monster screenshot.jpg|296x500px]]',
tpl_args.name or tpl_args.monster_type_id
)
end,
},
-- {
-- header = i18n.tooltips.rarity,
-- func = display.value{arg='rarity'},
-- },
{
header = i18n.tooltips.areas,
func = function(tpl_args, frame)
local out = {}
for i, v in ipairs(tpl_args.monster_usages) do
out[#out+1] = string.format(
'[[%s|%s]]',
v['areas.main_page'] or v['areas._pageName'],
v['areas.name'] or v['areas.id']
)
end
return table.concat(out, ', ')
end
},
{
header = i18n.tooltips.stat_text,
func = function (tpl_args, frame)
local out = {}
for _, modid in ipairs(tpl_args._mods) do
local mod = tpl_args._mod_data[modid] or {}
local stat_text = {}
-- Add stat_text for each modifier, ignore duplicates:
for _, v in ipairs(mod) do
if v['mods.stat_text'] then
if stat_text[v['mods.stat_text']] == nil then
stat_text[v['mods.stat_text']] = true
out[#out+1] = v['mods.stat_text']
end
end
end
end
return table.concat(out, '<br>')
end,
},
{
header = 'Skills',
func = function (tpl_args, frame)
local out = {}
for _, id in ipairs(tpl_args.skill_ids or {}) do
out[#out+1] = f_skill_link{id=id}
if string.find(out[#out], 'class="module%-error"') then
out[#out] = id
end
end
return table.concat(out, '<br>')
end,
},
{
header = 'Life',
func = function(tpl_args, frame)
-- Should this be stored to cargo?
-- Get monster level from the area level unless it's been
-- user defined.
local monster_level = {}
for _, v in ipairs(tpl_args.monster_usages) do
local lvl = v['maps.area_level'] or v['areas.area_level']
monster_level[#monster_level+1] = lvl
end
tpl_args.monster_level = tpl_args.monster_level or table.concat(monster_level, ',')
-- Stop if no monster level was found:
if tpl_args.monster_level == nil or tpl_args.monster_level == '' then
return nil
end
tpl_args.monster_level = m_util.string.split(tpl_args.monster_level, ',')
local results = m_cargo.query(
{
'monster_base_stats',
'monster_life_scaling',
'monster_map_multipliers',
-- 'monster'
},
{
'monster_base_stats.level',
'monster_base_stats.life',
'monster_life_scaling.magic',
'monster_life_scaling.rare',
'monster_map_multipliers.life',
'monster_map_multipliers.boss_life',
-- 'monster.health_multiplier',
},
{
join=[[
monster_base_stats.level=monster_life_scaling.level,
monster_base_stats.level=monster_map_multipliers.level
]],
where=string.format(
'monster_base_stats.level IN (%s)',
table.concat(tpl_args.monster_level, ', ')
),
}
)
-- Add monster modifiers. Min-max range necessary? Do item2
-- have a smarter way to set mods and stats?
local results2 = m_cargo.query(
{
'mods',
'mod_stats',
},
{
'mods.domain',
'mods.generation_type',
'mods.mod_group',
'mods.id',
'mod_stats.id',
'mod_stats.max',
'mod_stats.min',
},
{
join='mods._pageID=mod_stats._pageID',
where=string.format([[
mods.domain = 3
AND mods.generation_type = 3
AND mods.id LIKE "Monster%s%%"
AND mod_stats.id = "monster_life_+%%_final_from_rarity"
]],
tpl_args.rarity_id
),
}
)
local mods = results2[1] or {}
local out = {}
for i, result in ipairs(results) do
local stats = {
added={
result['monster_base_stats.life'],
}
,
increased={
result['monster_life_scaling.' .. tpl_args.rarity_id] or 0,
},
more={
mods['mod_stats.max'] or 0,
},
m1 = tpl_args.health_multiplier or 1,
m2 = (result['monster_map_multipliers.life'] or 100)/100,
m3 = (result['monster_map_multipliers.boss_life'] or 100)/100,
}
local life = h.stat_calc(stats)
local life_verb = h.stat_calc_verbose(stats)
out[i] = m_util.html.abbr(
string.format('%0.0f', life),
string.format(
'Lvl. %s: %s',
result['monster_base_stats.level'],
life_verb
)
)
end
return table.concat(out, ', ')
end,
},
{
header = i18n.tooltips.resistances,
func = function (tpl_args, frame)
local tbl = mw.html.create('table')
tbl
:attr('class', 'wikitable')
:tag('tr')
:tag('th')
:wikitext(i18n.tooltips.difficulty)
:attr('rowspan', 2)
:done()
-- :tag('th')
-- :wikitext(i18n.tooltips.resistances)
-- :attr('colspan', 4)
-- :done()
:done()
:tag('tr')
:tag('th')
:wikitext(i18n.tooltips.fire)
:done()
:tag('th')
:wikitext(i18n.tooltips.cold)
:done()
:tag('th')
:wikitext(i18n.tooltips.lightning)
:done()
:tag('th')
:wikitext(i18n.tooltips.chaos)
:done()
:done()
local difficulties = {'part1', 'part2', 'maps'}
local elements = {'fire', 'cold', 'lightning', 'chaos'}
for _, k in ipairs(difficulties) do
local tr = tbl:tag('tr')
tr
:tag('th')
:wikitext(i18n.tooltips[k])
:done()
for _, element in ipairs(elements) do
local field = string.format(
'monster_resistances.%s_%s',
k,
element
)
tr
:tag('td')
:attr('class', 'tc -' .. element)
:wikitext(tpl_args.monster_type[field])
:done()
end
end
-- -- Compressed resistance table:
-- local tbl = mw.html.create('table')
-- local tr = tbl:tag('tr')
-- local res = {}
-- for _, element in ipairs(elements) do
-- if res[element] == nil then
-- res[element] = {}
-- end
-- for _, k in ipairs(difficulties) do
-- local r = string.format('monster_resistances.%s_%s', k, element)
-- res[element][#res[element]+1] = m_util.html.abbr(
-- tpl_args.monster_type[r],
-- k
-- )
-- end
-- tr
-- :tag('td')
-- :attr('class', 'tc -' .. element)
-- :wikitext(table.concat(res[element], '/'))
-- :done()
-- end
return tostring(tbl)
end,
},
{
header = i18n.tooltips.experience_multiplier,
func = display.value{arg='experience_multiplier'},
},
{
header = i18n.tooltips.health_multiplier,
func = display.value{arg='health_multiplier'},
},
{
header = i18n.tooltips.damage_multiplier,
func = display.value{arg='damage_multiplier'},
},
{
header = i18n.tooltips.attack_speed,
func = display.value{arg='attack_speed', fmt='%.3fs',},
},
{
header = i18n.tooltips.critical_strike_chance,
func = display.value{arg='critical_strike_chance', fmt='%.2f%%',},
},
{
header = i18n.tooltips.minimum_attack_distance,
func = display.value{arg='minimum_attack_distance'},
},
{
header = i18n.tooltips.maximum_attack_distance,
func = display.value{arg='maximum_attack_distance'},
},
{
header = i18n.tooltips.size,
func = display.value{arg='size'},
},
{
header = i18n.tooltips.model_size_multiplier,
func = display.value{arg='model_size_multiplier'},
},
{
header = i18n.tooltips.tags,
func = function (tpl_args, frame)
if tpl_args.tags == nil or #tpl_args.tags == 0 then
return
end
return table.concat(tpl_args.tags, '<br>')
end,
},
{
header = i18n.tooltips.metadata_id,
func = display.value{arg='metadata_id'},
},
{
header = i18n.tooltips.monster_type_id,
func = display.value{arg='monster_type_id'},
},
}
local list_view = {
}
-- ----------------------------------------------------------------------------
-- Page views
-- ----------------------------------------------------------------------------
p.table_monsters = m_cargo.declare_factory{data=tables.monsters}
p.table_monster_types = m_cargo.declare_factory{data=tables.monster_types}
p.table_monster_resistances = m_cargo.declare_factory{data=tables.monster_resistances}
p.table_monster_base_stats = m_cargo.declare_factory{data=tables.monster_base_stats}
p.table_monster_map_multipliers = m_cargo.declare_factory{data=tables.monster_map_multipliers}
p.table_monster_life_scaling = m_cargo.declare_factory{data=tables.monster_life_scaling}
p.store_data = m_cargo.store_from_lua{tables=tables, module='Monster'}
function p.monster(frame)
--[[
Stores data and display infoboxes of monsters.
Example
-------
= p.monster{
metadata_id='Metadata/Monsters/Bandits/BanditBossHeavyStrike_',
monster_type_id='BanditBoss',
mod_ids='MonsterAttackBlock30Bypass20',
tags='red_blood',
skill_ids='Melee, MonsterHeavyStrike',
name='Calaf, Headstaver',
size=3,
minimum_attack_distance=4,
maximum_attack_distance=5,
model_size_multiplier=1.15,
experience_multiplier=1.0,
damage_multiplier=1.0,
health_multiplier=1.0,
critical_strike_chance=5.0,
attack_speed=1.35,
rarity_id = 'unique'
}
]]
-- Get args
tpl_args = getArgs(frame, {
parentFirst = true
})
frame = m_util.misc.get_frame(frame)
tpl_args._mods = {}
-- Parse and store the monster table:
m_cargo.parse_field_arguments{
tpl_args=tpl_args,
frame=frame,
table_map=tables.monsters,
}
-- Create the infobox:
local tbl = mw.html.create('table')
tbl
:attr('class', 'wikitable')
:attr('style', 'float:right; margin-left: 10px;')
for _, data in ipairs(tbl_view) do
local v = data.func(tpl_args, frame)
if v ~= nil and v ~= '' then
local tr = tbl:tag('tr')
if data.header then
tr:tag('th'):wikitext(data.header):done()
tr:tag('td'):wikitext(v):done()
else
tr:tag('th'):attr('colspan', 2):wikitext(v):done()
end
end
end
local out = {
tostring(tbl),
h.intro_text(tpl_args, frame),
}
for _, data in ipairs(list_view) do
out[#out+1] = data.func(tpl_args, frame)
end
local cats = {
i18n.cats.data,
}
return table.concat(out) .. m_util.misc.add_category(cats)
end
return p