More actions
Content deleted Content added
// via Wikitext Extension for VSCode |
// via Wikitext Extension for VSCode |
||
Line 1: | Line 1: | ||
local p = {} |
|||
local p = {} |
local p = {} |
||
local function makeBar(frame, title, content, link, flags, bottom) |
local function makeBar(frame, title, content, link, flags, bottom) |
||
-- ... (unchanged) |
|||
if content == '' then return '' end |
|||
local barSpace = mw.html.create('span') |
|||
barSpace:wikitext(frame:preprocess(' ')):css('display', 'none') |
|||
local barTitle = mw.html.create('span') |
|||
local barTitleClass = "{{lc:" .. title .. "}}" |
|||
barTitleClass = barTitleClass:gsub(' ', '-') |
|||
barTitleClass = barTitleClass:gsub('\'', '') |
|||
barTitleClass = barTitleClass:gsub('\"', '') |
|||
local barText = "{{ucfirst:" .. title .. "}}" |
|||
if link then barText = "[[" .. link .. "|" .. barText .. "]]" end |
|||
barText = barText .. ":" |
|||
barTitle:addClass('ability-bar-title'):wikitext(frame:preprocess(barText)) |
|||
:css('font-weight', 'bold'):css('margin-right', '0.5em') |
|||
local barContent = mw.html.create('span') |
|||
barContent:addClass('ability-bar-content'):wikitext(content) |
|||
local output = mw.html.create('div') |
|||
if bottom then output = mw.html.create('span') end |
|||
if not flags then flags = {} end |
|||
for k, v in pairs(flags) do |
|||
if type(v) == 'string' then |
|||
output:addClass('flag-' .. k .. '-' .. v) |
|||
end |
|||
end |
|||
output:addClass('ability-bar'):addClass('ability-bar-' .. barTitleClass) |
|||
:attr(flags):attr('test', 'out'):node(barSpace):node(barTitle):node( |
|||
barSpace):node(barContent):css('display', 'block') |
|||
-- if flags then |
|||
-- for k, v in ipairs(flags) do |
|||
-- output:attr(k, v) |
|||
-- end |
|||
-- end |
|||
return tostring(output) |
|||
end |
end |
||
-- === NEW: shared abilities parsing helpers === |
|||
function p.c(frame) |
|||
local function parseAbilitiesString(abilitiesString) |
|||
local args = frame.args |
|||
local rawAbilities = args['a'] or '' |
|||
-- === TAGS & CATEGORIES via TagBuilder === |
|||
local TagBuilder = require('Module:TagBuilder') |
|||
local tRaw = args['t'] or '' |
|||
local looks = args['l'] or '' |
|||
local name = args['name'] or '' |
|||
local baseHp = args['hp'] or '1' |
|||
local baseMp = args['mp'] or '1' |
|||
local size = args['size'] or '3' |
|||
local int = args['int'] or '0' |
|||
local str = args['str'] or '0' |
|||
local mov = args['mov'] or '0' |
|||
local snk = args['snk'] or '0' |
|||
local per = args['per'] or '0' |
|||
local preAbilities = '' |
|||
if (int == '0') then |
|||
preAbilities = preAbilities .. "Normal Intelligence;; " |
|||
end |
|||
if (str == '0') then preAbilities = preAbilities .. "Normal Strength;; " end |
|||
if (mov == '0') then preAbilities = preAbilities .. "Normal Movement;; " end |
|||
if (snk == '0') then preAbilities = preAbilities .. "Normal Sneak;; " end |
|||
if (per == '0') then |
|||
preAbilities = preAbilities .. "Normal Perception;; " |
|||
end |
|||
local abilitiesString = preAbilities .. rawAbilities |
|||
local opts = { |
|||
name = name, |
|||
ns = 'Creature', -- gate categories to the Creature namespace |
|||
transparent = args.o or args.transparent -- optional passthrough |
|||
} |
|||
-- Use TagCreatures data and traits scope |
|||
local tagOut, catOut = |
|||
TagBuilder.build(tRaw, 'TagCreatures', 'traits', opts) |
|||
-- === Parse abilities into a structured table === |
|||
local abilities = {} |
local abilities = {} |
||
for ability in mw.text.gsplit(abilitiesString, ";;", true) do |
for ability in mw.text.gsplit(abilitiesString or '', ";;", true) do |
||
ability = mw.text.trim(ability) |
ability = mw.text.trim(ability) |
||
if ability ~= "" then |
if ability ~= "" then |
||
Line 87: | Line 22: | ||
-- notes (order-insensitive, tolerate any following marker) |
-- notes (order-insensitive, tolerate any following marker) |
||
local limitedMatch = mw.ustring.match(ability, |
local limitedMatch = mw.ustring.match(ability, "%-l%-(.-)(%-[liag]%-|$)") |
||
or mw.ustring.match(ability, "%-l%-(.+)$") |
|||
mw.ustring.match(ability, "%-l%-(.+)$") |
|||
if limitedMatch then limited = mw.text.trim(limitedMatch) end |
if limitedMatch then limited = mw.text.trim(limitedMatch) end |
||
local improvedMatch = mw.ustring.match(ability, |
local improvedMatch = mw.ustring.match(ability, "%-i%-(.-)(%-[liag]%-|$)") |
||
or mw.ustring.match(ability, "%-i%-(.+)$") |
|||
if improvedMatch then improved = mw.text.trim(improvedMatch) end |
|||
if improvedMatch then |
|||
improved = mw.text.trim(improvedMatch) |
|||
end |
|||
-- clean name (strip markers + |
-- clean name (strip markers + payloads/flags) |
||
name = mw.ustring.gsub(name, "%-l%-.+", "") |
name = mw.ustring.gsub(name, "%-l%-.+", "") |
||
name = mw.ustring.gsub(name, "%-i%-.+", "") |
name = mw.ustring.gsub(name, "%-i%-.+", "") |
||
Line 116: | Line 47: | ||
end |
end |
||
-- Sort alphabetically by name (stable) |
|||
table.sort(abilities, function(a, b) return a.name < b.name end) |
table.sort(abilities, function(a, b) return a.name < b.name end) |
||
return abilities |
|||
end |
|||
local function buildAETransclusions(abilities) |
|||
-- Build the out string (NO visible separators between AE templates) |
|||
local transclusions = {} |
local transclusions = {} |
||
for _, a in ipairs(abilities) do |
for _, a in ipairs(abilities or {}) do |
||
local t = {"{{AE|", a.name} |
local t = {"{{AE|", a.name} |
||
if a.limited ~= "" then table.insert(t, "|limited=" .. a.limited) end |
if a.limited ~= "" then table.insert(t, "|limited=" .. a.limited) end |
||
if a.improved ~= "" then |
if a.improved ~= "" then table.insert(t, "|improved=" .. a.improved) end |
||
table.insert(t, "|improved=" .. a.improved) |
|||
end |
|||
if a.gifted then table.insert(t, "|gifted=1") end |
if a.gifted then table.insert(t, "|gifted=1") end |
||
if a.adept then table.insert(t, "|adept=1") end |
if a.adept then table.insert(t, "|adept=1") end |
||
table.insert(t, "}}") |
table.insert(t, "}}") |
||
table.insert(transclusions, table.concat(t)) |
table.insert(transclusions, table.concat(t)) |
||
end |
end |
||
-- no visible separators between AE templates |
|||
return table.concat(transclusions, "") |
|||
end |
|||
-- === END helpers === |
|||
function p.c(frame) |
|||
-- Use "" (or "\n") so no semicolons are emitted |
|||
local |
local args = frame.args |
||
local rawAbilities = args['a'] or '' |
|||
-- === TAGS & CATEGORIES via TagBuilder === |
|||
local categoryString = '' |
|||
local TagBuilder = require('Module:TagBuilder') |
|||
local tRaw = args['t'] or '' |
|||
local looks = args['l'] or '' |
|||
local name = args['name'] or '' |
|||
local baseHp = args['hp'] or '1' |
|||
local baseMp = args['mp'] or '1' |
|||
local size = args['size'] or '3' |
|||
local int = args['int'] or '0' |
|||
local str = args['str'] or '0' |
|||
local mov = args['mov'] or '0' |
|||
local snk = args['snk'] or '0' |
|||
local per = args['per'] or '0' |
|||
local |
local preAbilities = '' |
||
if (int == '0') then preAbilities = preAbilities .. "Normal Intelligence;; " end |
|||
statContent = |
|||
if (str == '0') then preAbilities = preAbilities .. "Normal Strength;; " end |
|||
statContent .. "{{Tag|" .. baseHp .. " HP|❤️|l=:Category:" .. baseHp .. |
|||
if (mov == '0') then preAbilities = preAbilities .. "Normal Movement;; " end |
|||
" HP creatures|c=#e01b24|class=cost-tagged hp" .. baseHp .. "}}" |
|||
if (snk == '0') then preAbilities = preAbilities .. "Normal Sneak;; " end |
|||
categoryString = categoryString .. "[[Category:" .. baseHp .. |
|||
if (per == '0') then preAbilities = preAbilities .. "Normal Perception;; " end |
|||
" HP creatures" .. "]]" |
|||
statContent = |
|||
local abilitiesString = preAbilities .. rawAbilities |
|||
statContent .. "{{Tag|" .. baseMp .. " MP|🩵|l=:Category:" .. baseMp .. |
|||
local opts = { |
|||
" MP creatures|c=#3584e4|class=cost-tagged hp" .. baseMp .. "}}" |
|||
name = name, |
|||
categoryString = categoryString .. "[[Category:" .. baseMp .. |
|||
ns = 'Creature', |
|||
" MP creatures" .. "]]" |
|||
transparent = args.o or args.transparent |
|||
statContent = statContent .. "{{Tag|Size " .. size .. |
|||
} |
|||
"|⬆️|l=:Category:Size " .. size .. |
|||
local tagOut, catOut = TagBuilder.build(tRaw, 'TagCreatures', 'traits', opts) |
|||
" creatures|c=#e4a835|class=size-tagged size" .. size .. |
|||
"}}" |
|||
-- === Parse and render main abilities with shared helpers === |
|||
categoryString = categoryString .. "[[Category:Size " .. size .. |
|||
local abilities = parseAbilitiesString(abilitiesString) |
|||
" creatures" .. "]]" |
|||
local inner = buildAETransclusions(abilities) |
|||
local categoryString = '' |
|||
-- (stats/attributes rendering unchanged) |
|||
local attributeContent = '' |
|||
-- ... |
|||
attributeContent = "" |
|||
attributeContent = attributeContent .. "{{Tag|" .. int .. |
|||
"|INT|l=:Category:INT value of " .. int .. |
|||
" creatures}}" |
|||
categoryString = categoryString .. "[[Category:INT value of " .. int .. |
|||
" creatures]]" |
|||
attributeContent = attributeContent .. "{{Tag|" .. str .. |
|||
"|STR|l=:Category:STR value of " .. str .. |
|||
" creatures}}" |
|||
categoryString = categoryString .. "[[Category:STR value of " .. str .. |
|||
" creatures]]" |
|||
attributeContent = attributeContent .. "{{Tag|" .. mov .. |
|||
"|MOV|l=:Category:MOV value of " .. mov .. |
|||
" creatures}}" |
|||
categoryString = categoryString .. "[[Category:MOV value of " .. mov .. |
|||
" creatures]]" |
|||
attributeContent = attributeContent .. "{{Tag|" .. snk .. |
|||
"|SNK|l=:Category:SNK value of " .. snk .. |
|||
" creatures}}" |
|||
categoryString = categoryString .. "[[Category:SNK value of " .. snk .. |
|||
" creatures]]" |
|||
attributeContent = attributeContent .. "{{Tag|" .. per .. |
|||
"|PER|l=:Category:PER value of " .. per .. |
|||
" creatures}}" |
|||
categoryString = categoryString .. "[[Category:PER value of " .. per .. |
|||
" creatures]]" |
|||
-- Assemble output: tags (visible), abilities, then categories (gated by name/ns) |
|||
local out = "" |
local out = "" |
||
out = out .. makeBar(frame, "Stats", statContent, nul, nul, false) |
out = out .. makeBar(frame, "Stats", statContent, nul, nul, false) |
||
Line 192: | Line 116: | ||
if args['lifespan'] then |
if args['lifespan'] then |
||
local lifespanText = args['lifespan'] .. " years." |
local lifespanText = args['lifespan'] .. " years." |
||
categoryString = categoryString .. "[[Category:" .. args['lifespan'] .. |
categoryString = categoryString .. "[[Category:" .. args['lifespan'] .. " year lifespan creatures]]" |
||
" year lifespan creatures]]" |
|||
if args['adult'] then |
if args['adult'] then |
||
lifespanText = lifespanText .. " Adult at age " .. args['adult'] .. |
lifespanText = lifespanText .. " Adult at age " .. args['adult'] .. "." |
||
"." |
|||
end |
end |
||
out = out .. makeBar(frame, "Lifespan", lifespanText, nul, nul, false) |
out = out .. makeBar(frame, "Lifespan", lifespanText, nul, nul, false) |
||
end |
end |
||
out = out .. '<hr>' |
out = out .. '<hr>' |
||
if args['d'] then out = out .. args['d'] .. '<hr>' end |
if args['d'] then out = out .. args['d'] .. '<hr>' end |
||
out = out .. '<div class="expandable-table"><div>' .. |
|||
frame:preprocess(inner) .. '</div></div>' |
|||
out = out .. (catOut or '') |
|||
-- |
-- main abilities block |
||
out = out .. '<div class="expandable-table"><div>' .. frame:preprocess(inner) .. '</div></div>' |
|||
-- out = out .. '<hr>' |
|||
-- === familiar abilities (args['f']) using the same parsing === |
|||
if args['f'] and mw.text.trim(args['f']) ~= '' then |
|||
local fAbilities = parseAbilitiesString(args['f']) |
|||
local fInner = buildAETransclusions(fAbilities) |
|||
-- You can wrap in a bar or just mirror the main output style; here we label it: |
|||
out = out .. makeBar(frame, "Familiar Abilities", |
|||
frame:preprocess('<div class="expandable-table"><div>' .. fInner .. '</div></div>'), |
|||
nul, nul, false) |
|||
end |
|||
out = out .. (catOut or '') |
|||
local page = mw.title.getCurrentTitle().text |
local page = mw.title.getCurrentTitle().text |
||
Line 215: | Line 147: | ||
end |
end |
||
-- local tt = mw.title.makeTitle("Ability", "Normal Strength") |
|||
-- out = out .. tt.categories |
|||
-- Preprocess the whole thing so {{Tag}} expands |
|||
return frame:preprocess(out) |
return frame:preprocess(out) |
||
end |
end |
Revision as of 22:03, 12 August 2025
Documentation for this module may be created at Module:C/doc
local p = {}
local p = {}
local function makeBar(frame, title, content, link, flags, bottom)
-- ... (unchanged)
end
-- === NEW: shared abilities parsing helpers ===
local function parseAbilitiesString(abilitiesString)
local abilities = {}
for ability in mw.text.gsplit(abilitiesString or '', ";;", true) do
ability = mw.text.trim(ability)
if ability ~= "" then
local name = ability
local limited, improved = "", ""
local gifted, adept = false, false
-- flags
if mw.ustring.find(ability, "%-g%-") then gifted = true end
if mw.ustring.find(ability, "%-a%-") then adept = true end
-- notes (order-insensitive, tolerate any following marker)
local limitedMatch = mw.ustring.match(ability, "%-l%-(.-)(%-[liag]%-|$)")
or mw.ustring.match(ability, "%-l%-(.+)$")
if limitedMatch then limited = mw.text.trim(limitedMatch) end
local improvedMatch = mw.ustring.match(ability, "%-i%-(.-)(%-[liag]%-|$)")
or mw.ustring.match(ability, "%-i%-(.+)$")
if improvedMatch then improved = mw.text.trim(improvedMatch) end
-- clean name (strip markers + payloads/flags)
name = mw.ustring.gsub(name, "%-l%-.+", "")
name = mw.ustring.gsub(name, "%-i%-.+", "")
name = mw.ustring.gsub(name, "%-g%-", "")
name = mw.ustring.gsub(name, "%-a%-", "")
name = mw.text.trim(name)
table.insert(abilities, {
name = name,
limited = limited,
improved = improved,
gifted = gifted,
adept = adept
})
end
end
table.sort(abilities, function(a, b) return a.name < b.name end)
return abilities
end
local function buildAETransclusions(abilities)
local transclusions = {}
for _, a in ipairs(abilities or {}) do
local t = {"{{AE|", a.name}
if a.limited ~= "" then table.insert(t, "|limited=" .. a.limited) end
if a.improved ~= "" then table.insert(t, "|improved=" .. a.improved) end
if a.gifted then table.insert(t, "|gifted=1") end
if a.adept then table.insert(t, "|adept=1") end
table.insert(t, "}}")
table.insert(transclusions, table.concat(t))
end
-- no visible separators between AE templates
return table.concat(transclusions, "")
end
-- === END helpers ===
function p.c(frame)
local args = frame.args
local rawAbilities = args['a'] or ''
-- === TAGS & CATEGORIES via TagBuilder ===
local TagBuilder = require('Module:TagBuilder')
local tRaw = args['t'] or ''
local looks = args['l'] or ''
local name = args['name'] or ''
local baseHp = args['hp'] or '1'
local baseMp = args['mp'] or '1'
local size = args['size'] or '3'
local int = args['int'] or '0'
local str = args['str'] or '0'
local mov = args['mov'] or '0'
local snk = args['snk'] or '0'
local per = args['per'] or '0'
local preAbilities = ''
if (int == '0') then preAbilities = preAbilities .. "Normal Intelligence;; " end
if (str == '0') then preAbilities = preAbilities .. "Normal Strength;; " end
if (mov == '0') then preAbilities = preAbilities .. "Normal Movement;; " end
if (snk == '0') then preAbilities = preAbilities .. "Normal Sneak;; " end
if (per == '0') then preAbilities = preAbilities .. "Normal Perception;; " end
local abilitiesString = preAbilities .. rawAbilities
local opts = {
name = name,
ns = 'Creature',
transparent = args.o or args.transparent
}
local tagOut, catOut = TagBuilder.build(tRaw, 'TagCreatures', 'traits', opts)
-- === Parse and render main abilities with shared helpers ===
local abilities = parseAbilitiesString(abilitiesString)
local inner = buildAETransclusions(abilities)
local categoryString = ''
-- (stats/attributes rendering unchanged)
-- ...
local out = ""
out = out .. makeBar(frame, "Stats", statContent, nul, nul, false)
out = out .. makeBar(frame, "Attributes", attributeContent, nul, nul, false)
out = out .. makeBar(frame, "Traits", (tagOut or ''), nul, nul, false)
out = out .. makeBar(frame, "Looks", looks, nul, nul, false)
if args['lifespan'] then
local lifespanText = args['lifespan'] .. " years."
categoryString = categoryString .. "[[Category:" .. args['lifespan'] .. " year lifespan creatures]]"
if args['adult'] then
lifespanText = lifespanText .. " Adult at age " .. args['adult'] .. "."
end
out = out .. makeBar(frame, "Lifespan", lifespanText, nul, nul, false)
end
out = out .. '<hr>'
if args['d'] then out = out .. args['d'] .. '<hr>' end
-- main abilities block
out = out .. '<div class="expandable-table"><div>' .. frame:preprocess(inner) .. '</div></div>'
-- === familiar abilities (args['f']) using the same parsing ===
if args['f'] and mw.text.trim(args['f']) ~= '' then
local fAbilities = parseAbilitiesString(args['f'])
local fInner = buildAETransclusions(fAbilities)
-- You can wrap in a bar or just mirror the main output style; here we label it:
out = out .. makeBar(frame, "Familiar Abilities",
frame:preprocess('<div class="expandable-table"><div>' .. fInner .. '</div></div>'),
nul, nul, false)
end
out = out .. (catOut or '')
local page = mw.title.getCurrentTitle().text
local namespace = frame:preprocess('{{NAMESPACE}}')
if ((namespace == "Creature") and (page == name)) then
out = out .. categoryString
end
return frame:preprocess(out)
end
return p