Module:CharacterToken

--[=[ Lua script replacement for wikitext template



Parameters: 1: Token = (character,token type,count) count is optional Separate multiple items with dollar sign "$" if the item is blank or "&", line break " " will be inserted instead. if the string "multi" is input then lists all tokens of rarity specified in parameter 2 2: Size in pixels (or token rarity in case of "multi") optional, defaults to 30 If equal to "N", includes the token Name Link also If equal to "L", includes the token Name Link only 3: Option For normal, if non-blank, will automatically insert line breaks " " after every 4 tokens. Any specified line breaks ("&") are ignored. For "multi", if non-blank, specifies the string to strip from the end of the token name. 4: Skip Name of the token to be skipped or removed from displayed list, on pages other than token pages.

The list of available tokens is kept in the module data

Unknown Token is returned if Token Type is not in data. --]=]

local p = {}

local util = require("Module:Utility") local COLL = require("Module:ItemCollection") local availableData = mw.loadData('Module:Available/data')

---[==[ For testing purposes local tokenData = mw.loadData('Module:CharacterToken/data') --[===[]==] local tokenData = { ["ip-ts"] = { ["0"] = {"Pixar Ball", 0, 1} },   ["jessie"] = { ["2"] = {"Lasso", 2}, ["3"] = {"Jessie Ears Hat", 3} },   ["woody"] = { ["2"] = {"Sheriff Star", 2}, ["3"] = {"Woody Ears Hat", 9, 5} },   ["yoda"] = { ["2"] = {"Yoda's Gimer Stick", 104}, ["3"] = {"Yoda Ears Hat", 105} },   ["fabric bounty hunter boba fett"] = { ["0"] = {"Bounty Hunter Boba Fett Fabric", 106, 4} }, } --]===]

local rarityType = { ["collection"]		= 0, ["common"]		= 1, ["uncommon"]		= 2, ["rare"]		= 3, ["epic"]		= 4, ["legendary"]		= 5, ["fabric"]		= 6, ["blueprint"]		= 7, ["common relic"]	= 81, ["uncommon relic"]	= 82, ["rare relic"]		= 83, ["event"]		= 9, ["npc"]			= 10, ["elixir ingot"]	= 11, } local elixircost = { [0]		= {[1] = "75"},	[1]		= "150",	[2]		= "225",	[3]		= "375",	[4]		= "600",	[5]		= "1,000",	[6]		= {[1] = "?", [2] = "190", [3] = "375", [4] = "800", [5] = "1,600"},	[7]		= {[1] = "?", [2] = "?", [3] = "?", [4] = "?", [5] = "?"},	[81]	= {[1] = "100"},	[82]	= {[2] = "?"},	[83]	= {[3] = "?"},	[9]		= {[1] = "150", [2] = "225", [3] = "375", [4] = "600", [5] = "1,000"},	[10]	= {[1] = "?", [2] = "?", [3] = "?", [4] = "?", [5] = "?"},	[11]	= {[1] = "?", [2] = "?", [3] = "?", [4] = "?", [5] = "?"},	}

local function getElixirCost(tok) local tType = tok[2]

if tType and math.floor(tType/100) == 1 then tType = math.mod(tType, 100) end

if tok[3] and elixircost[tType] then return elixircost[tType][tok[3]] or "?" elseif elixircost[tType] then return elixircost[tType] or "?" end return "?" end

local function getRarity(tok) local nRarity = tok[3] or tok[2] or 999

if nRarity and math.floor(nRarity/100) == 1 then nRarity = math.mod(nRarity, 100) end

if nRarity == 1 or nRarity == 2 or nRarity == 3 or nRarity == 4 or nRarity == 5 then for rar, numb in pairs(rarityType) do			if numb == nRarity then return rar end end end return "unknown" end

-- Display Token Icon(s) local function tokenIcon(token, size, addbreaks, skip) local outType = ""

if not token or token == "" then return "" end

if not tonumber(size) then outType = size size = 30 end

local autoBreaks = false if addbreaks and addbreaks ~= "" then autoBreaks = true end

