Re: help with making a harvester
Posted: Sat May 10, 2014 6:23 pm
Ok thanks for the fast reply. 

they are 'bound' to the collision box, so you could change the collision box of the refinery but that's the only way I really know of...McSpiffy wrote:Is there any way to make the inserters reach in a normal way or no?
FreeER wrote:...of course you could have the control.lua transfer the ore when you are close to a refinery (as if you were 'dumping' the ore into it), rather than using inserters.
oh, right that makes sense tooMcSpiffy wrote:I wanted to make taking the ore out of the refinery faster.
Code: Select all
game.onevent(defines.events.onputitem, function(event)
if event.onputitem.name == "refinery" then
game.createentity{name = "stone",}
end
end)
Code: Select all
game.createentity{name="stone", position=event.position}
ok I will try this do you have any pointers or guide lines I should follow to attempt this. I'm starting to feel like I'm not very good at thisFreeER wrote: Well...sorry for wasting your time with that ideathough you should be able to approximate it with code if you wanted (check every second or so if the refinery has items in it's inventory if so remove x amount and create an item entity with a stack of that name and x amount at a position relative to the refinery's position).
Code: Select all
game.onevent(defines.events.ontick, function()
if game.tick % 60 == 0 then
if game.container.name == "refinery" then
local storageItem = game.container.getinventory(1)
local itemAmount = 7 -- stack size
if item.name > 0 then
game.container.remove{name = item.name, count = itemAmount}
game.createentity{name = name= "storageItem", position = {game.container.name == "refinery", 2}, count = itemAmount}
end
end
end
end)
Don't worry, it takes a bit of time to really understand it but after you do you'll be fine (obviously...McSpiffy wrote:I'm starting to feel like I'm not very good at this
Code: Select all
game.oninit(function() --create refineries table on new game
if not glob.refineries then glob.refineries = {} end
end)
game.onload(function()
--create refineries table on load (if it does not exist)
if not glob.refineries then glob.refineries = {} end
end)
game.onevent(defines.events.onbuiltentity, function(event)
if event.createdentity.name = "refinery" then
table.insert(glob.refineries, event.createdentity)
end
end)
game.onevent(defines.events.ontick, function()
if game.tick % 60 == 0 then
for index, refinery in ipairs(glob.refineries) do
if refinery.valid then
if refinery.getitemcount() > 0 then -- if the refinery has items
-- the inventory number may be wrong... the [1] selects
-- the first item stack in the inventory
local item = refinery.getinventory(1)[1]
local itemAmount = 7 -- stack size
-- make item.count reflect the amount we are inserting/removing
-- only checking for > because we don't want to insert more if
-- if there are actually less than itemAmount in the refinery
if item.count > itemAmount then item.count = itemAmount end
-- you'll probably need to play with these number to get it to
-- place where you want it to...
-- there is also refinery.direction which tells you whether
-- the refinery is pointing north, south etc. so if you get
-- ambitious you can try to make it place the output to the
-- same relative side rather than always in one direction...
local storagePos = {refinery.position.x + 5, refinery.position.y + 5}
-- get any entities at that storagePosition
local storageEntities = game.findentities(storagePos)
local storageEntity = false -- temp bool
for _, entity in ipairs(storageEntities) do
if entity.caninsert(item) then
storageEntity = entity -- save a reference to this entity
break -- and break out of the loop
end
end
if storageEntity then -- if an entity that we can place the item into was found
storageEntity.insert(item)
refinery.remove(item)
-- no entities at all (just an else statement would allow dropping them even if there was, say, a wall there
elseif storageEntities == nil then
-- just place the item on the ground
game.createentity{name="item-on-ground", position=storagePos, stack=item}
refinery.remove(item)
end
end
else -- not a valid refinery anymore
table.remove(glob.refineries, index) -- remove from table
end
end
end
end)
Code: Select all
local storageEntities = game.findentities(storagePos)
Code: Select all
local storageEntities = game.findentities(getBoundingBox(storagePos, 1))
Code: Select all
local item
for _, slot in pairs(refinery.getinventory(1)) do -- find the first slot with an item instead of assuming the first slot
if slot then -- if the inventory slot has something in it
item = slot -- set item to hold the same item stack
break
end
end
Code: Select all
require "defines" -- has a bunch of defined constants for events and inventory, etc. the file itself is data\core\lualib\defines.lua
--// Harvester //--
game.onevent(defines.events.ontick, function() --tell game we want to do stuff every tick (60 times per second)
if game.tick % 60 == 0 then -- do this only once per second, you can decrease 60 if needed...but it'd probably be better to increase the amount of ore being removed
if game.player.vehicle and game.player.vehicle.name == "harvester" then -- if the player is in a vehicle and it is a harvester
local ore = game.findentitiesfiltered{type = "resource", area=getBoundingBox(game.player.vehicle.position, 2)} -- get a table of the ore within a (square) radius of 10 around the harvester, thankfully that was fairly easy, change the '10' to any value you think is appropriate, the 'type = "resource"' might allow it to 'mine' trees as well...if so and you didn't want that you'd need to have multiple tables and instead search using 'name = "name_of_ores"'
local oreAmount = 1 -- amount of ore to mine from each resource spot
for _, ore in ipairs(ore) do -- loop through those ores
if ore.name ~= "crude-oil" and ore.name:sub(-4) ~= "tree" then
if game.player.vehicle.caninsert{name = ore.name, count = oreAmount} then -- if the harvester is not full
if ore.amount >= oreAmount then -- if there is more than enough ore
ore.amount = ore.amount - oreAmount -- decrement the ore by oreAmount
game.player.vehicle.insert{name = ore.name, count = oreAmount} -- and insert it into the harvester
else -- if the amount of ore left is not greater than or equal to what we want to remove, just remove all of it (without the else, it'd leave any spots less than oreAmount...which would be somewhat annoying lol)
game.player.vehicle.insert{name = ore.name, count = ore.amount} -- insert first so that we don't need a local variable to store the amount
ore.amount = 0 -- then just set ore amount to 0 instead doing ore.amount = ore.amount - ore.amount (cause that looks silly :))
end
end
end
end
end
--auto coal placement into burner from trunk
if game.player.vehicle and game.player.vehicle.name == "harvester" then
local burnerCoal = game.player.vehicle.getinventory(1)
local trunkCoal = game.player.vehicle.getinventory(2)
-- notice that I combined these since you won't do anything if only one is true
if burnerCoal.getitemcount() <= 19 and trunkCoal.getitemcount("coal") > 0 then
trunkCoal.remove({name="coal", count="1"})
burnerCoal.insert({name="coal", count="1"})
end
end
end
end) -- end anonymous function and onevent/ontick call5
function getBoundingBox(position, radius)
return {{position.x - radius, position.y-radius}, {position.x + radius, position.y + radius}}
end
--// Refinery //--
game.oninit(function() --create refineries table on new game
if not glob.refineries then glob.refineries = {} end
end)
game.onload(function()
--create refineries table on load (if it does not exist)
if not glob.refineries then glob.refineries = {} end
end)
game.onevent(defines.events.onbuiltentity, function(event)
if event.createdentity.name == "refinery" then
table.insert(glob.refineries, event.createdentity)
end
end)
game.onevent(defines.events.ontick, function()
if game.tick % 60 == 0 then
for index, refinery in ipairs(glob.refineries) do
if refinery.valid then
if refinery.getitemcount() > 0 then -- if the refinery has items
-- the inventory number may be wrong... the [1] selects
-- the first item stack in the inventory
local item = refinery.getinventory(1)[1]
local itemAmount = 1 -- stack size
-- make item.count reflect the amount we are inserting/removing
-- only checking for > because we don't want to insert more if
-- if there are actually less than itemAmount in the refinery
if item.count > itemAmount then item.count = itemAmount end
-- you'll probably need to play with these number to get it to
-- place where you want it to...
-- there is also refinery.direction which tells you whether
-- the refinery is pointing north, south etc. so if you get
-- ambitious you can try to make it place the output to the
-- same relative side rather than always in one direction...
local storagePos = {refinery.position.x + 0, refinery.position.y + 5 }
-- get any entities at that storagePosition
local storageEntities = game.findentities(getBoundingBox(storagePos, 1))
local storageEntity = false -- temp bool
for _, entity in ipairs(storageEntities) do
if entity.caninsert(item) then
storageEntity = entity -- save a reference to this entity
break -- and break out of the loop
end
end
if storageEntity then -- if an entity that we can place the item into was found
storageEntity.insert(item)
refinery.remove(item)
-- no entities at all (just an else statement would allow dropping them even if there was, say, a wall there
elseif storageEntities == nil then
-- just place the item on the ground
game.createentity{name="item-on-ground", position=storagePos, stack=item}
refinery.remove(item)
end
end
else -- not a valid refinery anymore
table.remove(glob.refineries, index) -- remove from table
end
end
end
end)
Code: Select all
require "defines" -- has a bunch of defined constants for events and inventory, etc. the file itself is data\core\lualib\defines.lua
game.oninit(function() --create refineries table on new game
if not glob.refineries then glob.refineries = {} end
end)
game.onload(function()
--create refineries table on load (if it does not exist)
if not glob.refineries then glob.refineries = {} end
end)
-- store each built refinery in the glob.refineries table
game.onevent(defines.events.onbuiltentity, function(event)
if event.createdentity.name == "refinery" then
table.insert(glob.refineries, event.createdentity)
end
end)
--// Harvester //--
game.onevent(defines.events.ontick, function() --tell game we want to do stuff every tick (60 times per second)
if game.tick % 60 == 0 then -- do this only once per second, you can decrease 60 if needed...but it'd probably be better to increase the amount of ore being removed
if game.player.vehicle and game.player.vehicle.name == "harvester" then -- if the player is in a vehicle and it is a harvester
local ore = game.findentitiesfiltered{type = "resource", area=getBoundingBox(game.player.vehicle.position, 2)} -- get a table of the ore within a (square) radius of 10 around the harvester, thankfully that was fairly easy, change the '10' to any value you think is appropriate, the 'type = "resource"' might allow it to 'mine' trees as well...if so and you didn't want that you'd need to have multiple tables and instead search using 'name = "name_of_ores"'
local oreAmount = 7 -- amount of ore to mine from each resource spot
for _, ore in ipairs(ore) do -- loop through those ores
if ore.name ~= "crude-oil" and ore.name:sub(-4) ~= "tree" then
if game.player.vehicle.caninsert{name = ore.name, count = oreAmount} then -- if the harvester is not full
if ore.amount >= oreAmount then -- if there is more than enough ore
ore.amount = ore.amount - oreAmount -- decrement the ore by oreAmount
game.player.vehicle.insert{name = ore.name, count = oreAmount} -- and insert it into the harvester
else -- if the amount of ore left is not greater than or equal to what we want to remove, just remove all of it (without the else, it'd leave any spots less than oreAmount...which would be somewhat annoying lol)
game.player.vehicle.insert{name = ore.name, count = ore.amount} -- insert first so that we don't need a local variable to store the amount
ore.amount = 0 -- then just set ore amount to 0 instead doing ore.amount = ore.amount - ore.amount (cause that looks silly :))
end
end
end
end
end
--auto coal placement into burner from trunk
if game.player.vehicle and game.player.vehicle.name == "harvester" then
local burnerCoal = game.player.vehicle.getinventory(1)
local trunkCoal = game.player.vehicle.getinventory(2)
-- notice that I combined these since you won't do anything if only one is true
if burnerCoal.getitemcount() <= 19 and trunkCoal.getitemcount("coal") > 0 then
trunkCoal.remove({name="coal", count="1"})
burnerCoal.insert({name="coal", count="1"})
end
end
-- start of refinery code
for index, refinery in ipairs(glob.refineries) do
if refinery.valid then
if refinery.getitemcount() > 0 then -- if the refinery has items
-- the inventory number may be wrong... the [1] selects
-- the first item stack in the inventory
local item
-- bit of a 'hack' here...
-- the bug did occur where just selecting the first inventory
-- would be nil fairly quickly...but the for loop I posted
-- on the forums didn't work because the slot is 'userdata'
-- and you can not index userdata...
-- so I use getcontents() which returns a regular lua table
-- but it returns it indexed by the item name...and that's
-- one of the pieces of info that we actually need to get back
-- soo here's a for loop that simply selects whatever lua gives
-- back first (since associative arrays have no guarenteed order)
-- and uses that as the 'first' item
for name, count in pairs(refinery.getinventory(defines.inventory.chest).getcontents()) do
item = {name=name, count=count}
break
end
local itemAmount = 7 -- stack size
-- make item.count reflect the amount we are inserting/removing
-- only checking for > because we don't want to insert more if
-- if there are actually less than itemAmount in the refinery
if item.count > itemAmount then item.count = itemAmount end
-- you'll probably need to play with these number to get it to
-- place where you want it to...
-- there is also refinery.direction which tells you whether
-- the refinery is pointing north, south etc. so if you get
-- ambitious you can try to make it place the output to the
-- same relative side rather than always in one direction...
local storagePos = {x = refinery.position.x + 0, y = refinery.position.y + 5 }
-- get any entities at that storagePosition
local storageEntities = game.findentities(getBoundingBox(storagePos, 1))
local storageEntity = false -- temp bool
for _, entity in ipairs(storageEntities) do
if entity.caninsert(item) then
storageEntity = entity -- save a reference to this entity
break -- and break out of the loop
end
end
if storageEntity then -- if an entity that we can place the item into was found
storageEntity.insert(item)
refinery.getinventory(defines.inventory.chest).remove(item)
-- no entities at all (just an else statement would allow dropping them even if there was, say, a wall there
elseif #storageEntities == 0 then
-- just place the item on the ground
game.createentity{name="item-on-ground", position=storagePos, stack=item}
refinery.getinventory(defines.inventory.chest).remove(item)
end
end
else -- not a valid refinery anymore
table.remove(glob.refineries, index) -- remove from table
end
end -- end of refinery code
end -- end of ontick%60
end) -- end anonymous function and onevent/ontick calls
function getBoundingBox(position, radius)
return {{position.x - radius, position.y - radius}, {position.x + radius, position.y + radius}}
end