Discuss game development here, from a distinct game project to an accessible third-party mutator, down to the interaction and design of individual units if you like.
Hello all I want to make an autoharvest gadget. Does anyone know if there is such one. What I mean is a gadget which forces the harvestunits to harvest automatically.
So I made a map (I know its ugly cause its my first one) and there is a "metal-cube" on it. I also modified the "DummyMod" and took models from Spring1944 (I hope they dont mind). Now when you start the "mod" there is a unit which can build a "factory" and this factory can build harvestunits (how I call them). So when a harvestunit is build it should look for features/resources nearby and drive there. When the harvestunit gets there it should start harvest the resource until it harvested/reclaimed 20 of metal. After that go back to the factory and unload the metal. And than search again for resource and so on...
Or is it better to search after some frames for a unit with a specific name and then look what the unit is doing. When the unit already harvested then send it to factory for unloading. If the unit unloaded it should search for resources or go back to the place it harcested/reclaimed before and start to reclaim again util it reached a specific amount of resources.
I also wondered if I can use
ouf...
I guess you should go for something event-driven. Like:
If done reclaiming, go here, and when destination reached, go back again.
One thing you could do is see if there are similar widgets around. They often contain snippets that are useful (perhaps the swarming widget?)
Good luck, anyways! Would be fun to have another mod around soon
When the unit already harvested then send it to factory for unloading
I am not sure if there is a way create custom unit-tied variables.
Because you need to store if/how many ressource-cubes a harvester has already harvested.
Maybe you could use fuel or experience. There are functions to set these: http://springrts.com/wiki/Lua_SyncedCtrl
Instead of reclaiming features maybe try making the ressources be units of a neutral faction that the harvester "kills." This way you can just send the harvester across the map with a fight-command and it will attack/harvest all ressources it comes across.
The weapon of the harvester and the armor of the ressource would have to be set up in a way so no other unit can harvest and the harvester can not attack other units.
So when the harvester killed a ressourcething it will also get experience and you can do something like if experience > 0.5 return to base
There is probally some unit-killed lua_callin that you can use, too.
For returning it should probally loop through all units and if it is a ressourcedepot, calculate the distance depot<->harvester.
Then send the harvester to the closest depot. At the depot reset its experience and send it out again.
just a random idea:
make some gaia units that are worth resources (like cubes or containers), and use a transport unit to transport them (like a truck or a plane). Then you can just modify a transport widget (I've seen a few), to make it suit your requirements, and the spring engine will do the rest
bartvbl wrote:just a random idea:
make some gaia units that are worth resources (like cubes or containers), and use a transport unit to transport them (like a truck or a plane). Then you can just modify a transport widget (I've seen a few), to make it suit your requirements, and the spring engine will do the rest
Now that's a good idea. Have a static reclaimer back at base that needs features brought to it. I like it.
wouldnt this get quite complicated and also memory wasting?
because you probally do not want want a table with 1000 entries of which like only 10 entries are actually used because of 1000 units only 10 are harvesters...
and you would have to make sure you always use the right index. for example a full harvester with id=544 dies. Then a new harvester is built that gets the same id=544 by coindence. The new harvester would now leave the factory fully loaded...
But is there a really no good way to make unit-tied variables? Without tables or other workarounds?
For example there are functions to get and set unit.health.
If it was possible to make specific units have a unit.ore_loaded stuff would surely be a lot easier?
Or if you want to make some like a unit.killcounter for each unit.
One idea: instead of transporting a Feature, just set a COB state. I.E., if a Unit is full of Wood, then WoodState=1;
Then, if you want resources to be preserved even if the carrier dies, you can always trigger the creation of a Feature that, when harvested, yields 1 Wood (or WoodState 1, or however much is allowed before the Unit is "full").
As for automating the back-and-forth: the easiest thing to do is to set a state on the Unit- what are we capturing- and then have it search a radius when it hits a Patrol point. If it can't find the resource, and is not at a Dump point, then have it give the user an alert.
If you're going to write it, CR, I'd probably be willing to read it over, and try to get it solid and well-commented with your assistance. This is a MTR thing, and the last person who solved this showed us a demo, then disappeared from the Spring community. I would be willing to help, regardless of the solution you want to pursue, in making it as easy to read / modify as possible for future use.
In my current project I'm going for the radical "each faction has a different econ" thing like in *craft. I already have one of them mostly done, which is based on tree planting. For another faction I was going to try my hand at a a critter harvesting econ, similar to what is suggested in this thread except the critters brought back are placed in farms where they multiply. So I was already planning on doing this. But it could be easily adapted to variations such as a reclaiming tower of some sort at your headquarters which automatically sucks up the features/gaia-units brought back (I'm not certain you can even transport features, but there are workarounds if not).
wouldnt this get quite complicated and also memory wasting?
because you probally do not want want a table with 1000 entries of which like only 10 entries are actually used because of 1000 units only 10 are harvesters...
and you would have to make sure you always use the right index. for example a full harvester with id=544 dies. Then a new harvester is built that gets the same id=544 by coindence. The new harvester would now leave the factory fully loaded...
But is there a really no good way to make unit-tied variables? Without tables or other workarounds?
For example there are functions to get and set unit.health.
If it was possible to make specific units have a unit.ore_loaded stuff would surely be a lot easier?
Or if you want to make some like a unit.killcounter for each unit.
uhm, i know how this would work in theory. i was just wondering if there is a better way than
You'd do
Code:
myTableOfVars[unitID] = someValueOfOreCollected
because you would have an array with 5000 entries (or whatever maxunits is set to) of which only a few entries are used...
or do arrays work different in lua?
Arrays in Lua are sparse (dictionary with integer keys, although they contain a special optimization for the case when they are used as a dense array.)
Here's a sketch of the entire program. I haven't had time to write it all yet, but this is pretty much all of the logic we need, I think. I think we can build this in 200 lines of code or so. I'm contributing some code here, and I'll take a look at this in detail at some point when I am (finally) done with the other crap I'm working on.
1. End-user clicks on a harvester Unit. Then mouse-overs the resource.
Then we use some Lua to automatically set the command as "harvest". A simple example of how to do that in a transparent way is attached to this message.
2. A click using that command triggers two bits of logic:
A. A search for the nearest drop-off point. This is non-trivial, but if you store drop-off points in a table when they're Finished, then you can do a very short sort.
B. An entry in a table somewhere, specifying the unitID, and the X,Z locations of the resource, the type of resource, and the X,Z of the drop-off point.
3. Every second or two, for each entry in the harvester table, check to see if they're "full" of any resource. If "full", then they should move towards the "collector" point. If not full, then do a further check, and see if they are currently harvesting. If they are not currently harvesting, then give them a Move order to their harvest point.
If they are harvesting, that's a simple COB callout, triggering a state that allows a "harvesting" animation to play. While "harvesting", they do a search for harvestable Units around them, and, if desired, move towards them (one of the issues with polish is that making Units face one another nicely is kinda tricky, without resorting to MoveCtrl fiat, so the WCIII "woodsman" behavior would be a bit of a pain, although if you watch closely, you'll see they're mainly faking it).
Also, while harvesting, they need to drain the harvestable Unit of X units of whatever it is. Yup, another table, holding all the harvestable stuff, and how much they have left.
4. Whenever a harvestable object reaches 0, then trigger the "I'm empty" behavior, whatever that is (tree falls, mine collapses, etc.), and ALSO, search for nearby harvesters, and have them automatically pick a new target.
This presents a special problem, btw: the fastest way is to find it by a search and pick the next valid unitID. However, that is frequently the object that's furthest away, because of the way that unitIDs are returned. Doing a distance sort, on the other hand, is pretty expensive. So, it's probably best to do a small search first, and if empty, do a bigger one and just use unitID order. An example of using unitID searches to find a valid target and issue a Command is attached.
Once they've found a target (or failed the larger search) the pattern repeats.
5. Lastly, the harvest-point needs to an area search around itself every half-second or so, looking for harvesters. If found, it needs to query their position in the harvester table, and if they have any resources, remove them.
If all of these searches / table operations sound expensive, don't worry. They are, but they're infrequent. Also, if CPU use becomes an issue, they can be staggered a bit, by using COB to trigger their searches randomly within a range of frames, providing better load-balancing.
So, other than the polish stages, it's a pretty simple program.
Let's say there is one tree with 5000 woodunits and two harvestunits which are ordered to harvest the tree (their harvestlimit is 20). So the units move there and start to harvest. The amount of woodunits of the tree is lowered by the two harvestunits. How can I now get the amount of woodunits one of the harvestunits harvested to check if one of them reached the harvestlimit?
(Can I do this: set an amount of woodunits which are harvested for each harvestanimation, for example the unit harvest 30 woodunits everytime the animation ends. Maybe there is already a better way.)
I tried to make something I can build on this gadget but it seems not to work the way I would like it to work.
What this gadget should do:
-implement a new command ("moveto")
(this command should tell a unit to move to a metal feature when build)
-when a unit with the customParameter harvest=1 is created, give "moveto" command to this unit
-when game starts all metal features should be saved in the metalplat table
function gadget:GetInfo()
return {
name = "bla",
desc = "blabla",
author = "blablabla",
date = "bla",
license = "bla",
layer = 0,
enabled = true
}
end
local CMD_MOVETO=30002
if (gadgetHandler:IsSyncedCode()) then
--SYNCED
local metalplat={}
local movetoCmd={
name="moveto",
tooltip="movesunitto",
action="move",
id=CMD_MOVETO,
type=CMDTYPE.ICON_MAP,
cursor="Move",
}
function gadget:AllowCommand(u, ud, team, cmd, param, opt)
if cmd == CMD_MOVETO then
Spring.GiveOrderToUnit(u,CMD.MOVE,metalplat[1].pos,0);
--return false
end
return true
end
function gadget:UnitCreated(u, ud, team)
if UnitDefs[ud].customParams.canharvest=="1" then
Spring.Echo("harvestunit created");
Spring.GiveOrderToUnit(u,CMD_MOVETO,0);
end
end
function gadget:UnitFinished(u,ud,team)
if ud == RUSK31 then
Spring.GiveOrderToUnit(u,CMD.MOVETO);
end
end
else
--UNSYNCED
function gadget.Initialize()
local i = 1
for _,a in ipairs(Spring.GetAllFeatures()) do
if Spring.GetFeatureDefID(a) == metal then
local x,y,z=Spring.GetFeaturePosition(a)
metalplat[i]={pos={x,y,z}}
i=i+1
end
end
if i==1 then
Spring.Echo("removed")
gadgetHandler:RemoveGadget()
end
end
end