mNo edit summary |
No edit summary |
||
(32 intermediate revisions by 4 users not shown) | |||
Line 2: | Line 2: | ||
local currentFrame | local currentFrame | ||
local | local html | ||
local frameChartDataHtml | |||
function drawFrame(frames, frameType) | |||
if tonumber(frames) ~= nil then | |||
for i=1, tonumber(frames) do | |||
currentFrame = currentFrame + 1 | |||
local frameDataHtml = mw.html.create('div') | |||
frameDataHtml | |||
:addClass('frame-data') | |||
:addClass('frame-data-' .. frameType) | |||
if checkCancel() then | |||
frameDataHtml:addClass('frame-data-frc') | |||
end | |||
frameDataHtml:done() | |||
frameChartDataHtml:node(frameDataHtml) | |||
end | |||
end | |||
end | |||
-- Checks if currentFrame is within one of the cancel/FRC windows | |||
function checkCancel() | |||
local i = 1 | |||
while cList[i] ~= nil do | |||
if currentFrame <= cList[i+1] and currentFrame >= cList[i] then | |||
return true | |||
end | |||
i = i + 2 | |||
end | |||
return false | |||
end | |||
function p.drawFrameData(frame) | function p.drawFrameData(frame) | ||
currentFrame = 0 | |||
html = mw.html.create('div') | |||
html:addClass('frameChart') | |||
-- Optional field to add title | |||
local title | |||
if frame.args['title'] ~= nil then | |||
title = frame.args['title'] | |||
end | |||
-- Startup is the first active frame. Sets to true if empty. Otherwise it's false. | |||
local startupIsFirstActive | |||
if frame.args['startupIsFirstActive'] == nil then | |||
startupIsFirstActive = true | |||
else | |||
startupIsFirstActive = false | |||
end | |||
-- Startup of move, substract 1 if startupIsFirstActive | |||
local startup = frame.args['startup'] | |||
if tonumber(startup) ~= nil then | |||
if startupIsFirstActive and tonumber(startup) > 0 then | |||
startup = tonumber(startup) - 1 | |||
end | |||
end | |||
-- Active of move | |||
local active = frame.args['active'] | |||
-- Inactive of move | |||
local inactive = frame.args['inactive'] | |||
-- Recovery of move | |||
local recovery = frame.args['recovery'] | |||
-- Special Recovery of move | |||
local specialRecovery = frame.args['specialRecovery'] | |||
-- How many frames into active frames the inactive period occurs | |||
local offset = frame.args['offset'] | |||
-- Display projectile spawn bar after startup? | |||
local isProjectile = frame.args['isProjectile'] | |||
-- Display projectile spawn bar after actives? | |||
local isStrikeProjectile = frame.args['isStrikeProjectile'] | |||
-- Defining FRC / Cancel windows | |||
local cIndex = 1 | |||
cList = {} | |||
-- Supporting frcStart/End as optional arguments | |||
if frame.args['frcStart'] ~= nil then | |||
cList[cIndex] = tonumber(frame.args['frcStart']) | |||
end | |||
if frame.args['frcEnd'] ~= nil then | |||
cList[cIndex+1] = tonumber(frame.args['frcEnd']) | |||
cIndex = cIndex + 2 | |||
end | |||
-- Creating list of cancel windows from N potential fields | |||
local index = 1 | |||
while tonumber(frame.args['cancelStart' .. index]) ~= nil or tonumber(frame.args['cancelEnd' .. index]) ~= nil do | |||
cList[cIndex] = tonumber(frame.args['cancelStart' .. index]) | |||
cList[cIndex+1] = tonumber(frame.args['cancelEnd' .. index]) | |||
cIndex = cIndex + 2 | |||
index = index + 1 | |||
end | |||
if title ~= nil then | |||
html | |||
:tag('div') | |||
:addClass('frameChart-title') | |||
:wikitext(title) | |||
:done() | |||
end | |||
-- Create container for frame data | |||
frameChartDataHtml = mw.html.create('div') | |||
frameChartDataHtml:addClass('frameChart-data') | |||
html:node(frameChartDataHtml) | |||
drawFrame(startup, "startup") | |||
if isProjectile ~= nil then | |||
frameChartDataHtml | |||
:tag('div') | |||
:addClass('spawn-projectile') | |||
:done() | |||
end | |||
-- Alternate way of inputting multihits, only works for moves with a single gap in active frames | |||
if offset ~= nil then | |||
drawFrame(offset, "active") | |||
drawFrame(inactive, "inactive") | |||
drawFrame(active-offset, "active") | |||
else | |||
drawFrame(active, "active") | |||
end | |||
-- Option for inputting multihits, works for moves with 1+ gaps in the active frames | |||
index = 2 | |||
while tonumber(frame.args['active' .. index]) ~= nil or tonumber(frame.args['inactive' .. index]) ~= nil do | |||
drawFrame(frame.args['active' .. index], "active") | |||
drawFrame(frame.args['inactive' .. index], "inactive") | |||
index = index + 1 | |||
end | |||
if isStrikeProjectile ~= nil then | |||
frameChartDataHtml | |||
:tag('div') | |||
:addClass('spawn-projectile') | |||
:done() | |||
end | |||
drawFrame(recovery, "recovery") | |||
drawFrame(specialRecovery, "specialRecovery") | |||
html | |||
:tag('div') | |||
:addClass('frame-data-total') | |||
:wikitext("'''Total:''' " .. currentFrame ) | |||
:done() | |||
return tostring(html) .. mw.getCurrentFrame():extensionTag{ | |||
name = 'templatestyles', args = { src = 'Module:FrameChart/styles.css' } | |||
} | |||
end | |||
p.drawFrame = drawFrame | |||
p.checkCancel = checkCancel | |||
return p | return p |
Latest revision as of 11:32, 10 January 2024
Module:FrameChart
is used to generate timelines which represent the given frame data as a set of discrete frames color coded by their classification.
Usage
Any page which uses the FrameChart module should include the template Template:FrameChartKey which explains each of the colored squares generated by the graph.
Creating a frame chart involves defining a number of values for the code to plot on the timeline. If a given value is left out, it will not be drawn.
- startup - the quantity of startup frames. By default, this includes the first active frame of the move. As is standard for Dustloop.
- active - the quantity of active frames. Can be multiple sections [2-N].
- recovery - the quantity of recovery frames after all active frames have ended.
- inactive - The quantity of frames during which the move is not active which occur in between two sets of active frames. Can be multiple sections [2-N].
- specialRecovery - The quantity of non-standard recovery frames tied to a move. These include things such as Landing Recovery.
- offset - The quantity of active frames which occur before the inactive frames. This is used for handling edge cases, or as an alternative syntax to inactive.
- isProjectile - a bar created after startup frames indicating a projectile was spawned.
- isStrikeProjectile - a bar created after active frames indicating a projectile was spawned. Used when the attack starts with a strike and is followed up by a projectile
- frcStart - the first frame which an FRC can occur on.
- frcEnd - the last frame which an FRC can occur on.
- cancelStart - the first frame a cancel can occur on, an alternative syntax to frcStart. Can be multiple sections [2-N].
- cancelEnd - the last frame a cancel can occur on, an alternative syntax to frcEnd. Can be multiple sections [2-N].
- title - a title for a given FrameChart, most useful when making multiple FrameCharts in one area.
- startupIsFirstActive - the first active frame is the last frame of startup. True by default as that is the standard. Set to false for cases such as when Active frames are skipped.
Examples
Frame Chart Key
StartupThe time before an attack is active. Written startup values include the first active frame, so the startup on a frame chart will display one less square than the written value. Frames
Active The active frames of an attack refers to the amount of time an attack can hit the opponent. Frames
InactiveFrames in the middle of multi-hit attacks which cannot hit the opponent, but are after the move has become active at least once. Frames
Recovery The recovery of an attack refers to the amount of time an attacker must wait before they may perform another action, even blocking. Frames
Special RecoveryThe recovery of an attack refers to the amount of time an attacker must wait before they may perform another action.Recovery frames which happen under abnormal conditions, such as after landing. Frames
ProjectileIndicates an entity that exists separately from the character has become active. Usually something like a Fireball A projectile which usually travels slowly across the screen in a horizontal path above the ground.. Active
CancelA window in which to cancel a move. Can be varied in usage. Window
Simple
Startup | Active | Recovery |
---|---|---|
8 | 2 | 10 |
{{#invoke:FrameChart|drawFrameData |startup = 8 |active = 2 |recovery = 10 }}
Total: 19
Inactive Frames
Startup | Active | Recovery |
---|---|---|
8 | 2(3)2 | 10 |
{{#invoke:FrameChart|drawFrameData |startup = 8 |active = 2 |inactive2 = 3 |active3 = 2 |recovery = 10 }}
Total: 24
Complex
The following example uses multiple optional features of the framechart: title, frc window, and special recovery.
Startup | Active | Recovery |
---|---|---|
8 | 4 | 5+10 |
{{#invoke:FrameChart|drawFrameData |title = Complex Example |startup = 8 |active = 4 |recovery = 5 |specialRecovery = 10 |frcStart = 9 |frcEnd = 10 }}
Complex Example
Total: 26
Projectile + Cancel Window
Startup | Active | Recovery |
---|---|---|
18 | 32 | Total 51 |
{{#invoke:FrameChart|drawFrameData |startup = 18 |isProjectile = true |startupIsFirstActive = false |recovery = 33 |cancelStart1 = 20 |cancelEnd1 = 21 |cancelStart2 = 25 |cancelEnd2 = 26 }}
Total: 51
local p = {} local currentFrame local html local frameChartDataHtml function drawFrame(frames, frameType) if tonumber(frames) ~= nil then for i=1, tonumber(frames) do currentFrame = currentFrame + 1 local frameDataHtml = mw.html.create('div') frameDataHtml :addClass('frame-data') :addClass('frame-data-' .. frameType) if checkCancel() then frameDataHtml:addClass('frame-data-frc') end frameDataHtml:done() frameChartDataHtml:node(frameDataHtml) end end end -- Checks if currentFrame is within one of the cancel/FRC windows function checkCancel() local i = 1 while cList[i] ~= nil do if currentFrame <= cList[i+1] and currentFrame >= cList[i] then return true end i = i + 2 end return false end function p.drawFrameData(frame) currentFrame = 0 html = mw.html.create('div') html:addClass('frameChart') -- Optional field to add title local title if frame.args['title'] ~= nil then title = frame.args['title'] end -- Startup is the first active frame. Sets to true if empty. Otherwise it's false. local startupIsFirstActive if frame.args['startupIsFirstActive'] == nil then startupIsFirstActive = true else startupIsFirstActive = false end -- Startup of move, substract 1 if startupIsFirstActive local startup = frame.args['startup'] if tonumber(startup) ~= nil then if startupIsFirstActive and tonumber(startup) > 0 then startup = tonumber(startup) - 1 end end -- Active of move local active = frame.args['active'] -- Inactive of move local inactive = frame.args['inactive'] -- Recovery of move local recovery = frame.args['recovery'] -- Special Recovery of move local specialRecovery = frame.args['specialRecovery'] -- How many frames into active frames the inactive period occurs local offset = frame.args['offset'] -- Display projectile spawn bar after startup? local isProjectile = frame.args['isProjectile'] -- Display projectile spawn bar after actives? local isStrikeProjectile = frame.args['isStrikeProjectile'] -- Defining FRC / Cancel windows local cIndex = 1 cList = {} -- Supporting frcStart/End as optional arguments if frame.args['frcStart'] ~= nil then cList[cIndex] = tonumber(frame.args['frcStart']) end if frame.args['frcEnd'] ~= nil then cList[cIndex+1] = tonumber(frame.args['frcEnd']) cIndex = cIndex + 2 end -- Creating list of cancel windows from N potential fields local index = 1 while tonumber(frame.args['cancelStart' .. index]) ~= nil or tonumber(frame.args['cancelEnd' .. index]) ~= nil do cList[cIndex] = tonumber(frame.args['cancelStart' .. index]) cList[cIndex+1] = tonumber(frame.args['cancelEnd' .. index]) cIndex = cIndex + 2 index = index + 1 end if title ~= nil then html :tag('div') :addClass('frameChart-title') :wikitext(title) :done() end -- Create container for frame data frameChartDataHtml = mw.html.create('div') frameChartDataHtml:addClass('frameChart-data') html:node(frameChartDataHtml) drawFrame(startup, "startup") if isProjectile ~= nil then frameChartDataHtml :tag('div') :addClass('spawn-projectile') :done() end -- Alternate way of inputting multihits, only works for moves with a single gap in active frames if offset ~= nil then drawFrame(offset, "active") drawFrame(inactive, "inactive") drawFrame(active-offset, "active") else drawFrame(active, "active") end -- Option for inputting multihits, works for moves with 1+ gaps in the active frames index = 2 while tonumber(frame.args['active' .. index]) ~= nil or tonumber(frame.args['inactive' .. index]) ~= nil do drawFrame(frame.args['active' .. index], "active") drawFrame(frame.args['inactive' .. index], "inactive") index = index + 1 end if isStrikeProjectile ~= nil then frameChartDataHtml :tag('div') :addClass('spawn-projectile') :done() end drawFrame(recovery, "recovery") drawFrame(specialRecovery, "specialRecovery") html :tag('div') :addClass('frame-data-total') :wikitext("'''Total:''' " .. currentFrame ) :done() return tostring(html) .. mw.getCurrentFrame():extensionTag{ name = 'templatestyles', args = { src = 'Module:FrameChart/styles.css' } } end p.drawFrame = drawFrame p.checkCancel = checkCancel return p