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 959: Line 959:


-- ============================================================
-- ============================================================
-- Module 3 – Skill Source (Basis + Source + Scaling)
-- Module 3 – Skill Source (Modifier + Source + Scaling)
-- UPDATES:
-- - Modifier column (optional): "Modifier" pill + Attack/Magic Attack/Hybrid
-- 1) If basisWord is nil/empty -> hide column 1 entirely
-- - Source column: Kind pill + big % value
-- 2) Basis word is bold + emphasis; "Magic Attack" forced to wrap nicely
-- - Scaling column: "Scaling" pill + compact lines
-- 3) Source/Scaling pills always align (header row), regardless of scaling height
--
-- RULE: If BOTH Source and Scaling are missing -> return nil (slot stays blank)
-- - Supports BOTH new (rec.Source) and legacy (rec.Damage) formats.
-- ============================================================
-- ============================================================


Line 1,009: Line 1,011:
end
end


-- Prefer the “current level value” (dynSpan when we have a series list)
local function sourceValueForLevel(src, maxLevel, level)
local function sourceValueForLevel(src, maxLevel, level)
if type(src) ~= "table" then
if type(src) ~= "table" then
Line 1,017: Line 1,020:
local per  = src["Per Level"]
local per  = src["Per Level"]


-- Preferred: expanded series list (wikiprep)
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 1,031: Line 1,035:
end
end


-- Fallback: may show "X (Per Level: Y)" if not expanded
return valuePairDynamicValueOnly(src, maxLevel, level)
return valuePairDynamicValueOnly(src, maxLevel, level)
end
end


-- Legacy (pre-Source) damage entry: compute a simple % at the current level
local function legacyPercentAtLevel(entry, level)
local function legacyPercentAtLevel(entry, level)
if type(entry) ~= "table" then
if type(entry) ~= "table" then
Line 1,044: Line 1,050:
local perN    = toNum(perRaw)
local perN    = toNum(perRaw)


-- If Per Level exists, level 1 shows at least per*1 even when base is 0/missing.
if perN ~= nil and perN ~= 0 then
if perN ~= nil and perN ~= 0 then
local total = (baseN or 0) + (perN * level)
local total = (baseN or 0) + (perN * level)
Line 1,057: Line 1,064:


return nil
return nil
end
local function buildBasisMarkup(word)
if not word or word == "" then
return nil
end
local wrap = mw.html.create("div")
wrap:addClass("sv-basis-word")
wrap:addClass("sv-basis-emph")
local strong = wrap:tag("strong")
if word == "Magic Attack" then
-- forced clean wrap at the desired boundary
strong:wikitext("Magic<br />Attack")
else
strong:wikitext(mw.text.nowiki(word))
end
return tostring(wrap)
end
end


Line 1,086: Line 1,072:
local scaling    = nil
local scaling    = nil


-- Preferred: new unified Source block
if type(rec.Source) == "table" then
if type(rec.Source) == "table" then
local src = rec.Source
local src = rec.Source


local atkFlag  = src["ATK-Based"] == true
local atkFlag  = (src["ATK-Based"] == true)
local matkFlag = src["MATK-Based"] == true
local matkFlag = (src["MATK-Based"] == true)
basisWord = basisWordFromFlags(atkFlag, matkFlag)
basisWord = basisWordFromFlags(atkFlag, matkFlag)


Line 1,098: Line 1,085:
end
end


-- Backcompat: legacy Damage block
if (sourceVal == nil or sourceVal == "") and type(rec.Damage) == "table" then
if (sourceVal == nil or sourceVal == "") and type(rec.Damage) == "table" then
local dmg = rec.Damage
local dmg = rec.Damage
Line 1,106: Line 1,094:
local flat = dmg["Flat Damage"]
local flat = dmg["Flat Damage"]


-- priority: Main Damage > Reflect > Flat
if type(main) == "table" and #main > 0 then
if type(main) == "table" and #main > 0 then
local pick = nil
local pick = nil
Line 1,117: Line 1,106:


if type(pick) == "table" then
if type(pick) == "table" then
local atkFlag  = pick["ATK-Based"] == true
local atkFlag  = (pick["ATK-Based"] == true)
local matkFlag = pick["MATK-Based"] == true
local matkFlag = (pick["MATK-Based"] == true)
basisWord = basisWord or basisWordFromFlags(atkFlag, matkFlag)
basisWord = basisWord or basisWordFromFlags(atkFlag, matkFlag)


Line 1,126: Line 1,115:
elseif type(refl) == "table" and #refl > 0 and type(refl[1]) == "table" then
elseif type(refl) == "table" and #refl > 0 and type(refl[1]) == "table" then
local pick = refl[1]
local pick = refl[1]
local atkFlag  = pick["ATK-Based"] == true
local atkFlag  = (pick["ATK-Based"] == true)
local matkFlag = pick["MATK-Based"] == true
local matkFlag = (pick["MATK-Based"] == true)
basisWord = basisWord or basisWordFromFlags(atkFlag, matkFlag)
basisWord = basisWord or basisWordFromFlags(atkFlag, matkFlag)


