Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Join the Playtest on Steam Now: SpiritVale

Module:GameSkills: Difference between revisions

From SpiritVale Wiki
No edit summary
No edit summary
Line 6: Line 6:
--  - Adds .sv-skill-card + data-max-level / data-level hooks for JS
--  - Adds .sv-skill-card + data-max-level / data-level hooks for JS
--  - Replaces large Lv1/Lv2/... lists with data-series dynamic spans
--  - Replaces large Lv1/Lv2/... lists with data-series dynamic spans
--  - NEW: Removes "General" + "Type" section bars and merges Level Select + Type into one unified top band
--        (Level Select on the left; Type/Element/Target/Cast Type list on the right)
--
--
-- Requires the JS you installed in MediaWiki:Common.js.
-- Requires the JS you installed in MediaWiki:Common.js.
Line 543: Line 545:
end
end


-- UPDATED: Special Mechanics now supports dynamic Per Level lists
-- Special Mechanics supports dynamic Per Level lists
local function formatMechanicEffects(effects, maxLevel, level)
local function formatMechanicEffects(effects, maxLevel, level)
if type(effects) ~= "table" then
if type(effects) ~= "table" then
Line 557: Line 559:
local parts = {}
local parts = {}


-- Helper: returns a dynamic amount when Per Level is a list
local function effectAmount(block)
local function effectAmount(block)
if type(block) ~= "table" then
if type(block) ~= "table" then
Line 565: Line 566:
local per = block["Per Level"]
local per = block["Per Level"]


-- If Per Level is a list, show a dynamic span unless it's flat (no scaling)
if type(per) == "table" and #per > 0 then
if type(per) == "table" and #per > 0 then
if isFlatList(per) then
if isFlatList(per) then
Line 577: Line 577:
end
end


-- Fallback: old raw text (scalar Base/Per Level)
local pair = { Base = block.Base, ["Per Level"] = block["Per Level"] }
local pair = { Base = block.Base, ["Per Level"] = block["Per Level"] }
local txt = valuePairRawText(pair)
local txt = valuePairRawText(pair)
Line 588: Line 587:
local t = block.Type
local t = block.Type


-- If effect has a Type, keep "Type - Name + Amount"
if t ~= nil and tostring(t) ~= "" then
if t ~= nil and tostring(t) ~= "" then
local amt = effectAmount(block)
local amt = effectAmount(block)
Line 596: Line 594:
end
end
table.insert(parts, seg)
table.insert(parts, seg)
-- Otherwise render like "Chains: <dynamic>"
else
else
local txt = valuePairDynamicText(name, block, maxLevel, level, ", ")
local txt = valuePairDynamicText(name, block, maxLevel, level, ", ")
Line 703: Line 699:


local amt = nil
local amt = nil
-- If this removal has a Per Level list, make it dynamic
if type(r["Per Level"]) == "table" and #r["Per Level"] > 0 and not isFlatList(r["Per Level"]) then
if type(r["Per Level"]) == "table" and #r["Per Level"] > 0 and not isFlatList(r["Per Level"]) then
local series = {}
local series = {}
Line 812: Line 807:


----------------------------------------------------------------------
----------------------------------------------------------------------
-- Infobox builder
-- Infobox builder (Top band: Level Select + Type)
----------------------------------------------------------------------
----------------------------------------------------------------------


local function buildLevelSelectUI(level, maxLevel)
local function buildLevelSelectUI(level, maxLevel)
-- Matches JS expectations:
-- JS expectations:
--  .sv-level-slider placeholder for the <input type="range">
--  .sv-level-slider placeholder for the <input type="range">
--  .sv-level-num span for updating the number
--  .sv-level-num span for updating the number
local wrap = mw.html.create("div")
local wrap = mw.html.create("div")
wrap:addClass("sv-level-ui")
wrap:addClass("sv-level-ui")
wrap:addClass("sv-level-box")


local label = wrap:tag("div"):addClass("sv-level-label")
-- Top box (label + current level)
label:wikitext("Level <span class=\"sv-level-num\">" .. tostring(level) .. "</span> / " .. tostring(maxLevel))
local top = wrap:tag("div"):addClass("sv-level-top")
top:tag("div"):addClass("sv-level-title"):wikitext("Level Select")
top:tag("div"):addClass("sv-level-label")
:wikitext("Level <span class=\"sv-level-num\">" .. tostring(level) .. "</span> / " .. tostring(maxLevel))
 
-- Bottom box (slider placeholder)
wrap:tag("div"):addClass("sv-level-bottom")
:tag("div"):addClass("sv-level-slider")


wrap:tag("div"):addClass("sv-level-slider")
return tostring(wrap)
return tostring(wrap)
end
local function buildTypeListUI(typeBlock)
if type(typeBlock) ~= "table" or next(typeBlock) == nil then
return nil
end
local wrap = mw.html.create("div")
wrap:addClass("sv-type-box")
local function addItem(label, value)
if not value or value == "" then return end
local row = wrap:tag("div"):addClass("sv-type-row")
row:tag("span"):addClass("sv-type-key"):wikitext(mw.text.nowiki(label))
row:tag("span"):addClass("sv-type-val"):wikitext(mw.text.nowiki(value))
end
local dt = typeBlock["Damage Type"]
if type(dt) == "table" and dt.Name then
addItem("Type", dt.Name) -- renamed from "Damage Type"
end
local et = typeBlock["Element Type"]
if type(et) == "table" and et.Name then
addItem("Element", et.Name)
end
local tt = typeBlock["Target Type"]
if type(tt) == "table" and tt.Name then
addItem("Target", tt.Name)
end
local ct = typeBlock["Cast Type"]
if type(ct) == "table" and ct.Name then
addItem("Cast Type", ct.Name)
end
-- If nothing was added, return nil
if not wrap or tostring(wrap) == "" then
return nil
end
return tostring(wrap)
end
local function addTopBand(tbl, levelUI, typeUI)
-- One row (colspan=2) that *contains* a 2-column grid:
--  - left: level select (top text + bottom slider)
--  - right: type list (label/value pairs)
if not levelUI and not typeUI then
return
end
local row = tbl:tag("tr")
local cell = row:tag("td")
cell:attr("colspan", 2)
cell:addClass("sv-topband-cell")
local wrap = cell:tag("div")
wrap:addClass("sv-skill-topband")
local left = wrap:tag("div"):addClass("sv-topband-left")
left:wikitext(levelUI or "")
local right = wrap:tag("div"):addClass("sv-topband-right")
right:wikitext(typeUI or "")
-- Styling is handled via Common.css (recommended).
end
end


