Module:Database

From Aethermancer Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Database/doc

local p = { }

local modMonsters = require('Module:Monsters');
local modActions = require('Module:Actions');
local modTraits = require('Module:Traits');
local modSigTraits = require('Module:SignatureTraits');
local modEquipment = require('Module:Equipment');
local parse = require("Module:Parse");
local errorMsg = "'''An invalid parameter or value may have been entered. Refer to [[Module:Database]] for help.'''"

-- Checks if values are present within an array
local function hasValue (array, value, orValue1, orValue2)
	orValue1 = orValue1 or "none"
	orValue2 = orValue2 or "none"
	if array ~= nil then
		if type(array) == "string" then
			if string.lower(array) == string.lower(value) or string.lower(array) == string.lower(orValue1) or string.lower(array) == string.lower(orValue2) then return true
			else return false end
		end
		for k, v in pairs(array) do
			if string.lower(v) == string.lower(value) or string.lower(v) == string.lower(orValue1) or string.lower(v) == string.lower(orValue2) then return true end
		end
	else return true end
	return false
end
		
-- Filters a table, taking only those that matches the given values
local function filterTable (tab, filterType, value, orValue1, orValue2)
	orValue1 = orValue1 or "none"
	orValue2 = orValue2 or "none"
	local list = { }
	filterType = string.lower(filterType)
	for k, v in pairs(tab) do
		if hasValue (v[filterType], value, orValue1, orValue2) then
			table.insert(list, v)
	end end
	return list
end

-- Checks if a monster meets an action or trait's requirements
local function meetsReqs (att, monsterAtt, attMaverick, occurence)
	if (occurence or "") ~= "" and attMaverick == "true" then
		local num = 0
		local match = 0
		for k, v in pairs(att) do
			num = num + 1
			if hasValue (monsterAtt, v) then match = match + 1 end
		end
		if (num == match and occurence == "always") or (match > 0 and num ~= match and occurence == "condition") then return true end
	elseif occurence ~= "condition" then
		for k, v in pairs(monsterAtt) do
			if hasValue (att, v) then return true end
		end
	end
	return false
end

-- Filters only actions or traits that the given monster can learn.
local function filterMonster (monster, tab, tabType, occurence)
	local list = { }
	local monData = modMonsters.getMonster (monster)
	local monElements = monData["elements"]
	local monTypes = monData["types"]
	for k, v in pairs(tab) do
		if tabType == "actions" then
			local actMaverick = v["maverick"]
			local actElements = v["elements"]
			local actTypes = v["types"]
			if meetsReqs (actElements, monElements, actMaverick, "") and meetsReqs (actTypes, monTypes, actMaverick, occurence) then table.insert(list, v) end
		elseif tabType == "traits" then
			local traMaverick = v["maverick"]
			local traTypes = v["types"]
			if meetsReqs (traTypes, monTypes, traMaverick, occurence) then table.insert(list, v) end
	end end
	return list
end

-- Filters only monsters that can have the given action.
local function filterAction (action, tab, occurence)
	local list = { }
	local actData = modActions.getAction (action)
	local actMaverick = actData["maverick"]
	local actElements = actData["elements"]
	local actTypes = actData["types"]
	for k, v in pairs(tab) do
		local monElements = v["elements"]
		local monTypes = v["types"]
		if meetsReqs (actElements, monElements, actMaverick, "") and meetsReqs (actTypes, monTypes, actMaverick, occurence) then table.insert(list, v) end
	end
	return list
end

-- Filters only monsters that can have the given trait.
local function filterTrait (trait, tab, occurence)
	local list = { }
	local traData = modTraits.getTrait (trait)
	local traMaverick = traData["maverick"]
	local traTypes = traData["types"]
	for k, v in pairs(tab) do
		local monTypes = v["types"]
		if meetsReqs (traTypes, monTypes, traMaverick, occurence) then table.insert(list, v) end
	end
	return list
end

