Module:Environments

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

Environments contains details of Risk of Rain 2's environments.

Documentation

Package items

environments.EnvironmentExpansion(frame) (function)
Builds a template for an environment's expansion.
Parameter: frame Frame object (table)
Returns: Preprocessed wikitext of expansion template. (string)
environments.InteractableList(frame) (function)
Builds a list of interactables, given environment
Parameter: frame Frame object (table)
Returns: Preprocessed wikitext of interactable list. (string)
environments.MonsterList(frame) (function)
Builds a list of monsters, given environment
Parameter: frame Frame object (table)
Returns: Preprocessed wikitext of monster list. (string)
environments.EnvInfobox(frame) (function)
Builds a template for an environment's infobox.
Parameter: frame Frame object (table)
Returns: Preprocessed wikitext of environment infobox. (string)


---	'''Environments''' contains details of Risk of Rain 2's environments.
--	
--	@module		environments
--	@alias		p
--	@author		[[User:Thundermaker300]]
--	@attribution	All who helped to update enemy infoboxes
--	@require	[[Module:Environments/Data]]
--  @require    [[Module:Interactables/Data]]
--	@release	stable
--	<nowiki>

local EnvData = mw.loadData('Module:Environments/Data')
local Environments = EnvData.Environments
local Interactables = mw.loadData('Module:Interactables/Data').interactables

local expansions = { EnvData.NO_DLC, EnvData.SOTV, EnvData.SOTS }

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

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

local function groupStartingStagePerExpansion(data)
	-- Keep track of all hash keys for counting
	local out = { ["index"] = {} }
	local count = 0
	for _, e in ipairs(expansions) do
		if data[e] ~= nil then
			count = count + 1
			local stage = data[e].Stage or 1
			if out[stage] == nil then
				out[stage] = {}
				table.insert(out.index, stage)
			end
			table.insert(out[stage], e)
		end
	end
	out["isInAll"] = count == #expansions
	return out
end