local tokTbl = {} if (type(token) == "table") then tokTbl = token else token = mw.ustring.gsub(token, "^%s*(.-)%s*$", "%1") or '' tokTbl = mw.text.split(token, "%s*$%s*") end

local tAll = {} local space = ""

-- get the current page/token name local pagename = mw.title.getCurrentTitle.text:match("(.+)%s+Token$") or "" -- use the name of token to skip if specified if skip then pagename = skip end -- count of icons on 1 row to insert line break local iconCount = 0

for _, tok in ipairs(tokTbl) do		local addThis = false local tToken = {space, "", "", "", "", "", "", "t-", "", "",		   	"", ".png", "", "", "", "", "", "", ""	   	}

local cName, tokenType, count = mw.ustring.match(tok,                       	        "^([^,]-)%s*,%s*(%d+)%s*[,%#]*%s*([\/%d%?]*)$") if not cName then cName, count = mw.ustring.match(tok, "^([^,]-)%s*,%s*[,%#]*%s*([\/%d]*)$") end

if not cName then cName, count = mw.ustring.match(tok, "^([^,]-)%s*[,%#]%s*([\/%d]*)$") end

if not cName then cName = tok end

if not tokenType or tokenType == "" then tokenType = "0" end if tokenData[cName] and tokenData[cName][tokenType] then local tokName = tokenData[cName][tokenType][1]

addThis = true -- not current token so add to output

if outType == "I" then tToken[20] = ": "				tToken[24] = mw.ustring.gsub(tokName, "^([^%(]-) *%(([^%(]-)%)", "%1")				tToken[25] = "" elseif outType == "N" then tToken[ 2] = ""				tToken[ 5] = mw.ustring.gsub(tokName, "^([^%(]-) *%(([^%(]-)%)", "%1")				tToken[ 6] = " Token ("				tToken[20] = ") " elseif outType == "L" then tToken[ 7] = ""					tToken[14] = mw.ustring.gsub(tokName, "^([^%(]-) *%(([^%(]-)%)", "%1")					tToken[16] = " Token"				end				tToken[18] = "" elseif outType == "S" then tToken[ 7] = ""					tToken[14] = mw.ustring.gsub(tokName, "^([^%(]-) *%(([^%(]-)%)", "%1")				end				tToken[16] = "" tToken[18] = "" elseif outType == "P" then tToken[21] = " "				tToken[22] = tokName				tToken[23] = " Token " end if outType ~= "L" and outType ~= "S" then local tokFile = mw.ustring.lower(tokenData[cName].F or cName) tokFile = mw.ustring.gsub(tokFile, "fabric ", "f-") tokFile = mw.ustring.gsub(tokFile, " ", "_") tokFile = mw.ustring.gsub(tokFile, "[':\"%,%.]", "")				tokFile = mw.ustring.gsub(tokFile, "^([^%(]-) *%(([^%(]-)%)", "%1_%2")				tToken[ 9] = mw.ustring.lower(tokFile)				if tokenType ~= "0" then					tToken[10] = "-"					tToken[11] = tokenType				end				tToken[15] = mw.ustring.gsub(tokName, "^([^%(]-) *%(([^%(]-)%)", "%1")				tToken[17] = tokName			end			if outType == "T" then				return tokName .. " Token"			elseif outType == "X" then				return tokenData[cName][tokenType]["ch"] or {cName}			elseif outType == "E" then				return getElixirCost(tokenData[cName][tokenType])			elseif outType == "R" then				return getRarity(tokenData[cName][tokenType])			elseif outType == "C" then				local tokType = tokenData[cName][tokenType][2] or 999

if tokType and math.floor(tokType/100) == 1 then tokType = math.mod(tokType, 100) end

if tokType == 0 then return COLL.getCollection({mw.ustring.lower(cName):match("^ip%-(.+)$"), 35}) elseif tokType == 6 then return '' elseif tokType == 81 then return '' elseif tokType == 10 then return '' elseif tokenType ~= "0" then return '' end end if autoBreaks and pagename == tokName then addThis = false tToken = {space, ""} end else if outType == "R" then tToken = {space, "Unknown"} end addThis = true tToken[8] = "" tToken[ 9] = "work_in_progress" tToken[15] = cName tToken[17] = "Work In Progress" end if count and count ~= "" then tToken[20] = count end

