Module:Storyline

--[=[

Lua Module for Stroylines Function

--]=]

local p = {}

local util = require("Module:Utility") local collectionData = mw.loadData( 'Module:ItemCollection/data' ) local COLL = require("Module:ItemCollection").getCollection local ICON = require("Module:CharacterAvatar").getAvatar local EC = require("Module:EC").getEC local NPC = require("Module:NPC").getNPC local LTE = require("Module:LTEvent").getLTE

---[==[ local storylineData = mw.loadData( 'Module:Storyline/data' ) --[===[]==] local storylineData = { ["Colors"] = { ["main"] = {nil, "ffc823", "ffff6b", "cc6600"}, ["side"] = {nil, "18e8ca", "36ffbe", "005555"}, ["ttc"] = {true, "450a6c", "930eb9", "dc86ee", "31ac2a"}, }, } --]===]

local function oneArrow(qLinks) local tOut = {'\n', "", ' '}

for idx = 0, #qLinks do		if storylineData["Arrows"][qLinks[idx]] then local tArrow = storylineData["Arrows"][qLinks[idx]] tOut[2] = tOut[2] .. table.concat({(idx ~= 1 and " " or ""), ' '}) end end

return table.concat(tOut) end

local function questIcon(qType, infobox) local qLink = "Main Storyline Walkthrough"

local qName, qDisp = mw.ustring.match(qType:lower, 		"^([^,]-)%s*-%s*(.-)$") if not qName then qName = qType:lower end

if qName:match("^act%d") then qLink = "Main Storyline Walkthrough/Act " .. qName:match("^act(%d)") qName = "Kingdom" --	elseif qName:match("^act%d%-side") then --		qLink = "Main Storyline Walkthrough/Act " .. qName:match("^act(%d)") --		qName = "Side" elseif qName == "char" then qLink = "Characters Storylines" qName = "Character" elseif qName == "main" then qName = "Kingdom" elseif qName == "side" then qName = "Side" elseif qName == "ttc" then qLink = ":Category:The Tower Challenge Events" qName = "Event" else qLink = LTE({qName, "N", "WS"}) qName = "Event" end

if qDisp and qName~="Side" then qName = qName .. " Side" end

local tOut = {""}

if infobox then tOut = {"", qName, " Quest (", table.concat(tOut), ") "} end

return table.concat(tOut) end

local function oneLink(qLinks, color) local tOut = {}

for qLink in mw.text.gsplit(qLinks, "%s*$%s*") do		local tLink = {"%{%}]", ""), "|", qLink, "", ""}

if qLink:match("^.+%#%d$") then tLink[2] = qLink local qName, qAnch = qLink:match("^(.+)%#(%d)$") tLink[5] = " Level " .. qAnch qLink = qName elseif qLink:match("^.+%#Part %d+$") then tLink[2] = qLink local qName, qAnch = qLink:match("^(.+)%#Part (%d+)$") tLink[5] = ", Pt. " .. qAnch qLink = qName end local i = 1 local tIn = mw.text.split(qLink, "%s*%-%s*") for idx = 0, #tIn do i = idx end if tIn[i] and storylineData["Colors"][tIn[i]:lower] then qLink = mw.ustring.gsub(qLink, "-" .. tIn[i]:upper .. "$", "") end if qLink:match("^.+%-%d+$") then qLink = qLink:match("(.+)%-%d+$") elseif qLink:match("^.+ %(%d+%)$") then qLink = qLink:match("(.+) %(%d+%)$") end tLink[4] = qLink

if color then tLink[4] = '' .. tLink[4] tLink[5] = tLink[5] .. ' '		end

table.insert(tOut, table.concat(tLink)) end

return table.concat(tOut, " ") end

local function oneMilestone(qAll, qType, qLink, qCost) local tOut = {}

if storylineData["Arrows"][qType] then return oneArrow(qAll) else tOut = {'\n', "", " ", oneLink(qLink, "08598e"), " (", qCost, ") "} end

if qLink ~= "" then local fname = qLink:lower:gsub("[':\"%,%.*]", ""):gsub(" ", "_")		fname = fname:gsub("^([^%(]-)%/([^%(]-)$", "%1-%2")		fname = mw.ustring.gsub(fname, "^([^%(]-) *%(([^%(]-)%)$", "%1_%2")

local iType = "C" if collectionData["Items"][qLink] and collectionData["Items"][qLink][2] and collectionData["Items"][qLink][2] == "ba" then iType = "Ba" end tOut[6] = table.concat({""}) tOut[6] = ' ' .. tOut[6] .. ' ' .. COLL({qLink, 30}) .. ' '	end

if qCost:match("^EC") then tOut[10] = EC({qCost, nil, nil, nil, 25}) end

