Module:Traits: Difference between revisions
From Elwiki
No edit summary Tag: Reverted |
No edit summary Tag: Reverted |
||
Line 139: | Line 139: | ||
t.multi_cooldown = args['cd' .. t.index] or default_multiplier | t.multi_cooldown = args['cd' .. t.index] or default_multiplier | ||
t.multi_duration = args['duration' .. t.index] or default_multiplier | t.multi_duration = args['duration' .. t.index] or default_multiplier | ||
t.multi_hits = args['damage' .. t.index] | t.multi_hits = args['damage' .. t.index] or default_multiplier | ||
t.chance = args['chance' .. t.index] | t.chance = args['chance' .. t.index] | ||
t.unnamed_2 = args['desc1_trait' .. t.index] | t.unnamed_2 = args['desc1_trait' .. t.index] |
Revision as of 23:30, 27 October 2022
Documentation for this module may be created at Module:Traits/doc
require('Module:CommonFunctions')
local getArgs = require('Module:Arguments').getArgs
local p = {}
-- Main process
function p.main(frame)
local args = getArgs(frame);
-- Argument init
local traits = args[3] or args.traits
if (traits == nil) then
traits = '-, -'
end
traits = split(traits);
for k, v in ipairs(traits) do
traits[k] = trim(v)
end
local skill = args[2] or args.skill
local default_multiplier = 100
-- Dictionary for headers
local headers = {'MP Usage', 'Cooldown', 'Duration', 'MP Recovery', 'Max Hits'}
local properties = {'mp_cost', 'cooldown', 'duration', 'mp_cost'}
local header_dict = {
[1] = {'Light', 'Critical', 'Reversed'},
[2] = {'Heavy', 'Haste', 'Regenerating (2)', 'Ruthless', 'Powerful', 'Reversed'},
[3] = {'Killing Blow (1)'},
[4] = {'Regenerating (1)'},
[5] = {'Useful'}
}
-- Default values
local default_trait_values = {
Heavy = {
multi_cooldown = 120
},
Light = {
multi_mp_cost = 80
},
Critical = {
multi_mp_cost = 120
},
Haste = {
multi_cooldown = 80
},
Ruthless = {
multi_cooldown = 200
},
Powerful = {
multi_cooldown = 150
}
}
-- Define the class blueprint for traits.
Trait = {}
function Trait:new(t)
t = t or {}
-- Define all values taken from arguments.
t.details_mp_cost = {
[1] = args.mp or -1,
[2] = args.mp_pvp,
[3] = args.mp_enhanced
}
t.details_cooldown = {
[1] = args.cd or -1,
[2] = args.cd_pvp,
[3] = args.cd_enhanced
}
t.details_duration = {
[1] = args.duration or -1,
[2] = args.duration_pvp,
[3] = args.duration_enhanced
}
t.details_hits = {
[1] = args.hits or -1,
[2] = args.hits_pvp,
[3] = args.hits_enhanced
}
-- Automatic math and pvp/enhanced check
local has_multiple_rows;
t.multiple_rows = {}
for k, v in pairs(t) do
if string.find(k, 'details_') then
for k2, v2 in pairs(v) do
local kind = k:gsub('details_', '')
if (t.multiple_rows[kind] == nil) then
t.multiple_rows[kind] = {}
end
if (k2 == 2) then
t.multiple_rows[kind]['pvp'] = true
elseif (k2 == 3) then
t.multiple_rows[kind]['enhanced'] = true
end
t[k][k2] = frame:preprocess('{{#expr: ' .. v2 .. '}}')
end
end
end
-- Solution for custom headers
for k, v in pairs(args) do
if string.find(k, 'detail') then
if t.multiple_rows[k] == nil then
t.multiple_rows[k] = {}
end
if string.find(k, '_pvp') then
local kind = k:gsub('_pvp', '')
t.multiple_rows[kind] = {}
t.multiple_rows[kind]['pvp'] = true
elseif string.find(k, '_enhanced') then
local kind = k:gsub('_enhanced', '')
t.multiple_rows[kind] = {}
t.multiple_rows[kind]['enhanced'] = true
end
end
end
-- Check if multiple_rows property has ANY values in the 2nd depth
for k, v in pairs(t.multiple_rows) do
if next(v) ~= nil then
has_multiple_rows = true
end
end
-- Figure out how many columns there is to span
if has_multiple_rows and t.index == 1 then
t.mode_row = true
end
t.colspan = 1
t.colspan = t.colspan + table.matches(header_dict, t.name)
-- Get multipliers from args
t.multi_mp_cost = args['mp' .. t.index] or default_multiplier
t.multi_cooldown = args['cd' .. t.index] or default_multiplier
t.multi_duration = args['duration' .. t.index] or default_multiplier
t.multi_hits = args['damage' .. t.index] or default_multiplier
t.chance = args['chance' .. t.index]
t.unnamed_2 = args['desc1_trait' .. t.index]
t.unnamed_3 = args['desc2_trait' .. t.index]
-- Set defaults for generic trait values.
local default = default_trait_values[t.name]
if (default ~= nil) then
for k, v in pairs(default) do
if (t[k] == default_multiplier) then
t[k] = v
end
end
end
-- Figure out if there are any pvp or enhanced values
for k, v in pairs(t.multiple_rows) do
for k2, v2 in pairs(v) do
if k2 == 'pvp' and v2 == true then
t.has_pvp = true
end
if k2 == 'enhanced' and v2 == true then
t.has_enhanced = true
end
end
end
self.__index = self
setmetatable(t, self)
return t
end
function Trait:onError(message)
assert(false, message)
end
-- Calculation method
function Trait:calc()
for k, v in pairs(self) do
if (string.find(k, 'details_')) then
local current_data = k:gsub('details_', '')
local current_multiplier = self['multi_' .. current_data]
-- -- Handle errors
-- if not next(v) and current_multiplier ~= default_multiplier then
-- self:onError("Cannot calculate the '" .. current_data .. "' property that is not defined")
-- end
-- local requires_current_data
-- for k1, v1 in pairs(header_dict) do
-- for k2, v2 in pairs(v1) do
-- if v2 == self.name and properties[k1] == current_data then
-- requires_current_data = true
-- end
-- end
-- end
-- if current_multiplier == default_multiplier and next(v) ~= nil and requires_current_data then
-- self:onError("Cannot calculate the '" .. current_data .. "' property: " .. self.name ..
-- " trait description is not enough")
-- end
for k2, v2 in pairs(v) do
self[k][k2] = current_multiplier / 100 * v2
if self[k][k2] < 0 then
self[k][k2] = '-'
end
if current_data == 'mp_cost' then
self[k][k2] = self[k][k2] .. ' MP'
elseif current_data ~= 'hits' then
self[k][k2] = self[k][k2] .. ' Seconds'
end
end
end
end
return self
end
local trait_left = Trait:new({
name = traits[1],
index = 1
})
local trait_right = Trait:new({
name = traits[2],
index = 2
})
-- Main block
-- Get table head color
local function color(char)
char = char or args[1] or args.char
return char:gsub('/', '')
end
local trait_table = mw.html.create('div'):attr('class', 'content-table'):tag('table'):attr({
cellpadding = '5',
border = '1',
class = 'colortable-' .. color()
}):css({
['border-collapse'] = 'collapse',
['text-align'] = 'center'
})
function newtr()
return trait_table:tag('tr')
end
local thead = newtr()
local tr = newtr()
local tr_2 = newtr()
-- Header spawning method
function Trait:do_headers(tr)
local function getCustomHeader(spawn)
local i = 1
while true do
local custom_header = args['header' .. i .. '_trait' .. self.index]
if custom_header ~= nil then
if spawn then
tr_2:tag('th'):wikitext(custom_header)
end
i = i + 1
else
break
end
end
return i - 1
end
if self.mode_row then
if self.has_enhanced == true then
thead:tag('th'):wikitext('Stage'):attr('rowspan', '2')
else
thead:tag('th'):wikitext('Mode'):attr('rowspan', '2')
end
end
thead:tag('th'):attr('colspan', self.colspan + getCustomHeader()):wikitext(self.name .. ' ' .. skill)
tr_2:tag('th'):wikitext('Attribute Effect')
local has_details = table.matches(header_dict, self.name);
if has_details then
if self.multi_mp_cost ~= default_multiplier then
if self.name == 'Regenerating (1)' then
tr_2:tag('th'):wikitext('MP Recovery')
else
tr_2:tag('th'):wikitext('MP Usage')
end
end
if self.multi_cooldown ~= default_multiplier then
tr_2:tag('th'):wikitext('Cooldown')
end
if self.multi_duration ~= default_multiplier then
local duration_name = args.duration_name or ''
if duration_name then
duration_name = duration_name .. ' '
end
tr_2:tag('th'):wikitext(duration_name .. 'Duration')
end
if self.name == 'Useful' then
tr_2:tag('th'):wikitext('Max Hits')
end
end
getCustomHeader(true)
end
trait_left:do_headers()
trait_right:do_headers()
trait_left:calc()
trait_right:calc()
function Trait:do_content(tr, mode)
-- Generate appropriate headers on the left
if self.mode_row then
if mode then
if self.has_enhanced == true then
if mode == 'enhanced' then
tr:tag('td'):wikitext("'''[Enhanced]'''")
end
elseif mode == 'pvp' then
tr:tag('td'):wikitext(frame:expandTemplate{
title = 'PvP'
})
end
else
if self.has_enhanced == true then
tr:tag('td'):wikitext("'''Normal'''")
else
tr:tag('td'):wikitext(frame:expandTemplate{
title = 'PvE'
})
end
end
end
-- Generate trait descriptions
if not mode then
local rowspan = 1
if next(self.multiple_rows) ~= nil then
rowspan = 2
end
tr:tag('td'):wikitext(frame:expandTemplate{
title = 'SkillText',
args = {
self.name,
self.unnamed_2,
self.unnamed_3,
MP = self.multi_mp_cost,
CD = self.multi_cooldown,
DURATION = self.multi_duration,
CHANCE = self.chance,
DAMAGE = self.multi_hits
}
}):attr('rowspan', rowspan)
end
-- Fill cells with values
local function addIfMultiExists(param_tbl)
for k, v in ipairs(param_tbl) do
if (self['multi_' .. v] ~= default_multiplier) then
local info;
if mode == 'enhanced' then
info = self['details_' .. v][3]
elseif mode == 'pvp' then
info = self['details_' .. v][2]
else
info = self['details_' .. v][1]
end
if (info ~= nil) then
local td = tr:tag('td'):wikitext(info)
if next(self.multiple_rows[v]) ~= nil then
td:attr('rowspan', 1)
else
td:attr('rowspan', 2)
end
end
end
end
end
addIfMultiExists({'mp_cost', 'cooldown', 'duration'})
-- Custom data support
local function getCustomContent()
local i = 1
local y = 1
while true do
local mode_str = mode or ''
if mode_str ~= '' then
mode_str = '_' .. mode_str
end
local custom_content_arg = 'detail' .. i .. '_trait' .. self.index .. mode_str;
local custom_content = args[custom_content_arg]
if custom_content ~= nil then
local rowspan = 1
for k, v in pairs(self.multiple_rows) do
if k == custom_content_arg and next(v) == nil then
rowspan = 2
end
end
tr:tag('td'):wikitext(custom_content):attr('rowspan', rowspan)
i = i + 1
else
y = y + 1
if (y == 5) then
break
else
i = i + 1
end
end
end
end
getCustomContent()
end
local tr = trait_table:tag('tr')
trait_left:do_content(tr)
trait_right:do_content(tr)
local tr_2 = trait_table:tag('tr')
-- Will use the same table row. Enhanced + pvp not supported for now.
trait_left:do_content(tr_2, 'enhanced')
trait_right:do_content(tr_2, 'enhanced')
trait_left:do_content(tr_2, 'pvp')
trait_right:do_content(tr_2, 'pvp')
return tostring(trait_table);
-- return dump(trait_left) .. '<br><br>' .. dump(trait_right);
end
return p