beyond-all-reason / spring

A powerful free cross-platform RTS game engine
https://beyond-all-reason.github.io/spring/
Other
196 stars 98 forks source link

harvestStorage bugs #315

Closed MaDDoXbr closed 7 months ago

MaDDoXbr commented 2 years ago

harvestStorage can be set in UnitDefs but it can't be read in-game, requiring the use of a customParams (we're using unitDef.customParams.maxorestorage).

Also, currently Spring.SetUnitHarvestStorage respects the unitDef's harvestStorage (max amount), but if the harvester unit is reclaiming a metal feature, that limit is not respected.

lhog commented 2 years ago

harvestStorage is considered deprecated, use harvestMetalStorage and harvestEnergyStorage instead.

Also, currently Spring.SetUnitHarvestStorage respects the unitDef's harvestStorage (max amount), but if the harvester unit is reclaiming a metal feature, that limit is not respected.

For this one I need a code of what you're trying to do and there the issue is. I understand the code better than the textual description.

lhog commented 2 years ago

@MaDDoXbr have you checked by a chance?

MaDDoXbr commented 2 years ago

Sorry @lhog, somehow notifications aren't getting to my email.. I just decided to check on this issue now, as you were discussing resources in the #engine discord channel.

As for the issue itself, the wording is probably poor. It's as simple as, 'setting the unitDef.harvestStorage fires no error, but reading it in game results in nil'. Probably because of the 'harvestMetalStorage' change, although I believe I tested it and it also didn't work. I'll test it again to be sure.

The second point seems to be related to something else, apparently the metalStorage is somehow being affected, it even show in the unit's infobox.. ouch, what a mess, let me dig through this again and I'll create a specific repro scenario + lua script so you can easily see it yourself in-game.

lhog commented 2 years ago

@MaDDoXbr any feedback?

sprunk commented 1 year ago

I can't reproduce the "cannot read the value ingame", works for me. But I can confirm some other issues:

Expected behaviour: either the reclaim meter starts lowering proportionally slower and the feature is left at 5m/0e (11% reclaim), or the harvest stops already at 5m/10e.

Side note, ZK isn't the main client here but we somewhat wanted to make Puppy work via harvest. All trees in ZK contain 0.001 metal (because otherwise the engine would deproritize them on area reclaim) so a metal-only harvester would 100% waste all trees.

Other notes:

MaDDoXbr commented 1 year ago

I've just checked, there's no Spring.GetUnitHarvestMetalStorage (or "Set"). Sorry that I'm so bad to create repro scenes Ivand. I'll deem this entire harvestStore toolset useless and FUBAR and move it to customParams. It's not worth it really. Just to report the final (and terrible) related bug, when you do a regular reclaim the harvestStorage (or whatever) is used, the max harvestStorage is not respected, and the corpse gets into a "limbo" state - it is fully reclaimed but it's not removed from the game, nor can be reclaimed anymore. Doh.

sprunk commented 1 year ago

there's no Spring.GetUnitHarvestMetalStorage (or "Set").

local metalCurrent, metalMax, energyCurrent, energyMax = Spring.GetUnitHarvestStorage(unitID)
Spring.SetUnitHarvestStorage(unitID, metalCurrent, metalMax, energyCurrent, energyMax)

Set accepts nil not to change the value.

If you want convenience functions you can do (for example):

Spring.GetUnitHarvestEnergyStorage = function (unitID)
  local metalCurrent, metalMax, energyCurrent, energyMax = Spring.GetUnitHarvestStorage(unitID)
  return energyCurrent, energyMax
end

the corpse gets into a "limbo" state - it is fully reclaimed but it's not removed from the game, nor can be reclaimed anymore.

Can you give specific values at which this happens? Feature metal, energy and reclaimtime; unit harveststorage and buildpower? See above for my examples with values which generally work https://github.com/beyond-all-reason/spring/issues/315#issuecomment-1257128570

I tried a bit and corpses do stop getting reclaimed at some point and become unable to be reclaimed by a constructor, but that's just because the constructor is full. In my testing if the constructor is not full it removes features too eagerly even.

lhog commented 1 year ago

@MaDDoXbr leave at least a replay where it happens, preferably on the latest engine version.

MaDDoXbr commented 1 year ago

@sprunk I believe you got this from the source code? 'Coz those params are not described in the wiki anyhow, and I didn't go check the source code (trying to keep my sanity at the high level lua scripts, but obviously failing). I'm having a hard time replicating that exact behavior to send you a replay, even if it has happened some times in some of our games (most in not-so-recent BAR engine versions). I believe the "limbo corpse" is created from my usage of gadget:AllowFeatureBuildStep, to try and deliver the feature-reclaimed metal directly to the economy (the behavior I want) instead of it being stored in the harvesting unit (which should only happen when actually harvesting). This has been a source of all sorts of issues, and even with Sprung and other trying to help me with that, the "part" calculation (of featureBuildStep) has been really inconsistent in my tests. It seems that the amount of harvestStorage affects the part calculation, instead of only considering the reclaimed amount, I'm not sure. Anyways, I'll try it a bit more with the params Sprung has mentioned, but I'm not keeping my hopes high at this point.

