Module:Recipe: Difference between revisions

From Subnautica Wiki
(Attempting a bug fix for checking whether a page exists)
(creating two new functions to facilitate two new templates to show power output for the Bioreactor and Nuclear Reactor)
Line 130: Line 130:
local output = ""
local output = ""
for _, product in ipairs(allProducts) do
for _, product in ipairs(allProducts) do
output = output .. p.getRecipe(product, data)
output = output .. p.getRecipe(product, false, data)
end
end
Line 136: Line 136:
end
end


function p.getRecipe(id, data)
function p.getRecipe(id, power, data)
-- First, get the ID of the product item provided by template; pagename used by default
-- First, get the ID of the product item provided by template; pagename used by default
local itemID = p.getItemID(id, data)
local itemID = p.getItemID(id, data)
Line 145: Line 145:
local arrow = "<div class='recipe__step'><div class='recipe__step__arrow'>[[File:Item Arrow.png|20px|link=]]</div><span class='recipe__step__pseudo'><span class='recipe__step__pseudo__img'></span>×0</span></div>"
local arrow = "<div class='recipe__step'><div class='recipe__step__arrow'>[[File:Item Arrow.png|20px|link=]]</div><span class='recipe__step__pseudo'><span class='recipe__step__pseudo__img'></span>×0</span></div>"
if data[itemID].original then
if data[itemID].original and not power then
-- If the item is made as part of a different item's recipe
-- If the item is made as part of a different item's recipe
error ("No standalone recipe for item '" .. itemID .. "' (use '" .. data[itemID].original .. "' instead)")
error ("No standalone recipe for item '" .. itemID .. "' (use '" .. data[itemID].original .. "' instead)")
elseif power then
-- power
output = output .. "<div class='recipe__machine'>"
local machineID = ""
local outNum = 0
if data[itemID].energy then
machineID = "basebioreactor"
outNum = data[itemID].energy
elseif data[itemID].nuclear then
machineID = "basenuclearreactor"
outNum = data[itemID].nuclear
else
error("Item '" .. itemID .. "' does not generate power")
end
local iconMachine = p.getIcon(machineID, 0, data, false)
output = output .. iconMachine .. "</div>"
output = output .. arrow .. "<div class='recipe__ingredients'>"
output = output .. p.getIcon(itemID, 1, data, true)
output = output .. "</div>"
output = output .. arrow .. "<div class='recipe__output'>"
local iconProduct = p.getIcon("energy", outNum, data, false)
output = output .. iconProduct
output = output .. "</div>"
return output .. "</div>"
else
else
-- standard recipe
if data[itemID].recipe and data[itemID].machine then
if data[itemID].recipe and data[itemID].machine then
-- Recipe is found, start writing the output
-- Recipe is found, start writing the output
Line 201: Line 229:
local args = getArgs(frame)
local args = getArgs(frame)
local id = args[1] or mw.title.getCurrentTitle().text
local id = args[1] or mw.title.getCurrentTitle().text
return p.getRecipe(id, dataSN)
return p.getRecipe(id, false, dataSN)
end
end


Line 209: Line 237:
local machine = args[2] or "all"
local machine = args[2] or "all"
return p.getAllRecipes(id, machine, dataSN)
return p.getAllRecipes(id, machine, dataSN)
end

function p.powerSN(frame)
local args = getArgs(frame)
local id = args[1] or mw.title.getCurrentTitle().text
return p.getRecipe(id, true, dataSN)
end
end


Line 214: Line 248:
local args = getArgs(frame)
local args = getArgs(frame)
local id = args[1] or mw.title.getCurrentTitle().text
local id = args[1] or mw.title.getCurrentTitle().text
return p.getRecipe(id, dataBZ)
return p.getRecipe(id, false, dataBZ)
end
end


Line 222: Line 256:
local machine = args[2] or "all"
local machine = args[2] or "all"
return p.getAllRecipes(id, machine, dataBZ)
return p.getAllRecipes(id, machine, dataBZ)
end

function p.powerBZ(frame)
local args = getArgs(frame)
local id = args[1] or mw.title.getCurrentTitle().text
return p.getRecipe(id, true, dataBZ)
end
end



Revision as of 06:56, 25 June 2022

This module standardizes the display of crafting recipes and makes it easy to display a specified item's recipe or all recipes that use a specified ingredient. See Template:RecipeNew for more information. Thanks to BryghtShadow for helping out with the loops!


--[[
	This module standardizes the display of crafting recipes
	and makes it easy to display a specified item's recipe
	or all recipes that use a specified ingredient.
	Thanks to User:BryghtShadow for helping out with the loops!
--]]