if storylineData["Colors"][qType] then local eData = storylineData["Colors"][qType] tOut[2] = eData[3] or "1ca1fc" tOut[4] = eData[2] or "36d0ff" tOut[8] = oneLink(qLink, (eData[4] or "08598e")) end

return table.concat(tOut) .. " " end

local function oneCell(qAll, qType, qLink, qRequirement, qActivity, noTable) local bgName = qType local qTable = {} local qText = {}

if storylineData["Arrows"][qAll[1]] and noTable then return "" elseif storylineData["Arrows"][qAll[1]] then return oneArrow(qAll) else qTable = {'\n', questIcon(qType), " ", oneLink(qLink, "08598e"), " ", "", "", "", " "}

qText = {questIcon(qType), " ", oneLink(qLink), " ", "", "", "", " "} end

if qType:match("side$") then qText[2] = " " qText[4] = "" if qType:match("^.+%-side$") then bgName = qType:match("^(.+)%-side$") end end

if qRequirement ~= "" then local qReq = mw.text.split(qRequirement, "%s*%&%&%s*") for idx = 1, #qReq do			local aa = mw.text.split(qReq[idx], "%s*^%s*")

if aa[1] and aa[2] then if aa[1] == "R" then qTable[18] = qTable[18] .. " (Requires " .. aa[2] .. ")" qText[7] = qText[7] .. " (Requires " .. aa[2] .. ")" elseif aa[1]:match("R%d+") then local A = aa[1]:match("R(%d+)") qTable[18] = qTable[18] .. " (Required for " .. oneLink(aa[2]) .. ')' qText[7] = qText[7] .. " (Required for " .. oneLink(aa[2]) .. ' [&#x25BD; ' .. A .. '] )' elseif aa[1]:match("P%d+") then local A = aa[1]:match("P(%d+)") qTable[18] = qTable[18] .. " (Prerequisite " .. oneLink(aa[2]) .. ')' qText[7] = qText[7] .. " (Prerequisite " .. oneLink(aa[2]) .. ' [&#x25B3; ' .. A .. '] )' else qTable[18] = qTable[18] .. " (" .. NPC({aa[1], nil, nil, 20}) .. aa[2] .. ")" qText[7] = qText[7] .. " (" .. NPC({aa[1], nil, nil, 20}) .. aa[2] .. ")" end else qTable[16] = qTable[16] .. " (" .. qReq[idx] .. ")" qText[5] = qText[5] .. " (" .. qReq[idx] .. ")" end end end

if qActivity ~= "" then for idx = 4, #qAll do			local aa = mw.text.split(qAll[idx], "%s*^%s*")

if aa[1] and aa[2] and aa[3] then if aa[1]:match(".+ %#%d+ %+ .+ %#%d+$") then local ch1name, ch1lvl, ch2name, ch2lvl = mw.ustring.match(aa[1], "^(.-)%s*#%s*([%d%,]*)%s*+%s*(.-)%s*#%s*([%d%,]*)$") if ch1lvl == "0" then ch1lvl = "?" end if ch2lvl == "0" then ch2lvl = "?" end aa[1] = ICON({(ch1name or "?"), nil, 25}) .. " Lvl " .. (ch1lvl or "?") .. " + " .. ICON({(ch2name or "?"), nil, 25}) .. " Lvl " .. (ch2lvl or "?") elseif aa[1]:match(".+ %#%d+$") then local chname, chlvl = mw.ustring.match(aa[1], "^(.-)%s*#%s*([%d%,]*)$") if chlvl == "0" then chlvl = "?" end aa[1] = ICON({(chname or "?"), nil, 25}) .. " Lvl " .. (chlvl or "?") else local iType = "default" if collectionData["Items"][aa[1]] then iType = collectionData["Items"][aa[1]][2] end local tAct = { ["ch"] = "Welcome", ["ba"] = "Build", ["cos"] = "Get", ["default"] = "Unlock", }					aa[1] = tAct[iType] .. " " .. aa[1] .. ""

if aa[2]:match("^EC%-") then aa[2] = EC({aa[2], nil, nil, nil, 20}) end end

qTable[18] = qTable[18] .. " - " .. aa[1] .. " - " .. aa[2] .. " - " .. aa[3] qText[7] = qText[7] .. " - " .. aa[1] .. " - " .. aa[2] .. " - " .. aa[3] else qTable[18] = qTable[18] .. " - " .. qAll[idx] qText[7] = qText[7] .. " - " .. qAll[idx] end end end

if (storylineData["Colors"][qType] or storylineData["Colors"][bgName]) and not noTable then local eData = storylineData["Colors"][qType] or storylineData["Colors"][bgName] if eData[1] and eData[1] == true then qTable[2] = "white" qTable[4] = "white" end qTable[6] = eData[3] or "1ca1fc" qTable[8] = eData[2] or "36d0ff" qTable[10] = eData[5] or "ffffff00" qTable[14] = oneLink(qLink, (eData[4] or "08598e")) end if noTable then return table.concat(qText) else return table.concat(qTable) .. " "	end end

