251 lines
9.2 KiB
Lua
Raw Blame History

-------------------------------------------------------------------------------
---Description of the module.
---@class Product
Product = newclass(Prototype,function(base, object)
Prototype.init(base, object)
base.classname = "HMProduct"
base.belt_ratio = 45/0.09375
end)
Product.classname = "HMProduct"
-------------------------------------------------------------------------------
---Return localised name of Prototype
---@return string
function Product:getLocalisedName()
if self.lua_prototype ~= nil then
local localisedName = self.lua_prototype.name
if self.lua_prototype.type == 0 or self.lua_prototype.type == "item" then
local item = Player.getItemPrototype(self.lua_prototype.name)
if item ~= nil then
localisedName = item.localised_name
end
end
if self.lua_prototype.type == 1 or self.lua_prototype.type == "fluid" then
local item = Player.getFluidPrototype(self.lua_prototype.name)
if item ~= nil then
localisedName = item.localised_name
end
end
return localisedName
end
return "unknow"
end
-------------------------------------------------------------------------------
---Return table key
---@return string
function Product:getTableKey()
if self.lua_prototype ~= nil then
if self.lua_prototype.type == 1 or self.lua_prototype.type == "fluid" then
local T = self.lua_prototype.temperature
if T ~= nil then
return string.format("%s#%s", self.lua_prototype.name,T)
end
local Tmin = self.lua_prototype.minimum_temperature
local Tmax = self.lua_prototype.maximum_temperature
if Tmin ~= nil or Tmax ~= nil then
Tmin = Tmin or -1e300
Tmax = Tmax or 1e300
if Tmin < -1e300 and Tmax < 1e300 then
return string.format("%s#inf#%s", self.lua_prototype.name, Tmax)
end
if Tmin > -1e300 and Tmax > 1e300 then
return string.format("%s#%s#inf", self.lua_prototype.name, Tmin)
end
if Tmin > -1e300 and Tmax < 1e300 then
return string.format("%s#%s#%s", self.lua_prototype.name, Tmin, Tmax)
end
end
end
return self.lua_prototype.name
end
return "unknow"
end
-------------------------------------------------------------------------------
---Has Burnt Result
---@return boolean
function Product:hasBurntResult()
if self.lua_prototype ~= nil then
if self.lua_prototype.type == 0 or self.lua_prototype.type == "item" then
local item = Player.getItemPrototype(self.lua_prototype.name)
return item.burnt_result ~= nil
end
end
return false
end
-------------------------------------------------------------------------------
---Clone prototype model
---@return table
function Product:clone()
local prototype = {
type = self.lua_prototype.type,
name = self.lua_prototype.name,
amount = self:getElementAmount(),
state = self.lua_prototype.state,
temperature = self.lua_prototype.temperature,
minimum_temperature = self.lua_prototype.minimum_temperature,
maximum_temperature = self.lua_prototype.maximum_temperature,
burnt = self.lua_prototype.burnt,
constant = self.lua_prototype.constant
}
return prototype
end
-------------------------------------------------------------------------------
---Get amount of element
---@see http://lua-api.factorio.com/latest/Concepts.html#Product
---@return number
function Product:getElementAmount()
local element = self.lua_prototype
if element == nil then return 0 end
if element.amount ~= nil then
---In 0.17, it seems probability can be used with just 'amount' and it
---doesn't need to use amount_min/amount_max
if element.probability ~= nil then
return element.amount * element.probability
else
return element.amount
end
end
if element.probability ~= nil and element.amount_min ~= nil and element.amount_max ~= nil then
return ((element.amount_min + element.amount_max) * element.probability / 2)
end
return 0
end
-------------------------------------------------------------------------------
---Get amount of element for bonus
---@return number
function Product:getBonusAmount()
local element = self.lua_prototype
if element == nil then return 0 end
local catalyst_amount = element.catalyst_amount or 0
local probability = element.probability or 1
local amount = 0
---If amount not specified, amount_min, amount_max and probability must all be specified.
---Minimal amount of the item or fluid to give. Has no effect when amount is specified.
---Maximum amount of the item or fluid to give. Has no effect when amount is specified.
if element.probability ~= nil and element.amount_min ~= nil and element.amount_max ~= nil then
amount = (element.amount_min + element.amount_max) / 2
end
if element.amount ~= nil then
amount = element.amount
end
if amount >= catalyst_amount then
return (amount - catalyst_amount) * probability
end
return 0
end
-------------------------------------------------------------------------------
---Get type of element (item or fluid)
---@return string
function Product:getType()
if self.lua_prototype.type == 1 or self.lua_prototype.type == "fluid" then return "fluid" end
return "item"
end
-------------------------------------------------------------------------------
---Get amount of element
---@param recipe table
---@return number
function Product:getAmount(recipe)
local amount = self:getElementAmount()
local bonus_amount = self:getBonusAmount() ---if there are no catalyst amount = bonus_amount
if recipe == nil then
return amount
end
return amount + bonus_amount * self:getProductivityBonus(recipe)
end
-------------------------------------------------------------------------------
---Count product
---@param model table
---@param recipe table
---@return number
function Product:countProduct(model, recipe)
local amount = self:getElementAmount()
local bonus_amount = self:getBonusAmount() ---if there are no catalyst amount = bonus_amount
return (amount + bonus_amount * self:getProductivityBonus(recipe) ) * recipe.count
end
-------------------------------------------------------------------------------
---Count ingredient
---@param model table
---@param recipe table
---@return number
function Product:countIngredient(model, recipe)
local amount = self:getElementAmount()
return amount * recipe.count
end
-------------------------------------------------------------------------------
---Count container
---@param count number
---@param container string
---@param time number
---@return number
function Product:countContainer(count, container, time)
if count == nil then return 0 end
if self.lua_prototype.type == 0 or self.lua_prototype.type == "item" then
local entity_prototype = EntityPrototype(container)
if entity_prototype:getType() == "inserter" then
local inserter_capacity = entity_prototype:getInserterCapacity()
local inserter_speed = entity_prototype:getInserterRotationSpeed()
---temps pour 360<36> t=360/360*inserter_speed
local inserter_time = 1 / inserter_speed
return count * inserter_time / (inserter_capacity * (time or 1))
elseif entity_prototype:getType() == "transport-belt" then
---ratio = item_per_s / speed_belt (blue belt)
local belt_speed = entity_prototype:getBeltSpeed()
return count / (belt_speed * self.belt_ratio * (time or 1))
elseif entity_prototype:getType() ~= "logistic-robot" then
local cargo_wagon_size = entity_prototype:getInventorySize(1)
if cargo_wagon_size == nil then return 0 end
if entity_prototype:getInventorySize(2) ~= nil and entity_prototype:getInventorySize(2) > entity_prototype:getInventorySize(1) then
cargo_wagon_size = entity_prototype:getInventorySize(2)
end
local stack_size = ItemPrototype(self.lua_prototype.name):stackSize()
if cargo_wagon_size * stack_size == 0 then return 0 end
return count / (cargo_wagon_size * stack_size)
else
local cargo_wagon_size = entity_prototype:native().max_payload_size + (Player.getForce().worker_robots_storage_bonus or 0 )
return count / cargo_wagon_size
end
end
if self.lua_prototype.type == 1 or self.lua_prototype.type == "fluid" then
local entity_prototype = EntityPrototype(container)
if entity_prototype:getType() == "pipe" then
local fluids_logistic_maximum_flow = User.getParameter("fluids_logistic_maximum_flow")
return count / (fluids_logistic_maximum_flow or defines.constant.logistic_flow_default)
else
local cargo_wagon_size = EntityPrototype(container):getFluidCapacity()
if cargo_wagon_size == 0 then return 0 end
return count / cargo_wagon_size
end
end
end
-------------------------------------------------------------------------------
---Get the productivity bonus of the recipe
---@param recipe table
---@return number
function Product:getProductivityBonus(recipe)
if recipe.isluaobject or recipe.factory == nil or recipe.factory.effects == nil then return 1 end
local productivity = recipe.factory.effects.productivity
local capped_time = recipe.time / recipe.factory.speed
local factory_speed = recipe.factory.speed_total or 1
local adjusted_time = recipe.time / factory_speed
local speed_adjustment = capped_time / adjusted_time
productivity = productivity * speed_adjustment
return productivity
end