-- <nowiki>
local p = {}
local dataSN = mw.loadData('Module:Recipe/SN')
local dataBZ = mw.loadData('Module:Recipe/BZ')
local getArgs = require('Dev:Arguments').getArgs
local width = 50
local widthBig = 75

function p.getItemID(id, data)
	-- removing disambiguations from pagenames
	id = string.gsub(id, " %(Subnautica%)", "")
	id = string.gsub(id, " %(Below Zero%)", "")
	
	-- if item ID is provided directly...
	if data[id] then
		return id
	end
	
	-- ...otherwise try to find by item name
	for k, v in pairs(data) do
		if v.name == id then -- item found
			return k
		end
	end
	
	return nil -- Could not find item
end

function p.getIcon(item, quantity, data, mid)
	if not data[item] then error("Could not generate icon for item '" .. item .. "'") end
	local iconOut = ""
	
	local iconWidth = width
	if not mid then
		iconWidth = widthBig
	end
	local iconHeight = iconWidth
	local iconOffset = 0
	
	local name = data[item].name
	
	local image = data[item].image
	local iconBG
	if not image then
		image = name .. " Icon.png"
		if data[item].icon then
			local iconBGSize = data[item].icon.size or "1x1"
			local iconBGType = data[item].icon.bg or "default"
			iconBG = iconBGSize .. " " .. iconBGType
			if iconBGSize == "1x2" then
				iconHeight = iconWidth * 2
			elseif iconBGSize == "3x2" then
				iconHeight = (iconWidth / 3) * 2
			elseif iconBGSize == "2x3" then
				iconHeight = (iconWidth / 2) * 3
			end
			iconOffset = math.max(0, ((iconHeight - iconWidth) / 2))
		else
			iconBG = "1x1 default"
		end
	end
	
	iconOut = "<div class='recipe__icon' style='width:" .. iconWidth .. "px;'>"
	
	if iconBG then
		iconOut = iconOut .. "<span class='recipe__icon__bg'>[[File:" .. iconBG .. " bg.png|" .. iconWidth .. "px|link=]]</span>"
	end
	
	-- disambiguation check
	local namefix = ""
	if data == dataBZ then
		namefix = name .. " (Below Zero)"
	else
		namefix = name .. " (Subnautica)"
	end
	local exists = mw.getCurrentFrame():callParserFunction('PROTECTIONEXPIRY:edit', namefix) ~= ''
	if not exists then
		-- disambiguated poge does not exist
		namefix = name
	end
	
	iconOut = iconOut .. "<span class='recipe__icon__img' style='top:" .. iconOffset .. "px;'>[[File:" .. image .. "|" .. iconWidth .. "px|link=" .. namefix .. "|" .. namefix .. "]]</span><span class='recipe__icon__pseudo' style='width:" .. iconWidth .. "px;'><span class='recipe__icon__pseudo__img' style='height:" .. iconHeight .. "px;width:" .. iconWidth .. "px;'></span>×0</span>"
	
	if quantity > 1 then
		iconOut = iconOut .. "<span class='recipe__icon__quantity' style='top:" .. iconHeight .. "px;'>×" .. quantity .. "</span>"
	end
	
	return iconOut .. "</div>"
end

