but the game wont load
And 2nd would be the refinery still won't place the ore on the ground maybe its just I didn't set the storage position correctly like you said on line 87 I have been messing with it a bit but still no anvil.
So I'm going to up load the mod here so you could take a look at it.
And once again thank you for all the help if it weren't for you none of this mod would be possible and I am very grateful
Update: I Seem to have fixed the 2nd problem. I had to change
ok, 1 was a simple bug that I didn't realize was a bug lol (apparently you can not set the ore.amount to less than 1)
As for 2, it works for me.... edit: oh, oops i see what I did now... I thought I'd keep it from simply placing the items on top of everything that way and forgot that it'd see a transport belt as a regular entity and then not place the ore there lol. yeah that's probably the simplest fix... the 'better' way would be to check if (one of) the entities that it found were transport belts (that's what I've done below).
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
elseif ore.amount > 0 and ore.amount <= oreAmount then
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.destroy() -- we used all the ore so destroy it
elseif ore.amount == 0 then
ore.destroy() -- I thought the game would destroy it when the amount was set to 0 but maybe not..so do so explicitly
else -- the only other else is if the ore has a negative count (which can be used for infinite ore)
game.player.vehicle.insert{name = ore.name, count = oreAmount} -- just insert oreAmount
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)
else --storageEntities is not 0
local belt = false
for _, entity in pairs(storageEntities) do
if entity.type == "transport-belt" then
belt = true
break
end
end
if belt then
game.createentity{name="item-on-ground", position=storagePos, stack=item}
refinery.getinventory(defines.inventory.chest).remove(item)
end
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
btw, the refinery inventory...is absolutely huge, it actually goes a bit off of my screen (on a laptop) https://www.dropbox.com/s/cfsn3uwfdbwzaco/refinery.png, sigh silly img tag doesn't work for dropbox apparently
btw, the chest there (if you can see it through the inventory screen) is where the refinery was outputting items (before I place the chest it'd place a piece of ore down)
Re: help with making a harvester
Posted: Fri May 16, 2014 4:33 am
by McSpiffy
Ok kool everything seems to work fine now Thanks!
Yea sry for the inventory i made it 3x the size of the harvester's inventory so I could dump full loads of ore. It fits on my 1920 x 1080 res monitor. I didn't realize the Gui
didn't get re-sized on different resolutions. I might just make it 2x the size of the harvester's inventory.
Time for me to work on getting the harvester to dump its cargo now ^_^
Update: Harvester still depletes ore fields after its inventory has filled up tiny bug. I will see what I can manage to come up with as a fix.
Re: help with making a harvester
Posted: Fri May 16, 2014 4:39 am
by FreeER
McSpiffy wrote:I didn't realize the Gui didn't get re-sized on different resolutions
Yeah, it's one of the more annoying um, features, yeah, of Factorio I hope they get some time in 0.10 or 0.11 to change that (and add scrollbars to really long lists of inventories, filters menus, etc)
Re: help with making a harvester
Posted: Fri May 16, 2014 11:05 am
by rk84
Instead using pairs() for getting one pair out of table, you could use next(table, key)
local name, count = next(refinery.getinventory(defines.inventory.chest).getcontents(), nil) -- nil key makes it return first pair
item = {name=name, count=count}
Re: help with making a harvester
Posted: Fri May 16, 2014 5:13 pm
by FreeER
rk84 wrote:Instead using pairs() for getting one pair out of table, you could use next(table, key)
hm, yeah you're right. I figured there was a different way but I wasn't sure what it was
Re: help with making a harvester
Posted: Sun May 25, 2014 5:09 pm
by McSpiffy
Ok so how should I go about adding the code to make the harvester empty Its "trunk" into the refinery? Also Is it possible to add a "Dumping" animation when Its over the refinery? And one more question Is it possible to set the animation property in the entity file(harv_entity) to a variable and use the control lua to tell what animation or sprite sheet to use under certain conditions example :
harv_entity : pictures = "animation_state"
controle.lua
if havrester is on ore then
get direction(?)
if harvester.direction = North then
animation_state = "N_mining"
N_mining=
{
filename = "__harvester-mod__/graphics/entity/harvester/north-sheet.png",
line_length = 5
frame_width = 140,
frame_height = 110,
shift={0.5, 0},
axially_symmetrical = false,
direction_count = 64
},
if harvester.direction = south then
animation_state = "S_mining"
S_mining=
{
filename = "__harvester-mod__/graphics/entity/harvester/south-sheet.png",
line_length = 5
frame_width = 140,
frame_height = 110,
shift={0.5, 0},
axially_symmetrical = false,
direction_count = 64
},
and so on
then else if its not on ore or refinery revert back to the original sprite sheet.
else if harvester. not on ore
animation_state = "normal"
normal =
{
filename = "__harvester-mod__/graphics/entity/harvester/harv-sheet.png",
line_length = 8,
frame_width = 140,
frame_height = 110,
shift={0.5, 0},
axially_symmetrical = false,
direction_count = 64
},
yes? no?
I just can't think of a way for the harv_entity file to read from the control.lua
Re: help with making a harvester
Posted: Sun May 25, 2014 5:46 pm
by FreeER
McSpiffy wrote:Is it possible to set the animation property in the entity file(harv_entity) to a variable and use the control lua to tell what animation or sprite sheet to use under certain conditions
no, this is not possible. You can not change the prototypes from the control.lua at this time. You can make an interface request for this, but it'll be up to the developers to implement it (and I don't think the 0.10 release date is too far off so it might not make it in until 0.11).
McSpiffy wrote:Ok so how should I go about adding the code to make the harvester empty Its "trunk" into the refinery?
For this I'd probably just add something like this on line 44 (before the end of the if statement on line 24)
-- find refinery's within a 5x5 square centered around the vehicle
local refineries = game.findentitiesfiltered{name="refinery", area=getBoundingBox(game.player.vehicle.position, 5)}
if #refineries > 0 then -- if the returned table has at least one entry
-- I think this is the correct inventory...I might be wrong
local inventory = game.player.vehicle.getinventory(2)
local contents = inventory.getcontents()
local itemstack = {} -- temp var
for name, count in pairs(contents) do
itemstack.name = name
itemstack.count = count
-- loop through found refineries (err on side of caution, a radius of 5 might find more than one refinery)
for _, refinery in pairs(refineries) do
if refinery.caninsert(itemstack) then -- if this refinery can hold the items
refinery.insert(itemstack)
inventory.remove(itemstack) -- remove from inventory (the harvester)
break
-- do not continue looking at the next refinery...this might be optimized by
-- removing the full refinery from the refineries table...
-- but it has a few caveats, if the refinery can accept say,
-- copper but not iron, then if you had both in the harvester the refinery
-- might not be filled properly, you'd also need a check for if
-- the one you removed was the last possible refinery
end
end
end
end
Since all of that is within the if statement on line 24 it requires the player to stay in the harvester, you could however use (in a loop over the glob.refineries table) game.findentitiesfiltered{name="harvester", area=getBoundingBox(refinery.pos, 5)}, and that way the player doesn't need to be in the harvesters, but it's also a bit more game intensive (since it must search the areas around all the refineries rather than just search for refineries around the harvester the player is in). You also might have noticed the for loop over the refineries, if it's impossible to get more than one refinery in the radius that loop can be removed (and just use the if statement without the break), though it shouldn't have a significant performance impact even if it's impossible to have more than on refinery in that radius (and 'future-proofs' the code against future changes that might allow such possibilities)
Re: help with making a harvester
Posted: Sun May 25, 2014 7:57 pm
by McSpiffy
Good stuff! I just got done tweaking it a bit and everything seems to be running great. I just need to do a bit more to it before I can release it. I need to set it so the harvester won't collide with the refinery is there a way to do that in the control.lua or should I just remove the collision box from the refinery? Also the refinery won't out put ore if it placed in the map editor and played after but if picked back up and placed it works fine. Minor bug was driving me crazy when trying to test >.<
Re: help with making a harvester
Posted: Sun May 25, 2014 8:26 pm
by FreeER
McSpiffy wrote: I need to set it so the harvester won't collide with the refinery is there a way to do that in the control.lua or should I just remove the collision box from the refinery?
I do not think this is possible with control.lua since it's part of the prototype of the entity(ies), you can remove the collision box or play around with collision masks (collision_mask = {"mask1", "mask2", "etc"}, the collision layers/masks are documented on the wiki here).
McSpiffy wrote:Also the refinery won't out put ore if it placed in the map editor and played after but if picked back up and placed it works fine. Minor bug was driving me crazy when trying to test >.<
This is because the code can only check the glob.refinery table which only gets entries from when the player places the refinery, you can add a script interface and/or use some code to insert entities that were given 'tags' in the map editor to get this to work.
script interface
-- this can simply be at the bottom of your control.lua
-- to activate this function you'd type remote.call("harvester", "findrefineries" [, radius]) into the console
-- radius is optional, thus the square brackets
remote.addinterface("harvester",{
findrefineries = function(radius)
if radius and (radius < 1) then
game.player.print("Radius must be greater than or equal to 1, it defaults to 10")
return
end -- a bit of error checking for 0 or negative radii
local radius = radius or 10 -- sets radius to either pass parameter or 10 as a default
local refineries = game.findentitiesfiltered{name="refinery", area=getBoundingBox(game.player.position, radius)}
if #refineries > 0 then
local isNew
local totalNew = 0
for _, refinery in ipairs(refineries) do
isNew = true -- assume it's a new refinery, until tested in the next for loop
for _, globref in pairs(glob.refineries) do
if globref.valid and globref.equals(refinery) then
isNew = false
break
end
end
if isNew then
table.insert(glob.refineries, refinery)
totalNew = totalNew + 1
end
end
-- could add a script locale for these strings if you want translations to be possible
game.player.print("Found "..totalNew.." new refineries, "..#glob.refineries.." are now known")
else
game.player.print("No refineries found") -- same here
end
end
})
-- I think this would be in oninit...not sure if oninit would fire on opening of edited maps though
-- if not it'd need to be in onload and you'd need a loop like the script interface
table.insert(glob.refineries, game.getentitybytag("tag name"))
obviously you could have a table of tag names and use a for statement to loop through it and call getentitybytag with each name instead of copy/pasting this line several times for multiple refineries.
The loop in the script interface code (and that I alluded in the map editor discovery code) is one that loops through the glob.refineries table and makes sure that the refinery about to be added is not already in the glob table...otherwise you could get duplicate entries
edit: the script interface is more flexible since it allows for finding refineries placed by construction robots or console game.createentity commands, however it requires user interaction (even if you were to add a gui that ran it when clicking a button, it's not automatic like the map editor code is, of course you can have both)
Re: help with making a harvester
Posted: Sun May 25, 2014 8:56 pm
by McSpiffy
Is there a way to remote call without needing to have the player use the console? I would to prefer not needing to use it. I could just leave it the way it is. I don't think its a big deal I could just make a note of it when I update the mod.
Re: help with making a harvester
Posted: Sun May 25, 2014 9:34 pm
by FreeER
McSpiffy wrote:Is there a way to remote call without needing to have the player use the console?
You can run that function when the player does something (like hovering over a certain area of the screen [time buttons and few other mods] or placing an entity on the ground [fmod], etc) or use a gui and a button within that gui and then tie that scan function to run when the button is clicked...I haven't actually used the guis yet however so you'd need to read the wiki and probably look at a few of the mods that use it (timebuttons, testingmode, fmod, etc.) to learn how to implement it yourself, it shouldn't be particularly difficult. Of course, you'd either need that gui to pop up whenever the game is loaded (which might be annoying for users who don't actually need it) or only pop up the gui when the player does something (see prior examples). It's possible to do it, but considering how rare it probably is to need it then it's usually easier to just use the console imo...I guess it really depends on if you want to put a bit more effort into it
Re: help with making a harvester
Posted: Sun May 25, 2014 9:52 pm
by McSpiffy
lol well idk if im up for that today maybe in the future. But I am have a problem with get my tech to pop up when running the game I want to make it so you need to research something in order to be able to craft the items in the mod. I have made a tech.lua and have added it to my data.lua but it still won't show >.>
Re: help with making a harvester
Posted: Sun May 25, 2014 10:19 pm
by FreeER
McSpiffy wrote:I have made a tech.lua and have added it to my data.lua but it still won't show
hm, I can't think of anything other than not having the data:extend({...}) in the tech file, so I'd probably have to see the code to pin-point anything