Modul:HeroCard: Unterschied zwischen den Versionen
Die Seite wurde neu angelegt: „-- Modul:HeroCard local p = {} -- ======= CONFIG / DEFAULTS ======= local CFG = { -- Reihenfolge + Labels/Standard-Icons für Haupt-/Erweiterte Attribute main_order = { "damage", "hp", "armor" }, main_meta = { damage = { label = "Damage", icon = "AttackIcon.png" }, hp = { label = "Health", icon = "HealthIcon.png" }, armor = { label = "Armor", icon = "ArmorIcon.png" }, }, adv_order = { "precision", "bonus_damag…“ |
Keine Bearbeitungszusammenfassung |
||
| Zeile 51: | Zeile 51: | ||
if isempty(s) then return "" end | if isempty(s) then return "" end | ||
s = mw.ustring.lower(mw.text.trim(s)) | s = mw.ustring.lower(mw.text.trim(s)) | ||
s = s:gsub("%s+", " ") | s = s:gsub("%s+", " ") | ||
return s | return s | ||
| Zeile 65: | Zeile 64: | ||
local function heroFromData(name) | local function heroFromData(name) | ||
local ok, data = pcall(require, "Modul:HeroData") | local ok, data = pcall(require, "Modul:HeroData") -- auf DE: „Modul:“ | ||
if not ok or type(data) ~= "table" then return nil end | if not ok or type(data) ~= "table" then return nil end | ||
local H = data.heroes or {} | local H = data.heroes or {} | ||
| Zeile 83: | Zeile 82: | ||
if not isempty(override) then return override end | if not isempty(override) then return override end | ||
local t = CFG.icon_map[kind] or {} | local t = CFG.icon_map[kind] or {} | ||
return t[norm(value)] | |||
end | end | ||
local function pill(htmlParent, label, val, icon) | local function pill(htmlParent, label, val, icon) | ||
if isempty(val) then return end | if isempty(val) then return end | ||
local box = htmlParent:tag("div"):addClass("kr-hc-pill") | local box = htmlParent:tag("div"):addClass("kr-hc-pill") | ||
local left = box:tag("div"):addClass("kr-hc-pill-icon") | local left = box:tag("div"):addClass("kr-hc-pill-icon") | ||
if not isempty(icon) then left:wikitext(fileWikitext(icon, { size="24x24px", link="" })) end | if not isempty(icon) then left:wikitext(fileWikitext(icon, { size="24x24px", link="" })) end | ||
| Zeile 99: | Zeile 97: | ||
local function adv(htmlParent, label, val, icon) | local function adv(htmlParent, label, val, icon) | ||
if isempty(val) then return end | if isempty(val) then return end | ||
local box = htmlParent:tag("div"):addClass("kr-hc-adv") | local box = htmlParent:tag("div"):addClass("kr-hc-adv") | ||
local left = box:tag("div"):addClass("kr-hc-adv-icon") | local left = box:tag("div"):addClass("kr-hc-adv-icon") | ||
if not isempty(icon) then left:wikitext(fileWikitext(icon, { size="24x24px", link="" })) end | if not isempty(icon) then left:wikitext(fileWikitext(icon, { size="24x24px", link="" })) end | ||
| Zeile 128: | Zeile 126: | ||
-- Bilder/Links | -- Bilder/Links | ||
local linkto | local linkto = pick(args.linkto, name) | ||
local avatar | local avatar = pick(args.avatar, (not isempty(name) and (name .. ".png")) or nil) | ||
local root = mw.html.create("div"):addClass("kr-hero-card") | local root = mw.html.create("div"):addClass("kr-hero-card") | ||
-- Avatar (links) | -- Avatar (links) — div statt figure | ||
local fig = root:tag(" | local fig = root:tag("div"):addClass("kr-hc-avatar") | ||
fig:wikitext(fileWikitext(avatar, { class="kr-hc-avatar-img", link=linkto })) | fig:wikitext(fileWikitext(avatar, { class="kr-hc-avatar-img", link=linkto })) | ||
-- Content (rechts) | -- Content (rechts) — div statt section | ||
local content = root:tag(" | local content = root:tag("div"):addClass("kr-hc-content") | ||
if not isempty(name) then content:tag("h2"):addClass("kr-hc-name"):wikitext(name) end | if not isempty(name) then content:tag("h2"):addClass("kr-hc-name"):wikitext(name) end | ||
-- Basics | -- Basics | ||
local basics = content:tag("div"):addClass("kr-hc-basics") | local basics = content:tag("div"):addClass("kr-hc-basics") | ||
local function row(label, value, icon) | local function row(label, value, icon) | ||
| Zeile 150: | Zeile 148: | ||
cell:wikitext(value) | cell:wikitext(value) | ||
end | end | ||
row("Class:", class, nil) | row("Class:", class, nil) | ||
row("Attack style:", attackstyle, attackstyle_icon) | row("Attack style:", attackstyle, attackstyle_icon) | ||
row("Specialization:", specialization, specialization_icon) | row("Specialization:", specialization, specialization_icon) | ||
| Zeile 158: | Zeile 156: | ||
-- Main attributes | -- Main attributes | ||
content:tag("h3"):addClass("kr-hc-h"):wikitext("Main attributes") | content:tag("h3"):addClass("kr-hc-h"):wikitext("Main attributes") | ||
local mains = content:tag("div"):addClass("kr-hc-main-attrs") | local mains = content:tag("div"):addClass("kr-hc-main-attrs") | ||
local heroMain = type(data.main) == "table" and data.main or {} | local heroMain= type(data.main) == "table" and data.main or {} | ||
for i, key in ipairs(CFG.main_order) do | for i, key in ipairs(CFG.main_order) do | ||
local meta = CFG.main_meta[key] | local meta = CFG.main_meta[key] | ||
| Zeile 170: | Zeile 168: | ||
-- Advanced attributes | -- Advanced attributes | ||
content:tag("h3"):addClass("kr-hc-h"):wikitext("Advanced attributes") | content:tag("h3"):addClass("kr-hc-h"):wikitext("Advanced attributes") | ||
local advs = content:tag("div"):addClass("kr-hc-adv-attrs") | local advs = content:tag("div"):addClass("kr-hc-adv-attrs") | ||
local heroAdv = type(data.adv) == "table" and data.adv or {} | local heroAdv= type(data.adv) == "table" and data.adv or {} | ||
for i, key in ipairs(CFG.adv_order) do | for i, key in ipairs(CFG.adv_order) do | ||
local meta = CFG.adv_meta[key] | local meta = CFG.adv_meta[key] | ||
| Zeile 185: | Zeile 183: | ||
end | end | ||
-- Awakening bonus | -- Awakening bonus | ||
if not isempty(awakening_bonus) then | if not isempty(awakening_bonus) then | ||
content:tag("h3"):addClass("kr-hc-h"):wikitext("Awakening bonus") | content:tag("h3"):addClass("kr-hc-h"):wikitext("Awakening bonus") | ||
local awk = content:tag("div"):addClass("kr-hc-awakening | local awk = content:tag("div"):addClass("kr-hc-awakening") | ||
local box = awk:tag("div"):addClass("kr-hc-adv") | local box = awk:tag("div"):addClass("kr-hc-adv") | ||
if not isempty(awakening_bonus_icon) then | if not isempty(awakening_bonus_icon) then | ||
box:tag("div"):addClass("kr-hc-adv-icon") | box:tag("div"):addClass("kr-hc-adv-icon") | ||
| Zeile 197: | Zeile 195: | ||
main:tag("div"):addClass("kr-hc-adv-label"):wikitext("Bonus") | main:tag("div"):addClass("kr-hc-adv-label"):wikitext("Bonus") | ||
main:tag("div"):addClass("kr-hc-adv-value"):wikitext(awakening_bonus) | main:tag("div"):addClass("kr-hc-adv-value"):wikitext(awakening_bonus) | ||
end | |||
-- optional: Debug-Ausgabe ({{HeroCard|name=Talia|debug=1}}) | |||
if norm(args.debug) == "1" or norm(args.debug) == "yes" then | |||
root:tag("pre"):addClass("kr-hc-debug") | |||
:wikitext(mw.text.encode(mw.dumpObject({name=name, found=(data and true) or false, data=data}), true)) | |||
end | end | ||
Version vom 8. Oktober 2025, 17:47 Uhr
Die Dokumentation für dieses Modul kann unter Modul:HeroCard/Doku erstellt werden
-- Modul:HeroCard
local p = {}
-- ======= CONFIG / DEFAULTS =======
local CFG = {
-- Reihenfolge + Labels/Standard-Icons für Haupt-/Erweiterte Attribute
main_order = { "damage", "hp", "armor" },
main_meta = {
damage = { label = "Damage", icon = "AttackIcon.png" },
hp = { label = "Health", icon = "HealthIcon.png" },
armor = { label = "Armor", icon = "ArmorIcon.png" },
},
adv_order = { "precision", "bonus_damage", "speed", "dodge" },
adv_meta = {
precision = { label = "Precision", icon = "Icon_Target.png" },
bonus_damage = { label = "Damage Bonus", icon = "Icon_DamageUp.png" },
speed = { label = "Speed", icon = "Icon_Boots.png" },
dodge = { label = "Dodge", icon = "Icon_Dodge.png" },
},
-- Icon-Mapping nach Wert (case-/whitespace-insensitiv)
icon_map = {
attackstyle = {
malee = "MeleeIcon.png",
spellcaster = "SpellcasterIcon.png",
ranged = "RangedIcon.png",
},
specialization = {
healer = "HealerIcon.png",
damage = "DamageIcon.png",
tank = "TankIcon.png",
},
resource = {
mana = "ManaIcon.png",
rage = "RageIcon.png",
energy = "EnergyIcon.png",
},
awakening_bonus = {
["raining gold"] = "RainingGold.png",
["all main attributes"] = "AllAttributes.png",
prestigious = "Prestigious.png",
}
}
}
-- ======= HELPERS =======
local function isempty(v) return v == nil or v == "" end
local function pick(...) for _,v in ipairs{...} do if not isempty(v) then return v end end end
local function norm(s)
if isempty(s) then return "" end
s = mw.ustring.lower(mw.text.trim(s))
s = s:gsub("%s+", " ")
return s
end
local function getArgs(frame)
local args = {}
local f1, f2 = frame.args or {}, (frame:getParent() and frame:getParent().args) or {}
for k,v in pairs(f1) do if not isempty(v) then args[k]=v end end
for k,v in pairs(f2) do if not isempty(v) then args[k]=v end end
return args
end
local function heroFromData(name)
local ok, data = pcall(require, "Modul:HeroData") -- auf DE: „Modul:“
if not ok or type(data) ~= "table" then return nil end
local H = data.heroes or {}
return H[name] or H[mw.ustring.gsub(name or "", "_", " ")]
end
local function fileWikitext(filename, opts)
if isempty(filename) then return "" end
local parts = { ("Datei:%s"):format(filename) }
if opts and opts.size then table.insert(parts, opts.size) end
if opts and opts.link then table.insert(parts, "link=" .. opts.link) end
if opts and opts.class then table.insert(parts, "class=" .. opts.class) end
return string.format("[[%s]]", table.concat(parts, "|"))
end
local function mapIcon(kind, value, override)
if not isempty(override) then return override end
local t = CFG.icon_map[kind] or {}
return t[norm(value)]
end
local function pill(htmlParent, label, val, icon)
if isempty(val) then return end
local box = htmlParent:tag("div"):addClass("kr-hc-pill")
local left = box:tag("div"):addClass("kr-hc-pill-icon")
if not isempty(icon) then left:wikitext(fileWikitext(icon, { size="24x24px", link="" })) end
local text = box:tag("div"):addClass("kr-hc-pill-text")
text:tag("div"):addClass("kr-hc-pill-label"):wikitext(label or "")
text:tag("div"):addClass("kr-hc-pill-value"):wikitext(val)
end
local function adv(htmlParent, label, val, icon)
if isempty(val) then return end
local box = htmlParent:tag("div"):addClass("kr-hc-adv")
local left = box:tag("div"):addClass("kr-hc-adv-icon")
if not isempty(icon) then left:wikitext(fileWikitext(icon, { size="24x24px", link="" })) end
local main = box:tag("div"):addClass("kr-hc-adv-main")
main:tag("div"):addClass("kr-hc-adv-label"):wikitext(label or "")
main:tag("div"):addClass("kr-hc-adv-value"):wikitext(val)
end
-- ======= RENDER =======
function p.render(frame)
local args = getArgs(frame)
local name = pick(args.name, args[1]) or ""
local data = heroFromData(name) or {}
-- Basics (Werte)
local class = pick(args.class, data.class)
local attackstyle = pick(args.attackstyle, data.attackstyle)
local specialization = pick(args.specialization, data.specialization)
local resource = pick(args.resource, data.resource)
local unlock_at = pick(args.unlock_at, data.unlock_at)
local awakening_bonus= pick(args.awakening_bonus,data.awakening_bonus)
-- Icons (kein Icon für class!)
local attackstyle_icon = mapIcon("attackstyle", attackstyle, pick(args.attackstyle_icon, data.attackstyle_icon))
local specialization_icon = mapIcon("specialization", specialization, pick(args.specialization_icon, data.specialization_icon))
local resource_icon = mapIcon("resource", resource, pick(args.resource_icon, data.resource_icon))
local awakening_bonus_icon= mapIcon("awakening_bonus",awakening_bonus,pick(args.awakening_bonus_icon,data.awakening_bonus_icon))
-- Bilder/Links
local linkto = pick(args.linkto, name)
local avatar = pick(args.avatar, (not isempty(name) and (name .. ".png")) or nil)
local root = mw.html.create("div"):addClass("kr-hero-card")
-- Avatar (links) — div statt figure
local fig = root:tag("div"):addClass("kr-hc-avatar")
fig:wikitext(fileWikitext(avatar, { class="kr-hc-avatar-img", link=linkto }))
-- Content (rechts) — div statt section
local content = root:tag("div"):addClass("kr-hc-content")
if not isempty(name) then content:tag("h2"):addClass("kr-hc-name"):wikitext(name) end
-- Basics
local basics = content:tag("div"):addClass("kr-hc-basics")
local function row(label, value, icon)
if isempty(value) then return end
basics:tag("div"):addClass("kr-hc-kv kr-hc-k"):wikitext(label)
local cell = basics:tag("div"):addClass("kr-hc-kv kr-hc-v")
if not isempty(icon) then cell:tag("span"):addClass("kr-hc-v-icon"):wikitext(fileWikitext(icon, { size="20x20px", link="" })) end
cell:wikitext(value)
end
row("Class:", class, nil)
row("Attack style:", attackstyle, attackstyle_icon)
row("Specialization:", specialization, specialization_icon)
row("Resource:", resource, resource_icon)
row("Unlock at:", unlock_at, nil)
-- Main attributes
content:tag("h3"):addClass("kr-hc-h"):wikitext("Main attributes")
local mains = content:tag("div"):addClass("kr-hc-main-attrs")
local heroMain= type(data.main) == "table" and data.main or {}
for i, key in ipairs(CFG.main_order) do
local meta = CFG.main_meta[key]
local val = pick(args["main"..i.."_val"], heroMain[key])
local label = pick(args["main"..i.."_label"], meta.label)
local icon = pick(args["main"..i.."_icon"], meta.icon)
pill(mains, label, val, icon)
end
-- Advanced attributes
content:tag("h3"):addClass("kr-hc-h"):wikitext("Advanced attributes")
local advs = content:tag("div"):addClass("kr-hc-adv-attrs")
local heroAdv= type(data.adv) == "table" and data.adv or {}
for i, key in ipairs(CFG.adv_order) do
local meta = CFG.adv_meta[key]
local val = pick(args["adv"..i.."_val"], heroAdv[key])
local label = pick(args["adv"..i.."_label"], meta.label)
local icon = pick(args["adv"..i.."_icon"], meta.icon)
adv(advs, label, val, icon)
end
for i = #CFG.adv_order + 1, 8 do
local val = args["adv"..i.."_val"]
if isempty(val) then break end
adv(advs, args["adv"..i.."_label"] or "", val, args["adv"..i.."_icon"])
end
-- Awakening bonus
if not isempty(awakening_bonus) then
content:tag("h3"):addClass("kr-hc-h"):wikitext("Awakening bonus")
local awk = content:tag("div"):addClass("kr-hc-awakening")
local box = awk:tag("div"):addClass("kr-hc-adv")
if not isempty(awakening_bonus_icon) then
box:tag("div"):addClass("kr-hc-adv-icon")
:wikitext(fileWikitext(awakening_bonus_icon, { size="24x24px", link="" }))
end
local main = box:tag("div"):addClass("kr-hc-adv-main")
main:tag("div"):addClass("kr-hc-adv-label"):wikitext("Bonus")
main:tag("div"):addClass("kr-hc-adv-value"):wikitext(awakening_bonus)
end
-- optional: Debug-Ausgabe ({{HeroCard|name=Talia|debug=1}})
if norm(args.debug) == "1" or norm(args.debug) == "yes" then
root:tag("pre"):addClass("kr-hc-debug")
:wikitext(mw.text.encode(mw.dumpObject({name=name, found=(data and true) or false, data=data}), true))
end
return tostring(root)
end
return p