Module:Enemies

From Risk of Rain 2 Wiki
Jump to navigation Jump to search

Enemies contains details of Risk of Rain 2's monsters.

Documentation

Package items

enemies.FamilyLink(frame) (function)
Builds a template for a family link.
Parameter: frame Frame object (table)
Returns: Preprocessed wikitext of link. (string)
enemies.MonsterExpansion(frame) (function)
Builds a template for a monster's expansion.
Parameter: frame Frame object (table)
Returns: Preprocessed wikitext of expansion template. (string)
enemies.MonsterGallery(frame) (function)
Builds a gallery of all monsters, or of a specific type.
Parameter: frame Frame object (table)
Returns: Preprocessed wikitext of resultant gallery (string)
Usage: p.MonsterGallery(mw.getCurrentFrame()) or {{#invoke:Enemies|MonsterGallery|type}}
enemies.BuildAllMonstersTable(frame) (function)
Builds a wikitable of all monsters.
Parameter: frame Frame object (table)
Returns: Preprocessed wikitext of resultant wikitable (string)
Usage: p.BuildAllMonstersTable(mw.getCurrentFrame()) or {{#invoke:Enemies|BuildAllMonstersTable}}
enemies.EnvironmentList(frame) (function)
Builds a list of environments, given monster
Parameter: frame Frame object (table)
Returns: Preprocessed wikitext of environment list. (string)


---	'''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
--	<nowiki>

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 .. "{{MonsterLink|" .. entry.Name .. "|altText=|noDLC=true}} "
		end
	end
	if ret == "" then
		return error("Enemies.FamilyLink: Invalid family name '" .. frame.args[1] .. "'.")
	end
	ret = ret:sub(1, -2) .. " [[Family Events#" .. frame.args[1] .. "|" .. 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("{{" .. data.Expansion .. "|" .. data.Name .. "}}") or ""
end

local gallery = "<gallery class=\"nobackground\" widths=\"128px\" heights=\"128px\">%s</gallery>"
local galleryElement = "File:%s|link=%s|{{MonsterLink|%s|displayIcon=false}}%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 {{#invoke:Enemies|MonsterGallery|type}}
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 ("<br>" .. 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 {{#invoke:Enemies|BuildAllMonstersTable}}
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 || ... || %s"
	-- Would eventually become something like:
	-- | [[File:Gup.png]] || [[Gup|Gup]]{{SotV}} || 1000 || 300 || 12 || 2.4 || N/A || N/A || N/A || 12
	local tableRow = (function()
		local temp = { "| [[File:%s|40px|link=%s]] || {{MonsterLink|%s|displayIcon=false}}" }
		
		-- 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, "{{Color|yellow|" .. 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* {{EnvironmentLink|" .. entry.Name .. "}}" .. (mData.Note and " (" .. mData.Note .. ")" or "")
			end
		end
	end
	if loopFlag then
		ret = ret .. "\n*After [[Environments#Looping|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** {{EnvironmentLink|" .. entry.Name .. "}}" .. (mData.Note and " (" .. mData.Note .. ")" or "")
				end
			end
		end
	end
	if familyFlag ~= "" then
		ret = ret .. "\n* [[Family Events#" .. familyFlag .. "|" .. 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** {{EnvironmentLink|" .. entry.Name .. "}}" .. (mData.Note and " (" .. mData.Note .. ")" or "")
				end
			end
		end
	end
	if not data.IgnoreDissonance then
		ret = ret .. "\n* Other Environments with the {{Artifact|Dissonance}} enabled"
	end
	return frame:preprocess(ret)
end

return p