Line 881: Line 950:
end
end


-- General
------------------------------------------------------------------
addSectionHeader(root, "General")
-- NEW: Unified top band (replaces "General" + "Type" section bars)
addRow(root, "Level Select", buildLevelSelectUI(level, maxLevel))
------------------------------------------------------------------
local typeUI = buildTypeListUI(rec.Type or {})
local levelUI = buildLevelSelectUI(level, maxLevel)
addTopBand(root, levelUI, typeUI)


------------------------------------------------------------------
-- Users (kept as rows, but no "General" header)
------------------------------------------------------------------
if showUsers then
if showUsers then
local users = rec.Users or {}
local users = rec.Users or {}
Line 893: Line 968:
end
end


------------------------------------------------------------------
-- Requirements
-- Requirements
------------------------------------------------------------------
local req = rec.Requirements or {}
local req = rec.Requirements or {}
if (req["Required Skills"] and #req["Required Skills"] > 0)
if (req["Required Skills"] and #req["Required Skills"] > 0)
Line 919: Line 996:
end
end


-- Type
------------------------------------------------------------------
local typeBlock = rec.Type or {}
if next(typeBlock) ~= nil then
addSectionHeader(root, "Type")
 
local dt = typeBlock["Damage Type"]
if type(dt) == "table" and dt.Name then
addRow(root, "Damage Type", dt.Name)
end
 
local et = typeBlock["Element Type"]
if type(et) == "table" and et.Name then
addRow(root, "Element", et.Name)
end
 
local tt = typeBlock["Target Type"]
if type(tt) == "table" and tt.Name then
addRow(root, "Target", tt.Name)
end
 
local ct = typeBlock["Cast Type"]
if type(ct) == "table" and ct.Name then
addRow(root, "Cast Type", ct.Name)
end
end
 
-- Mechanics
-- Mechanics
------------------------------------------------------------------
local mech = rec.Mechanics or {}
local mech = rec.Mechanics or {}
if next(mech) ~= nil then
if next(mech) ~= nil then
Line 951: Line 1,004:


addRow(root, "Range", formatUnitValue(mech.Range))
addRow(root, "Range", formatUnitValue(mech.Range))
addRow(root, "Area", formatArea(mech.Area, maxLevel, level))
addRow(root, "Area", formatArea(mech.Area, maxLevel, level))


Line 959: Line 1,011:


addRow(root, "Timing", formatTimingBlock(mech["Basic Timings"], maxLevel, level))
addRow(root, "Timing", formatTimingBlock(mech["Basic Timings"], maxLevel, level))
addRow(root, "Resource Cost", formatResourceCost(mech["Resource Cost"], maxLevel, level))
addRow(root, "Resource Cost", formatResourceCost(mech["Resource Cost"], maxLevel, level))
addRow(root, "Combo", formatCombo(mech.Combo))
addRow(root, "Combo", formatCombo(mech.Combo))


Line 968: Line 1,018:
end
end


------------------------------------------------------------------
-- Damage & Scaling
-- Damage & Scaling
------------------------------------------------------------------
local dmg = rec.Damage or {}
local dmg = rec.Damage or {}
if next(dmg) ~= nil then
if next(dmg) ~= nil then
Line 1,002: Line 1,054:
end
end


------------------------------------------------------------------
-- Modifiers
-- Modifiers
------------------------------------------------------------------
local modsText = formatModifiers(rec.Modifiers)
local modsText = formatModifiers(rec.Modifiers)
if modsText then
if modsText then
Line 1,009: Line 1,063:
end
end


------------------------------------------------------------------
-- Status
-- Status
------------------------------------------------------------------
local statusApps = formatStatusApplications(rec["Status Applications"], maxLevel, level)
local statusApps = formatStatusApplications(rec["Status Applications"], maxLevel, level)
local statusRem  = formatStatusRemoval(rec["Status Removal"], maxLevel, level)
local statusRem  = formatStatusRemoval(rec["Status Removal"], maxLevel, level)
Line 1,018: Line 1,074:
end
end


------------------------------------------------------------------
-- Events
-- Events
------------------------------------------------------------------
local eventsText = formatEvents(rec.Events)
local eventsText = formatEvents(rec.Events)
if eventsText then
if eventsText then
Line 1,025: Line 1,083:
end
end


------------------------------------------------------------------
-- Notes
-- Notes
------------------------------------------------------------------
if type(rec.Notes) == "table" and #rec.Notes > 0 then
if type(rec.Notes) == "table" and #rec.Notes > 0 then
addSectionHeader(root, "Notes")
addSectionHeader(root, "Notes")