Description
Handles the creation of the playable cards' appearences in the wiki.
See also
- Module Card/class
- Module Card/for each
- Module Card/custom
- Module Card/get
- Module Card/has
- Module Card/data
- Category Modules
-- Questions? Ask them on Message_Wall:FabianLars or Discord (User:FabianLars for contact details)
local p = {}
local get = require("Module:Card/get")
local has = require("Module:Card/has")
local lib = require("Module:Shared")
local concat = lib.concat
local format = lib.format
local getArgs = lib.getArgs
--- get name, affinity and promo from given cardname
---@param n string name of card in form of 'name', 'name (affinity)' or 'name (Promo)'
---@return string, string|nil, boolean Cardname without parantheses; affinity or nil; true if promo
---@private
local function verifyName(n)
local aff, promo = nil, false
local name, var = string.find(n, " (", 1, true)
name, _ = name and string.sub(n, 1, (name or 0) - 1) or n, nil
var, _ = string.gsub(string.sub(n, (var or 0) + 1), "%)", "")
if var ~= name then
if var == "Promo" then
promo = true
elseif var == "Lost Souls" or var == "Twilight" or var == "Superpig" then
name = format("%s (%s)", name, var)
elseif var == "Fire" or var == "Frost" or var == "Nature" or var == "Shadow" then
if has.affinity(name, var) then
aff = var
end
end
end
return name, aff, promo
end
local function ErrorCard(err, scaling)
return require("Module:Card/class")({
scaling = scaling,
display_name = "ERROR",
artwork_wktxt = "[[File:Quests_warning.png||link=|320px]]",
abilities_node = mw.html.create("div"):cssText("width: 320px;line-height: 32px;"):wikitext(err),
err = err,
}).build()
end
local function chargeRules(index)
local charge_rules = {
[4] = { 1, 1, 1, 1 },
[8] = { 4, 2, 1, 1 },
[10] = { 5, 2, 2, 1 },
[12] = { 6, 2, 2, 2 },
[16] = { 8, 3, 3, 2 },
[20] = { 10, 4, 3, 3 },
[24] = { 12, 4, 4, 4 },
}
if index then
return charge_rules[index]
end
return charge_rules
end
local function getProgressionArgs(v1, v2, v3, v4)
if v1 and v1 ~= "" then
return { texttip = "true", v1, "Base / U-0", v2, "U-1", v3, "U-2", v4, "U-3" }
elseif v2 and v2 ~= "" then
return { texttip = "true", v2, "U-1", v3, "U-2", v4, "U-3" }
elseif v3 and v3 ~= "" then
return { texttip = "true", v3, "U-2", v4, "U-3" }
elseif v4 and v4 ~= "" then
return { texttip = "true", v4, "U-3" }
else
return
end
end
local function getAbilAvail(t)
if type(t) ~= "table" then
return nil
end
local from, to
for k, v in ipairs(t) do
if v and not from then
from = k - 1
end
if from and not v then
to = k - 2
end
end
if from == 3 then
return 3
end
if from == to then
if from == 0 then
return nil
end
return from
else
return (from or 0) .. "-" .. (to or 3)
end
end
local function general_desc(key)
local d = get.description(key)
if type(d) == "string" and d ~= "" then
return format('<div class="ability">%s</div>', d)
end
if type(d) == "table" and lib.length(d) > 0 then
return format('<div class="ability">%s</div>', lib.p(getProgressionArgs(d[1], d[2], d[3], d[4])))
end
return ""
end
function p.ability(frame)
local args = getArgs(frame)
if not (args[1] and args[2]) then
return "Invalid Input"
end
local getAbInfo = function(v, affinity, promo)
local text = v.description or ""
if v.values and v.values[1] then
local temp = {}
if type(v.values[1]) == "number" or type(v.values[1]) == "string" then
temp[#temp + 1] = frame:expandTemplate({
title = "p",
args = getProgressionArgs(v.values[1], v.values[2], v.values[3], v.values[4]),
})
else
for _, vv in ipairs(v.values) do
temp[#temp + 1] = frame:expandTemplate({
title = "p",
args = getProgressionArgs(vv[1], vv[2], vv[3], vv[4]),
})
end
end
local temp_text, _ = mw.ustring.gsub(text, "%%([^s])", "%%%%%1")
text = format(temp_text, unpack(temp))
end
local icon_name = format("%s%s %s Ability Icon.png", args[2], promo and " (Promo)" or "", v.name)
return frame:expandTemplate({
title = "Ability",
args = {
name = v.name,
type = v.type,
cost = type(v.cost) == "table" and frame:expandTemplate({
title = "p",
args = getProgressionArgs(v.cost[1], v.cost[2], v.cost[3], v.cost[4]),
}) or v.cost,
affinity_dependency = v.affinity_dependency and affinity or nil,
upgrade_availability = getAbilAvail(v.upgrade_availability),
icon = mw.title.new(icon_name, "File").exists and icon_name or nil,
description = frame:preprocess(text or ''), --TODO: remove preprocess once fandom gets their issues resolved
card = args[2],
},
})
end
local exts = { "", " (Fire)", " (Frost)", " (Nature)", " (Shadow)", " (Lost Souls)", " (Twilight)", " (Superpig)" }
local affs = { nil, "Fire", "Frost", "Nature", "Shadow" }
local abilities = {}
if string.find(args[2], " (Promo)", 1, true) then
exts = { " (Promo)" }
affs = { get.affinity(args[2] .. " (Promo)") }
end
-- iterate over cards
for k, v in ipairs(exts) do
-- iterate over abilities
for _, vv in ipairs(get.abilities(exts[1] == " (Promo)" and args[2] or args[2] .. v) or {}) do
if vv.name == args[1] then
return getAbInfo(vv, affs[k], k == 6 or string.find(args[2], " (Promo)", 1, true) ~= nil)
end
end
end
return format('Ability "%s" for "%s" not found.', args[1], args[2])
end
function p.abilities(frame)
local args = getArgs(frame)
local tagArgs = {}
local getInfo = function(aData, affinity, promo, special)
local res = ""
local key = "Z"
for _, v in ipairs(aData or {}) do
local text = v.description or ""
if v.values and v.values[1] then
local temp = {}
if type(v.values[1]) == "number" or type(v.values[1]) == "string" then
temp[#temp + 1] = frame:expandTemplate({
title = "p",
args = getProgressionArgs(v.values[1], v.values[2], v.values[3], v.values[4]),
})
else
for _, vv in ipairs(v.values) do
temp[#temp + 1] = frame:expandTemplate({
title = "p",
args = getProgressionArgs(vv[1], vv[2], vv[3], vv[4]),
})
end
end
local temp_text, _ = mw.ustring.gsub(text, "%%([^s])", "%%%%%1")
text = format(temp_text, unpack(temp))
end
if text == "" then
text = nil
end
local icon_tabber
local icon_name = format(
"%s%s %s Ability Icon.png",
args.name or args[1],
promo and " (Promo)" or special or "",
v.name
)
local icon2_name = format(
"%s%s %s 2 Ability Icon.png",
args.name or args[1],
promo and " (Promo)" or special or "",
v.name
)
icon_name = mw.title.new(icon_name, "File").exists and icon_name or nil
icon2_name = mw.title.new(icon2_name, "File").exists and icon2_name or nil
if icon2_name then
icon_tabber = mw.html.create("div")
:addClass("flip-container lazyimg-wrapper")
:cssText("margin-right:0.75rem;margin-bottom:0.25rem;width:64px;")
:tag("div")
:addClass("flip-content-1 flip-switch")
:tag("div")
:cssText("box-shadow:0 2px 5px 0 black;")
:wikitext(format("[[File:%s|64px|link=]]", icon_name))
:done()
:tag("div")
:cssText("display:flex;justify-content:center;align-items:center;")
:tag("div")
:cssText(
"height:12px;width:12px;border:1px solid black;border-radius:50%;background:white;margin:5px 2px 5px 5px;box-shadow:1px 1px 3px 0 black;"
)
:done()
:tag("div")
:cssText(
"height:12px;width:12px;border:1px solid black;border-radius:50%;background:gray;margin:5px 5px 5px 2px;box-shadow:1px 1px 3px 0 black;"
)
:done()
:done()
:done()
:tag("div")
:addClass("flip-content-2 flip-switch")
:cssText("display:none")
:tag("div")
:cssText("box-shadow:0 2px 5px 0 black;")
:wikitext(format("[[File:%s|64px|link=]]", icon2_name))
:done()
:tag("div")
:cssText("display:flex;justify-content:center;align-items:center;")
:tag("div")
:cssText(
"height:12px;width:12px;border:1px solid black;border-radius:50%;background:gray;margin:5px 2px 5px 5px;box-shadow:1px 1px 3px 0 black;"
)
:done()
:tag("div")
:cssText(
"height:12px;width:12px;border:1px solid black;border-radius:50%;background:white;margin:5px 5px 5px 2px;box-shadow:1px 1px 3px 0 black;"
)
:done()
:done()
:done()
:done()
icon_name = nil
icon2_name = nil
end
res = res
.. frame:expandTemplate({
title = "Ability",
args = {
hotkey = (v.type == "Active" or v.type == "Toggle") and key or nil,
name = v.name,
type = v.type,
cost = type(v.cost) == "table" and frame:expandTemplate({
title = "p",
args = getProgressionArgs(v.cost[1], v.cost[2], v.cost[3], v.cost[4]),
}) or v.cost,
affinity_dependency = v.affinity_dependency and affinity or nil,
upgrade_availability = getAbilAvail(v.upgrade_availability),
icon = icon_name,
icon2 = icon2_name,
icontabber = icon_tabber and tostring(icon_tabber) or nil,
details = args["ability_details_" .. (tostring(v.name or ""):lower():gsub("%s+", "_"))]
and frame:preprocess(
args["ability_details_" .. (tostring(v.name or ""):lower():gsub("%s+", "_"))]
)
or nil,
description = frame:preprocess(text or ""), --TODO: remove preprocess once fandom gets their issues resolved
},
})
if v.type == "Active" or v.type == "Toggle" then
if key == "Z" then
key = "X"
elseif key == "X" then
key = "C"
elseif key == "C" then
key = "V"
end
end
end
return res
end
local promo_aff = get.affinity(args[1] .. " (Promo)")
if get.abilities(args[1]) then
tagArgs[#tagArgs + 1] = args[1] .. "=" .. general_desc(args[1]) .. getInfo(get.abilities(args[1]))
end
if get.abilities(args[1] .. " (Fire)") then
tagArgs[#tagArgs + 1] = args[1]
.. " (Fire)="
.. general_desc(args[1] .. " (Fire)")
.. getInfo(get.abilities(args[1] .. " (Fire)"), "Fire")
end
if get.abilities(args[1] .. " (Frost)") then
tagArgs[#tagArgs + 1] = args[1]
.. " (Frost)="
.. general_desc(args[1] .. " (Frost)")
.. getInfo(get.abilities(args[1] .. " (Frost)"), "Frost")
end
if get.abilities(args[1] .. " (Nature)") then
tagArgs[#tagArgs + 1] = args[1]
.. " (Nature)="
.. general_desc(args[1] .. " (Nature)")
.. getInfo(get.abilities(args[1] .. " (Nature)"), "Nature")
end
if get.abilities(args[1] .. " (Shadow)") then
tagArgs[#tagArgs + 1] = args[1]
.. " (Shadow)="
.. general_desc(args[1] .. " (Shadow)")
.. getInfo(get.abilities(args[1] .. " (Shadow)"), "Shadow")
end
if get.abilities(args[1] .. " (Promo)") then
tagArgs[#tagArgs + 1] = args[1]
.. " (Promo)="
.. general_desc(args[1] .. " (Promo)")
.. getInfo(get.abilities(args[1] .. " (Promo)"), promo_aff, true)
end
if get.abilities(args[1] .. " (Lost Souls)") then
tagArgs[#tagArgs + 1] = args[1]
.. " (Lost Souls)="
.. general_desc(args[1] .. " (Lost Souls)")
.. getInfo(get.abilities(args[1] .. " (Lost Souls)"), nil, false, " (Lost Souls)")
end
if get.abilities(args[1] .. " (Twilight)") then
tagArgs[#tagArgs + 1] = args[1]
.. " (Twilight)="
.. general_desc(args[1] .. " (Twilight)")
.. getInfo(get.abilities(args[1] .. " (Twilight)"), nil, false, " (Twilight)")
end
if get.abilities(args[1] .. " (Superpig)") then
tagArgs[#tagArgs + 1] = args[1]
.. " (Superpig)="
.. general_desc(args[1] .. " (Superpig)")
.. getInfo(get.abilities(args[1] .. " (Superpig)"), nil, false, " (Superpig)")
end
return (#tagArgs or 0) <= 1 and (tagArgs[1] or ""):gsub("^.-=", "", 1)
or frame:preprocess("<tabber>" .. concat(tagArgs, "|-|") .. "</tabber>")
end
--- returns html for a card to display
---@param frame table mw.frame object
---@return string card as mw.html
---@public
function p.card(frame)
local args = getArgs(frame)
if not get.exists(args.name or args[1]) then
return ErrorCard(
format('Card or Variant "%s" not found', args.name or args[1]),
args.scaling or args.displayscaling or 0.74
)
end
local data = get.card(args.name or args[1])
local card = require("Module:Card/class")()
local charge_rules = chargeRules()
local name = args.name or args[1] or "Name missing"
local display_name, aff, promo = verifyName(args.name or args[1] or "Name missing")
if data.affinity then
aff = data.affinity
end
if data.promo then
promo = data.promo
end
if data.temporary_card then
promo = true
end
local scaling = args.scaling or data.scaling or args.displayscaling or data.displayscaling or 0.74
--local err = nil
local check_size = {
S = true,
M = true,
L = true,
XL = true,
}
local link = display_name
if data.nolink or args.nolink then
link = ""
end
local res = data.orbs and get["factions"](name, data.orbs)
local factionLR = data.orbs and (res[1] ~= res[2] and res[1] .. res[2] or res[1]) or "Blank"
local factionLeft = res and res[1] or nil
local factionRight = res and res[2] or nil
card.filter = args.filter
card.infobox = args.infobox
card.link = link
card.type = data.type
card.faction = get.faction(name)
card.factionLR = factionLR
card.factionLeft = factionLeft
card.factionRight = factionRight
card.affinity = aff
card.notooltip = args.notooltip or data.notooltip or false
card.scaling = scaling
card.artwork_wktxt = format(
data.artwork and format("[[File:%s||link=|320px]]", data.artwork) or "[[File:%s%s_Card_Artwork.png||link=]]",
display_name,
promo and "_(Promo)" or ""
)
card.spell_background_wktxt = data.type == "Spell"
and format("[[File:Spell_Card_Overlay_%s.png||link=]]", factionLR)
or nil
local cardupgrade = promo and 3 or (tonumber(data.cardupgrade) or tonumber(args.cardupgrade) or 0)
local applied_charges = promo and 3 or (tonumber(data.applied_charges) or tonumber(args.applied_charges) or 0)
card.cardupgrade = cardupgrade
card.applied_charges = applied_charges
if promo and not data.temporary_card then
card.promo = true
card.promo_icon_wktxt = format("[[File:Promo_Icon_%s.png||link=]]", factionLeft)
elseif data.starter_card and (args.infobox or (cardupgrade or 0) == 0) then
card.promo_icon_class = "cv-upgradeparts cv-A0"
card.promo_icon_wktxt = format("[[File:Starter_Icon_%s.png||link=]]", factionLeft)
elseif data.temporary_card then
card.promo_icon_wktxt = format("[[File:Temporary_Icon_%s.png||link=]]", factionLeft)
end
card.upgrade_left_1_wktxt = format("[[File:%s_Upgrade_1_Left.png||link=]]", factionLeft)
card.upgrade_left_2_wktxt = format("[[File:%s_Upgrade_2_Left.png||link=]]", factionLeft)
card.upgrade_left_3_wktxt = format("[[File:%s_Upgrade_3_Left.png||link=]]", factionLeft)
card.charge_left_1_wktxt = factionLeft == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]"
or format("[[File:%s_Charge_1_Left.png||link=]]", factionLeft)
card.charge_left_2_wktxt = factionLeft == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]"
or format("[[File:%s_Charge_2_Left.png||link=]]", factionLeft)
card.charge_left_3_wktxt = factionLeft == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]"
or format("[[File:%s_Charge_3_Left.png||link=]]", factionLeft)
card.upgrade_right_1_wktxt = format("[[File:%s_Upgrade_1_Right.png||link=]]", factionRight)
card.upgrade_right_2_wktxt = format(
"[[File:%s_Upgrade_%s_Right.png||link=]]",
factionRight,
factionRight == "Neutral" and "1" or "2"
)
card.upgrade_right_3_wktxt = format(
"[[File:%s_Upgrade_%s_Right.png||link=]]",
factionRight,
factionRight == "Neutral" and "1" or "3"
)
card.charge_right_1_wktxt = factionRight == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]"
or format("[[File:%s_Charge_1_Right.png||link=]]", factionRight)
card.charge_right_2_wktxt = factionRight == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]"
or format("[[File:%s_Charge_2_Right.png||link=]]", factionRight)
card.charge_right_3_wktxt = factionRight == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]"
or format("[[File:%s_Charge_3_Right.png||link=]]", factionRight)
card.full_name = display_name
card.display_name = display_name:gsub(" %(Lost Souls%)", ""):gsub(" %(Twilight%)", ""):gsub(" %(Superpig%)", "")
local dataorbs = {}
for k, v in ipairs(data.orbs or {}) do
dataorbs[k] = v
end
card.orbs = dataorbs
card.data_cost_attr = format('["%s"]', concat(data.power_cost, '","'))
card.power_cost_wktxt = type(data.power_cost) == "table" and data.power_cost[cardupgrade + 1] or data.power_cost
local actualChargeRule = (
promo and { data.charges or 4, 0, 0, 0 }
or (type(data.charges) == table and data.charges or charge_rules[data.charges or 4] or charge_rules[4])
)
local actualCurrentCharge
for i = 0, applied_charges do
actualCurrentCharge = (actualCurrentCharge or 0) + (actualChargeRule[i + 1] or 0)
end
card.charges_wktxt = actualCurrentCharge
card.data_charges_attr = format('["%s"]', concat(actualChargeRule or {}, '","'))
card.squadsize = data.squadsize
card.class = data.class
card.weapon_type = data.weapon_type
card.weapon_type_wktxt = (data.weapon_type and data.type ~= "Spell")
and format("[[File:Card_Icon_%s_Unit.png||link=]]", data.weapon_type)
or ""
card.counter = data.counter
card.counter_wktxt = (
data.weapon_type
and data.weapon_type ~= "Special"
and data.type ~= "Spell"
and check_size[data.counter or "Nope"]
)
and format("[[File:Card_Icon_Unit_Size_%s.png|38px|link=]]", data.counter)
or ""
card.data_damage_attr = format('["%s"]', concat(data.damage, '","'))
card.damage_wktxt = type(data.damage) == "table" and data.damage[cardupgrade + 1] or data.damage
card.unit_size = check_size[data.size or "Nope"] and data.size or nil
card.unit_size_wktxt = check_size[data.size or "Nope"]
and format("[[File:Card_Icon_Unit_Size_%s.png|38px|link=]]", data.size)
or nil
card.data_health_attr = format('["%s"]', concat(data.health, '","'))
card.health_wktxt = type(data.health) == "table" and data.health[cardupgrade + 1] or data.health
card.edition = data.edition
card.rarity = data.rarity
card.abilities_node = data.abilities_done
if not card.abilities_node then
local abilities_node = mw.html.create()
local ab_count = 0
for k, v in ipairs(data.abilities or {}) do
if ab_count < 4 and not v.hide_on_card then
ab_count = ab_count + 1
local abil = mw.html.create("div")
local avail = v.upgrade_availability
if avail then
local s = ""
local from
for k, v in ipairs(avail) do
if v and not from then
from = k - 1
end
if v then
s = s .. " cv-A" .. (k - 1)
end
end
abil:addClass("cv-upgradeparts" .. s)
if from > cardupgrade then
abil:cssText("display: none;")
end
end
if v["type"] then
abil:addClass(
format(
"cv-abil cv-abil-%s%s",
string.lower(v["type"]),
v["affinity_dependency"] and "-" .. string.lower(aff) or ""
)
)
else
abil:addClass("cv-abil-none")
end
abil:wikitext(v["name"])
if not promo then
local a = 0
for i = 1, 3 do
local avail = type(v.upgrade_availability) ~= "table" or v.upgrade_availability[i] == true
if
avail
and (
(v.upgrade_text and tostring(v.upgrade_text[i] or ""):len() > 0)
or (type(v.cost) == "table" and v.cost[i] ~= v.cost[i + 1] or false)
)
then
a = a + 1
end
if a ~= 0 then
abil
:tag("span")
:addClass(format("cv-upgradeparts cv-abil-upgrade-%s cv-A%s", a, i))
:css("display", (i == cardupgrade and "" or "none"))
end
end
end
abil:allDone()
abilities_node:node(abil)
end
end
card.abilities_node = abilities_node
end
return card.build()
end
function p.count(frame)
local args = getArgs(frame)
local i = 0
local list = get.list()
if args[1] ~= "" and args[2] ~= "" and args[1] ~= "cardtype" then
for _, k in ipairs(list) do
if get[args[1]](k) == args[2] then
i = i + 1
end
end
else
if (args[1] == "cardtype" and args[2] == "cards") or args[1] == nil or args[1] == "" then
for _, k in ipairs(list) do
if not k:find("(Promo)") then
i = i + 1
end
end
elseif (args[1] == "cardtype" and args[2] == "promos") or args[1] == nil or args[1] == "" then
for _, k in ipairs(list) do
if k:find("(Promo)") then
i = i + 1
end
end
end
end
return i
end
function p.custom_card(frame)
return require("Module:Card/custom").card(frame)
end
function p.custom_upgrade(frame)
return require("Module:Card/custom").upgrade(frame)
end
--- returns a list of cards formatted as a deck display
---@param frame table mw.frame object
---@return string deck as mw.html
---@public
function p.deck(frame)
local args = getArgs(frame)
local res = mw.html.create("div"):cssText("display:flex;flex-wrap:wrap;")
if args.maxperrow then
res:cssText(
format(
"max-width:100%%;width:calc(%spx * %s);",
args.icononly and 82 * (tonumber(args.scaling) or tonumber(args.displayscaling) or 1)
or 370 * (tonumber(args.scaling) or tonumber(args.displayscaling) or 0.22),
args.maxperrow
)
)
end
for i = 1, 20 do
local t = mw.text.split(args[i] or "", ";", true)
if t[1] ~= "" then
if args.icononly then
res:node(p.icon({
t[1],
size = format("%spx", (args.scaling or args.displayscaling or 1) * 80),
icononly = true,
nolink = args.nolink == true and true or false,
c = tonumber(t[2] or 0),
u = tonumber(t[3] or 0),
}))
else
res:node(p.card({
t[1],
cardupgrade = tonumber(t[2] or 0),
applied_charges = tonumber(t[3] or 0),
scaling = args.scaling or args.displayscaling or "0.22",
nolink = args.nolink == true and true or false,
}))
end
end
end
return res
end
function p.for_each(frame)
return require("Module:Card/for_each").main(frame)
end
function p.gallery(frame)
local args = getArgs(frame)
local name = args.name or args[1]
if not name then
return "Error: Missing Card Name"
end
local artwork = "File:" .. name .. "_Card_Artwork.png"
local art_promo = "File:" .. name .. "_(Promo)_Card_Artwork.png"
local art_old1 = "File:" .. name .. "_Card_Artwork_Old.png"
local art_old2 = "File:" .. name .. "_Card_Artwork_Old_2.png"
local images = {}
if mw.title.new(artwork).fileExists then
images[#images + 1] = artwork .. "|Card Artwork"
end
if mw.title.new(art_promo).fileExists then
images[#images + 1] = art_promo .. "|Card Artwork (Promo)"
end
if mw.title.new(art_old1).fileExists then
images[#images + 1] = art_old1 .. "|Old Card Artwork - Version 1"
end
if mw.title.new(art_old2).fileExists then
images[#images + 1] = art_old2 .. "|Old Card Artwork - Version 2"
end
local gal = frame:extensionTag(
"gallery",
concat(images, "\n"),
{ type = "slideshow", widths = "420px", position = "center", hideaddbutton = "true" }
)
return gal
end
--- returns values from Card/data for a card
---@param frame table mw.frame object
---@return string value from card
---@public
function p.get(frame)
local args = getArgs(frame)
local skip_verify = {
affinity_variants = true,
editions = true,
verified_name = true,
}
local cardname = (args[2]:find("affini") or skip_verify[args[2]]) and args[1] or get.verified_name(args[1])
local val = args[2]
local returntype = args[3]
-- 'return' one of: array, count, 'index' (eg 1).
-- nil returns default (tables as array (wikitext-string separated by ';'), single value as single value)
if not get[val] then
return format("No getter for %s", val)
end
if val:lower() == 'counter' then
if get.weapon_type(cardname) == 'Special' then return "Special" end
end
-- if not get['card'](cardname) then return format('Card %s not found (fn 'get')', cardname) end
--if not get[val](cardname, cardtype) then return format('Value %s not found for %s (%s)', val, cardname, get[val](cardname, cardtype)) end
local returnval = cardname == "list" and get.list() or get[val](cardname)
mw.logObject(returnval)
if returnval == nil then
return format('Card %s or value %s not found (fn "get")', cardname, val)
end
if returntype == "count" then
local i = 0
for _ in pairs(returnval or {}) do
i = i + 1
end
return i
elseif returntype == "array" then
if not type(returnval) == "table" then
return format("Value %s not an array (lua table)", val)
end
return concat(returnval, "; ")
elseif type(returntype) == "number" and returntype == math.floor(returntype) and returntype < 10 then
return returnval[tonumber(returntype)]
else
-- Something's not workin' here
if type(returnval) == "table" then
return concat(returnval, "; ")
elseif type(returnval) == "string" or type(returnval) == "number" or type(returnval) == "boolean" then
return returnval
else
return "Something went wrong. Check: card, value, return and Module:Card/data"
end
end
end
--- check if card has value
---@param frame table mw.frame object
---@return boolean true if card/data contains value for card; else nothing
---@public
function p.has(frame)
local args = getArgs(frame)
if has[args[2]] and has[args[2]](args[1]) then
return true
end
local cardname = args[2]:find("affini") and args[1] or get.verified_name(args[1])
if get[args[2]] and get[args[2]](cardname) then
return true
end
end
--- returns the content for Template:Card_icon
---@param frame table mw.frame object
---@return string icon_text or icon as mw.html
---@public
function p.icon(frame)
local args = getArgs(frame)
local name, var
if string.find(args[1], " (", 1, true) and string.find(args[1], ")", 1, true) then
name, var = string.match(args[1], "(.+) %((.+)%)")
else
name = args[1]
end
local ran, val_or_err = pcall(
get.verified_name,
format(
"%s%s",
name,
var == "Twilight" and " (Twilight)"
or var == "Lost Souls" and " (Lost Souls)"
or var == "Superpig" and " (Superpig)"
or ""
)
)
if not ran then
return format(
'<span style="cursor:help; border-bottom:1px dotted; color: red;" title="Error: Card "%s" not found.">Error</span>[[Category:Pages with script errors]]',
name or ""
)
end
if var and not get.exists(format("%s (%s)", name, var)) then
return format(
'<span style="cursor:help; border-bottom:1px dotted; color: red;" title="Error: Variant "%s" not found.>Error</span>[[Category:Pages with script errors]]',
var or ""
)
end
local firstfile = ""
if var == "Promo" then
firstfile = "_(Promo)"
elseif var == "Twilight" then
firstfile = "_(Twilight)"
elseif var == "Lost Souls" then
firstfile = "_(Lost_Souls)"
elseif var == "Superpig" then
firstfile = "_(Superpig)"
end
local linkdest = args.nolink == true and ""
or (name == "Mo" and "Mo#Card" or (var ~= "Promo" and format("%s%s", name, firstfile) or name))
local size = math.floor(string.gsub(args.size or "20px", "px", "") + 0.5)
local aff = false
if not args["hide_affinity"] and (var == "Fire" or var == "Frost" or var == "Nature" or var == "Shadow") then
aff = true
end
local linktext = name
if args[2] ~= nil and args[2] ~= "" then
linktext = args[2]
elseif var then
linktext = format("%s (%s)", linktext, var)
end
local u = args.u or args.upgrade or args.upgrades or args.applied_upgrade or args.applied_upgrades or 0
local c = args.c or args.charge or args.charges or args.applied_charge or args.applied_charges or 0
local span = mw.html.create("span")
:addClass("card-icon custom-tooltip ci")
:attr("data-tt-type", args.show_upgrade and "upgrade" or "card")
:attr("data-1", args[1])
:attr("data-2", u)
:attr("data-3", c)
local span_icon = mw.html.create("span"):wikitext(
format("[[File:%s%s_Card_Icon.png|%spx|border|link=%s]]", name, firstfile, size, linkdest)
)
if aff then
span_icon
:tag("span")
:wikitext(format("[[File:Affinity_Orb_%s.png|%spx|link=%s]]", var, math.floor(size * 0.4 + 0.5), linkdest))
end
span:node(span_icon:allDone())
if not args.icononly then
span:wikitext(format(" [[%s|%s]]", linkdest, linktext))
end
return span:done()
end
function p.infobox(frame)
local args = getArgs(frame)
local vname, _, _ = get.verified_name(args[1])
return frame:expandTemplate({
title = "Infobox card",
args = {
name = args[1],
artwork = format("[[File:%s_Card_Artwork.png|link=]]", args[1]),
card_type = get.type(vname) or nil,
faction = get.faction(vname) == "Neutral" and "None (Neutral / Legendary)" or get.faction(vname),
class = get.class(vname) or nil,
has_normal = has.normal(args[1]) or nil,
has_promo = has.promo(args[1]) or nil,
affinity1 = has.affinities(args[1]) and get.affinity_variants(args[1])[1] or nil,
affinity2 = has.affinities(args[1]) and get.affinity_variants(args[1])[2] or nil,
power_cost = type(get.power_cost(vname)) == "table" and frame:expandTemplate({
title = "pu",
args = {
get.power_cost(vname)[1],
get.power_cost(vname)[2],
get.power_cost(vname)[3],
get.power_cost(vname)[4],
},
}) or get.power_cost(vname),
orbs = get.orbs(vname) and concat(get.orbs(vname), ", ") or nil,
charges = has.nonpromo(vname) and frame:expandTemplate({ title = "pc", args = { get.charges(vname) } })
or get.charges(vname),
squadsize = get.squadsize(vname),
damage_bonus = get.counter(vname),
damage = type(get.damage(vname)) == "table" and frame:expandTemplate({
title = "pu",
args = { get.damage(vname)[1], get.damage(vname)[2], get.damage(vname)[3], get.damage(vname)[4] },
}) or get.damage(vname),
size = get.size(vname),
gender = get.gender(vname),
booster = concat(get.boosters(vname), ", "),
card_id = get.card_id(args[1]),
card_id_fire = get.card_id(args[1] .. " (Fire)"),
card_id_frost = get.card_id(args[1] .. " (Frost)"),
card_id_nature = get.card_id(args[1] .. " (Nature)"),
card_id_shadow = get.card_id(args[1] .. " (Shadow)"),
card_id_promo = get.card_id(args[1] .. " (Promo)"),
movement_speed = get.type(vname) == "Unit"
and (type(get.movement_speed(vname)) == "table" and frame:expandTemplate({
title = "pu",
args = {
get.movement_speed(vname)[1],
get.movement_speed(vname)[2],
get.movement_speed(vname)[3],
get.movement_speed(vname)[4],
},
}) or get.movement_speed(vname))
or nil,
construction_time = get.type(vname) == "Building"
and (type(get.construction_time(vname)) == "table" and frame:expandTemplate({
title = "pu",
args = {
get.construction_time(vname)[1],
get.construction_time(vname)[2],
get.construction_time(vname)[3],
get.construction_time(vname)[4],
},
}) or get.construction_time(vname))
or nil,
health = type(get.health(vname)) == "table" and frame:expandTemplate({
title = "pu",
args = { get.health(vname)[1], get.health(vname)[2], get.health(vname)[3], get.health(vname)[4] },
}) or get.health(vname),
edition = get.edition(vname),
rarity = get.rarity(vname),
},
})
end
--- returns a filtered list of cards
---@param frame table mw.frame object
---@return string list of cards as mw.html
---@public
function p.list(frame)
local args = getArgs(frame)
local list = get.list()
local cardcount = 0
local div = args.ci == true and mw.html.create()
or mw.html.create("div")
:addClass("list-of-cards" .. (args.filter and " collapsed" or ""))
:attr("id", args.filter and "card-grid" or "")
:css({
["display"] = "flex",
["flex-wrap"] = "wrap",
["justify-content"] = "center",
["overflow"] = "hidden",
["max-height"] = args.filter and "500px" or nil,
["margin"] = "0 -1px",
})
if args[1] ~= "" and args[2] ~= "" and args[1] ~= "cardtype" then
for i, k in ipairs(list) do
if get[args[1]](k) == args[2] then
cardcount = cardcount + 1
if args.ci == true then
div:wikitext("\n* "):node(p.icon({ k }))
else
div:node(p.card({ k, filter = args.filter, scaling = 0.5487 }))
end
end
end
else
if (args[1] == "cardtype" and args[2] == "all") or args[1] == nil or args[1] == "" then
for _, k in ipairs(list) do
cardcount = cardcount + 1
div:node(p.card({ k, filter = args.filter, scaling = 0.5487 }))
end
elseif (args[1] == "cardtype" and args[2] == "cards") or args[1] == nil or args[1] == "" then
for _, k in ipairs(list) do
if not k:find("(Promo)") then
cardcount = cardcount + 1
div:node(p.card({ k, filter = args.filter, scaling = 0.5487 }))
end
end
elseif (args[1] == "cardtype" and args[2] == "promos") or args[1] == nil or args[1] == "" then
for _, k in ipairs(list) do
if k:find("(Promo)") then
cardcount = cardcount + 1
div:node(p.card({ k, filter = args.filter, scaling = 0.5487 }))
end
end
end
end
if args.filter then
local filterContainer = mw.html.create("div")
:attr("id", "grid-filter-container")
:cssText("background-color:#060e1f;padding:0.5rem")
local arg1 = tostring(args[1] or ""):lower()
local arg2 = tostring(args[2] or ""):lower()
filterContainer:addClass("hide-" .. arg1)
if arg1 == "faction" then
if arg2 == "fire" then
filterContainer:addClass("hide-frost hide-nature hide-shadow")
elseif arg2 == "frost" then
filterContainer:addClass("hide-fire hide-nature hide-shadow")
elseif arg2 == "nature" then
filterContainer:addClass("hide-fire hide-frost hide-shadow")
elseif arg2 == "shadow" then
filterContainer:addClass("hide-fire hide-frost hide-nature")
elseif arg2 == "neutral" or arg2 == "legendary" then
filterContainer:addClass("hide-fire hide-frost hide-nature hide-shadow")
elseif arg2 == "amii" then
filterContainer:addClass("hide-fire hide-frost")
elseif arg2 == "bandit" then
filterContainer:addClass("hide-nature hide-shadow")
elseif arg2 == "lost souls" then
filterContainer:addClass("hide-fire hide-nature")
elseif arg2 == "stonekin" then
filterContainer:addClass("hide-fire hide-shadow")
elseif arg2 == "twilight" then
filterContainer:addClass("hide-frost hide-shadow")
end
end
-- omg the formatter f'ed up
div
:attr("data-card-count", tostring(cardcount))
:tag("div")
:attr("id", "grid-matches")
:attr("title", "If applicable, this count includes affinity and promo variants.")
:wikitext(cardcount .. " matching cards")
:allDone()
return filterContainer
:tag("div"):attr("id", "grid-filter-buttons")
:tag("div"):attr("id", "grid-filter-orbs-wrapper")
:tag("div"):cssText("font-size: 15px; font-weight: 700"):wikitext("Orbs"):done()
:tag("div"):attr("id", "grid-filter-orbs"):cssText("display: flex"):done()
:done()
:tag("div"):attr("id", "grid-filter-orbsamount-wrapper")
:tag("div"):cssText("font-size: 15px; font-weight: 700"):wikitext("Number of Orbs"):done()
:tag("div"):attr("id", "grid-filter-orbsamount"):cssText("display: flex"):done()
:done()
:tag("div"):attr("id", "grid-filter-type-wrapper")
:tag("div"):cssText("font-size: 15px; font-weight: 700"):wikitext("Type"):done()
:tag("div"):attr("id", "grid-filter-type"):cssText("display: flex"):done()
:done()
:tag("div"):attr("id", "grid-filter-rarity-wrapper")
:tag("div"):cssText("font-size: 15px; font-weight: 700"):wikitext("Rarity"):done()
:tag("div"):attr("id", "grid-filter-rarity"):cssText("display: flex"):done()
:done()
:done()
:tag("div"):attr("id", "grid-filter-dropdowns")
:tag("div"):attr("id", "grid-filter-search"):attr("data-placeholder", "Search..."):done()
:tag("div"):attr("id", "grid-filter-affinities"):done()
:tag("div"):attr("id", "grid-filter-edition"):done()
:tag("div"):attr("id", "grid-filter-faction"):done()
:tag("div"):attr("id", "grid-filter-counter"):done()
:tag("div"):attr("id", "grid-filter-size"):done()
:tag("div"):attr("id", "grid-filter-weapontype"):done()
:tag("div"):attr("id", "grid-filter-special"):done()
:tag("div"):attr("id", "grid-filter-sort"):done()
:tag("div"):attr("id", "grid-filter-reset"):done()
:done()
:node(div)
:tag("div"):attr("id", "grid-collapse")
:allDone()
else
return div:done()
end
end
function p.map_drops(frame)
local args = getArgs(frame)
local mapData = mw.loadData("Module:Map/data")
local res = get.map_drops(args[1], args[2])
if args[3] == "list" then
local d = ({ "standard", "advanced", "expert" })[args[2]]
local dt = mapData[args[1]].difficulties or {}
if #res == 0 then
if dt[d] then
return format("No card upgrades as reward for this scenario on %s difficulty.", d)
else
return format("Scenario not available on %s difficulty.", d)
end
elseif not dt[d] then
return format(
'<span style="color:red;">Error: %s rewards found in [[Module:Card/data]], but %s isn\'t available on %s difficulty ([[Module:Map/data]]).</span>',
#res,
args[1],
d
)
end
local res2 = mw.html.create("ul")
for i = 1, #res do
res2:tag("li"):node(p.icon({ res[i], show_upgrade = true, upgrade = args[2] })):done()
end
return res2
elseif args[3] == "count" then
return #res
else
return concat(res, ";")
end
end
function p.navigation(frame)
local list = get.list()
local cardcount = 0
local previous_card
local incrH = (
frame:getParent()["args"] and frame:getParent()["args"]["mainpage"]
or frame:getParent()["args"]["increased-height"]
)
and true
or false
local height = incrH and "400px" or "230px"
local grid = mw.html.create("div")
:attr("id", "card-grid")
:css({ ["max-height"] = height })
:addClass("lazyimg-wrapper collapsed" .. (incrH and " increased-height" or ""))
for k, v in ipairs(list) do
cardcount = k
local name, _ = v
:gsub(" %(Fire%)", "")
:gsub(" %(Frost%)", "")
:gsub(" %(Nature%)", "")
:gsub(" %(Shadow%)", "")
:gsub(" %(Promo%)", "")
:gsub(" %(Superpig%)", "")
if name ~= previous_card then
local data_orbs = get.orbs(v)
local orbs = { data_orbs[1], data_orbs[2], data_orbs[3], data_orbs[4] }
local non_legendary = (function()
for _, v in ipairs(orbs) do
if v and v ~= "Neutral" then
return true
end
end
end)()
local affinities = get.affinity_variants(name) or {}
if affinities[1] then
affinities[#affinities + 1] = "All"
else
affinities[1] = "None"
end
local cost = get.power_cost(v)
local faction = get.faction(v)
local faction = faction == "Neutral" and "Legendary" or faction
local special = { get.gender(v) or "None" }
if has.promo(name) then
special[#special + 1] = "Promo"
end
if has.starter_card(name) then
special[#special + 1] = "Starter"
end
if has.normal(name) then
special[#special + 1] = "Normal"
end
if non_legendary then
special[#special + 1] = "Non-Legendary"
end
grid:tag("span")
:addClass("grid-icon custom-tooltip")
:attr("data-tt-type", "card")
:attr("data-1", name)
:attr("data-search", name)
:attr("data-rarity", get.rarity(v))
:attr("data-cost", type(cost) == "table" and cost[1] or cost or 0)
:attr("data-edition", concat(get.editions(name), ","))
:attr("data-faction", faction)
:attr("data-counter", get.counter(v))
:attr("data-weapontype", get.weapon_type(v))
:attr("data-special", concat(special, ","))
:attr("data-orbs", concat(orbs, ","))
:attr("data-orbsamount", #orbs)
:attr("data-affinities", concat(affinities, ","))
:attr("data-size", get.size(v))
:attr("data-type", get.type(v))
:wikitext(format("[[File:%s_Card_Icon.png|56px|alt=%s|link=%s]]", name, name, name))
:done()
end
previous_card = name
end
grid:attr("data-card-count", tostring(cardcount))
:tag("div")
:attr("id", "grid-matches")
:attr("title", "If applicable, this count includes affinity and promo variants.")
:wikitext((cardcount - 1) .. " matching cards")
:allDone()
-- minus QueekQueek (Superpig)
return mw.html.create("div"):attr("id", "grid-filter-container")
:tag("div"):attr("id", "grid-filter-buttons")
:tag("div")
:tag("div"):cssText("font-size: 15px; font-weight: 700"):wikitext("Orbs"):done()
:tag("div"):attr("id", "grid-filter-orbs"):cssText("display: flex"):done()
:done()
:tag("div")
:tag("div"):cssText("font-size: 15px; font-weight: 700"):wikitext("Number of Orbs"):done()
:tag("div"):attr("id", "grid-filter-orbsamount"):cssText("display: flex"):done()
:done()
:tag("div")
:tag("div"):cssText("font-size: 15px; font-weight: 700"):wikitext("Type"):done()
:tag("div"):attr("id", "grid-filter-type"):cssText("display: flex"):done()
:done()
:tag("div")
:tag("div"):cssText("font-size: 15px; font-weight: 700"):wikitext("Rarity"):done()
:tag("div"):attr("id", "grid-filter-rarity"):cssText("display: flex"):done()
:done()
:done()
:tag("div"):attr("id", "grid-filter-dropdowns")
:tag("div"):attr("id", "grid-filter-search"):attr("data-placeholder", "Search..."):done()
:tag("div"):attr("id", "grid-filter-affinities"):done()
:tag("div"):attr("id", "grid-filter-edition"):done()
:tag("div"):attr("id", "grid-filter-faction"):done()
:tag("div"):attr("id", "grid-filter-counter"):done()
:tag("div"):attr("id", "grid-filter-size"):done()
:tag("div"):attr("id", "grid-filter-weapontype"):done()
:tag("div"):attr("id", "grid-filter-special"):done()
:tag("div"):attr("id", "grid-filter-sort"):done()
:tag("div"):attr("id", "grid-filter-reset"):done()
:done()
:node(grid)
:tag("div"):attr("id", "grid-collapse")
:allDone()
end
function p.progression_charges(frame)
local args = getArgs(frame)
if not args.index and not args[1] then
return "Missing max charge value"
end
local rule = chargeRules(tonumber(args.index or args[1]))
if not rule then
return "Value " .. (args.index or args[1]) .. " not found in ruleset"
end
return frame:expandTemplate({
title = "p",
args = {
[1] = rule[1],
[2] = "No extra charges applied",
[3] = rule[1] + rule[2],
[4] = "1 extra charge applied",
[5] = rule[1] + rule[2] + rule[3],
[6] = "2 extra charges applied",
[7] = rule[1] + rule[2] + rule[3] + rule[4],
[8] = "3 extra charges applied",
texttip = "true",
},
})
end
function p.upgrade(frame)
local args = getArgs(frame)
local upgrade = args.upgrade or args.cardupgrade or 0
if upgrade == 0 or upgrade > 3 then
return "upgrade needs to be 1, 2 or 3"
end
local name = args.name or args[1] or "Name missing"
local display_name, aff, _promo = verifyName(args.name or args[1] or "Name missing")
local res = get.orbs(name) and get.factions(name, get.orbs(name)) or nil
local factionLR = res and (res[1] ~= res[2] and res[1] .. res[2] or res[1]) or "Blank"
local factionLeft = res and res[1] or nil
local factionRight = res and res[2] or nil
local description = mw.html.create("div")
local general = get.general_upgrade_text(name)
if general and (general[upgrade] or "") ~= "" then
description
:tag("div")
:cssText("margin-left:5px;margin-right:10px;line-height:25px;white-space:pre-line")
:wikitext(general[upgrade])
:done()
end
local abilities = get.abilities(name)
local has_autocast = false
for _, v in ipairs(abilities) do
if v.type == "Autocast" then
has_autocast = true
end
end
local cost, dmg, hp = get.power_cost(name), get.damage(name), get.health(name)
if type(cost) == "table" and cost[upgrade] ~= cost[upgrade + 1] then
description
:tag("div")
:cssText("margin-left:5px;margin-right:10px;line-height:25px")
:wikitext(
(cost[upgrade + 1] > cost[upgrade] and "+" or "-")
.. math.abs(cost[upgrade + 1] - cost[upgrade])
.. " power cost"
)
:done()
end
if not has_autocast and type(dmg) == "table" and dmg[upgrade] ~= dmg[upgrade + 1] then
local s = get.squadsize(name) or 1
local u = s ~= 1 and (tostring(math.abs(dmg[upgrade + 1] - dmg[upgrade]) / s) .. "x" .. tostring(s))
or math.abs(dmg[upgrade + 1] - dmg[upgrade])
description
:tag("div")
:cssText("margin-left:5px;margin-right:10px;line-height:25px")
:wikitext("Damage " .. (dmg[upgrade + 1] > dmg[upgrade] and "+" or "-") .. u)
:done()
end
if type(hp) == "table" and hp[upgrade] ~= hp[upgrade + 1] then
local s = get.squadsize(name) or 1
local u = s ~= 1 and (tostring(math.abs(hp[upgrade + 1] - hp[upgrade]) / s) .. "x" .. tostring(s))
or math.abs(hp[upgrade + 1] - hp[upgrade])
description
:tag("div")
:cssText("margin-left:5px;margin-right:10px;line-height:25px")
:wikitext("Lifepoints " .. (hp[upgrade + 1] > hp[upgrade] and "+" or "-") .. u)
:done()
end
for _, v in ipairs(abilities) do
local from, to = 0, 9
local at = v.upgrade_availability or {}
if at[4] then
from = 3
end
if at[3] then
from = 2
end
if at[2] then
from = 1
end
if at[3] and not at[4] then
to = 3
end
if at[2] and not at[3] then
to = 2
end
if at[1] and not at[2] then
to = 1
end
local learned = from > 0 and upgrade == from
local unlearned = upgrade == to
local cost_change
if not learned and not unlearned and type(v.cost) == "table" then
if v.cost[upgrade] ~= v.cost[upgrade + 1] then
cost_change = (v.cost[upgrade + 1] < v.cost[upgrade] and "-" or "+")
.. math.abs(v.cost[upgrade + 1] - v.cost[upgrade])
end
end
if (v.upgrade_text and (v.upgrade_text[upgrade] or "") ~= "") or learned or unlearned or cost_change then
local abil = mw.html.create("div"):cssText("line-height:25px")
local upgrade_count = 0
local cost = v.cost
local avai = type(v.upgrade_availability) == "table" and v.upgrade_availability or { true, true, true }
if type(v.upgrade_text) == "table" or type(cost) == "table" then
if
upgrade >= 1
and (
avai[1] == true
and (
(type(v.upgrade_text) == "table" and (v.upgrade_text[1] or "") ~= "")
or (type(cost) == "table" and cost[1] ~= cost[2])
)
)
then
upgrade_count = upgrade_count + 1
end
if
upgrade >= 2
and (
avai[2] == true
and (
(type(v.upgrade_text) == "table" and (v.upgrade_text[2] or "") ~= "")
or (type(cost) == "table" and cost[2] ~= cost[3])
)
)
then
upgrade_count = upgrade_count + 1
end
if
upgrade >= 3
and (
avai[3] == true
and (
(type(v.upgrade_text) == "table" and (v.upgrade_text[3] or "") ~= "")
or (type(cost) == "table" and cost[3] ~= cost[4])
)
)
then
upgrade_count = upgrade_count + 1
end
end
if v.type then
abil:addClass(
format(
"cv-abil cv-abil-%s%s",
string.lower(v.type),
v.affinity_dependency and "-" .. string.lower(aff) or ""
)
)
else
abil:addClass("cv-abil-none")
end
abil:wikitext(v.name)
if from < upgrade and not (learned or unlearned) then
abil
:tag("span")
:cssText("margin-top:3px")
:addClass(format("cv-upgradeparts cv-abil-upgrade-%s", upgrade_count))
:done()
end
description:node(abil:done())
if learned or unlearned then
description
:tag("div")
:cssText("margin-left:5px;margin-right:10px;line-height:25px")
:wikitext((learned and "+ " or "- ") .. v.name)
:done()
end
if cost_change then
description
:tag("div")
:cssText("margin-left:5px;margin-right:10px;line-height:25px")
:wikitext(cost_change .. " power cost")
:done()
end
if v.upgrade_text and (v.upgrade_text[upgrade] or "") ~= "" then
description
:tag("div")
:cssText("margin-left:5px;margin-right:10px;line-height:25px;white-space:pre-line")
:wikitext(v.upgrade_text[upgrade])
:done()
end
end
end
return require("Module:Card/class")({
is_upgrade = true,
scaling = args.scaling or args.displayscaling or nil,
--TODO: notooltip = args.notooltip or false,
notooltip = true,
link = args.nolink and "" or display_name,
full_name = display_name,
display_name = display_name:gsub(" %(Lost Souls%)", ""):gsub(" %(Twilight%)", ""):gsub(" %(Superpig%)", ""),
artwork_wktxt = format("[[File:%s_Card_Artwork.png||link=]]", display_name),
factionLR = factionLR,
factionLeft = factionLeft,
factionRight = factionRight,
affinity = aff,
abilities_node = description:allDone(),
cardupgrade = upgrade,
upgrade_left_1_wktxt = format("[[File:%s_Upgrade_1_Left.png||link=]]", factionLeft),
upgrade_left_2_wktxt = format("[[File:%s_Upgrade_2_Left.png||link=]]", factionLeft),
upgrade_left_3_wktxt = format("[[File:%s_Upgrade_3_Left.png||link=]]", factionLeft),
upgrade_right_1_wktxt = format("[[File:%s_Upgrade_1_Right.png||link=]]", factionRight),
upgrade_right_2_wktxt = format(
"[[File:%s_Upgrade_%s_Right.png||link=]]",
factionRight,
factionRight == "Neutral" and "1" or "2"
),
upgrade_right_3_wktxt = format(
"[[File:%s_Upgrade_%s_Right.png||link=]]",
factionRight,
factionRight == "Neutral" and "1" or "3"
),
}).build():tag('div'):cssText('display:none'):node(description):done()
end
return p