autoharvest gadget

autoharvest gadget

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.

Moderator: Moderators

thedude
Posts: 66
Joined: 21 Aug 2009, 12:47

autoharvest gadget

Post by thedude »

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...

so here is my "mod" and my map

http://www.filefront.com/14910157/resource.7z

I fournd this function

Code: Select all

function gadget:DefaultCommand(type, id)
is it possible to use it for that?

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

Code: Select all

gadget:UnitCreated(unitID, unitDefID, unitTeam, builderID)
to give the unit an order to start searching for resource and then start to harvest.
I'm a bad coder would be nice if someone could help.
User avatar
bartvbl
Posts: 346
Joined: 21 Mar 2009, 15:55

Re: autoharvest gadget

Post by bartvbl »

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 :-)
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: autoharvest gadget

Post by knorke »

weee cool idea.
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.
User avatar
CarRepairer
Cursed Zero-K Developer
Posts: 3359
Joined: 07 Nov 2007, 21:48

Re: autoharvest gadget

Post by CarRepairer »

knorke wrote:I am not sure if there is a way create custom unit-tied variables.
Get/SetUnitRulesParam - however this is gettable by any player using a widget.

@knorke: You have some very imaginative ideas! I wouldn't recommend anyone implement those ideas however. By "experience" wow that's out there! :P
User avatar
bartvbl
Posts: 346
Joined: 21 Mar 2009, 15:55

Re: autoharvest gadget

Post by bartvbl »

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 :-)
User avatar
CarRepairer
Cursed Zero-K Developer
Posts: 3359
Joined: 07 Nov 2007, 21:48

Re: autoharvest gadget

Post by CarRepairer »

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.
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7052
Joined: 16 Nov 2004, 13:08

Re: autoharvest gadget

Post by zwzsg »

Just Lua it.
CarRepairer wrote:
knorke wrote:I am not sure if there is a way create custom unit-tied variables.
Get/SetUnitRulesParam - however this is gettable by any player using a widget.
If you don't want anything else looking at your custom unit-tied variables, just use a local table index by unitID.

Anyway, you will need Lua to automate the going to refinery then going to field and back again procedure.

There's really no point in hackish solution like transporting feature or using XP or fuel now that the Spring engine has Lua.
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: autoharvest gadget

Post by knorke »

just use a local table index by unitID.
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.
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: autoharvest gadget

Post by knorke »

Have a static reclaimer back at base that needs features brought to it. I like it.
Thats actually cool because if the transporter gets destroyed, the ressources can be picked up again!
User avatar
CarRepairer
Cursed Zero-K Developer
Posts: 3359
Joined: 07 Nov 2007, 21:48

Re: autoharvest gadget

Post by CarRepairer »

zwzsg wrote:Anyway, you will need Lua to automate the going to refinery then going to field and back again procedure.
I realize that. I didn't say it wouldn't involve any lua.
zwzsg wrote:There's really no point in hackish solution like transporting feature
Transporting is the least hackish solution, in my opinion.

I will write this gadget.
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: autoharvest gadget

Post by Argh »

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.
User avatar
CarRepairer
Cursed Zero-K Developer
Posts: 3359
Joined: 07 Nov 2007, 21:48

Re: autoharvest gadget

Post by CarRepairer »

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).
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6242
Joined: 29 Apr 2005, 01:14

Re: autoharvest gadget

Post by FLOZi »

knorke wrote:
just use a local table index by unitID.
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.
You'd do

Code: Select all

myTableOfVars[unitID] = someValueOfOreCollected
And in gadget:UnitDied()

Code: Select all

myTableOfVars[unitID] = nil
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: autoharvest gadget

Post by knorke »

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?
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: autoharvest gadget

Post by Tobi »

knorke wrote:or do arrays work different in lua?
that

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.)
thedude
Posts: 66
Joined: 21 Aug 2009, 12:47

Re: autoharvest gadget

Post by thedude »

Thanks for the help!
One idea: instead of transporting a Feature, just set a COB state. I.E., if a Unit is full of Wood, then WoodState=1;
How can I test if the unit is full of Wood or something else?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: autoharvest gadget

Post by Argh »

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.
Attachments
AutoHack.lua
Example of automatic interception of user commands.
(1.04 KiB) Downloaded 23 times
KvartAutoTarget.lua
Example of auto-targeting behavior code.
(1.16 KiB) Downloaded 19 times
thedude
Posts: 66
Joined: 21 Aug 2009, 12:47

Re: autoharvest gadget

Post by thedude »

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.)
thedude
Posts: 66
Joined: 21 Aug 2009, 12:47

Re: autoharvest gadget

Post by thedude »

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


the code :

Code: Select all

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

Can someone help me, please?
User avatar
Argh
Posts: 10920
Joined: 21 Feb 2005, 03:38

Re: autoharvest gadget

Post by Argh »

-when game starts all metal features should be saved in the metalplat table
That needs to be done on the sync side.
Post Reply

Return to “Game Development”