No edit summary |
No edit summary |
||
Line 123: | Line 123: | ||
.. " AND (type = 'Standing' OR type = 'Crouching')" | .. " AND (type = 'Standing' OR type = 'Crouching')" | ||
}) | }) | ||
--[[ | --[[ | ||
Line 216: | Line 190: | ||
for _, punishers in ipairs(block) do | for _, punishers in ipairs(block) do | ||
table.sort(punishers, function(l, r) return l.frames < r.frames end) | table.sort(punishers, function(l, r) return l.frames < r.frames end) | ||
end | |||
local span = 80 | |||
for _, punishers in pairs(block) do | |||
for _, punisher in pairs(punishers) do | |||
for _, dmg in pairs(punisher.damages) do | |||
if dmg > span then | |||
span = dmg | |||
end | |||
end | |||
end | |||
end | |||
if span % 5 ~= 0 then | |||
span = span + 5 - (span % 5) | |||
end | |||
local scale = mw.html.create('div'):addClass('punishment-scale') | |||
for i = 0,span,5 do | |||
local pip = mw.html.create('div'):addClass('punishment-scalepip') | |||
:css("width", string.format("%.2f%%", 100 * i / span)) | |||
:node(mw.html.create('div'):addClass('punishment-piplabel'):wikitext(i)) | |||
if i % 50 == 0 then | |||
pip:addClass('major') | |||
elseif i % 25 == 0 then | |||
pip:addClass('minor') | |||
end | |||
scale:node(pip) | |||
end | end | ||
Revision as of 22:03, 1 September 2023
Documentation for this module may be created at Module:Move7/doc
local p = {};
local cargo = mw.ext.cargo
local tables = 'MoveDataCargoTest'
p.fields = 'id,name,input,target,damage,reach,tracksLeft,tracksRight,startup,recv,tot,crush,block,hit,ch,notes'
-- Get move id for querying, which is the 1st unnamed param of a template.
-- Moves are queried like this: {{TempateName|<moveId>}}
function getQueryId(frame)
local id = assert(frame:getParent().args[1], '1st unnamed param must be move id')
return mw.text.trim(id) -- whitespace is stripped only from named params
end
function moveNotFoundMsg(id)
return "move with id = '" .. id .. "' not found"
end
p.display = function(frame)
local function appendFrom(dst, src)
for k, v in pairs(src) do
dst[k] = v
end
end
local function getLeads(parentId)
local leads = {}
while (parentId ~= nil and parentId ~= '') do
local parent = cargo.query(tables, 'input,target,damage,parent', { where = "id='" .. parentId .. "'" })[1]
assert(parent, 'parent = "' .. parentId .. '" not found')
parentId = parent['parent']
parent['parent'] = nil
for k, v in pairs(parent) do
local leadName = k .. 'Lead'
if leads[leadName] == nil then
leads[leadName] = ''
end
leads[leadName] = v .. leads[leadName]
end
end
return leads
end
local leads = getLeads(frame:getParent().args['parent'])
if next(leads) == nil then
return frame:expandTemplate{ title = 'MoveData', args = frame:getParent().args }
end
local args = {}
appendFrom(args, frame:getParent().args)
appendFrom(args, leads)
return frame:expandTemplate{ title = 'MoveData', args = args }
end
p.query = function(frame)
local id = getQueryId(frame)
local result = cargo.query(tables, p.fields, { where = "id = '" .. id .. "'" })[1]
assert(result, moveNotFoundMsg)
for k, v in pairs(result) do
local override = frame:getParent().args[k]
if override ~= nil then
result[k] = override
end
end
return frame:expandTemplate{ title = 'MoveDataCargoTest/Display', args = result }
end
p.punisher = function(frame)
local id = getQueryId(frame)
local frames = frame:getParent().args['frames']
local rowspan = frame:getParent().args['rowspan']
local combo = frame:getParent().args['combo']
local type = frame:getParent().args['type']
local input = ''
local damage = 0
local hit = nil
while (id ~= '') do
local move = cargo.query(tables, 'parent,input,damage,hit', { where = "id = '" .. id .. "'" })[1]
assert(move, moveNotFoundMsg(id))
input = move['input'] .. input
damage = damage + move['damage']
if hit == nil then
hit = move['hit']
end
id = move['parent']
end
frame:callParserFunction{ name = '#cargo_store', args = {
'_table=Punisher',
type = type,
frames = frames,
damage = combo or damage
} }
local row = mw.html.create('tr')
if rowspan ~= 'skip' then
row:tag('td'):wikitext(frames):attr('rowspan', rowspan or 1)
end
row:tag('td'):wikitext(input)
if combo ~= nil then
row:tag('td'):wikitext(damage .. ' (' .. combo .. ')')
else
row:tag('td'):wikitext(damage)
end
row:tag('td'):wikitext(hit)
return row
end
p.punishment = function(frame)
local character = frame:getParent().args[1]
local data = mw.loadData('Module:Fighter/punishment')
local punishers = cargo.query('Punisher', 'type,frames,damage', {
where = "Punisher._pageName='User:Lume/Cargo testing/" .. character .. " punishers'"
.. " AND (type = 'Standing' OR type = 'Crouching')"
})
--[[
block = {
Standing = {
{ frames, damages = {
regular = int
rage = int
wall = int
} }
...
}
Crouching = {
...
}
}
--]]
local block = {}
for _, p in pairs(punishers) do
local type = p['type']
local frames = -tonumber(p['frames'])
local damageStrings = mw.text.split(p['damage'], ', ', true)
--[[
damages = {
regular = int
rage = int
wall = int
}
--]]
local damages = {}
for _, dmgStr in pairs(damageStrings) do
local dmgSplit = mw.text.split(dmgStr, ' ', true)
local value = tonumber(dmgSplit[1])
local dmgType = 'regular'
if #dmgSplit == 2 then
dmgType = dmgSplit[2]
end
if damages[dmgType] == nil or damages[dmgType] < value then
damages[dmgType] = value
end
end
if block[type] == nil then
block[type] = {}
end
local sameFramePunisherFound = false
for _, p in block[type] do
if p.frames == frames then
sameFramePunisherFound = true
for dmgType, dmg in damages do
if p.damages[dmgType] == nil or p.damages[dmgType] < dmg then
p.damages[dmgType] = dmg
end
end
end
end
if not sameFramePunisherFound then
table.insert(block[type], { frames = frames, damages = damages })
end
end
for _, punishers in ipairs(block) do
table.sort(punishers, function(l, r) return l.frames < r.frames end)
end
local span = 80
for _, punishers in pairs(block) do
for _, punisher in pairs(punishers) do
for _, dmg in pairs(punisher.damages) do
if dmg > span then
span = dmg
end
end
end
end
if span % 5 ~= 0 then
span = span + 5 - (span % 5)
end
local scale = mw.html.create('div'):addClass('punishment-scale')
for i = 0,span,5 do
local pip = mw.html.create('div'):addClass('punishment-scalepip')
:css("width", string.format("%.2f%%", 100 * i / span))
:node(mw.html.create('div'):addClass('punishment-piplabel'):wikitext(i))
if i % 50 == 0 then
pip:addClass('major')
elseif i % 25 == 0 then
pip:addClass('minor')
end
scale:node(pip)
end
local root = mw.html.create('div'):addClass('punishment')
for pos,punishment in pairs(block) do
local group = mw.html.create('div'):addClass('punishment-group')
root:node(group)
group:node(mw.html.create("div"):addClass('punishment-label')
:wikitext(pos .. " punishment")
)
local grid = mw.html.create('div'):addClass('punishment-grid')
group:node(grid)
local dmgClasses = {
regular = 'bg-blue',
rage = 'bg-purple',
wall = 'bg-orange',
}
best = {}
for _, punisher in pairs(punishment) do
-- don't carry rage/meter punishment, makes viz. look funky
best[dmgClasses.rage] = nil
for dmgType, dmg in punisher.damages do
local dmgClass = dmgClasses[dmgType]
if best[dmgClass] == nil or best[dmgClass] < dmg then
best[dmgClass] = dmg
end
end
if best[dmgClass.regular] then
for k, v in pairs(best) do
if k ~= dmgClass.regular and best[k] <= best[dmgClass.regular] then
best[k] = nil
end
end
end
if punishment[i] ~= nil or (i >= 10 and i <= 15) then
bestSortedKeys = {}
for k,_ in pairs(best) do
table.insert(bestSortedKeys, k)
end
table.sort(bestSortedKeys, function (a, b)
-- Larger bars first so that smaller bars are actually visible
return best[a] > best[b]
end)
grid:node(mw.html.create('div'):addClass('punishment-startup')
:wikitext("-" .. i)
)
local bars = mw.html.create('div'):addClass('punishment-bars')
grid:node(bars)
for i,k in ipairs(bestSortedKeys) do
local class = k
bars:node(
mw.html.create('div'):addClass('punishment-bar')
:addClass(class)
:css("width", string.format("%.2f%%", 100 * best[k] / span))
:wikitext(best[k])
)
end
local median = data.median[pos][i]
if median ~= nil then
bars:node(
mw.html.create('div'):addClass('punishment-median')
:css('width', string.format("%.2f%%", 100 * median / span))
)
end
end
end
grid:node(mw.clone(scale))
end
return root
end
return p