sprunk commented 1 year ago

I believe you got this from the source code? 'Coz those params are not described in the wiki anyhow, and I didn't go check the source code

Wiki is sometimes outdated, sometimes incorrect, and generally sucks ass. Don't trust it. (Wiki sucking ass is a valid complaint, but orthogonal to harvest storage.)

gadget:AllowFeatureBuildStep, to try and deliver the feature-reclaimed metal directly to the economy (the behavior I want) instead of it being stored in the harvesting unit (which should only happen when actually harvesting)

When should these two things (delivering to the economy VS being stored in the harvester) happen? If you just want a harvester to harvest first and then return the metal to the economy (at a town hall like in warcraft), that's not done via AllowFeatureBuildStep (but manually via a custom command, perhaps triggered by the max storage event). Or do you have two feature types, one that should be harvested and one that shouldn't, that are supposed to both be handled by the same constructors? If yes then that's a use case that the current setup just doesn't support (perhaps there should be a feature tag that forces the feature to have different reclaim semantics regardless of the constructor).

MaDDoXbr commented 1 year ago

@sprunk The resource (ore chunk) is actually a neutral unit, and not a feature. This allowed me to make it targettable only by a certain weapon type, used by builders exclusively for that (as you mentioned, that's unsupported for features). HarvestStorage being used for regular metal reclaim (when the unitDef is set) was a surprise for me, and even if it makes sense I didn't want it in TAP for a number of reasons, some gameplay-related and other balance-related. Then I tried to use AllowFeatureBuildStep to circumvent this behavior, by adding to the team resources directly whatever was harvest-stored, then revert harvestStorage to the previous value. Terrible idea, it threw me into this rabbit hole. For the record, I've just removed harvestStorage-related entries completely from the game, and after a couple hours it's all working perfectly. I also found out that simply having harvestmetalstorage set in a unitDef would cause the 'limbo feature corpse' issue, every time, but it might be related to other gadgets I'm using in-game so I wouldn't bother with that. I certainly don't wanna waste not even one more second on this, I'll just pretend it never existed in the engine.

Thus, I'd recommend totally deprecating harvestmetalstorage & related, it's pretty easy to replicate in lua (some sendluauimsg and customparams here and there, but no biggie), and it's much more flexible - not to mention reliable - this way.

Thanks for the help guys.

sprunk commented 1 year ago

is actually a neutral unit, and not a feature. (...) targettable only by a certain weapon type

That's the problem, it only supports features and the native reclaim command. This is because keeping track of four numbers isn't really the point of it, it's replicating the reclaim behaviour for free. See below.

it's pretty easy to replicate in lua

Are you sure about the minor things and edge cases required to make it polished? Area commands, pathing to difficult-to-reach objects, handling right-click by default, ...? Even if each individual facet is fairly easy there's just a lot to do. Note that harvesting is a fairly fundamental mechanic to how resources work in most RTS games so are one of the first things a new modder would likely ask for, and the expected skill/awareness of the user could be low. As far as I am aware harvesting as-is is essentially sufficient to implement Starcraft and Red Alert style resources in the naive way (where minerals/ore are just features and workers/miners are reclaim-only constructors) and adding the "drop off to base" mechanic to TA style reclaim only requires some thought around things that contain both resources. Fancy handling of specialized constructors that can only target specific reclaim etc (which seems to be your use case) is not the use case harvesting is currently designed for. I agree it would be good if this was communicated better, but I don't think it would be good to deprecate it if the engine aims to be a general RTS one (as long as it isn't unreasonably expensive, but given the point is that it reuses 99% of regular reclaim it should never be since it's just a bunch of if's).

MaDDoXbr commented 1 year ago

A specific armor category makes that pretty simple to apply for weapons. As for the actual harvesting AI, so the units do the back-and-forth to drop-off points, handle edge cases, etc, that took a lot of effort indeed, you’re very right. But it’s now done and pretty solid on TAP, (talks with auto-reclaim, etc) so we have at least one working example for new modders. It could be good leaving it as-is, if you think it’s good enough (personally I don’t). If so, I can add some extra warnings to the wiki, to warn any poor souls of its shortcomings.

lhog commented 7 months ago

Is this one still unclear or considered broken? I'm going to close if there's no replay is provided to show the broken behavior in a reasonable amount of time.

MaDDoXbr commented 7 months ago

@lhog I consider harvestStorage broken, as in it's got erratic behavior and its value can't be read in one of the spaces (wg or gg, can't recall which). When I tested harvestStorageMetal the result was the same, but Sprung's results vastly differed.

I'm not using it anymore like I said, but since removing harvestStorage would harm ZK, I recommend leaving it untouched. Another specific issue can be created when more specific / replicate-able errors can be pointed.