Use item::energy to stash sub-kJ power quantities for more precise power usage #75912
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
Bugfixes "Allow tiny continuous power draw in electronic devices."
Purpose of change
TODO find related issues
We've had issues with low-draw devices that are supposed to work for a very long time for practically forever. There are workarounds such as tool::turns_per_charge, but that's gnarly and has weird side effects.
The root cause is that the lower bound of charge resolution has been "one battery charge", which we set at 1kJ because there's also a rather large number of charges we need to handle for e.g. electric cars, and the "number of charges" type is an int.
Describe the solution
I poked around and we already have a member of the item class that is type units::energy which is backed by a int64_t and has a resolution of one mJ. Due to an int64_t being staggeringly large, this really can handle whatever we feel like throwing at it, so why isn't the problem fixed?
The problem is legacy code that treats electrical capacity as "charges" and a whole ton of infrastructure, mostly in crafting code, and specifies power drain in "charges of battery", which again are 1kJ each.
After rooting around though, I realized we don't have to overhaul all the crafting code to fix this particular issue, because the "process_tool()" code responsible for e.g. spending power every turn for an active flashlight doesn't interact with any of that code.
So what I've done here is I updated item::process_tool() to call item::energy_consume() and item::energy_consume() to use item::energy to stash residual energy as needed. So if your flashlight has 10 "charges" of battery and you try to spend 20J, it spends one "charge", but stashes the remaining 980J of energy in item::energy, which can be used next turn instead of burning more charges.
Describe alternatives you've considered
There's a huge overhaul I eventually want to happen here where the itype_battery item that represents a distinct amount of charge just goes away and instead a battery item like a light_battery instead just uses it's item::energy member and islot::battery::max_charges member to handle how much charge it can hold. That requires overhauling a huge amount of crafting code though and I'm not up to that at the moment.
Testing
I haven't tested this yet, just putting up a draft for feedback.
Additional context
See e.g. #75903 for other aspects of the same problem.