if addThis then if autoBreaks and iconCount >= 3 and tok ~= "" then tToken[ 1] = ' '				iconCount = 1 elseif tok ~= "" then iconCount = iconCount + 1 end

if autoBreaks and tokenData[cName] and tokenData[cName][tokenType] then local tokName = tokenData[cName][tokenType][1] if availableData["Tokens"][tokName] then local date = require("Dev:Date") local today = os.date("%Y/%m/%d %H:%M:%S") local UnlockDate = availableData["Tokens"][tokName][1] .. util.dayStart local LockDate = date(availableData["Tokens"][tokName][1]):adddays(availableData["Tokens"][tokName][2]):fmt("%Y/%m/%d") .. (availableData["Tokens"][tokName][3] or util.dayStart) if today < UnlockDate then tToken = {""} elseif today > LockDate and availableData["Tokens"][tokName][3] ~= 0 then tToken = {""} end end end

if tok == "" then tToken = {} end

table.insert(tAll, table.concat(tToken))

if outType == "P" then space = ' '			elseif outType == "I" then space = ' '			elseif outType == "N" or outType == "L" or (count and count ~= "" and size ~= "50") then space = ", " else space = " " end end end

return table.concat(tAll) end

-- Dislplay list if token links local function tokenList(rarity, stripend) local nRarity = tonumber(rarity) if not nRarity then if rarityType[string.lower(rarity or "")] then nRarity = rarityType[string.lower(rarity)] end end

local tAll = {}

for _, data in pairs(tokenData) do		for _, tok in pairs(data) do			if type(tok) == "table" then if not nRarity or (tok[2] and nRarity == math.mod(tok[2], 100)) then local sortkey = tok[1]:lower:gsub("[\"']", "")					table.insert(tAll, {sortkey, tok[1], tok[2]})				end			end		end	end

table.sort(tAll, function(a,b) return a[1] < b[1] end)

local tOut = {} local space = ""

for _, data in ipairs(tAll) do		local limited = "" if data[3] and math.floor(data[3]/100) == 1 then limited = "''" end tLink = {space, limited, "", "", "", limited} tLink[4] = data[2] local name = data[2] for strip in mw.text.gsplit(stripend, "%s*%$%s*") do name = name:gsub(" ".. strip .. "$", "") end tLink[7] = name table.insert(tOut, table.concat(tLink)) space = " · " end return table.concat(tOut) end

-- External Invokable Functions function p.getToken(frame) local tArgs = util.getArgs(frame)

local token = tArgs[1] or "" -- size is rarity for multi token list local size = tArgs[2] -- for multi token list the string to strip from end of name -- otherwise, if present then automatically add line breaks local stripend = tArgs[3] or "" -- Name of token to remove on non-token pages local skip = tArgs[4]

if token:lower:match("^multi") then return tokenList(size, stripend) else return tokenIcon(token, size, stripend, skip) end end

function p.getTokenDirect(tokens, size, addbreaks, skip) return tokenIcon(tokens, size, addbreaks, skip) end

function p.CharacterTokens(frame) local tArgs = util.getArgs(frame) local character = tArgs[1] or mw.title.getCurrentTitle.prefixedText local tTok = {} local tOut = "IP-" .. COLL.getCollection({character, "S"}):upper local space = ""

if not tokenData[character] then return "" end

for tNumb, tok in pairs(tokenData[character]) do		if not tokenData[character]["X"] then if tNumb == "2" or tNumb == "3" then table.insert(tTok, {tonumber(tNumb), ("$" .. character .. "," .. tNumb)}) elseif tonumber(tNumb) ~= nil then table.insert(tTok, {(tNumb + 10), ("$" .. character .. "," .. tNumb)}) end end end

table.sort(tTok, function(a,b) return a[1] < b[1] end) for _, item in pairs(tTok) do tOut = tOut .. item[2] end return p.getToken({tOut, "I", "B"}) end