-- Creates infobox.
p.infobox = function (frame)
	local infobox = ""
	local boxType = frame.args["type"]
	if boxType == "monsters" then -- {{ #invoke: Database | infobox | type = monsters | monster = }}
		local monster = frame.args["monster"]
		if modMonsters.isValid (monster) then
			local data = modMonsters.getMonster (monster)
			local sigArg = "" 
			if modSigTraits.isValid(data["sig"]) then 
				local temp = modSigTraits.getTrait (data["sig"]) ["name"]
				sigArg = frame:expandTemplate{title = "DisplaySig", args = {name = temp, link = temp .. " (Trait)", icon = "Trait " .. string.lower(temp) .. ".png", effect = modSigTraits.getDesc (data["sig"])} }
			end
			local infoboxArgs = {
				name = data["name"],
				sprite = data["name"] .. " Idle.gif",
				types = parse.tag (frame, data["types"], "linebreak icons", "types", nil),
				elements = parse.tag (frame, data["elements"], nil, "elements", nil),
				health = data["health"],
				sig = sigArg,
				perks = frame:expandTemplate{title = "DisplayWorth", args = {perk1 = data["perks"][1], perk2 = data["perks"][2], perk3 = data["perks"][3] } }
			}
			infobox = frame:expandTemplate{title = "InfoboxMonster", args = infoboxArgs}
		else return modMonsters.errorMsg
		end
	elseif boxType == "actions" then -- {{ #invoke: Database | infobox | type = actions | action = }}
		local action = frame.args["action"]
		if modActions.isValid (action) then
			local data = modActions.getAction (action)
			local infoboxArgs = {
				name = data["name"],
				icon = "Action " .. string.lower(data["name"]) .. ".png",
				actions = parse.tag (frame, data["actions"], "slash", "actions", nil),
				types = parse.tag (frame, data["types"], "linebreak", "types", nil),
				elements = parse.tag (frame, data["elements"], nil, "elements", nil),
				effect = parse.replaceTerm (data["effect"])
			}
			infobox = frame:expandTemplate{title = "InfoboxAction", args = infoboxArgs}
		else return modActions.errorMsg
		end
	elseif boxType == "traits" then -- {{ #invoke: Database | infobox | type = traits | trait = }}
		local trait = frame.args["trait"]
		if modTraits.isValid (trait) then
			local data = modTraits.getTrait (trait)
			local infoboxArgs = {
				name = data["name"],
				icon = "Trait " .. string.lower(data["name"]) .. ".png",
				types = parse.tag (frame, data["types"], "linebreak", "types", nil),
				effect = parse.replaceTerm (data["effect"])
			}
			infobox = frame:expandTemplate{title = "InfoboxTrait", args = infoboxArgs}
		else return modTraits.errorMsg
		end
	elseif boxType == "sigs" then -- {{ #invoke: Database | infobox | type = sigs | trait = }}
		local trait = frame.args["trait"]
		if modSigTraits.isValid (trait) then
			local data = modSigTraits.getTrait (trait)
			local infoboxArgs = {
				name = data["name"],
				icon = "Trait " .. string.lower(data["name"]) .. ".png",
				monster = v["monster"],
				effect = parse.replaceTerm (v["effect"])
			}
			infobox = frame:expandTemplate{title = "InfoboxTrait", args = infoboxArgs}
		else return modSigTraits.errorMsg
		end
	else return errorMsg
	end
	return infobox
end

-- Creates table based on filter types and values. Returns a full list if filters are not given.
p.table = function (frame)
	local tabType = frame.args["type"]
	local monster = frame.args["monster"] -- Should only be used when table type is either actions or traits.
	local action = frame.args["action"] -- Should only be used when table type is monsters.
	local trait = frame.args["trait"] -- Should only be used when table type is monsters.
	
	-- Filter variables
	local filterType1 = frame.args["filterType1"]
	local filterType2 = frame.args["filterType2"]
	local filterType3 = frame.args["filterType3"]
	local value1 = frame.args["value1"]
	local value2 = frame.args["value2"]
	local value3 = frame.args["value3"]
	local orValue11 = frame.args["orValue11"]
	local orValue21 = frame.args["orValue21"]
	local orValue31 = frame.args["orValue31"]
	local orValue12 = frame.args["orValue12"]
	local orValue22 = frame.args["orValue22"]
	local orValue32 = frame.args["orValue32"]
	
	-- Empty list
	local list = { }
	local maverickList = { }
	
	-- Get list
	if tabType == "monsters" then list = modMonsters.getAllMonsters () -- {{ #invoke: Database | table | type = monsters }}
	elseif tabType == "actions" then list = modActions.getAllActions () -- {{ #invoke: Database | table | type = actions }}
	elseif tabType == "traits" then list = modTraits.getAllTraits () -- {{ #invoke: Database | table | type = traits }}
	elseif tabType == "sigs" then list = modSigTraits.getAllTraits () -- {{ #invoke: Database | table | type = sigs }}
	elseif tabType == "equipment" then list = modEquipment.getAllEquip () -- {{ #invoke: Database | table | type = equipment }}
	else return errorMsg end
	
	-- Limit list
	if (tabType == "monsters") and (action or "") ~= "" then -- To only show monsters that can have the given action.
		if modActions.isValid (action) then
			maverickList = filterAction (action, list, "condition")
			list = filterAction (action, list, "always")
		else return modActions.errorMsg end
	end
	if (tabType == "monsters") and (trait or "") ~= "" then -- To only show monsters that can have the given trait.
		if modTraits.isValid (trait) then
			maverickList = filterTrait (trait, list, "condition")
			list = filterTrait (trait, list, "always")
		else return modTraits.errorMsg end
	end
	if (tabType == "actions" or tabType == "traits") and (monster or "") ~= "" then -- To only show actions/traits that the given monster can have.
		if modMonsters.isValid (monster) then
			maverickList = filterMonster (monster, list, tabType, "condition")
			list = filterMonster (monster, list, tabType, "always")
		else return modMonsters.errorMsg end
	end
	
	-- Filter list
	if (filterType1 or "") ~= "" and (value1 or "") ~= "" then -- First filter.
		list = filterTable (list, filterType1, value1, orValue11, orValue12)
		maverickList = filterTable (maverickList, filterType1, value1, orValue11, orValue12)
		if (filterType2 or "") ~= "" and (value2 or "") ~= "" then -- Second filter.
			list = filterTable (list, filterType2, value2, orValue21, orValue22)
			maverickList = filterTable (maverickList, filterType2, value2, orValue21, orValue22)
			if (filterType3 or "") ~= "" and (value3 or "") ~= "" then -- Third filter.
				list = filterTable (list, filterType3, value3, orValue31, orValue32)
				maverickList = filterTable (maverickList, filterType3, value3, orValue31, orValue32)
	end end end
	
	-- Sort list
	if tabType == "monsters" then
		table.sort(list, function (a,b) return a["name"] < b["name"] end) -- Temporary. Monster tables should sort by number.
		table.sort(maverickList, function (a,b) return a["name"] < b["name"] end)
	else
		table.sort(list, function (a,b) return a["name"] < b["name"] end) -- All other tables sort by name.
		table.sort(maverickList, function (a,b) return a["name"] < b["name"] end)
	end
	
	-- Create table header
	local tab = frame:expandTemplate{title = "TableHeader", args = {tableType = tabType} } .. "\n"
	
	-- Create table header row for maverick list
	if table.getn(maverickList) > 0 then
		if tabType == "actions" then
			tab = tab .. frame:expandTemplate{title = "TableRow", args = {tableType = "actionsMaverick1"} } .. "\n"
		elseif tabType == "traits" then
			tab = tab .. frame:expandTemplate{title = "TableRow", args = {tableType = "traitsMaverick1"} } .. "\n"
		end
	end
	
	-- Creeate table rows for main list
	for k, v in ipairs(list) do
		local tableRowArgs = { }
		if tabType == "monsters" then
			tableRowArgs = {
				tableType = tabType,
				name = v["name"],
				link = v["name"],
				icon = v["name"] .. ".png",
				types = parse.tag (frame, v["types"], "linebreak", "types", nil),
				elements = parse.tag (frame, v["elements"], nil, "elements", nil)
			}
		elseif tabType == "actions" then
			tableRowArgs = {
				tableType = tabType,
				name = v["name"],
				link = v["name"] .. " (Action)",
				icon = "Action " .. string.lower(v["name"]) .. ".png",
				maverick = v["maverick"],
				actions = parse.tag (frame, v["actions"], "slash", "actions", nil),
				types = parse.tag (frame, v["types"], "linebreak", "types", nil),
				elements = parse.tag (frame, v["elements"], nil, "elements", 24),
				effect = parse.replaceTerm (v["effect"])
			}
		elseif tabType == "traits" then
			tableRowArgs = {
				tableType = tabType,
				name = v["name"],
				link = v["name"] .. " (Trait)",
				icon = "Trait " .. string.lower(v["name"]) .. ".png",
				maverick = v["maverick"],
				types = parse.tag (frame, v["types"], "linebreak", "types", nil),
				effect = parse.replaceTerm (v["effect"])
			}
		elseif tabType == "sigs" then
			tableRowArgs = {
				tableType = tabType,
				name = v["name"],
				link = v["name"] .. " (Trait)",
				icon = "Trait " .. string.lower(v["name"]) .. ".png",
				monster = v["monster"],
				effect = parse.replaceTerm (v["effect"])
			}
		elseif tabType == "equipment" then
			tableRowArgs = {
				tableType = tabType,
				name = v["name"],
				icon = "Equipment " .. string.lower(v["name"]) .. ".png",
				common = parse.replaceTerm (v["common"]),
				rare = parse.replaceTerm (v["rare"]),
				epic = parse.replaceTerm (v["epic"]),
			}
		end
		tab = tab .. frame:expandTemplate{title = "TableRow", args = tableRowArgs} .. "\n"
	end
	
	-- Create table rows for maverick list
	if table.getn(maverickList) > 0 then
		if tabType == "actions" then
			tab = tab .. frame:expandTemplate{title = "TableRow", args = {tableType = "actionsMaverick2"} } .. "\n"
			for k, v in ipairs(maverickList) do
				local tableRowArgs = {
					tableType = tabType,
					name = v["name"],
					link = v["name"] .. " (Action)",
					icon = "Action " .. string.lower(v["name"]) .. ".png",
					maverick = v["maverick"],
					actions = parse.tag (frame, v["actions"], "slash", "actions", nil),
					types = parse.tag (frame, v["types"], "linebreak", "types", nil),
					elements = parse.tag (frame, v["elements"], nil, "elements", 24),
					effect = parse.replaceTerm (v["effect"])
				}
				tab = tab .. frame:expandTemplate{title = "TableRow", args = tableRowArgs} .. "\n"
			end
		elseif tabType == "traits" then
			tab = tab .. frame:expandTemplate{title = "TableRow", args = {tableType = "traitsMaverick2"} } .. "\n"
			for k, v in ipairs(maverickList) do
				local tableRowArgs = {
					tableType = tabType,
					name = v["name"],
					link = v["name"] .. " (Trait)",
					icon = "Trait " .. string.lower(v["name"]) .. ".png",
					maverick = v["maverick"],
					types = parse.tag (frame, v["types"], "linebreak", "types", nil),
					effect = parse.replaceTerm (v["effect"])
				}
				tab = tab .. frame:expandTemplate{title = "TableRow", args = tableRowArgs} .. "\n"
			end
		end
	end
	
	-- Create table footer
	tab = tab .. "|}</div>"
	return tab
end

-- Creates table with custom listings.
p.tablelist = function (frame)
	local tabType = frame.args["type"]
	local list = frame.args
	
	-- Create table header
	local tab = frame:expandTemplate{title = "TableHeader", args = {["tableType"] = tabType} } .. "\n"
	
	-- Create table row
	for k, v in ipairs(list) do
		local data = ""
		local tableRowArgs = { }
		if tabType == "monsters" and modMonsters.isValid (mw.text.trim(v)) then
			data = modMonsters.getMonster (mw.text.trim(v))
			tableRowArgs = {
				tableType = tabType,
				name = data["name"],
				link = data["name"],
				icon = data["name"] .. ".png",
				types = parse.tag (frame, data["types"], "linebreak", "types", nil),
				elements = parse.tag (frame, data["elements"], nil, "elements", nil)
			}
		elseif tabType == "actions" and modActions.isValid (mw.text.trim(v)) then
			data = modActions.getAction (mw.text.trim(v))
			tableRowArgs = {
				tableType = tabType,
				name = data["name"],
				link = data["name"] .. " (Action)",
				icon = "Action " .. string.lower(data["name"]) .. ".png",
				maverick = data["maverick"],
				actions = parse.tag (frame, data["actions"], "slash", "actions", nil),
				types = parse.tag (frame, data["types"], "linebreak", "types", nil),
				elements = parse.tag (frame, data["elements"], nil, "elements", 24),
				effect = parse.replaceTerm (data["effect"])
			}
		elseif tabType == "traits"  and modTraits.isValid (mw.text.trim(v)) then
			data = modTraits.getTrait (mw.text.trim(v))
			tableRowArgs = {
				tableType = tabType,
				name = data["name"],
				link = data["name"] .. " (Trait)",
				icon = "Trait " .. string.lower(data["name"]) .. ".png",
				maverick = data["maverick"],
				types = parse.tag (frame, data["types"], "linebreak", "types", nil),
				effect = parse.replaceTerm (data["effect"])
			}
		elseif tabType == "sigs" and modSigTraits.isValid (mw.text.trim(v)) then
			data = modSigTraits.getTrait (mw.text.trim(v))
			tableRowArgs = {
				tableType = tabType,
				name = data["name"],
				link = data["name"] .. " (Trait)",
				icon = "Trait " .. string.lower(data["name"]) .. ".png",
				monster = data["monster"],
				effect = parse.replaceTerm (data["effect"])
			}
		end
		if (data or "") ~= "" then tab = tab .. frame:expandTemplate{title = "TableRow", args = tableRowArgs} .. "\n" end
	end
	
	-- Create table footer
	tab = tab .. "|}</div>"
	return tab
end

-- Creates monster display based on filter types and values. Returns a full list if filters are not given.
p.display = function (frame)
	local displayType = frame.args["type"]
	local monster = frame.args["monster"] -- Should only be used when display type is either actions or traits.
	local action = frame.args["action"] -- Should only be used when display type is monsters.
	local trait = frame.args["trait"] -- Should only be used when display type is monsters.
	local show = frame.args["notes"]
	
	-- Filter variables
	local filterType1 = frame.args["filterType1"]
	local filterType2 = frame.args["filterType2"]
	local filterType3 = frame.args["filterType3"]
	local value1 = frame.args["value1"]
	local value2 = frame.args["value2"]
	local value3 = frame.args["value3"]
	local orValue11 = frame.args["orValue11"]
	local orValue21 = frame.args["orValue21"]
	local orValue31 = frame.args["orValue31"]
	local orValue12 = frame.args["orValue12"]
	local orValue22 = frame.args["orValue22"]
	local orValue32 = frame.args["orValue32"]
	
	-- Empty list
	local list = { }
	local maverickList = { }
	
	-- Get list
	if displayType == "monsters" then list = modMonsters.getAllMonsters () -- {{ #invoke: Database | display | type = monsters }}
	elseif displayType == "actions" then list = modActions.getAllActions () -- {{ #invoke: Database | display | type = actions }}
	elseif displayType == "traits" then list = modTraits.getAllTraits () -- {{ #invoke: Database | display | type = traits }}
	elseif displayType == "sigs" then list = modSigTraits.getAllTraits () -- {{ #invoke: Database | display | type = sigs }}
	else return errorMsg end
	
	-- Limit list
	if (displayType == "monsters") and (action or "") ~= "" then -- To only show monsters that can have the given action.
		if modActions.isValid (action) then
			maverickList = filterAction (action, list, "condition")
			list = filterAction (action, list, "always")
		else return modActions.errorMsg end
	end
	if (displayType == "monsters") and (trait or "") ~= "" then -- To only show monsters that can have the given trait.
		if modTraits.isValid (trait) then
			maverickList = filterTrait (trait, list, "condition")
			list = filterTrait (trait, list, "always")
		else return modTraits.errorMsg end
	end
	if (displayType == "actions" or displayType == "traits") and (monster or "") ~= "" then -- To only show actions/traits that the given monster can have.
		if modMonsters.isValid (monster) then
			maverickList = filterMonster (monster, list, displayType, "condition")
			list = filterMonster (monster, list, displayType, "always")
		else return modMonsters.errorMsg end
	end
	
	-- Filter list
	if (filterType1 or "") ~= "" and (value1 or "") ~= "" then -- First filter.
		list = filterTable (list, filterType1, value1, orValue11, orValue12)
		maverickList = filterTable (maverickList, filterType1, value1, orValue11, orValue12)
		if (filterType2 or "") ~= "" and (value2 or "") ~= "" then -- Second filter.
			list = filterTable (list, filterType2, value2, orValue21, orValue22)
			maverickList = filterTable (maverickList, filterType2, value2, orValue21, orValue22)
			if (filterType3 or "") ~= "" and (value3 or "") ~= "" then -- Third filter.
				list = filterTable (list, filterType3, value3, orValue31, orValue32)
				maverickList = filterTable (maverickList, filterType3, value3, orValue31, orValue32)
	end end end
	
	-- Sort list
	if displayType == "monsters" then
		table.sort(list, function (a,b) return a["name"] < b["name"] end) -- Temporary. Monster tables should sort by number.
		table.sort(maverickList, function (a,b) return a["name"] < b["name"] end)
	else
		table.sort(list, function (a,b) return a["name"] < b["name"] end) -- All other tables sort by name.
		table.sort(maverickList, function (a,b) return a["name"] < b["name"] end)
	end
	
	local display = ""
	
	-- Create maverick header text
	if table.getn(maverickList) > 0 then
		if displayType == "monsters" then
			local text = ""
			if (action or "") ~= "" then text = modActions.getAction (action)["name"]
			elseif (trait or "") ~= "" then text = modTraits.getTrait (trait)["name"] end
			if table.getn(list) > 0 then display = display .. "<b>" .. text .. "</b> will appear on these monsters independently of other monsters in the party.\n" end
		elseif displayType == "actions" then
			if table.getn(list) > 0 then display = display .. "These Maverick actions will appear independently of other monsters in the party. \n" end
		elseif displayType == "traits" then
			if table.getn(list) > 0 then display = display .. "These Maverick traits will appear independently of other monsters in the party. \n" end
		end
	end
	
	-- Create main display
	for k, v in ipairs(list) do
		local displayArgs = { }
		if displayType == "monsters" then
			displayArgs = {
				name = v["name"],
				link = v["name"],
				icon = v["name"] .. " Portrait.png",
				types = parse.tag (frame, v["types"], "linebreak", "types", nil),
				elements = parse.tag (frame, v["elements"], nil, "elements", nil)
			}
			display = display .. frame:expandTemplate{title = "DisplayMonster", args = displayArgs} .. "\n"
		elseif displayType == "actions" then
			local temp
			if v["maverick"] == "true" then temp = "plus" else temp = "slash" end
			elementArg = frame:expandTemplate{title = "DisplayCost", args = {cost1 = v["elements"][1], cost2 = v["elements"][2], cost3 = v["elements"][3], cost4 = v["elements"][4], cost5 = v["elements"][5]} }
			displayArgs = {
				skill = "action",
				name = v["name"],
				link = v["name"] .. " (Action)",
				icon = "Action " .. string.lower(v["name"]) .. ".png",
				maverick = v["maverick"],
				types = parse.tag (frame, v["types"], temp, "types", nil),
				elements = elementArg,
				effect = parse.replaceTerm (v["effect"]),
				shownotes = show,
				notes = v["requires"]
			}
			display = display .. frame:expandTemplate{title = "DisplaySkill", args = displayArgs} .. "\n"
		elseif displayType == "traits" then
			displayArgs = {
				skill = "trait",
				name = v["name"],
				link = v["name"] .. " (Trait)",
				icon = "Trait " .. string.lower(v["name"]) .. ".png",
				maverick = v["maverick"],
				types = parse.tag (frame, v["types"], "plus", "types", nil),
				effect = parse.replaceTerm (v["effect"]),
				shownotes = show,
				notes = v["requires"]
			}
			display = display .. frame:expandTemplate{title = "DisplaySkill", args = displayArgs} .. "\n"
		elseif displayType == "sigs" then
			displayArgs = {
				skill = "signature",
				name = v["name"],
				link = v["name"] .. " (Trait)",
				icon = "Trait " .. string.lower(v["name"]) .. ".png",
				monster = v["monster"],
				effect = parse.replaceTerm (v["effect"])
			}
			display = display .. frame:expandTemplate{title = "DisplaySkill", args = displayArgs} .. "\n"
		end
	end
	
	-- Create maverick display
	if table.getn(maverickList) > 0 then
		if displayType == "monsters" then
			local text = ""
			local type1 = ""
			local type2 = ""
			if (action or "") ~= "" then
				text = modActions.getAction (action)["name"]
				type1 = modActions.getAction (action)["types"][1]
				type2 = modActions.getAction (action)["types"][2]
			elseif (trait or "") ~= "" then
				text = modTraits.getTrait (trait)["name"]
				type1 = modTraits.getTrait (trait)["types"][1]
				type2 = modTraits.getTrait (trait)["types"][2]
			end
			display = display .. "<b>" .. text .. "</b> will only appear on these monsters if there is another monster in the party with the other required type.\n\n"
			if table.getn(filterTable (maverickList, "types", type1, nil, nil)) > 0 then display = display .. frame:expandTemplate{title = "Types", args = {type1} } .. " monsters that can learn " .. text .. ":\n" end
			for k, v in ipairs(filterTable (maverickList, "types", type1, nil, nil)) do
				local displayArgs = { }
				displayArgs = {
					name = v["name"],
					link = v["name"],
					icon = v["name"] .. " Portrait.png",
					types = parse.tag (frame, v["types"], "linebreak", "types", nil),
					elements = parse.tag (frame, v["elements"], nil, "elements", nil)
				}
				display = display .. frame:expandTemplate{title = "DisplayMonster", args = displayArgs} .. "\n"
			end
			if table.getn(filterTable (maverickList, "types", type2, nil, nil)) > 0 then  display = display .. frame:expandTemplate{title = "Types", args = {type2} } .. " monsters that can learn " .. text .. ":\n" end
			for k, v in ipairs(filterTable (maverickList, "types", type2, nil, nil)) do
				local displayArgs = { }
				displayArgs = {
					name = v["name"],
					link = v["name"],
					icon = v["name"] .. " Portrait.png",
					types = parse.tag (frame, v["types"], "linebreak", "types", nil),
					elements = parse.tag (frame, v["elements"], nil, "elements", nil)
				}
				display = display .. frame:expandTemplate{title = "DisplayMonster", args = displayArgs} .. "\n"
			end
		elseif displayType == "actions" then
			display = display .. "These Maverick actions will only appear if there is another monster in the party with the other required type. \n"
			for k, v in ipairs(maverickList) do
				local displayArgs = { }
				elementArg = frame:expandTemplate{title = "DisplayCost", args = {cost1 = v["elements"][1], cost2 = v["elements"][2], cost3 = v["elements"][3], cost4 = v["elements"][4], cost5 = v["elements"][5]} }
				displayArgs = {
					skill = "action",
					name = v["name"],
					link = v["name"] .. " (Action)",
					icon = "Action " .. string.lower(v["name"]) .. ".png",
					maverick = v["maverick"],
					types = parse.tag (frame, v["types"], "plus", "types", nil),
					elements = elementArg,
					effect = parse.replaceTerm (v["effect"]),
					shownotes = show,
					notes = v["requires"]
				}
				display = display .. frame:expandTemplate{title = "DisplaySkill", args = displayArgs} .. "\n"
			end
		elseif displayType == "traits" then
			display = display .. "These Maverick traits will only appear if there is another monster in the party with the other required type. \n"
			for k, v in ipairs(maverickList) do
				local displayArgs = { }
				displayArgs = {
					skill = "trait",
					name = v["name"],
					link = v["name"] .. " (Trait)",
					icon = "Trait " .. string.lower(v["name"]) .. ".png",
					maverick = v["maverick"],
					types = parse.tag (frame, v["types"], "plus", "types", nil),
					effect = parse.replaceTerm (v["effect"]),
					shownotes = show,
					notes = v["requires"]
				}
				display = display .. frame:expandTemplate{title = "DisplaySkill", args = displayArgs} .. "\n"
			end
		end
	end
	
	return display
end

-- Creates monster display with custom listings.
p.displaylist = function (frame)
	local displayType = frame.args["type"]
	local show = frame.args["notes"]
	local list = frame.args
	local display = ""
	
	-- Create display
	for k, v in ipairs(list) do
		local data = ""
		local displayArgs = { }
		if displayType == "monsters" and modMonsters.isValid (mw.text.trim(v)) then
			data = modMonsters.getMonster (mw.text.trim(v))
			displayArgs = {
				name = data["name"],
				link = data["name"],
				icon = data["name"] .. " Portrait.png",
				types = parse.tag (frame, data["types"], "linebreak", "types", nil),
				elements = parse.tag (frame, data["elements"], nil, "elements", nil)
			}
			if (data or "") ~= "" then display = display .. frame:expandTemplate{title = "DisplayMonster", args = displayArgs} .. "\n" end
		elseif displayType == "actions" and modActions.isValid (mw.text.trim(v)) then
			data = modActions.getAction (mw.text.trim(v))
			local temp
			if data["maverick"] == "true" then temp = "plus" else temp = "slash" end
			elementArg = frame:expandTemplate{title = "DisplayCost", args = {cost1 = data["elements"][1], cost2 = data["elements"][2], cost3 = data["elements"][3], cost4 = data["elements"][4], cost5 = data["elements"][5]} }
			displayArgs = {
				skill = "action",
				name = data["name"],
				link = data["name"] .. " (Action)",
				icon = "Action " .. string.lower(data["name"]) .. ".png",
				maverick = data["maverick"],
				types = parse.tag (frame, data["types"], temp, "types", nil),
				elements = elementArg,
				effect = parse.replaceTerm (data["effect"]),
				shownotes = show,
				notes = data["requires"]
			}
			if (data or "") ~= "" then display = display .. frame:expandTemplate{title = "DisplaySkill", args = displayArgs} .. "\n" end
		elseif displayType == "traits" and modTraits.isValid (mw.text.trim(v)) then
			data = modTraits.getTrait (mw.text.trim(v))
			displayArgs = {
				skill = "trait",
				name = data["name"],
				link = data["name"] .. " (Trait)",
				icon = "Trait " .. string.lower(data["name"]) .. ".png",
				maverick = data["maverick"],
				types = parse.tag (frame, data["types"], "plus", "types", nil),
				effect = parse.replaceTerm (data["effect"]),
				shownotes = show,
				notes = data["requires"]
			}
			if (data or "") ~= "" then display = display .. frame:expandTemplate{title = "DisplaySkill", args = displayArgs} .. "\n" end
		elseif displayType == "sigs" and modSigTraits.isValid (mw.text.trim(v)) then
			data = modSigTraits.getTrait (mw.text.trim(v))
			displayArgs = {
				skill = "signature",
				name = data["name"],
				link = data["name"] .. " (Trait)",
				icon = "Trait " .. string.lower(data["name"]) .. ".png",
				monster = data["monster"],
				effect = parse.replaceTerm (data["effect"])
			}
			if (data or "") ~= "" then display = display .. frame:expandTemplate{title = "DisplaySkill", args = displayArgs} .. "\n" end
		end
	end
	return display
end

p.navbox = function (frame)
	local navbox = ""
	local monster = frame.args["monster"]
	local gallery = frame.args["gallery"]
	local list = modMonsters.getAllMonsters ()
	table.sort(list, function (a,b) return a["name"] < b["name"] end)
	local prevArg = ""
	local nextArg = ""
	for k, v in ipairs(list) do
		if string.lower(v["name"]) == string.lower(monster) then
			if k - 1 > 0 then prevArg = list[k-1]["name"] end
			if k + 1 <= table.getn(list) then nextArg = list[k+1]["name"] end
			break
		end
	end
	navbox = frame:expandTemplate{title = "NavboxMonster", args = {gallery, prev = prevArg, next= nextArg} }
	return navbox
end

-- Creates a table for a monster's starting actions
p.start_actions = function (frame)
	local monster = frame.args["monster"]
	local display = ""
	local action1 = ""
	local action2 = ""
	if modMonsters.isValid (monster) then
		local data = modMonsters.getMonster (monster)
		if modActions.isValid(data["start_actions"][1]) then action1 = modActions.getAction (data["start_actions"][1])["name"] end
		if modActions.isValid(data["start_actions"][2]) then action2 = modActions.getAction (data["start_actions"][2])["name"] end
		display = display .. frame:expandTemplate{title = "Action", args = {"displaylist", action1, action2} }
	end
	return display
end

-- Automatically adds categories to the page
p.category = function (frame)
	local catType = frame.args["type"]
	local item = frame.args["item"]
	local categories = ""
	if catType == "monsters" and modMonsters.isValid (item) then -- {{ #invoke: Database | category | type = monsters }}
		categories = "[[Category:Monsters]]"
		local monster = modMonsters.getMonster (item)
		for k, v in pairs(monster["elements"]) do
			categories = categories .. "[[Category:" .. frame:expandTemplate{title = "Tag", args = {v, category = "elements", nolink = true} } .. " (Element) - Monsters]]"
		end
		for k, v in pairs(monster["types"]) do
			categories = categories .. "[[Category:" .. frame:expandTemplate{title = "Types", args = {v, nolink = true} } .. " (Type) - Monsters]]"
		end
	elseif catType == "actions" and modActions.isValid (item) then -- {{ #invoke: Database | category | type = actions }}
		local action = modActions.getAction (item)
	elseif catType == "traits" and modTraits.isValid (item) then -- {{ #invoke: Database | category | type = traits}}
		local trait = modTraits.getTrait (item)
	elseif catType == "sigs" and modSigTraits.isValid (item) then -- {{ #invoke: Database | category | type = sigs}}
		local trait = modSigTraits.getTrait (item)
	else return errorMsg
	end
	return categories
end

return p