Module:Recipe: Difference between revisions

From Subnautica Wiki
(adding createAllRecipes function to grab all recipes used by a provided ingredient; moving ID arguments to template calls to be able to create recipes inside createAllRecipes)
(adding smarter error handling for Template:UsesSN and Template:UsesBZ)
Line 164: Line 164:
else
else
-- If there is no recipe for the item
-- If there is no recipe for the item
if data == dataSN then
error ("Cannot craft item '" .. itemID .. "' (use Template:Uses instead)")
error ("Cannot craft item '" .. itemID .. "' (use Template:UsesSN instead)")
elseif data == dataBZ then
error ("Cannot craft item '" .. itemID .. "' (use Template:UsesBZ instead)")
else
error ("Cannot craft item '" .. itemID .. "'")
end
end
end
end
end

Revision as of 22:47, 22 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.createIcon(item, quantity, data, mid)
	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
	
	iconOut = iconOut .. "<span class='recipe__icon__img' style='top:" .. iconOffset .. "px;'>[[File:" .. image .. "|" .. iconWidth .. "px|link=" .. name .. "|" .. name .. "]]</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.getItemId(id)
    local id = id or mw.title.getCurrentTitle().text

    if data[id] then
        return id -- Entry by ID found.
    end
    -- Match by item name
    for k, v in pairs(data) do
        if v.name == id then
            return k -- Entry by name found.
        end
    end
    return nil -- Could not find entry
end

function p.createAllRecipes(id, data)
	local itemID = p.getItemID(id, data)
	if not itemID then error("Could not find item '" .. id .. "'") end
	
    local allProducts = {}

    -- Now try to find all products crafted using this ingredient
    for productID, product in pairs(data) do
        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
    -- Do something with all products IDs
    return ("%s is used by: %s"):format(id, table.concat(allProducts, ', '))
end

function p.createRecipe(id, 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
	
	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>"
	
	-- Item is found, start processing it
	if data[itemID].original 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)")
	else
		if data[itemID].recipe and data[itemID].machine then
			-- Recipe is found, start creating 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.createIcon(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.createIcon(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.createIcon(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.createIcon(v[1], v[2], data, false)
				    output = output .. addIcon
				end
			end
			output = output .. "</div>"
			
			return output .. "</div>"
		else
			-- If there is no recipe for the item
			if data == dataSN then
				error ("Cannot craft item '" .. itemID .. "' (use Template:UsesSN instead)")
			elseif data == dataBZ then
				error ("Cannot craft item '" .. itemID .. "' (use Template:UsesBZ instead)")
			else
				error ("Cannot craft item '" .. itemID .. "'")
			end
		end
	end
end

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

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

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

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

return p
-- </nowiki>