help with making a harvester

Place to get help with not working mods / modding interface.
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

Ok thanks for the fast reply. :D
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

Hey I'm working on the "refinery" building its like a really big storage chest, and I have ran into a problem. The image I'm using is rather large to match the scale of the harvester (216 x 216) and the inserters are taking longer to mover items back and forth then normal because the inserters are reaching to the center of the image and stretching. Is there any way to make the inserters reach in a normal way or no? Maybe increasing inserter's extension speed when it is taking from the refinery?
User avatar
FreeER
Smart Inserter
Smart Inserter
Posts: 1266
Joined: Mon Feb 18, 2013 4:26 am
Contact:

Re: help with making a harvester

Post by FreeER »

McSpiffy wrote:Is there any way to make the inserters reach in a normal way or no?
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...
...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.
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

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.

Yea that was the plan its just I wanted to make taking the ore out of the refinery faster.
Maybe something like if inserter is next to refinery change inserter speed to #
User avatar
FreeER
Smart Inserter
Smart Inserter
Posts: 1266
Joined: Mon Feb 18, 2013 4:26 am
Contact:

Re: help with making a harvester

Post by FreeER »

McSpiffy wrote:I wanted to make taking the ore out of the refinery faster.
oh, right that makes sense too :D
I'm not sure that you can change the speed of inserters through lua though...I'll assume you've tested with the fast inserters and not just the basic ones...trying to think of something that doesn't involve creating faster inserters and replacing nearby inserters with them (since that could cause issues)....hm... other than checking the nearby inserters' 'heldstack' and increasing it's count by a factor of 4 or so (and decrementing the refinery's) if it is holding something that is in the refinery (and even that could have issues depending on if other unrelated inserters are nearby), I'm not sure of a decent way to make it faster.
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

lol ok i guess i'll mess around with it and see
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

See this is the problem the inserters over extend and the take more time to retract.
Attachments
2014-05-13 21_56_47-Greenshot.jpg
2014-05-13 21_56_47-Greenshot.jpg (316.85 KiB) Viewed 4901 times
User avatar
FreeER
Smart Inserter
Smart Inserter
Posts: 1266
Joined: Mon Feb 18, 2013 4:26 am
Contact:

Re: help with making a harvester

Post by FreeER »

yeah, the same happens (at least it used to) in the treefarm mod...I was thinking they reached to the center of the collision box but from the image it looks like they actually reach for the center of the sprite...
hm...not certain it would work but maybe you could have a regular chest (or an invisible one) spawn with the placement of a refinery and use that for the inventory instead, though it might make some of the code a bit more complicated and would probably detract from the 'refinery' aspect a bit...another option might be to make it output items on it's own (using game.createentity{name="item-on-ground", position={refinery.position.x+5, refinery.position.y-7}, stack={name="ore-from-inventory", count=x} and game.canplaceentity, the 5 and 7 were just random numbers...x is of course how much to remove each time) so it acts similar to a mining drill (actually...I kind of wonder if you could use a mining drill with a larger inventory and have it do that for you whenever items are inserted...I'm not sure).
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

OK i'll look into it tomorrow. Thanks again for the advice!
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

Hey so I've been looking at making the refinery into a mining-drill entity and was wondering if I could disable the "resource_categories" in order to place it anywhere or maybe the "mining_power"
I was messing with it, and if i set the mining_power to 0.5 it can only be placed on stone if it is 3 it can be place on stone,coal,iron, and copper. Is there anyway of getting around this? Also can i make it so the inventory is visible?
So I can start seeing if it can draw from the inventory instead of mining. >.<
Or hell even making it spawn store ore under it when placing would be fine, or tricking it to think that ore is everywhere.
User avatar
FreeER
Smart Inserter
Smart Inserter
Posts: 1266
Joined: Mon Feb 18, 2013 4:26 am
Contact:

Re: help with making a harvester

Post by FreeER »

hm...forgot about that little 'feature' of the mining drill :)
the onputitem event would let you know when someone tries to place the harvester, you could then use game.createentity to either spawn ore there (since onputitem is called before onentitybuilt) or to place the harvester directly (game.createentity does little, if any, checks for valid placement)
as for the inventory...hm I didn't realize it was hidden...well that makes it pretty much useless...(I don't believe inserters would even put into a drill anything but fuel...)

Well...sorry for wasting your time with that idea :oops: though 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).
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

ok well I will see what I can do when I get back (need to head to the doctor's office >.<)
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

so I guess I'm not on the right track >.>

Code: Select all

game.onevent(defines.events.onputitem, function(event)
	if event.onputitem.name == "refinery"  then
		game.createentity{name = "stone",}
	end
end)
User avatar
FreeER
Smart Inserter
Smart Inserter
Posts: 1266
Joined: Mon Feb 18, 2013 4:26 am
Contact:

Re: help with making a harvester

Post by FreeER »

Well, for one thing createentity requires the position at which to create the entity, something like

Code: Select all

 game.createentity{name="stone", position=event.position}
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

FreeER wrote: Well...sorry for wasting your time with that idea :oops: though 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).
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 this :|

Update: I tried my hand at some of it and this is what I came up with.

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)
User avatar
FreeER
Smart Inserter
Smart Inserter
Posts: 1266
Joined: Mon Feb 18, 2013 4:26 am
Contact:

Re: help with making a harvester

Post by FreeER »

McSpiffy wrote:I'm starting to feel like I'm not very good at this :|
Don't worry, it takes a bit of time to really understand it but after you do you'll be fine (obviously... :D).

I think you'd use something along these lines (it's a bit late so if it doesn't work there's probably a bug...sorry). If you load a save you'll need to mine and replace the refineries for the code to actually detect them.

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)
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

Ok I'v been trying to use what you suggested but i got and error for this line

Code: Select all

 local storageEntities = game.findentities(storagePos) 
the error is: bad argument #-1 to 'findentities'(table expected, got number)
User avatar
FreeER
Smart Inserter
Smart Inserter
Posts: 1266
Joined: Mon Feb 18, 2013 4:26 am
Contact:

Re: help with making a harvester

Post by FreeER »

oh oops, can't believe I forgot that...

Code: Select all

local storageEntities = game.findentities(getBoundingBox(storagePos, 1))
findentities requires the bounding box of the area to search (and storagePos is just one point).

... theres probably a bug in onbuiltentity (name = "refinery" instead of name == "refinery")

... looking at this again there might be a bug with the item = code (now that I think about it the items probably are not sorted in the refinery like they would typically be in the player's inventory...). If that is the case then this should take care of that

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
again, sorry :oops:
McSpiffy
Long Handed Inserter
Long Handed Inserter
Posts: 51
Joined: Mon May 05, 2014 9:17 pm
Contact:

Re: help with making a harvester

Post by McSpiffy »

So I'm have problems when i put the harvester script and the refinery scrip in the same control lua. I think It has something to do with the getBoundingBox
This is what I have

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)

User avatar
FreeER
Smart Inserter
Smart Inserter
Posts: 1266
Joined: Mon Feb 18, 2013 4:26 am
Contact:

Re: help with making a harvester

Post by FreeER »

ok..there were a couple of little bugs, should be fixed now and you'll just need to play with the storage position (line 87). I suppose I should note that I used a wooden-chest for testing (since I haven't yet updated to the newest version of your mod :lol:)...but it should be fine, I hope...

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
Post Reply

Return to “Modding help”