Line 1,134: Line 1,123:
elseif type(flat) == "table" and #flat > 0 and type(flat[1]) == "table" then
elseif type(flat) == "table" and #flat > 0 and type(flat[1]) == "table" then
local pick = flat[1]
local pick = flat[1]
local atkFlag  = pick["ATK-Based"] == true
local atkFlag  = (pick["ATK-Based"] == true)
local matkFlag = pick["MATK-Based"] == true
local matkFlag = (pick["MATK-Based"] == true)
basisWord = basisWord or basisWordFromFlags(atkFlag, matkFlag)
basisWord = basisWord or basisWordFromFlags(atkFlag, matkFlag)


Line 1,147: Line 1,136:
local hasScaling  = (type(scalingLines) == "table" and #scalingLines > 0)
local hasScaling  = (type(scalingLines) == "table" and #scalingLines > 0)


-- RULE: if neither exists, leave module 3 blank
if (not hasSource) and (not hasScaling) then
if (not hasSource) and (not hasScaling) then
return nil
return nil
end
end


local basisMarkup = buildBasisMarkup(basisWord)
local hasMod = (basisWord ~= nil and tostring(basisWord) ~= "")
local hasBasis = (basisMarkup ~= nil and basisMarkup ~= "")


-- Classes drive grid layout in CSS
local extra = { "skill-source-module" }
local extra = { "skill-source-module" }
if hasSource then table.insert(extra, "sv-has-source") end
table.insert(extra, hasMod and "sv-has-mod" or "sv-no-mod")
if hasScaling then table.insert(extra, "sv-has-scaling") end
 
if hasBasis then
if hasSource and (not hasScaling) then
table.insert(extra, "sv-has-basis")
table.insert(extra, "sv-only-source")
else
elseif hasScaling and (not hasSource) then
table.insert(extra, "sv-no-basis")
table.insert(extra, "sv-only-scaling")
end
end


local wrap = mw.html.create("div")
local wrap = mw.html.create("div")
wrap:addClass("sv-source-grid")
wrap:addClass("sv-source-grid")
wrap:addClass(hasBasis and "sv-source-cols-3" or "sv-source-cols-2")


-- Helper to add a cell
-- Column 1: Modifier (optional)
local function addCell(row, colClass)
if hasMod then
local c = row:tag("div")
local modCol = wrap:tag("div"):addClass("sv-source-col"):addClass("sv-source-modifier")
c:addClass("sv-source-cell")
modCol:tag("div")
if colClass then c:addClass(colClass) end
:addClass("sv-source-pill")
return c
:wikitext("Modifier")
modCol:tag("div")
:addClass("sv-modifier-value")
:wikitext(mw.text.nowiki(basisWord))
end
end


-- Row 1: header pills (kept parallel)
-- Column 2: Source (optional)
local head = wrap:tag("div"):addClass("sv-source-row"):addClass("sv-source-head")
 
if hasBasis then
addCell(head, "sv-source-basis-head") -- empty header cell for alignment
end
 
local sourceHead = addCell(head, "sv-source-main-head")
if hasSource then
if hasSource then
sourceHead:tag("div")
local sourceCol = wrap:tag("div"):addClass("sv-source-col"):addClass("sv-source-main")
sourceCol:tag("div")
:addClass("sv-source-pill")
:addClass("sv-source-pill")
:wikitext(mw.text.nowiki(sourceKind or "Damage"))
:wikitext(mw.text.nowiki(sourceKind or "Source"))
sourceCol:tag("div")
:addClass("sv-source-value")
:wikitext(sourceVal)
end
end


local scalingHead = addCell(head, "sv-source-scaling-head")
-- Column 3: Scaling (optional)
if hasScaling then
if hasScaling then
scalingHead:tag("div")
local scalingCol = wrap:tag("div"):addClass("sv-source-col"):addClass("sv-source-scaling")
scalingCol:tag("div")
:addClass("sv-source-pill")
:addClass("sv-source-pill")
:wikitext("Scaling")
:wikitext("Scaling")
end
-- Row 2: values/content
local body = wrap:tag("div"):addClass("sv-source-row"):addClass("sv-source-body")
if hasBasis then
addCell(body, "sv-source-basis"):wikitext(basisMarkup)
end
local sourceBody = addCell(body, "sv-source-main")
if hasSource then
sourceBody:tag("div")
:addClass("sv-source-value")
:wikitext(sourceVal)
end


local scalingBody = addCell(body, "sv-source-scaling")
local list = scalingCol:tag("div"):addClass("sv-scaling-list")
if hasScaling then
local list = scalingBody:tag("div"):addClass("sv-scaling-list")
for _, line in ipairs(scalingLines) do
for _, line in ipairs(scalingLines) do
list:tag("div")
list:tag("div")
Line 1,221: Line 1,194:


return moduleBox(3, extra, tostring(wrap), false)
return moduleBox(3, extra, tostring(wrap), false)
end
local function buildEmptyModule(slot)
return moduleBox(slot, nil, "", true)
end
end