Module:Enemies

---	Enemies contains details of Risk of Rain 2's monsters. --	--	@module		enemies --	@alias		p --	@author		User:Cephalon Scientia --	@attribution	All who helped to update enemy infoboxes --	@require	Module:Enemies/Data -- @require	Module:Environments/Data --	@release	stable --

local MonsterData = mw.loadData('Module:Enemies/Data').Monsters local EnvData = mw.loadData("Module:Environments/Data").Environments

local p = {} table.unpack = unpack	-- pre-Lua 5.3 table library does not have unpack function

function pairsByKeys (t, f) -- Sort tables, copied from https://www.lua.org/pil/19.3.html local a = {} for n in pairs(t) do table.insert(a, n) end table.sort(a, f) local i = 0      -- iterator variable local iter = function   -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end

function p.TypeCount(frame) local c = 0 for _, entry in pairs(MonsterData) do		if entry.Type == frame.args[1] or frame.args[1]:lower == "all" then c = c + 1 end end return c end

---	Builds a template for a family link. --	@function		p.FamilyLink --	@param			{table} frame Frame object --	@return			{string} Preprocessed wikitext of link. function p.FamilyLink(frame) if (frame.args[1] == "" or frame.args[1] == nil) then return error("Enemies.FamilyLink: Invalid family name '" .. frame.args[1] .. "'.") end local ret = "" for _, entry in pairsByKeys(MonsterData) do		if entry.Family ~= nil and entry.Family == frame.args[1] then ret = ret .. " "		end end if ret == "" then return error("Enemies.FamilyLink: Invalid family name '" .. frame.args[1] .. "'.") end ret = ret:sub(1, -2) .. " " .. frame.args[1] .. "" return frame:preprocess(ret) end

---	Builds a template for a monster's expansion. --	@function		p.MonsterExpansion --	@param			{table} frame Frame object --	@return			{string} Preprocessed wikitext of expansion template. function p.MonsterExpansion(frame) local data = MonsterData[frame.args[1]] if data == nil then return "" end return data.Expansion and frame:preprocess("") or "" end

local gallery = "" local galleryElement = "File:%s|link=%s|%s\n"

---	Builds a gallery of all monsters, or of a specific type. --	@function		p.MonsterGallery --	@param			{table} frame Frame object --	@return			{string} Preprocessed wikitext of resultant gallery --	@usage			p.MonsterGallery(mw.getCurrentFrame) or function p.MonsterGallery(frame) local monsterType = frame.args[1] local str = "" for _, entry in pairsByKeys(MonsterData) do		if monsterType:lower == "none" or entry.Type:lower == monsterType:lower then str = str .. string.format(galleryElement, entry.Image, entry.Name, entry.Name, (entry.Family and (" " .. entry.Family .. " Family") or "")) end end return frame:preprocess(string.format(gallery, str)) end

---	Builds a wikitable of all monsters. --	@function		p.BuildAllMonstersTable --	@param			{table} frame Frame object --	@return			{string} Preprocessed wikitext of resultant wikitable --	@usage			p.BuildAllMonstersTable(mw.getCurrentFrame) or function p.BuildAllMonstersTable(frame) local wikitable = { [=[ {| class="wikitable sortable" ! Image ! Name ! data-sort-type="number" | Health ! data-sort-type="number" | Damage ! data-sort-type="number" | Health Regen ! data-sort-type="number" | Armor ! data-sort-type="number" | Movement Speed ! Class ! Type }	-- Corresponding to key names in /Data -- Order will determine which where data will appear in below format string local keyNames = { "Image", "Link", "Name", "Health", "Damage", "Regen", "BaseArmor", "BaseSpeed", "Class", "Type" }	-- Table row looks like format string: "| [[File:%s]] || %s%s || %s || ... || %s" -- Would eventually become something like: -- | [[File:Gup.png]] || Gup || 1000 || 300 || 12 || 2.4 || N/A || N/A || N/A || 12 local tableRow = (function		local temp = { "| %s || " }		-- For function chaining syntax		temp.remove = function(self, elem)			table.remove(self, #self)			return self		end		for _, key in ipairs(keyNames) do			table.insert(temp, " || %s")		end		-- Removing extra columns since first two columns have custom formatting		temp:remove:remove:remove		table.insert(temp, "\n|-")		return table.concat(temp, "")	end) for _, monsterEntry in pairsByKeys(MonsterData) do		local keyValues = {} for _, key in pairs(keyNames) do			if (key == "Health") then table.insert(keyValues, (monsterEntry["BaseHealth"] or "N/A") .. " (+" .. (monsterEntry["ScalingHealth"] or "N/A") .. ")" )			elseif (key == "Damage") then table.insert(keyValues, (monsterEntry["BaseDamage"] or "N/A") .. " (+" .. (monsterEntry["ScalingDamage"] or "N/A") .. ")" )			elseif (key == "Regen") then table.insert(keyValues, (monsterEntry["BaseHealthRegen"] or "0") .. "/s (+" .. (monsterEntry["ScalingHealthRegen"] or "0") .. "/s)" ) elseif (key == "Type") then if (monsterEntry[key] == "Boss" or monsterEntry[key] == "Special Boss") then table.insert(keyValues, "" .. monsterEntry[key] .. "") else table.insert(keyValues, monsterEntry[key] or "N/A") end elseif (key == "BaseSpeed") then table.insert(keyValues, (monsterEntry["BaseSpeed"] or "0") .. " m/s") else table.insert(keyValues, monsterEntry[key] or "N/A") end end table.insert(wikitable, tableRow:format(table.unpack(keyValues))) end table.insert(wikitable, "|}") return frame:preprocess(table.concat(wikitable, "\n")) end
 * -]=]

---	Builds a list of environments, given monster --	@function		p.EnvironmentList --	@param			{table} frame Frame object --	@return			{string} Preprocessed wikitext of environment list. function p.EnvironmentList(frame) local data = MonsterData[frame.args[1]] if data == nil then return error("Enemies.EnvironmentList: Invalid monster: " .. frame.args[1]) end local ret = "" local familyFlag = "" local loopFlag = false for _, entry in pairsByKeys(EnvData) do		if (entry.Monsters ~= nil and entry.Monsters[data.Name] ~= nil) then local mData = entry.Monsters[data.Name] if mData.FamilyEvent ~= nil then familyFlag = mData.FamilyEvent end if mData.Loop == true then loopFlag = true end if not mData.Loop and mData.FamilyEvent == nil then ret = ret .. "\n* " end end end if loopFlag then ret = ret .. "\n*After Looping:" for _, entry in pairsByKeys(EnvData) do			if (entry.Monsters ~= nil and entry.Monsters[data.Name] ~= nil) then local mData = entry.Monsters[data.Name] if mData.Loop and mData.FamilyEvent == nil then ret = ret .. "\n** " end end end end if familyFlag ~= "" then ret = ret .. "\n* " .. familyFlag .. " Family Event only:" for _, entry in pairsByKeys(EnvData) do			if (entry.Monsters ~= nil and entry.Monsters[data.Name] ~= nil) then local mData = entry.Monsters[data.Name] if not mData.Loop and mData.FamilyEvent ~= nil then ret = ret .. "\n** " end end end end if not data.IgnoreDissonance then ret = ret .. "\n* Other Environments with the enabled" end return frame:preprocess(ret) end

return p