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 CardClass(init)
local self = type(init) == "table" and init or {}
self.scaling = self.scaling or 0.74
self.cardupgrade = self.cardupgrade or 0
self.applied_charges = self.applied_charges or 0
self.notooltip = self.notooltip or false
self.infobox = self.infobox or false
self.orbs = self.orbs or {}
function self.build()
local card_container =
mw.html.create("div"):addClass(format("hidden cv-card-container%s", self.promo and " cv-promo" or "")):cssText(
format("transform: scale(%s)", self.scaling)
)
if self.err then
card_container:attr("title", self.err or "Error: Check your input")
end
local card_artwork =
mw.html.create("div"):addClass("cv-art"):wikitext(self.artwork_wktxt or ""):cssText(
self.err and "top: 0;" or ""
):done()
local card_background =
mw.html.create("div"):addClass(
"cv-bg c" .. (self.is_upgrade and "u" or "") .. "v-bg-" .. (self.factionLR or "Blank")
):wikitext((self.link and self.link ~= "") and ("[[" .. self.link .. "]]") or "")
if self.spell_background_wktxt then
card_background:tag("div"):addClass("cv-bg-spell"):wikitext(self.spell_background_wktxt):done()
end
card_background:done()
self.cardupgrade = self.cardupgrade or 0
self.applied_charges = self.applied_charges or 0
local upgradeLeft = mw.html.create()
if self.infobox or self.cardupgrade == 1 then
upgradeLeft:tag("div"):addClass("cv-upgradeparts cv-U1"):css {
["position"] = "absolute",
["bottom"] = "168px",
["left"] = 0,
["z-index"] = 150,
["display"] = (self.cardupgrade == 1 and "" or "none")
}:wikitext(self.upgrade_left_1_wktxt or ""):done()
end
if self.infobox or self.cardupgrade == 2 then
upgradeLeft:tag("div"):addClass("cv-upgradeparts cv-U2"):css {
["position"] = "absolute",
["bottom"] = "168px",
["left"] = 0,
["z-index"] = 150,
["display"] = (self.cardupgrade == 2 and "" or "none")
}:wikitext(self.upgrade_left_2_wktxt or ""):done()
end
if self.infobox or self.cardupgrade == 3 then
upgradeLeft:tag("div"):addClass("cv-upgradeparts cv-U3"):css {
["position"] = "absolute",
["bottom"] = "168px",
["left"] = 0,
["z-index"] = 150,
["display"] = (self.cardupgrade == 3 and "" or "none")
}:wikitext(self.upgrade_left_3_wktxt or ""):done()
end
if self.infobox or self.cardupgrade >= 1 then
upgradeLeft:tag("div"):addClass("cv-chargeparts cv-C1"):css {
["position"] = "absolute",
["bottom"] = (self.factionLeft == "Neutral" and "232px" or "233px"),
["left"] = (self.factionLeft == "Neutral" and "10px" or "4px"),
["z-index"] = 200,
["display"] = ((self.applied_charges >= 1 and self.applied_charges <= self.cardupgrade) and "" or "none")
}:wikitext(self.charge_left_1_wktxt or ""):done()
end
if self.infobox or self.cardupgrade >= 2 then
upgradeLeft:tag("div"):addClass("cv-chargeparts cv-C2"):css {
["position"] = "absolute",
["bottom"] = (self.factionLeft == "Neutral" and "312px" or "304px"),
["left"] = (self.factionLeft == "Neutral" and "10px" or "4px"),
["z-index"] = 200,
["display"] = ((self.applied_charges >= 2 and self.applied_charges <= self.cardupgrade) and "" or "none")
}:wikitext(self.charge_left_2_wktxt or ""):done()
end
if self.infobox or self.cardupgrade >= 3 then
upgradeLeft:tag("div"):addClass("cv-chargeparts cv-C3"):css {
["position"] = "absolute",
["bottom"] = (self.factionLeft == "Neutral" and "394px" or "372px"),
["left"] = (self.factionLeft == "Neutral" and "10px" or "4px"),
["z-index"] = 200,
["display"] = ((self.applied_charges >= 3 and self.applied_charges <= self.cardupgrade) and "" or "none")
}:wikitext(self.charge_left_3_wktxt or ""):done()
end
if self.promo_icon_wktxt then
upgradeLeft:tag("div"):addClass("cv-promo-icon " .. (self.promo_icon_class or "")):wikitext(
self.promo_icon_wktxt
):done()
end
upgradeLeft:done()
local upgradeRight = mw.html.create()
if self.infobox or self.cardupgrade >= 1 then
upgradeRight:tag("div"):addClass("cv-upgradeparts cv-U1"):css {
["position"] = "absolute",
["bottom"] = "168px",
["right"] = 0,
["z-index"] = 150,
["display"] = (self.cardupgrade >= 1 and "" or "none")
}:wikitext(self.upgrade_right_1_wktxt or ""):done()
end
if self.infobox or self.cardupgrade >= 2 then
upgradeRight:tag("div"):addClass("cv-upgradeparts cv-U2"):css {
["position"] = "absolute",
["bottom"] = (self.factionRight == "Neutral" and "248px" or "296px"),
["right"] = (self.factionRight == "Neutral" and 0 or "4px"),
["z-index"] = 150,
["display"] = (self.cardupgrade >= 2 and "" or "none")
}:wikitext(self.upgrade_right_2_wktxt or ""):done()
end
if self.infobox or self.cardupgrade >= 3 then
upgradeRight:tag("div"):addClass("cv-upgradeparts cv-U3"):css {
["position"] = "absolute",
["bottom"] = (self.factionRight == "Neutral" and "326px" or "362px"),
["right"] = (self.factionRight == "Neutral" and 0 or "4px"),
["z-index"] = 150,
["display"] = (self.cardupgrade == 3 and "" or "none")
}:wikitext(self.upgrade_right_3_wktxt or ""):done()
end
if self.infobox or self.cardupgrade >= 1 then
upgradeRight:tag("div"):addClass("cv-chargeparts cv-C1"):css {
["position"] = "absolute",
["bottom"] = (self.factionRight == "Neutral" and "232px" or "221px"),
["right"] = (self.factionRight == "Neutral" and "11px" or "4px"),
["z-index"] = 200,
["display"] = ((self.applied_charges >= 1 and self.applied_charges <= self.cardupgrade) and "" or "none")
}:wikitext(self.charge_right_1_wktxt or ""):done()
end
if self.infobox or self.cardupgrade >= 2 then
upgradeRight:tag("div"):addClass("cv-chargeparts cv-C2"):css {
["position"] = "absolute",
["bottom"] = (self.factionRight == "Neutral" and "312px" or "294px"),
["right"] = (self.factionRight == "Neutral" and "11px" or "4px"),
["z-index"] = 200,
["display"] = ((self.applied_charges >= 2 and self.applied_charges <= self.cardupgrade) and "" or "none")
}:wikitext(self.charge_right_2_wktxt or ""):done()
end
if self.infobox or self.cardupgrade >= 3 then
upgradeRight:tag("div"):addClass("cv-chargeparts cv-C3"):css {
["position"] = "absolute",
["bottom"] = (self.factionRight == "Neutral" and "390px" or "362px"),
["right"] = (self.factionRight == "Neutral" and "11px" or "4px"),
["z-index"] = 200,
["display"] = ((self.applied_charges >= 3 and self.applied_charges <= self.cardupgrade) and "" or "none")
}:wikitext(self.charge_right_3_wktxt or ""):done()
end
upgradeRight:done()
local card_name = mw.html.create("div"):addClass("cv-name"):wikitext(self.display_name or ""):done()
local card_tokenslot =
self.is_upgrade and mw.html.create() or
mw.html.create("div"):addClass(
format(
"cv-slot cv-slot-%s card-viewer-color-%s",
self.factionLR == "FireNature" and "FireNature" or (self.factionRight or "blank"),
string.lower(self.affinity or "blank")
)
):wikitext(self.affinity and "[[File:Affinity Tokenslot Overlay Blank.png|link=]]" or "")
local orb1 = mw.html.create("div"):addClass("cv-orb1 cv-orb-" .. (self.orbs[1] or "None")):done()
local orb2 = mw.html.create("div"):addClass("cv-orb2 cv-orb-" .. (self.orbs[2] or "None")):done()
local orb3 = mw.html.create("div"):addClass("cv-orb3 cv-orb-" .. (self.orbs[3] or "None")):done()
local orb4 = mw.html.create("div"):addClass("cv-orb4 cv-orb-" .. (self.orbs[4] or "None")):done()
local card_power_cost =
mw.html.create("div"):addClass("cv-cost"):attr("data-cost", self.data_cost_attr or ""):wikitext(
self.power_cost_wktxt or ""
):done()
local card_charges_squadsize_class =
mw.html.create("div"):addClass("cv-squad"):tag("span"):addClass("cv-charges"):attr(
"data-charges",
self.data_charges_attr or ""
):wikitext(self.charges_wktxt or ""):done()
if self.squadsize and self.squadsize > 1 then
card_charges_squadsize_class:wikitext(format("x%s", self.squadsize))
end
card_charges_squadsize_class:wikitext(format(" %s", self.class or "")):done()
local card_affinity_icon =
self.affinity and
(mw.html.create("div"):addClass("cv-aff-icon cv-aff-icon-" .. self.affinity) or mw.html.create()):done()
local card_abilities = mw.html.create("div"):addClass("cv-abilities"):node(self.abilities_node or "")
local card_weapon_type =
mw.html.create("div"):addClass(
format("cv-weapon card-viewer-layer-%s", string.lower(self.factionLeft or "blank"))
):wikitext(self.weapon_type_wktxt or ""):done()
local card_counter =
mw.html.create("div"):addClass(
format("cv-counter card-viewer-layer-%s", string.lower(self.factionLeft or "blank"))
):wikitext(self.counter_wktxt or ""):done()
local card_damage =
mw.html.create("div"):addClass("cv-damage"):attr("data-damage", self.data_damage_attr or ""):wikitext(
self.damage_wktxt or ""
):done()
local card_size_class = mw.html.create("div"):addClass("cv-size card-viewer-unit-size")
if self.unit_size_wktxt or self.health_wktxt then
card_size_class:addClass(format("card-viewer-layer-%s", string.lower(self.factionRight or "blank"))):wikitext(
"[[File:Card_Icon_HP.png||link=]]"
):wikitext(self.unit_size_wktxt or "")
end
local card_health =
mw.html.create("div"):addClass("cv-health"):attr("data-health", self.data_health_attr or ""):wikitext(
self.health_wktxt or ""
):done()
local card_edition_icon =
mw.html.create("div"):addClass(
(not self.edition or not self.rarity) and "cv-edition cv-edition-blank" or
format(
"cv-edition cv-edition-%s-%s",
string.gsub(self.edition, " ", "-"),
string.gsub(self.rarity, " ", "-")
)
)
card_container:node(card_artwork):node(card_background):node(upgradeLeft):node(upgradeRight):node(card_name):node(
card_tokenslot
):node(orb1):node(orb2):node(orb3):node(orb4):node(card_power_cost):node(card_charges_squadsize_class):node(
card_affinity_icon
):node(card_abilities):node(card_weapon_type):node(card_counter):node(card_damage):node(card_size_class):node(
card_health
):node(card_edition_icon):done()
local return_val =
mw.html.create("div"):addClass((not self.notooltip and not self.err) and "custom-tooltip" or ""):attr(
"data-tt-type",
"card"
):attr(
"data-1",
(self.full_name or self.display_name) ..
(self.promo and " (Promo)" or (self.affinity and " (" .. self.affinity .. ")" or ""))
):attr("data-2", self.cardupgrade):attr("data-3", self.applied_charges):css {
["width"] = format("%spx", 370 * self.scaling),
["height"] = format("%spx", 510 * self.scaling),
["display"] = "inline-block"
}:tag("div"):cssText("display:none"):wikitext(self.display_name and "[[" .. self.display_name .. "]]" or ""):done(
):node(card_container):allDone()
if self.filter then
local special = {}
if self.promo then special[#special+1] = 'Promo' end
if self.starter then special[#special+1] = 'Starter' end
if self.normal then special[#special+1] = 'Normal' end
local nl = (function()
for _, v in ipairs(self.orbs) do
if v and v ~= "Neutral" then
return true
end
end
end)()
if nl then special[#special+1] = "Non-Legendary" end
return_val:attr("data-search", self.full_name or self.display_name)
:attr("data-rarity", self.rarity)
:attr("data-cost", self.power_cost_wktxt)
:attr("data-edition", self.editions)
:attr("data-faction", self.faction)
:attr("data-counter", self.counter)
:attr("data-weapontype", self.weapon_type)
:attr("data-special", concat(special, ','))
:attr("data-orbs", concat(self.orbs, ","))
:attr("data-orbsamount", #self.orbs)
:attr("data-affinities", concat(self.affinity, ","))
:attr("data-size", self.size)
:attr("data-type", self.type)
end
return return_val
end
return self
end
local function ErrorCard(err, scaling)
return CardClass {
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)
local icon2_name = format("%s%s %s 2 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,
icon2 = mw.title.new(icon2_name, "File").exists and icon2_name or nil,
description = frame:preprocess(text),--TODO: remove preprocess once fandom gets their shit together
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(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')
:tag('div'):addClass('flip-content-1 flip-switch')
:tag('div'):wikitext(format('[[File:%s|64px|link=]]', icon_name)):done()
:tag('div'):cssText('display:flex;justify-content:center;align-items:center;')
:tag('div'):cssText('height:16px;width:16px;border:1px solid black;border-radius:50%;background:white;'):done()
:tag('div'):cssText('height:16px;width:16px;border:1px solid black;border-radius:50%;background:gray;'):done()
:done()
:done()
:tag('div'):addClass('flip-content-2 flip-switch')
:tag('div'):wikitext(format('[[File:%s|64px|link=]]', icon2_name)):done()
:tag('div'):cssText('display:flex;justify-content:center;align-items:center;')
:tag('div'):cssText('height:16px;width:16px;border:1px solid black;border-radius:50%;background:white;'):done()
:tag('div'):cssText('height:16px;width:16px;border:1px solid black;border-radius:50%;background:gray;'):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,
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),--TODO: remove preprocess once fandom gets their shit together
}
}
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 = CardClass()
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)
local args = getArgs(frame)
local name = args.name or args[1] or ""
local link = args.link or ""
if args.orbs then
args.orbs = mw.text.split(args.orbs, "%s*,%s*")
for k, v in ipairs(args.orbs or {}) do
args.orbs[k] = v:gsub("^%l", string.upper)
end
end
local res = args.orbs and get.factions(name, args.orbs) or {}
local factionLR = res[1] and (res[1] ~= res[2] and res[1] .. res[2] or res[1]) or "Blank"
local factionLeft = res[1]
local factionRight = res[2]
if args.type then
args.type = args.type:gsub("^%l", string.upper)
end
if args.edition then
args.edition = args.edition:gsub("^%l", string.upper)
if args.edition == "Lost souls" then
args.edition = "Lost Souls"
end
end
if args.rarity then
args.rarity = args.rarity:gsub("^%l", string.upper)
if args.rarity == "Ultra rare" then
args.rarity = "Ultra Rare"
end
end
if args.weapon_type then
args.weapon_type = args.weapon_type:gsub("^%l", string.upper)
end
if string.lower(args.affinity or "none") == "none" then
args.affinity = nil
end
if args.affinity then
args.affinity = args.affinity:gsub("^%l", string.upper)
end
if args.counter then
args.counter = string.upper(args.counter)
end
if args.size then
args.size = string.upper(args.size)
end
local promo_txt, promo_class
if type(args.upgrade) == "string" then
if args.upgrade:lower() == "promo" then
args.promo = true
args.cardupgrade = 3
args.applied_charges = 3
promo_txt = format("[[File:Promo_Icon_%s.png||link=]]", factionLeft)
end
if args.upgrade:lower() == "starter" then
args.starter_card = true
promo_class = "cv-upgradeparts cv-A0"
promo_txt = format("[[File:Starter_Icon_%s.png||link=]]", factionLeft)
end
if args.upgrade:lower() == "temp" or args.upgrade:lower() == "temporary" or args.upgrade:lower() == "tome" then
args.temporary_card = true
args.cardupgrade = 3
args.applied_charges = 3
promo_txt = format("[[File:Temporary_Icon_%s.png||link=]]", factionLeft)
end
else
args.cardupgrade = args.upgrade
end
local abilities_done = mw.html.create()
for i = 1, 5 do
local abil = mw.html.create("div")
if args["ability_" .. i .. "_type"] and string.lower(args["ability_" .. i .. "_type"]) ~= "none" then
abil:addClass(
format(
"cv-abil cv-abil-%s%s",
string.lower(args["ability_" .. i .. "_type"]),
(args["ability_" .. i .. "_affinity"] == true or
string.lower(args["ability_" .. i .. "_affinity"] or "") == "true") and
("-" .. string.lower(args.affinity)) or
""
)
)
end
abil:wikitext(args["ability_" .. i .. "_name"] or "")
if
tonumber(args["ability_" .. i .. "_upgrade"]) and tonumber(args["ability_" .. i .. "_upgrade"]) > 0 and
tonumber(args["ability_" .. i .. "_upgrade"]) <= 3
then
abil:wikitext(
format("[[File:Card_Icon_Upgrade_Status_0%s.png||link=]]", args["ability_" .. i .. "_upgrade"])
)
end
abil:allDone()
abilities_done:node(abil)
end
abilities_done:allDone()
local check_size = {
S = true,
M = true,
L = true,
XL = true
}
return CardClass {
scaling = args.displayscaling or args.scaling,
affinity = args.affinity,
factionLR = factionLR,
factionLeft = factionLeft,
factionRight = factionRight,
display_name = name,
artwork_wktxt = format("[[File:%s||link=|320px]]", args.artwork),
spell_background_wktxt = args.type == "Spell" and format("[[File:Spell_Card_Overlay_%s.png||link=]]", factionLR) or
nil,
cardupgrade = args.cardupgrade,
applied_charges = args.applied_charges,
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),
charge_left_1_wktxt = factionLeft == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]" or
format("[[File:%s_Charge_1_Left.png||link=]]", factionLeft),
charge_left_2_wktxt = factionLeft == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]" or
format("[[File:%s_Charge_2_Left.png||link=]]", factionLeft),
charge_left_3_wktxt = factionLeft == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]" or
format("[[File:%s_Charge_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"
),
charge_right_1_wktxt = factionRight == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]" or
format("[[File:%s_Charge_1_Right.png||link=]]", factionRight),
charge_right_2_wktxt = factionRight == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]" or
format("[[File:%s_Charge_2_Right.png||link=]]", factionRight),
charge_right_3_wktxt = factionRight == "Neutral" and "[[File:Neutral_Charge_All.png||link=]]" or
format("[[File:%s_Charge_3_Right.png||link=]]", factionRight),
promo_icon_wktxt = promo_txt,
promo_icon_class = promo_class,
orbs = args.orbs or {},
power_cost_wktxt = args.power_cost,
charges_wktxt = args.charges,
unit_size_wktxt = check_size[args.size or "Nope"] and
format("[[File:Card_Icon_Unit_Size_%s.png||link=]]", args.size) or
nil,
squadsize = args.squadsize,
class = args.class,
damage_wktxt = args.damage,
weapon_type_wktxt = (args.weapon_type and args.type ~= "Spell") and
format(
"[[File:Card_Icon_%s%s.png||link=]]",
args.weapon_type,
(check_size[args.counter or "Nope"] and args.weapon_type ~= "Special") and
format("_Unit_Countering_Size_%s", args.counter) or
(args.weapon_type ~= "Special" and "_Unit" or ""),
link
) or
((not args.weapon_type and check_size[args.counter or "Nope"] and args.type ~= "Spell") and
format(
'<span style="padding-left: 14px;">[[File:Card_Icon_Unit_Size_%s.png||link=]]</span>',
args.counter
)),
health_wktxt = args.health,
edition = args.edition,
rarity = args.rarity,
notooltip = true,
abilities_node = abilities_done
}.build()
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)
local args = getArgs(frame)
local list = get.list()
local result
if args[1] == "list_of_card_ids" then
result = mw.html.create()
for k, v in ipairs(list) do
local id = get.card_id(v) or 0
local ci = p.icon {v}
local id0 = tostring(id)
local id1 = string.format("1%06d", id)
local id2 = string.format("2%06d", id)
local id3 = string.format("3%06d", id)
result:tag("tr"):addClass("search-item"):attr("data-search", v .. id0):tag("td"):node(ci):done():tag("td"):wikitext(
id0
):done():tag("td"):wikitext(id1):done():tag("td"):wikitext(id2):done():tag("td"):wikitext(id3):done():done()
end
elseif args[1] == "list_of_card_upgrade_drop_locations" then
result = mw.html.create()
local mapData = mw.loadData("Module:Map/data")
for k, v in ipairs(list) do
local ci = p.icon {v}
local drops = get.upgrade_locations(v)
local ed = get.edition(v)
local ra = get.rarity(v)
local raso = 0
if ra == "Common" then
raso = 1
elseif ra == "Uncommon" then
raso = 2
elseif ra == "Rare" then
raso = 3
elseif ra == "Ultra Rare" then
raso = 4
end
if drops then
local d1 = drops[1] or ""
local d2 = drops[2] or ""
local d3 = drops[3] or ""
local dd1 = drops[1] and format("[[File:%s_Minimap.jpg|20px|link=%s]] [[%s]]", d1, d1, d1) or ""
local dd2 = drops[2] and format("[[File:%s_Minimap.jpg|20px|link=%s]] [[%s]]", d2, d2, d2) or ""
local dd3 = drops[3] and format("[[File:%s_Minimap.jpg|20px|link=%s]] [[%s]]", d3, d3, d3) or ""
if drops[1] and not mapData[d1].difficulties["standard"] then
dd1 =
'<span style="color:red;">Data Error: Upgrade drop location does not match available map difficulty.</span>'
end
if drops[2] and not mapData[d2].difficulties["advanced"] then
dd2 =
'<span style="color:red;">Data Error: Upgrade drop location does not match available map difficulty.</span>'
end
if drops[3] and not mapData[d3].difficulties["expert"] then
dd3 =
'<span style="color:red;">Data Error: Upgrade drop location does not match available map difficulty.</span>'
end
local search = v .. d1
if d2 ~= d1 then
search = search .. d2
end
if d3 ~= d2 and d3 ~= d1 then
search = search .. d3
end
result:tag("tr"):addClass("search-item"):attr("data-search", search):tag("td"):node(ci):done():tag("td"):attr(
"data-sort-value",
raso
):attr("title", ra):wikitext(format("[[File:Edition Icon %s %s.png|x22px|link=]]", ed, ra)):done():tag(
"td"
):wikitext(dd1):done():tag("td"):wikitext(dd2):done():tag("td"):wikitext(dd3):done():done()
end
end
elseif args[1] == "list_of_booster_pack_contents" then
result = mw.html.create()
local counter = {
[1] = 0,
[2] = 0,
[3] = 0,
[4] = 0,
[5] = 0,
[6] = 0,
[7] = 0,
[8] = 0,
[9] = 0,
[10] = 0,
[11] = 0
}
for k, v in ipairs(list) do
local name = v:gsub(" %(Fire%)", ""):gsub(" %(Frost%)", ""):gsub(" %(Nature%)", ""):gsub(" %(Shadow%)", "")
local ci = p.icon {[1] = v, ["hide_affinity"] = true}
local packs = get.boosters(v)
local p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 = "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X"
local c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 =
"nay",
"nay",
"nay",
"nay",
"nay",
"nay",
"nay",
"nay",
"nay",
"nay",
"nay"
local search = name
if packs[1] then
p0 = "✔"
c0 = "yea"
counter[1] = counter[1] + 1
else
search = search .. "None"
end
for _, pack in ipairs(packs) do
search = search .. pack
if pack == "Fire" then
p1 = "✔"
c1 = "yea"
counter[2] = counter[2] + 1
elseif pack == "Frost" then
p2 = "✔"
c2 = "yea"
counter[3] = counter[3] + 1
elseif pack == "Nature" then
p3 = "✔"
c3 = "yea"
counter[4] = counter[4] + 1
elseif pack == "Shadow" then
p4 = "✔"
c4 = "yea"
counter[5] = counter[5] + 1
elseif pack == "Amii" then
p5 = "✔"
c5 = "yea"
counter[6] = counter[6] + 1
elseif pack == "Bandit" then
p6 = "✔"
c6 = "yea"
counter[7] = counter[7] + 1
elseif pack == "Fire/Frost" then
p7 = "✔"
c7 = "yea"
counter[8] = counter[8] + 1
elseif pack == "Lost Souls" then
p8 = "✔"
c8 = "yea"
counter[9] = counter[9] + 1
elseif pack == "Stonekin" then
p9 = "✔"
c9 = "yea"
counter[10] = counter[10] + 1
elseif pack == "Twilight" then
p10 = "✔"
c10 = "yea"
counter[11] = counter[11] + 1
end
end
result:tag("tr"):addClass("search-item"):attr("data-search", search):tag("td"):node(ci):done():tag("td"):addClass(
c0
):wikitext(p0):done():tag("td"):addClass(c1):wikitext(p1):done():tag("td"):addClass(c2):wikitext(p2):done():tag(
"td"
):addClass(c3):wikitext(p3):done():tag("td"):addClass(c4):wikitext(p4):done():tag("td"):addClass(c5):wikitext(
p5
):done():tag("td"):addClass(c6):wikitext(p6):done():tag("td"):addClass(c7):wikitext(p7):done():tag("td"):addClass(
c8
):wikitext(p8):done():tag("td"):addClass(c9):wikitext(p9):done():tag("td"):addClass(c10):wikitext(p10):done(
):done()
end
result =
mw.html.create():tag("tr"):addClass("tr-force-show"):tag("th"):cssText(
"width: 30%; text-align:left; background-color: #092949"
):wikitext("Card Name"):done():tag("th"):cssText(
"width: 6%; background-color: #092949; padding: 6px 0; text-align: center"
):wikitext("[[File:General Booster Pack HD.png|40px|link=]]"):attr(
"title",
"General Booster Pack (Card Pool: " .. counter[1] .. ")"
):done():tag("th"):cssText("width: 6%; background-color: #092949; padding: 6px 0; text-align: center"):wikitext(
"[[File:Fire Booster Pack HD.png|40px|link=]]"
):attr("title", "Fire Booster Pack (Card Pool: " .. counter[2] .. ")"):done():tag("th"):cssText(
"width: 6%; background-color: #092949; padding: 6px 0; text-align: center"
):wikitext("[[File:Frost Booster Pack HD.png|40px|link=]]"):attr(
"title",
"Frost Booster Pack (Card Pool: " .. counter[3] .. ")"
):done():tag("th"):cssText("width: 6%; background-color: #092949; padding: 6px 0; text-align: center"):wikitext(
"[[File:Nature Booster Pack HD.png|40px|link=]]"
):attr("title", "Nature Booster Pack (Card Pool: " .. counter[4] .. ")"):done():tag("th"):cssText(
"width: 6%; background-color: #092949; padding: 6px 0; text-align: center"
):wikitext("[[File:Shadow Booster Pack HD.png|40px|link=]]"):attr(
"title",
"Shadow Booster Pack (Card Pool: " .. counter[5] .. ")"
):done():tag("th"):cssText("width: 6%; background-color: #092949; padding: 6px 0; text-align: center"):wikitext(
"[[File:Amii Booster Pack HD.png|40px|link=]]"
):attr("title", "Amii Booster Pack (Card Pool: " .. counter[6] .. ")"):done():tag("th"):cssText(
"width: 6%; background-color: #092949; padding: 6px 0; text-align: center"
):wikitext("[[File:Bandit Booster Pack HD.png|40px|link=]]"):attr(
"title",
"Bandit Booster Pack (Card Pool: " .. counter[7] .. ")"
):done():tag("th"):cssText("width: 6%; background-color: #092949; padding: 6px 0; text-align: center"):wikitext(
"[[File:Fire Frost Booster Pack HD.png|40px|link=]]"
):attr("title", "Fire Frost Booster Pack (Card Pool: " .. counter[8] .. ")"):done():tag("th"):cssText(
"width: 6%; background-color: #092949; padding: 6px 0; text-align: center"
):wikitext("[[File:Lost Souls Booster Pack HD.png|40px|link=]]"):attr(
"title",
"Lost Souls Booster Pack (Card Pool: " .. counter[9] .. ")"
):done():tag("th"):cssText("width: 6%; background-color: #092949; padding: 6px 0; text-align: center"):wikitext(
"[[File:Stonekin Booster Pack HD.png|40px|link=]]"
):attr("title", "Stonekin Booster Pack (Card Pool: " .. counter[10] .. ")"):done():tag("th"):cssText(
"width: 6%; background-color: #092949; padding: 6px 0; text-align: center"
):wikitext("[[File:Twilight Booster Pack HD.png|40px|link=]]"):attr(
"title",
"Twilight Booster Pack (Card Pool: " .. counter[11] .. ")"
):done():done():node(result:done()):done()
end
return result
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 cardname = (args[2]:find("affini")) 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 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)
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 = {}
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 CardClass {
is_upgrade = true,
scaling = args.scaling or args.displayscaling or nil,
--TODO: notooltip = args.notooltip or false,
notooltip = true,
link = (args.nolink or link == "") 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()
end
return p