function p.getStoryline(frame) local tArgs = util.getArgs(frame) local pagename = mw.title.getCurrentTitle.text or ""

local tOut = { '\n ', '\n ', '\n ', '\n ', '\n ', , , , } local mOut = "" local tTd = { '\n ', '\n ', '\n ', '\n ', '\n ', '\n<td style="width: 1%;"> ', '\n<td style="width: 10%;"> ', '\n<td style="width: 1%;"> ', '\n<td style="width: 10%;"> '}

local i = 1 local Args = {}

repeat if tArgs[i] == nil and (tArgs[i + 1] or tArgs[i + 2] or tArgs[i + 3] or tArgs[i + 4] or tArgs[i + 5] or tArgs[i + 6] or tArgs[i + 7] or tArgs[i + 8] or tArgs[i + 9]) then table.insert(Args, tArgs[i] or "X") else table.insert(Args, tArgs[i]) end i = i + 1 until i == 10

for i, item in pairs(Args) do		local tIn = mw.text.split(item, "%s*$%s*")

if tIn[1] == "X" then tOut[i] = tTd[i] elseif tIn[1] == "title" then tOut = {' <td colspan="9" style="text-align: left;"><h3 style="margin: 0px;">', (tIn[2] or "?"), ' ', ""} if pagename ~= "Main Storyline Walkthrough" then tOut[4] = '<b id="' .. (tIn[2] or "?") .. '">' .. (tIn[2] or "?") .. '</b>' end return table.concat(tOut) elseif pagename == "Main Storyline Walkthrough" then tOut[i] = oneMilestone(tIn, tIn[1], (tIn[2] or "?"), (tIn[3] or "?")) elseif i == 3 then mOut = oneCell(tIn, tIn[1], (tIn[2] or "?"), (tIn[3] or ""), (tIn[4] or ""), true) tOut[i] = oneCell(tIn, tIn[1], (tIn[2] or "?"), (tIn[3] or ""), (tIn[4] or "")) else tOut[i] = oneCell(tIn, tIn[1], (tIn[2] or "?"), (tIn[3] or ""), (tIn[4] or "")) end end if mOut ~= "" then return ' ' .. table.concat(tOut) .. '\n \n* ' .. mOut else return ' ' .. table.concat(tOut) .. '\n ' end end

function p.getTextStoryline(frame) local tArgs = util.getArgs(frame) if not tArgs[1] then return "" end local pagename = mw.title.getCurrentTitle.text or tArgs["P"] or ""

local tIn = mw.text.split(tArgs[1], "%s*$%s*")

if tIn[1] == "title" then return table.concat({, (tIn[2] or "?"), }) else return oneCell(tIn, tIn[1], (tIn[2] or "?"), (tIn[3] or ""), (tIn[4] or ""), true) end end

function p.getLink(link) return oneLink(link) end

function p.getTextStorylineCharacter(frame) local tArgs = util.getArgs(frame) local pagename = mw.title.getCurrentTitle.baseText or tArgs["P"] or "" local tOut = "" local space = "*"

for _, v in pairs(tArgs) do		local tIn = mw.text.split(v, "%s*$%s*") if tIn[1] == "title" then tOut = tOut .. (tIn[2] or "?") else tOut = tOut .. space .. oneCell(tIn, "char-side", (tIn[1] or "?"), (tIn[2] or ""), (tIn[3] or ""), true) end space = "\n*" end

return tOut .. (pagename=="Characters Storylines" and "" or ("\n: See more: " .. pagename .. " Quests")) end

local function findCharacter(collName, collNo, collId) local tOut = { '{| class="mw-collapsible mw-collapsed article-table" style="width: 100%;"\n| style="height: 35px;"|<span id="',		collId,		'">  ', collName, '  \n| style="text-align: right;"| [ Back to Top ] \n' }	local tChar = { '|-\n| style="border-bottom: none;height: 35px;"| <b><i>', '', -- Character '</i></b> \n| rowspan="2" style="text-align: center; width: 25%;"| Cp-',		'', -- Character file		'.png \n|-\n| style="width: 75%;"|\n', }   local tIndex = {} for coll, v in pairs(collectionData["Items"]) do   	if v[1] == collNo and v[2] and (v[2] == "ch" or v[2] == "cos") then table.insert(tIndex, {coll:lower:gsub(" ", "_"), coll}) end end

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

