Module:Environments

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

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 }

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("") 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", 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] -- Case to avoid stating "(only with SotV)" for each interactable for a DLC-related 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 .. ")" 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") table.insert(wikilist, "** Void Potential") table.insert(wikilist, "** 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 = "* " .. (note == nil and "" or " (" .. note .. ")") .. (family == nil and "" or (" (" .. family .. " Family event)")) if (monsterName == "Beetle Queen") then str = str .. "\n" .. stars .. " "	elseif (monsterName == "Gup") then str = str .. "\n" .. stars .. " \n" .. stars .. "*" .. " "	elseif (monsterName == "Solus Control Unit" or monsterName == "Alloy Worship Unit") then str = str .. "\n" .. stars .. " "	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 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 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 = [=[

]=]

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