function p.getAllRecipes(id, machine, data)
	-- First, get the ID of the product item provided by template; pagename used by default
	local itemID = p.getItemID(id, data)
	if not itemID then error("Could not find item '" .. id .. "'") end
	
	-- Item is found, start finding all recipes using it
    local allProducts = {}
    for productID, product in pairs(data) do
    	productMachine = product.machine or ""
    	if machine == "all" or machine == productMachine then
	        for _, ingredient in ipairs(product.recipe or {}) do
	            local ingredientID = ingredient[1]
	            local count = ingredient[2]
	            if ingredientID == itemID then
	                allProducts[#allProducts+1] = productID
	            end
	        end
        end
    end
    
    if #allProducts == 0 then
    	if machine == "all" then
    		error("No recipes use item '" .. id .. "'")
		else
			if(data[machine]) then
				error("No recipes use item '" .. id .."' and machine '" .. machine .. "'")
			else
				error("Machine '" .. machine .. "' does not exist")
			end
    	end
	end
    
    local output = ""
    for _, product in ipairs(allProducts) do
    	output = output .. p.getRecipe(product, false, data)
	end
    
    return output
end

function p.getRecipe(id, power, data)
	-- First, get the ID of the product item provided by template; pagename used by default
	local itemID = p.getItemID(id, data)
	if not itemID then error("Could not find recipe for item '" .. id .. "'") end
	
	-- Item is found, start processing it
	local output = "<div class='recipe'>"
	local arrow = "<div class='recipe__step'><div class='recipe__step__arrow'>[[File:Item Arrow.png|20px|link=]]</div><span class='recipe__step__pseudo'><span class='recipe__step__pseudo__img'></span>×0</span></div>"
	
	if data[itemID].original and not power then
		-- If the item is made as part of a different item's recipe
		error ("No standalone recipe for item '" .. itemID .. "' (use '" .. data[itemID].original .. "' instead)")
	elseif power then
		-- power
		output = output .. "<div class='recipe__machine'>"
		local machineID = ""
		local outNum = 0
		if data[itemID].energy then
			machineID = "basebioreactor"
			outNum = data[itemID].energy
		elseif data[itemID].nuclear then
			machineID = "basenuclearreactor"
			outNum = data[itemID].nuclear
		else
			error("Item '" .. itemID .. "' does not generate power")
		end
		local iconMachine = p.getIcon(machineID, 0, data, false)
		output = output .. iconMachine .. "</div>"
			
		output = output .. arrow .. "<div class='recipe__ingredients'>"
		output = output .. p.getIcon(itemID, 1, data, true)
		output = output .. "</div>"
		
		output = output .. arrow .. "<div class='recipe__output'>"
		local iconProduct = p.getIcon("energy", outNum, data, false)
		output = output .. iconProduct
		output = output .. "</div>"
			
		return output .. "</div>"
	else
		-- standard recipe
		if data[itemID].recipe and data[itemID].machine then
			-- Recipe is found, start writing the output
			output = output .. "<div class='recipe__machine'>"
			local machineID = data[itemID].machine
			if not data[machineID] then
				error ("Invalid machine listed in recipe for item '" .. itemID .. "'")
			end
			local iconMachine = p.getIcon(machineID, 0, data, false)
			output = output .. iconMachine .. "</div>"
			
			output = output .. arrow .. "<div class='recipe__ingredients'>"
			for i,v in ipairs(data[itemID].recipe) do
				local icon = p.getIcon(v[1], v[2], data, true)
				output = output .. icon
			end
			output = output .. "</div>"
			
			output = output .. arrow .. "<div class='recipe__output'>"
			local outNum = data[itemID].quantity or 1
			local iconProduct = p.getIcon(itemID, outNum, data, false)
			output = output .. iconProduct
			if data[itemID].additional then
				local addOut = data[itemID].additional
				local addIcon
				for i,v in ipairs(addOut) do
				    addIcon = p.getIcon(v[1], v[2], data, false)
				    output = output .. addIcon
				end
			end
			output = output .. "</div>"
			
			return output .. "</div>"
		else
			if data[itemID].recipe then
				error ("Machine is missing for item '" .. itemID .. "'")
			elseif data[itemID].machine then
				error ("Recipe is missing for item '" .. itemID .. "'")
			else
				-- If there is no recipe for the item
				if data == dataBZ then
					error ("Cannot craft item '" .. itemID .. "' (use Template:UsesBZ instead)")
				else
					error ("Cannot craft item '" .. itemID .. "' (use Template:UsesSN instead)")
				end
			end
		end
	end
end

function p.SN(frame)
	local args = getArgs(frame)
	local id = args[1] or mw.title.getCurrentTitle().text
	return p.getRecipe(id, false, dataSN)
end

function p.allSN(frame)
	local args = getArgs(frame)
	local id = args[1] or mw.title.getCurrentTitle().text
	local machine = args[2] or "all"
	return p.getAllRecipes(id, machine, dataSN)
end

function p.powerSN(frame)
	local args = getArgs(frame)
	local id = args[1] or mw.title.getCurrentTitle().text
	return p.getRecipe(id, true, dataSN)
end

function p.BZ(frame)
	local args = getArgs(frame)
	local id = args[1] or mw.title.getCurrentTitle().text
	return p.getRecipe(id, false, dataBZ)
end

function p.allBZ(frame)
	local args = getArgs(frame)
	local id = args[1] or mw.title.getCurrentTitle().text
	local machine = args[2] or "all"
	return p.getAllRecipes(id, machine, dataBZ)
end

function p.powerBZ(frame)
	local args = getArgs(frame)
	local id = args[1] or mw.title.getCurrentTitle().text
	return p.getRecipe(id, true, dataBZ)
end

return p
-- </nowiki>