function p.tokenType(frame) local tArgs = util.getArgs(frame) local token = tArgs[1] or mw.title.getCurrentTitle.prefixedText token = token:gsub(" Token$", "") local nRarity = nil

if tArgs[3] and tonumber(tArgs[3]) then nRarity = tArgs[3] else for name, data in pairs(tokenData) do			for _, tok in pairs(data) do				if type(tok) == "table" and not tokenData[name]["X"] then if tok[1] == token then if tArgs[2] and tok[2] then nRarity = tok[2] else nRarity = tok[3] or tok[2] end end end end end end if nRarity and math.floor(nRarity/100) == 1 then nRarity = math.mod(nRarity, 100) end for rar, numb in pairs(rarityType) do		if numb == nRarity then if (rar:match("relic") or rar == "blueprint") and tArgs[2] and tArgs[2] == "S" then return "ae" else return rar end end end return "unknown" end

local function itemList(tIndex, infobox) local tOut = {} local numb = 0

for key, item in ipairs(tIndex) do		if item ~= "" then table.insert(tOut, "" .. item .. "") numb = key end end

table.sort(tOut)

if numb > 3 and infobox then return ' ' .. table.concat(tOut, " ") .. ' '	elseif infobox then return table.concat(tOut, " ") else return table.concat(tOut, ", ") end end

function p.getTokeninfo(frame) local tArgs = util.getArgs(frame) local VL = mw.ext.VariablesLua

local token = tArgs[1] or mw.title.getCurrentTitle.prefixedText token = token:gsub(" Token$", "")

local characters = {} local costumes = {} local attractions = {} local collection = nil local prev = nil

for name, data in pairs(tokenData) do		for num, tok in pairs(data) do			if type(tok) == "table" and not tokenData[name]["X"] then if tok[1] == token then VL.vardefine("pagename", mw.ustring.gsub(token, "^([^%(]-) *%(([^%(]-)%)", "%1"))

if name:match("^IP%-.+$") and not tok["ch"] then characters = COLL.getCollItem(name:match("^IP%-(.+)$"))["ch"] if tokenData["Relic " .. name:match("^IP%-(.+)$")] then attractions = COLL.getCollItem(name:match("^IP%-(.+)$"))["ba"] end collection = COLL.getCollection({mw.ustring.lower(name):match("^ip%-(.+)$"), "L"}) elseif name:match("^Relic .+$") and not tok["ba"] then attractions = COLL.getCollItem(name:match("^Relic (.+)$"))["ba"] collection = COLL.getCollection({mw.ustring.lower(name):match("^relic (.+)$"), "L"}) end

local fname = mw.ustring.lower(tokenData[name]["F"] or name) fname = mw.ustring.gsub(fname, "fabric ", "f-") fname = mw.ustring.gsub(fname, " ", "_") fname = mw.ustring.gsub(fname, "[':\"%,%.]", "")					fname = mw.ustring.gsub(fname, "^([^%(]-) *%(([^%(]-)%)", "%1_%2")					if num ~= "0" then						fname = fname .. "-" .. num						VL.vardefine("prevtok", tokenIcon("IP-" .. COLL.getCollection({name, "S"}):upper, "I"))						if num == "1" and tokenData[name]["2"] then							VL.vardefine("nexttok", tokenIcon(name .. ",2", "I"))						elseif num == "2" and tokenData[name]["1"] then 							VL.vardefine("nexttok", tokenIcon(name .. ",1", "I"))						elseif num == "2" and tokenData[name]["3"] then 							VL.vardefine("nexttok", tokenIcon(name .. ",3", "I"))						else							VL.vardefine("nexttok", tokenIcon(name .. ",2", "I"))						end

table.insert(characters, name) end VL.vardefine("file", mw.ustring.lower("t-" .. fname .. ".png"))

VL.vardefine("rarity", getRarity(tok)) VL.vardefine("elixircost", getElixirCost(tok)) VL.vardefine("type", p.tokenType({token, "T", tok[2], name}))

characterlist = itemList((tok["ch"] or characters), true) costumelist = itemList((tok["cos"] or costumes), true) attractionlist = itemList((tok["ba"] or attractions), true)

