--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] local ix = ix ix.recipe = ix.recipe or {} ix.recipe.stored = ix.recipe.stored or {} --[[ Begin defining the recipe class base for other recipe's to inherit from. --]] --[[ Set the __index meta function of the class. --]] local CLASS_TABLE = {__index = CLASS_TABLE} CLASS_TABLE.name = "Blueprint Base" CLASS_TABLE.uniqueID = "blueprint_base" CLASS_TABLE.skin = 0 CLASS_TABLE.model = "models/error.mdl" CLASS_TABLE.category = "Other" CLASS_TABLE.description = "A recipe with no description." -- Called when the recipe is converted to a string. function CLASS_TABLE:__tostring() return "RECIPE["..self.name.."]" end --[[ A function to override an recipe's base data. This is just a nicer way to set a value to go along with the method of querying. --]] function CLASS_TABLE:Override(varName, value) self[varName] = value end -- A function to register a new recipe. function CLASS_TABLE:Register() return ix.recipe:Register(self) end function CLASS_TABLE:PlayerCanCraftRecipe(client) return ix.recipe:PlayerCanCraftRecipe(self, client) end --[[ End defining the base recipe class. Begin defining the recipe utility functions. --]] -- A function to get all recipes. function ix.recipe:GetAll() return self.stored end -- A function to get a new recipe. function ix.recipe:New() local object = {} setmetatable(object, CLASS_TABLE) CLASS_TABLE.__index = CLASS_TABLE return object end -- A function to register a new recipe. function ix.recipe:Register(recipe) recipe.uniqueID = string.utf8lower(string.gsub(recipe.uniqueID or string.gsub(recipe.name, "%s", "_"), "['%.]", "")) self.stored[recipe.uniqueID] = recipe if (recipe.model) then util.PrecacheModel(recipe.model) if (SERVER) then resource.AddFile(recipe.model) end end end -- A function to get an recipe by its name. function ix.recipe:FindByID(identifier) if (identifier and identifier != 0 and type(identifier) != "boolean") then if (self.stored[identifier]) then return self.stored[identifier] end local lowerName = string.utf8lower(identifier) local recipe = nil for _, v in pairs(self.stored) do local recipeName = v.name if (string.find(string.utf8lower(recipeName), lowerName) and (!recipe or string.utf8len(recipeName) < string.utf8len(recipe.name))) then recipe = v end end return recipe end end function ix.recipe:Initialize() local recipes = self:GetAll() for _, v in pairs(recipes) do if (v.OnSetup) then v:OnSetup() end end end -- Called when a player attempts to craft an item. function ix.recipe:PlayerCanCraftRecipe(recipe, client, inventory) local character = client:GetCharacter() inventory = inventory or character:GetInventory() if (recipe.skill != "bartering" and !character:CanDoAction("recipe_"..recipe.uniqueID)) then return false, "Vous n'avez pas le niveau requis pour craft cela." end -- Check if the player has all the needed tools if there are any needed if (recipe.tool and !istable(recipe.tool)) then if !ix.item.list[recipe.tool] then ErrorNoHalt("[Crafting] La recette "..recipe.name.." outil inexistant "..recipe.tool.."!\n") return false, "Recipe has unexisting tool "..recipe.tool.."!" elseif (!inventory:HasItem(recipe.tool)) then return false, "Vous n'avez pas : "..ix.item.list[recipe.tool].name.."." end end if recipe.tools and istable(recipe.tools) then for _, v in pairs(recipe.tools) do if ix.item.list[v] then if (!inventory:HasItem(v)) then return false, "Vous n'avez pas : "..ix.item.list[v].name.."." end else ErrorNoHalt("[Crafting] Recipe "..recipe.name.." has an unexisting tool "..v.."!\n") return false, "Recipe has unexisting tool "..v.."!" end end end -- Check for the ingredients if (recipe.ingredients) then for ingredient, amount in pairs(recipe.ingredients) do if (!ix.item.list[ingredient]) then ErrorNoHalt("[Crafting] Recipe "..recipe.name.." has an unexisting ingredient "..ingredient.."!\n") return false, "Recipe has unexisting ingredient "..ingredient.."!" end local count = inventory:GetItemCount(ingredient) if (count == 0) then return false, "You do not have any "..ix.item.list[ingredient].name.."." elseif (count < amount) then local name = ingredient if (amount > 1) then name = Schema:Pluralize(ix.item.list[ingredient].name) end return false, "You need at least "..tostring(amount).." "..name.."." end end end -- Check if player is near a crafting station if needed if (recipe.station) then if (!istable(recipe.station)) then if (ix.item.list[recipe.station]) then -- Find the entity the player is looking at local entity = client:GetEyeTraceNoCursor().Entity if (IsValid(entity)) then if (entity:GetClass() != "ix_item") then return false, "L'établi est invalide !" else if !entity.GetItemTable or (entity.GetItemTable and !entity:GetItemTable()) then return false, "Ce n'est pas le bon établi !" end local itemTable = entity:GetItemTable() if (itemTable.uniqueID != recipe.station) then return false, "C'est n'est pas le bon établi pour ce craft !" end if (client:GetShootPos():DistToSqr(entity:GetPos()) > 100 * 100) then return false, "Vous devez vous rapprocher de l'établi !" end end else return false, "Vous devez regardez un établi !" end else ErrorNoHalt("[Crafting] Recipe "..recipe.name.." has an unexisting station "..recipe.station.."!\n") return false, "Recipe has unexisting station "..recipe.station.."!" end else local validStations = {} local bFound, bInvalidStationEntity = false, false local entity = client:GetEyeTraceNoCursor().Entity local bEntityValid = IsValid(entity) if (!bEntityValid or client:GetShootPos():DistToSqr(entity:GetPos()) > 100 * 100) then bInvalidStationEntity = true end local campFire = recipe.canUseCampfire local campFireText = campFire and " or a Campfire" or "" if (campFire and !bInvalidStationEntity and bEntityValid and entity:GetClass() == "ix_campfire") then bFound = true end if (!bFound) then if (entity:GetClass() != "ix_item" or !entity:GetItemTable()) then bInvalidStationEntity = true end for _, v in pairs(recipe.station) do if ix.item.list[v] then validStations[#validStations + 1] = ix.item.list[v]:GetName() if (bInvalidStationEntity) then continue end -- too far/invalid/wrong class, don't bother checking local itemTable = entity:GetItemTable() if (itemTable.uniqueID != v) then continue end bFound = true break -- valid station found, stop checking station loop end end end if (!bFound) then return false, string.format("You need to be near and looking at a %s"..campFireText..".", table.concat(validStations, " or a ")) end end end -- Check if player has the crafting license if needed if (recipe.skill == "bartering" and !character:HasPermit(recipe.category)) then return false, "You do not have a business permit for this category of items, contact the Combine Civil Administration." end if (recipe.cost and isnumber(recipe.cost)) then local itemID = character:GetIdCard() if (itemID) then if (ix.item.instances[itemID]) then local credits = ix.item.instances[itemID]:GetCredits() if (credits < recipe.cost) then return false, "You do not have enough credits to purchase this item!" end else return false, "Could not find ID card!" end else return false, "You do not have an active ID card!" end end return true end if (CLIENT) then function ix.recipe:GetIconInfo(recipe) local model = recipe.model or "models/error.mdl" local skin = recipe.skin return model, skin end function ix.recipe:CanPlayerSeeRecipe(recipe) if (recipe.hidden) then return false end return true end else function ix.recipe:PlayerCraftRecipe(recipe, client) if (recipe.PlayerCraftRecipe) then recipe:PlayerCraftRecipe(client) return end local character = client:GetCharacter() local inventory = character:GetInventory() -- Take all the ingredients for ingredient, amount in pairs(recipe.ingredients) do for _ = 1, amount do local item = inventory:HasItem(ingredient) if (item) then item:Remove() else break end end end -- Break tools if (recipe.tools and !table.IsEmpty(recipe.tools)) then for k, v in pairs(recipe.tools) do local item = inventory:HasItem(v) if (item and item.isTool) then item:DamageDurability(1) end end end if (recipe.tool) then local item = inventory:HasItem(recipe.tool) if (item and item.isTool) then item:DamageDurability(1) end end -- Give the result for result, amount in pairs(recipe.result) do local item = ix.item.list[result] if (!item) then continue end local actualAmount if (type(amount) == "table") then actualAmount = amount[math.random(1, #amount)] else actualAmount = amount end if (item.maxStackSize) then -- fill up existing stacks if possible local items = inventory:GetItemsByUniqueID(result) for _, v in ipairs(items) do if (v:GetStackSize() < v.maxStackSize) then local toAdd = math.min(v.maxStackSize - v:GetStackSize(), actualAmount) actualAmount = actualAmount - toAdd v:AddStack(toAdd) if (actualAmount == 0) then break end end end end if (actualAmount > 0) then for i = 1, actualAmount, (item.maxStackSize or 1) do -- Give new items in stacks if possible local data if (item.maxStackSize) then data = {stack = math.min(actualAmount + 1 - i, item.maxStackSize)} end if (!inventory:Add(result, 1, data)) then ix.item.Spawn(result, client, nil, nil, data) end end end end -- Set the player's next crafting time client.ixNextCraftTime = CurTime() + 2 netstream.Start("CraftTime", client.ixNextCraftTime) character:DoAction("recipe_"..recipe.uniqueID) end end