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:GameInfo/Skills: Difference between revisions

From SpiritVale Wiki
No edit summary
Tags: Mobile edit Mobile web edit
No edit summary
Tags: Mobile edit Mobile web edit
Line 395: Line 395:
local body = pop:tag("div"):addClass("sv-tip-pop-body")
local body = pop:tag("div"):addClass("sv-tip-pop-body")
_render_notes_body(body, notes_wt)
_render_notes_body(body, notes_wt)
return wrap
end
-- ----------------------------------------------------------------------------
-- OVERCAP (Schema 2): Option A (Universal Popups)
-- Goal:
-- - Show a compact trigger near the level UI: "Overcap +N"
-- - Popup lists sources (links) and the level bonus each provides.
-- - If a source omits levels and it's the only missing one, infer from (max-default).
-- - If multiple sources omit levels, show "(+?)" for those items.
-- - No new slider CSS required; uses existing sv-tip / sv-tip-pop styling + Common.js popups.
-- ----------------------------------------------------------------------------
local function _normalize_overcap_sources(sources, total_bonus)
sources = _safe_tbl(sources)
local out = {}
local missing = 0
local explicit_sum = 0
for _, s in ipairs(sources) do
local page = ""
local lv = nil
if type(s) == "string" then
page = _trim(s)
elseif type(s) == "table" then
-- Accept {page="X", levels=2} and also array-ish { "X", 2 }
page = _safe_str(s.page or s[1] or "", "")
lv = _to_int(s.levels or s.level or s[2], nil)
end
if page ~= "" then
if lv and lv > 0 then
explicit_sum = explicit_sum + lv
else
lv = nil
missing = missing + 1
end
table.insert(out, { page = page, levels = lv })
end
end
local remaining = (_to_int(total_bonus, 0) or 0) - explicit_sum
if remaining < 0 then remaining = 0 end
-- If exactly one source is missing levels, infer it from the remaining bonus.
if missing == 1 and remaining > 0 then
for _, it in ipairs(out) do
if it.levels == nil then
it.levels = remaining
break
end
end
end
return out
end
local function _build_overcap_tip(root_id, default_cap, max_cap, sources)
default_cap = _to_int(default_cap, 1) or 1
max_cap = _to_int(max_cap, default_cap) or default_cap
if max_cap <= default_cap then return nil end
local total = max_cap - default_cap
local tip_id = root_id .. "-overcap"
local norm = _normalize_overcap_sources(sources, total)
-- If no sources provided, still show the badge, but mark unknown.
local show_unknown = (#norm == 0)
local wrap = mw.html.create("span")
:addClass("sv-tip")
:addClass("sv-overcap-tip")
local btn = wrap:tag("span")
:addClass("sv-tip-btn")
:addClass("sv-overcap-btn")
:attr("role", "button")
:attr("tabindex", "0")
:attr("data-sv-toggle", "1")
-- Click-only near slider (avoid hover spam while dragging)
:attr("data-sv-pop", "click")
:attr("data-sv-pop-size", "sm")
:attr("aria-label", "Overcap")
:attr("aria-controls", tip_id)
:attr("aria-expanded", "false")
:wikitext(mw.text.nowiki("Overcap +" .. tostring(total)))
local pop = wrap:tag("div")
:addClass("sv-tip-pop")
:addClass("sv-hidden")
:attr("hidden", "hidden")
:attr("id", tip_id)
:attr("aria-label", "Overcap")
local head = pop:tag("div"):addClass("sv-tip-pop-head")
head:tag("div"):addClass("sv-tip-pop-title"):wikitext("Overcap sources")
local body = pop:tag("div"):addClass("sv-tip-pop-body")
-- Summary line (always helpful)
body:tag("div"):addClass("sv-overcap-summary"):wikitext(mw.text.nowiki(
"Raises max from " .. tostring(default_cap) .. " to " .. tostring(max_cap) .. " (+" .. tostring(total) .. ")."
))
local ul = body:tag("ul"):addClass("sv-disclose-list")
if show_unknown then
ul:tag("li"):wikitext("Source unknown")
else
for _, it in ipairs(norm) do
local li = ul:tag("li")
local page = _safe_str(it.page, "")
if page ~= "" then
li:wikitext(string.format("[[%s|%s]]", page, mw.text.nowiki(page)))
else
li:wikitext("—")
end
if it.levels ~= nil and it.levels > 0 then
li:wikitext(mw.text.nowiki(" (+" .. tostring(it.levels) .. ")"))
else
-- Multiple sources but missing per-source split
li:wikitext(mw.text.nowiki(" (+?)"))
end
end
end


return wrap
return wrap
Line 748: Line 879:
end
end


local function _build_level(default_level, max_level, min_level)
local function _build_level(root_id, default_level, max_level, min_level, overcap_obj)
local min = _to_int(min_level, 1)
local min = _to_int(min_level, 1)
local default = _to_int(default_level, 1)
local default = _to_int(default_level, 1)
Line 767: Line 898:
label:wikitext(" / ")
label:wikitext(" / ")
label:tag("span"):addClass("sv-level-max"):wikitext(tostring(max))
label:tag("span"):addClass("sv-level-max"):wikitext(tostring(max))
-- Overcap badge + popup (Schema 2)
if type(overcap_obj) == "table" and max > default then
local oc = _safe_tbl(overcap_obj)
local tip = _build_overcap_tip(root_id, default, max, oc.sources)
if tip then ui:node(tip) end
elseif max > default then
-- Defensive fallback (in case a future schema sets max>default but omits overcap object)
local tip = _build_overcap_tip(root_id, default, max, nil)
if tip then ui:node(tip) end
end


local slider_wrap = root:tag("div"):addClass("sv-level-slider")
local slider_wrap = root:tag("div"):addClass("sv-level-slider")
Line 1,208: Line 1,350:
if reqrow then box.top:node(reqrow) end
if reqrow then box.top:node(reqrow) end


local level_panel, actual_default = _build_level(default_level, max_level, 1)
local level_panel, actual_default = _build_level(root_id, default_level, max_level, 1, nil)


box.bottom:node(level_panel)
box.bottom:node(level_panel)
Line 1,242: Line 1,384:
box.top:addClass("sv-skill-top")
box.top:addClass("sv-skill-top")
box.bottom:addClass("sv-skill-bottom")
box.bottom:addClass("sv-skill-bottom")
-- Helpful attributes (optional / future-proof)
box.root:attr("data-level-default", tostring(default_level))
do
local oc = _safe_tbl(_safe_tbl(payload.level).overcap)
if next(oc) ~= nil then
local safe_oc = { max = _to_int(oc.max, max_level), sources = _safe_tbl(oc.sources) }
box.root:attr("data-level-overcap", mw.text.jsonEncode(safe_oc))
end
end


box.top:node(_build_identity(frame, root_id, identity, notes_wt))
box.top:node(_build_identity(frame, root_id, identity, notes_wt))
Line 1,249: Line 1,401:
if reqrow then box.top:node(reqrow) end
if reqrow then box.top:node(reqrow) end


local level_panel, actual_default = _build_level(default_level, max_level, min_level)
local level_panel, actual_default = _build_level(root_id, default_level, max_level, min_level, _safe_tbl(payload.level).overcap)


box.bottom:node(level_panel)
box.bottom:node(level_panel)