if characterlist ~= "" then VL.vardefine("characters", characterlist) end if costumelist ~= "" then VL.vardefine("costumes", costumelist) end if attractionlist ~= "" then VL.vardefine("attractions", attractionlist) end

local text = "'''" .. VL.var("pagename") .. " Token''' is " local typetext = {["unknown"] = "an ", ["event"] = "an ", ["elixir ingot"] = "an ", ["uncommon relic"] = "an ", ["uncommon"] = "an ", ["epic"] = "an "} if VL.var("type"):match(" relic") then if typetext[VL.var("type")] then text = text .. "an " else text = text .. "a " end text = text .. VL.var("type") .. " token" elseif VL.var("type") ~= VL.var("rarity") and VL.var("rarity") ~= "unknown" and not VL.var("type"):match("relic") then if typetext[VL.var("rarity")] then text = text .. "an " else text = text .. "a " end text = text .. VL.var("rarity") .. " " .. VL.var("type") .. " token" else if typetext[VL.var("rarity")] then text = text .. "an " else text = text .. "a " end text = text .. VL.var("rarity") .. " token" end if VL.var("pagename") == "Refresh" then text = text .. " used to refresh characters during The Tower Challenge Events" elseif VL.var("type") == "elixir ingot" then text = text .. " used to provide an additional source for Elixirs" text = "" .. text elseif VL.var("type") == "npc" and characterslist ~= "" then text = text .. " used to catch " .. itemList(tok["ch"] or characters) text = "" .. text elseif characterlist ~= "" then if collection and not tok["ch"] then text = text .. " used to welcome and/or level up " .. collection .. " characters" text = "" .. text else text = text .. " used to welcome and/or level up " .. itemList(tok["ch"] or characters) end prev = true end if costumelist ~= "" then if prev and attractionlist ~= "" then text = text .. "," elseif prev then text = text .. " and" end text = text .. " used to create " .. itemList(tok["cos"] or costumes) prev = true text = "" .. text end if attractionlist ~= "" then if prev then text = text .. " and" end if collection and not tok["ba"] then text = text .. " used to enchant " .. collection .. " attractions" else text = text .. " used to enchant " .. itemList(tok["ba"] or attractions) end text = "" .. text end text = text .. "."

if not VL.var("type"):match(" relic") and VL.var("type") ~= "blueprint" and VL.var("type") ~= "elixir ingot" and not tArgs["image"] then local tokinfo = { ["event"] = {"?%", "?", "?", "?"}, ["unknown"] = {"?%", "?", "?", "?"}, ["common"] = {"90%", "3", "6", "8"}, ["uncommon"] = {"75%", "6", "10", "12"}, ["rare"] = {"35%", "10", "20", "20"}, ["epic"] = {"20%", "20", "40", "30"}, ["legendary"] = {"10%", "35", "80", "50"} }

VL.vardefine("droprate", tokinfo[VL.var("rarity")][1] or "") if VL.var("type") == "collection" then VL.vardefine("skipcost", "4") elseif VL.var("type") == "npc" then VL.vardefine("skipcost", tokinfo[VL.var("rarity")][2] or "") elseif VL.var("type") == "fabric" then VL.vardefine("skipcost", tokinfo[VL.var("rarity")][3] or "") else VL.vardefine("skipcost", tokinfo[VL.var("rarity")][4] or "") end VL.vardefine("skipcost", ("" .. VL.var("skipcost")))

if tArgs["rarity 2"] then VL.vardefine("droprate2", tokinfo[tArgs["rarity 2"]:lower][1] or "") if VL.var("type") == "npc" then VL.vardefine("skipcost2", tokinfo[tArgs["rarity 2"]:lower][2] or "") elseif VL.var("type") == "fabric" then VL.vardefine("skipcost2", tokinfo[tArgs["rarity 2"]:lower][3] or "") else VL.vardefine("skipcost2", tokinfo[tArgs["rarity 2"]:lower][4] or "") end VL.vardefine("skipcost2", ("" .. VL.var("skipcost2"))) end

if VL.var("type") == "event" then text = "" .. text end end

VL.vardefine("text", text) end end end end

return "" end

return p