local function joinPhrase(t)
	if #t == 0 then return "" end
	if #t == 1 then return t[1] end
	if #t == 2 then return t[1] .. " and " .. t[2] end
	if #t > 2 then
		return table.concat(t, ", ", 1, #t-1) .. ", and " .. t[#t]
	end
end

local function constructComplexNote(data)
	local note = {}
	local count = 0
	for _, stage in ipairs(data.index) do
		count = count + #data[stage]
		table.insert(note, joinPhrase(data[stage]) .. " starting stage " .. stage)
	end
	return (count == #expansions and " (" or " (only with ") .. table.concat(note, "; ") .. ")"
end

--- Builds a list of interactables, given environment
-- @function		p.InteractableList
-- @param			{table} frame Frame object
-- @return			{string} Preprocessed wikitext of interactable list.
function p.InteractableList(frame)
	local data = Environments[frame.args[1]]
	if data == nil then
		return error("Environments.InteractableList: Invalid environment: " .. frame.args[1])
	end
	local objects = data.Interactables
	if objects == nil then
		return frame:preprocess("None.")
	end
	local wikilist = {}
	for i in pairs(Interactables) do
		local name = Interactables[i].Name
		local interactable = objects[name]
		if interactable ~= nil then
			local text = string.format("* [[%s|%s]]", Interactables[i].NameLink or name, name)
			if interactable[EnvData.ALL] ~= nil then
				local stage = interactable[EnvData.ALL].Stage
				if stage ~= nil then
					text = text .. " (starting stage " .. stage .. ")"
				end
			end
			if interactable[EnvData.ALL] == nil then
				local stageData = groupStartingStagePerExpansion(interactable)
				if stageData.isInAll then
					if #stageData.index == 1 then
						local stage = stageData.index[1]
						if stage > 1 then
							text = text .. " (starting stage " .. stage .. ")"
						end
					else
						text = text .. constructComplexNote(stageData)
					end
				else
					if #stageData.index == 1 then
						stage = stageData.index[1]
						-- State "(only with SotV,SotS,etc)" for each DLC interactable in a base game environment
						if data.Expansion == nil then
							text = text .. " (only with " .. joinPhrase(stageData[stage])
							if stage > 1 then
								text = text .. " starting stage " .. stage
							end
							text = text .. ")"
						-- State "(only with SotS)" for each non-SotV DLC interactable in a SotV environment
						elseif data.Expansion == "SotV" then
						  if interactable[EnvData.ALL] == nil and interactable[EnvData.SOTV] == nil then
							text = text .. " (only with " .. joinPhrase(stageData[stage])
							if stage > 1 then
								text = text .. " starting stage " .. stage
							end
							text = text .. ")"
						  end
						-- State "(only with SotV)" for each non-SotS DLC interactable in a SotS environment
						elseif data.Expansion == "SotS" then
						  if interactable[EnvData.ALL] == nil and interactable[EnvData.SOTS] == nil then
							text = text .. " (only with " .. joinPhrase(stageData[stage])
							if stage > 1 then
								text = text .. " starting stage " .. stage
							end
							text = text .. ")"
						  end
						else
							if stage > 1 then
								text = text .. " (starting stage " .. stage .. ")"
							end
						end
					else
						text = text .. constructComplexNote(stageData)
					end
				end
			end
			table.insert(wikilist, text)
			if name == "Void Seed" then
				table.insert(wikilist, "** [[Void Cradle|Void Cradle]]")
				table.insert(wikilist, "** [[Void Potential|Void Potential]]")
				table.insert(wikilist, "** [[Stalk|Stalk]]")
			end
		end
	end
	return frame:preprocess(table.concat(wikilist, "\n"))
end

function listDisplay(monsterName, note, family, isSub) -- handle children cases (beetle queen, gup, solus probe)
	local stars = "**" .. (isSub and "*" or "")
	local str = "* {{MonsterLink|" .. monsterName .. "}}" .. (note == nil and "" or " (" .. note .. ")") .. (family == nil and "" or (" (" .. family .. " Family event)"))
	if (monsterName == "Beetle Queen") then
		str = str .. "\n" .. stars .. " {{MonsterLink|Beetle Guard}}"
	elseif (monsterName == "Gup") then
		str = str .. "\n" .. stars .. " {{MonsterLink|Geep}}\n" .. stars .. "*" .. " {{MonsterLink|Gip}}"
	elseif (monsterName == "Solus Control Unit" or monsterName == "Alloy Worship Unit") then
		str = str .. "\n" .. stars .. " {{MonsterLink|Solus Probe}}"
	end
	return str
end

---	Builds a list of monsters, given environment
--	@function		p.MonsterList
--	@param			{table} frame Frame object
--	@return			{string} Preprocessed wikitext of monster list.
function p.MonsterList(frame)
	local data = Environments[frame.args[1]]
	if data == nil then
		return error("Environments.MonsterList: Invalid environment: " .. frame.args[1])
	end
	if data.Monsters == nil then
		return frame:preprocess("None.")
	end
	local ret = ""
	local familyFlag = false
	local loopFlag = false
	for _, entry in pairsByKeys(data.Monsters) do
		if entry.FamilyEvent == nil and not entry.Loop then
			ret = ret .. "\n" .. listDisplay(entry.Name, entry.Note, nil, false)
		end
		if entry.FamilyEvent ~= nil then
			familyFlag = true
		end
		if entry.Loop == true then
			loopFlag = true
		end
	end
	if loopFlag then
		ret = ret .. "\n*After [[Environments#Looping|Looping]]:"
		for _, entry in pairsByKeys(data.Monsters) do
			if entry.Loop == true and entry.FamilyEvent == nil then
				ret = ret .. "\n*" .. listDisplay(entry.Name, entry.Note, nil, true)
			end
		end
	end
	if familyFlag then
		ret = ret .. "\n* [[Family Events|Family Event]] only:"
		for _, entry in pairsByKeys(data.Monsters) do
			if entry.FamilyEvent ~= nil and not entry.Loop then
				ret = ret .. "\n*" .. listDisplay(entry.Name, entry.Note, entry.FamilyEvent, true)
			end
		end
	end
	return frame:preprocess(ret)
end

local env_infobox = [=[
{{Environment
| title = %s
| image = %s
| caption = %s
| stage = %s
| soundtrack = %s
| dream = %s
| description = %s
}}
]=]

---	Builds a template for an environment's infobox.
--	@function		p.EnvInfobox
--	@param			{table} frame Frame object
--	@return			{string} Preprocessed wikitext of environment infobox.
function p.EnvInfobox(frame)
	local data = Environments[frame.args[1]]
	if data == nil then
		return error("Invalid environment!")
	end
	return frame:preprocess(string.format(
		env_infobox,
		data.Name,
		data.Image,
		data.SubName or "",
		data.Stage or "Unknown",
		data.Soundtrack or "Unknown",
		data.LunarSeer or "",
		data.Description or ""
	))
end

return p