for _, name in pairs(tIndex) do	name[1] = mw.ustring.gsub(mw.ustring.lower(name[2]), "[':\"%,%.]", "")	name[1] = name[1]:gsub(" ", "_")	name[1] = name[1]:gsub("^([^,]-)%s*/%s*(.-)$", "%1-%2")	name[1] = mw.ustring.gsub(name[1], "^([^%(]-) *%(([^%(]-)%)$", "%1_%2")

tChar[2] = name[2] tChar[4] = name[1] tChar[6] = name[2] tChar[8] = name[2] tChar[10] = name[2] table.insert(tOut, table.concat(tChar)) end

return table.concat(tOut) .. '|}' end

function p.getCharacterStorylines(frame) local collections = {} local allcollections = {} local storylines = "" local space = ""

for k, v in pairs(collectionData["Collections"]) do   	if k <= 9900 then table.insert(collections, {k, v[2], (v["A"] or v[2])}) end end

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

for _, coll in pairs(collections) do	table.insert(allcollections, coll[3])

storylines = storylines .. space .. findCharacter(coll[2], coll[1], coll[3])

space = "\n\n" end

storylines = COLL({table.concat(allcollections, "$"), "A"}) .. "\n" .. storylines

return frame:preprocess(storylines) end

function p.getRequiredLevel(frame) local tArgs = util.getArgs(frame) local characters = {} local tOut = {'{| class="article-table dmk-list" style="width: fit-content;"\n!'}

for arg, values in pairs(tArgs) do		if arg == 1 then for _, date in pairs(mw.text.split(values, "%s*%$%s*")) do table.insert(tOut, ('\n! style="line-height: 1.3;"|' .. date .. '')) end else table.insert(characters, {arg, mw.text.split(values, "%s*%$%s*")}) end end

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

for _, name in pairs(characters) do table.insert(tOut, '\n|-\n! style="width: 1%;"|') if name[2][1] ~= "?" then table.insert(tOut, ICON({name[2][1], nil, 40})) table.insert(tOut, ' ')			table.insert(tOut, name[2][1])			table.insert(tOut, ' ') else table.insert(tOut, ' All Characters ') end for _, lvl in pairs(mw.text.split(name[2][2], "%s*%/%s*")) do			table.insert(tOut, '\n|') if lvl ~= "0" then table.insert(tOut, lvl) end end end

table.insert(tOut, '\n|}')

return table.concat(tOut) end

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

local qName = tArgs["name"] or mw.title.getCurrentTitle.text local qType = tArgs["type"] or "char-side"

VL.vardefine("type", questIcon(qType, true)) local iName, iType = mw.ustring.match(qType, "^([^,]-)%s*-%s*(.-)$") if not iName then iName = qType end

if not tArgs["name"] then if qName:match("^.+%-" .. iName .. "$") then qName = qName:match("^(.+)%-" .. iName .. "$") end if qName:match("^.+%-%d+$") then qName = qName:match("^(.+)%-%d+$") end end VL.vardefine("dispname", qName) if tArgs["part"] then qName = qName .. ", Pt. " .. tArgs["part"] end VL.vardefine("pagename", qName)

VL.vardefine("requires", tArgs["requires"]) if tArgs["requires"] and (tArgs["requires"]:match("^.+%-" .. iName .. "$") or tArgs["requires"]:match("^.+%#Part %d+$")) then VL.vardefine("requires", oneLink(tArgs["requires"])) end VL.vardefine("unlocks", tArgs["unlocks"]) if tArgs["unlocks"] and (tArgs["unlocks"]:match("^.+%-" .. iName .. "$") or tArgs["unlocks"]:match("^.+%#Part %d+$")) then VL.vardefine("unlocks", oneLink(tArgs["unlocks"])) end

VL.vardefine("previous", tArgs["previous"]) if tArgs["previous"] and (tArgs["previous"]:match("^.+%-" .. iName .. "$") or tArgs["previous"]:match("^.+%#Part %d+$")) then VL.vardefine("previous", oneLink(tArgs["previous"])) end VL.vardefine("next", tArgs["next"]) if tArgs["next"] and (tArgs["next"]:match("^.+%-" .. iName .. "$") or tArgs["next"]:match("^.+%#Part %d+$")) then VL.vardefine("next", oneLink(tArgs["next"])) end

VL.vardefine("side", tArgs["side"]) if tArgs["side"] and (tArgs["side"]:match("^.+%-" .. iName .. "$") or tArgs["side"]:match("^.+%#Part %d+$")) then VL.vardefine("side", oneLink(tArgs["side"])) end VL.vardefine("branches", tArgs["branches"]) if tArgs["branches"] and (tArgs["branches"]:match("^.+%-" .. iName .. "$") or tArgs["branches"]:match("^.+%#Part %d+$")) then VL.vardefine("branches", oneLink(tArgs["branches"])) end

return "" end

return p