doc: commit sprunk's resource excess guide#2600
Conversation
| ### no excess gadget, sharing modrule = true (current state of affairs) | ||
|
|
||
| - you will receive the total excess 450 from frames 2 and 4, and have virtually 550/100 | ||
| - then, anything above your red slider value of 75 is distributed to allies and you virtually have 75/100 | ||
| - in case your allies are all above red slider, you may receive some metal back. this can put you at any value above 75 | ||
| - the stored value is then capped at your max storage of 100. | ||
|
|
||
| ### excess gadget, sharing modrule = true | ||
| - at the end of frame 2 you receive an event for 200 excess (a single event accumulated from that frame despite multiple individual chunks, and despite consumption attempts between them) and can consume it, or not | ||
| - at the end of frame 4 you receive an event for 250 excess and can consume it, or not | ||
| - you will receive either 0, 200, 250, or 450 excess depending on which of the two excess the gadget did not intercept, and virtually have either 100, 300, 350 or 550 | ||
| - then anything above your red slider value of 75 is distributed to allies and you virtually have 75/100 | ||
| - in case your allies are all above red slider, you may receive some metal back. this can put you at any value above 75 | ||
| the stored value is then capped at your max storage of 100. |
There was a problem hiding this comment.
terrible formatting and the explanation requires a lot of prior knowledge, who wrote this shit?
There was a problem hiding this comment.
You wrote it, I only formatted it. I thought it was readable for anyone who had thought through excess handling on their own. How can we improve this?
There was a problem hiding this comment.
I was being facetious, it would be good if somebody else than me reviewed this part.
There was a problem hiding this comment.
I will try documenting + providing an exemple gadget.
Since i've already been building it
|
Updated per Sprunk's comments, ready for someone else to review, since Sprunk approved. Or if acceptable, this can be merged. |
f442b40 to
aedb14d
Compare
|
Whats "excess gadget", whats "sharing modrules"? Looks good but would be better to be more objective. |
|
I think there needs to be a clarification about "excess" being different from "overflow". I think this is important because TeamResourceExcess (and more recent ResourceExcess) 1) don't expose the sharing part and 2) aren't called when a team is over their share cursor but under their maxStorage. This is obvious but also a cause to not being able to just leak on ResourceExcess callin but rather just accumulate excess and process from gameframe(post) in case of taking the whole overflow process from game side. As to how it works, i don't think using number really helps understand in this case. I would just say, engine natively stacks frame excess over 30 frames to process them all at once during GameFramePost, for each team. During slowUpdate(), resCurrent is incremented by the accumulated excess. The part that is over the share cursor is then natively shared among teammates. NativeExcessSharing (could actually use another label to keep consistency with what it actually does such as NativeOverflowSharing) controls overflow altogether, ResourceExcess only controls the excess part of the overflow. So a combination of ResourceExcess returns true and nativeExcessSharing = true is an hybrid version that ignores excess but still allows to share over your share cursor. While disabled NativeResourceExcess and still returning false in (Team)ResourceExcess allows to add excess to the counter and therefor account in teamstats without going through the Native overflowing process. Edit: |
Right, but the engine consistently calls all related phenomenons "excess", and doesn't call anything "overflow". AFAICT:
So there's up to 3 different phenomenons here. #2642 isn't yet merged, and I don't think anyone other than you uses the new modrule yet, so we can still rename both. 2642 could become
How about like this (taking 2642 into account, which the current text of the PR does anyway)?
|
|
2642 could become gadget:ResourceOverflow(), dunno how to call the
modrule though.
I would stick with keeping engine naming consistent,
gadget:ResourceExcess() is fine and if the game wants to rename it on the
UI side, it can.
Modrule is game-side, right? So that's a UI question and should not impact
engine naming.
Sure the community currently calls "excess" to be "overflow", but don't
break consistency just to follow a temporary slang used by the community.
For engine slow update, I suggest adding a description for how the game
(Lua) will be able to handle excess when system.nativeExcessSharing is
false. Is the excess just directly discarded without sharing among an
ally-team, or is it passed as a table to Lua to deal with? (e.g. tax,
redistribute, multiply, whatever) and Lua can return a table of adjusted
values to be applied as excess/negative tax to each player)
(sent from email, formatting may be off, have not had time to
cross-reference the mentioned pr, etc)
David Norton
…On Tue, Dec 2, 2025, 07:42 sprunk ***@***.***> wrote:
*sprunk* left a comment (beyond-all-reason/RecoilEngine#2600)
<#2600 (comment)>
I think there needs to be a clarification about "excess" being different
from "overflow".
Right, but the engine consistently calls all related phenomenons "excess",
and doesn't call anything "overflow". AFAICT:
- individual instances of resources being temporarily buffered due to
current storage getting truncated to max storage are not called anything in
the interface.
- the internal resDelayedShare var, which is per-slowupdate and is
currently an accumulator of those resources above, isn't called anything in
the interface.
- in #2642
<#2642>,
resDelayedShare becomes a metaaccumulator of the more granular
per-frame accumulator (internally called resExcessThisFrame), which
calls itself "excess", as in the callin is gadget:ResourceExcess().
- the resources that are voided at the end of the slowupdate step when
truncating current to max are called "excess" in statistics.
- resource above the "red share slider" are also called "excess"
implicitly by the system.nativeExcessSharing modrule.
So there's up to 3 different phenomenons here. #2642
<#2642> isn't yet
merged, and I don't think anyone other than you uses the new modrule yet,
so we can still rename both. 2642 could become gadget:ResourceOverflow(),
dunno how to call the modrule though.
Whats "excess gadget", whats "sharing modrules"?
Looks good but would be better to be more objective.
How about like this?
Engine-based resource generation, within a frame
- *unit incomes generate individual transactions, and are never
collected together.* For example, if you have two +5 generators, two
constructors reclaiming the same wreck for +2 each, and a unit consuming -8
upkeep, then it's five transactions of +5, +5, +2, +2, -8 respectively, not
a single transaction of +6.
- *transaction order is unspecified.* In the example above, maybe the
order is +5, +5, +2, +2, -8 or maybe it is +2, -8, +5, +2, +5.
- *transactions are handled individually to completion as they come*.
If you have 10/100 stored resources then you will always fail to pay costs
of -11, even if there's income transactions immediately after. If you've
got 80/100 stored then you will always generate overflow on incomes of +21
or more, even if there's transactions to consume resources immediately
after. In particular this means
- *overflow counter is an accumulator that is never directly used to
pay costs.* If you have 100/100 storage and get +10, -100, -5 then the
first transaction generates 10 overflow, the second empties your stored to
0 while maintaining 10 overflow, and the third fails due to insufficient
stored resources despite the 10 overflow.
- *Lua calls generate individual transactions, in the order they are
called.*
- *at the end of each frame, gadget:ResourceExcess is called with the
value of the accumulator.* Lua can return a boolean value that denotes
whether it considers the overflow handled.
- *if not handled by Lua, the per-frame overflow accumulator is added
to a per-slowupdate metaaccumulator. Either way it is then reset.*
Resource handling at slowupdate
- first, the overflow metaaccumulator is added to current stored
resources *disregarding the max storage cap*. If you've got 80/100
stored and 40 overflow, then you've got 120/100 stored for the purpose of
the following steps.
- then, if system.nativeExcessSharing modrule is true, anything above
the sharing level (aka the "red slider") is moved over into a common
per-allyteam pool to be distributed. In particular, the slider is capped at
100% of max storage so will always attempt to redistribute resources above
max storage, but they are not fundamentally treated any differently here.
- lastly, current storage is truncated to max storage. This is the
only stage at which resources are actually lost. These voided resources are
what stats collection calls "excess", any shuffling that happens in the
previous step is bookkept as sent/received.
—
Reply to this email directly, view it on GitHub
<#2600 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAET2W6L5ZKOPYC66YQE2MT37WJNDAVCNFSM6AAAAACJ6WQDMWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTMMBSGE2DAMRQGY>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
work done
screenshot
AI / LLM usage statement:
I did not use an LLM in the creation of this PR.