SetMeter Effect Current vs. Initial Value

This is for directed discussions on immediate questions of game design. Only moderators can create new threads.
Post Reply
Message
Author
User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

SetMeter Effect Current vs. Initial Value

#1 Post by Geoff the Medio »

I'm not sure where to put this post, but given the SetVisibility Issues thread in this forum, perhaps this belongs here as well.

I've recently been working on moving standard per-turn meter growth / decay from C++ into FOCS: https://github.com/freeorion/freeorion/pull/1941 This would be nice, as it moves more game logic out of C++ and would allow more varied meter growth / decay systems to be tested or used.

This is basically working so far, except that it takes an extra turn for any changes in target or max meters to lead to changes in the associated active meters, when those active meter changes are dependent on the value of the target or max meter. For example, if one changes from research to industry focus, there will be an immediate decrease in research due to the focus-change penalty, which doesn't depend on what the value of the target meter is... the research meter is just decreased by 1 immediately. It takes an extra turn for the industry meter to start increasing, though.

This occurs because the script that calculates how much the industry meter should increase depends on the value of the target industry meter, and during the turn when a player is changing focus, any evaluation of "Target.TargetIndustry" will return the initial value of that meter on that turn, before the focus change happened.

This is implemented this way so that references to other meter values in scripts don't depend on the order of evaulation of effects that alter meters; the script evaluation always gets a consistent result from referencing a meter value, which is the value it had on the previous turn, but not the value on the current turn that is being calculated by numerous different effects adding modifications to meter values that sum together or multiply. This was more important before effects priorities were implemented, but still important to how meter calculations that depend on other meter values work.

For the case of changing meters after focus changes, this is a bit awkward though, in that on the turn of the focus change, any scripted meter increase or decrease will be evaluated using the target meter values at the start of the turn, rather than the target meter values after the focus change takes effect. This means it takes a full extra turn before an active meter will start growing after the player switches to that meter's focus.

In this post, I'm pondering what to do about this... as it would be preferable to have meters immediately respond to focus changes (other than the focus change penalty).

A possibility would be to have some new FOCS syntax for specifying that the current value of a meter, rather than the initial value from the start of the turn, is needed.

There is already a way to do this within SetMeter effects, but just for the meter being set: reference "Value". This lets one write "SetTargetIndustry value = Value + 5" instead of "SetTargetIndustry value = Target.TargetIndustry + 5". It also lets the meter accumulation actually work by combining multiple effects. If "Target.TargetIndustry" was referenced instead of "Value" within a SetTargetIndustry effect, it would always return the value at the start of the turn, and multiple different effects adding to a meter with SetMeter effects would overwrite rather than combine their results.

"value = Value + 5" works fine for referencing the value of the meter being set, but is limited to only that meter. There's no way to get the current value of any other meter in a script, besides the meter being set in SetMeter. All other meter references will return the initial value for that meter.

I'm not sure what syntax would work well for this for referencing current values of other meters, though.

Something like "value = Value + Source.TargetIndustry.ImmediateValue" could work, but is awkward to implement given how the ValueRef evaluation works, as it will currently treat "ImmediateValue" as the property, and "TargetIndustry" as a container object, like System in "Source.System.Stealth".

Alternatively, there could be two ways to reference each meter, one with and one without "ImmediateValue" at the end, like "value = Value + Target.TargetIndustryImmediateValue", where if this appeared in a SetTargetIndustry effect, it would be the same as "value = Value + Value" or "value = 2*Value".

It could also be implemented as a ComplexValueRef, so one would write something like "ImmediateTargetIndustry object = Target.ID".

Alternatively, there could be something built into effects priorities that would cause a meter backpropegation between some of the effects executions, so that the current / immediate values would become the initial values and thus be returned by the existing scripting format.

In the above, I think I prefer "Immediate" to "Current" as the latter has been used to refer to non-max non-target meters, or what I called the active paired meters.

User avatar
Oberlus
Cosmic Dragon
Posts: 5715
Joined: Mon Apr 10, 2017 4:25 pm

Re: SetMeter Effect Current vs. Initial Value

#2 Post by Oberlus »

Geoff the Medio wrote:I think I prefer "Immediate" to "Current"
Maybe "Now" (and also Initial for the other meter, if ambiguity is not your friend)?. Target.TargetIndustryNow.

Gault.Drakkor
Space Floater
Posts: 40
Joined: Sat Jul 01, 2017 4:54 am

Re: SetMeter Effect Current vs. Initial Value

#3 Post by Gault.Drakkor »

So my understanding of this from what you have said:

For any given meter, there is the "value" that was computed by the next turn operations. There is a "second value" that is modified by FOCS. Which can be further modified by FOCS triggered by user (or AI). But this "second value" is not visible to FOCS that do not directly modify the "value".
Geoff the Medio wrote: This lets one write "SetTargetIndustry value = Value + 5" instead of "SetTargetIndustry value = Target.TargetIndustry + 5". It also lets the meter accumulation actually work by combining multiple effects.
So you are saying if you just have 4 multiple EffectsGroup that are all active but each do
"SetTargetIndustry value = Target.TargetIndustry + 5"
next turn you will have +5 TargetIndustry not not +20 TargetIndustry?


You are looking to name this "second value"?
Geoff the Medio wrote: It also lets the meter accumulation actually work by combining multiple effects
Target.TargetIndustry
Target.TargetIndustryAccumalator

User avatar
Vezzra
Release Manager, Design
Posts: 6095
Joined: Wed Nov 16, 2011 12:56 pm
Location: Sol III

Re: SetMeter Effect Current vs. Initial Value

#4 Post by Vezzra »

Geoff the Medio wrote:I'm not sure where to put this post, but given the SetVisibility Issues thread in this forum, perhaps this belongs here as well.
For the reason you cited, and because it's probably a rather pressing issue, I think posting here is fine.
Alternatively, there could be something built into effects priorities that would cause a meter backpropegation between some of the effects executions, so that the current / immediate values would become the initial values and thus be returned by the existing scripting format.
This.

I'd even go further and suggest to have several "phases" of effect execution during turn resolution ("end of old turn", "pre-combat", "post-combat", "begin of new turn", etc.). That would allow us to not only address this issue, but other limitations/ackwardnesses of the current effect execution implementation, like field or certain building effects always kicking in/expiring with a one turn delay.

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: SetMeter Effect Current vs. Initial Value

#5 Post by Geoff the Medio »

Adding multiple stages of effect execution is a bit more involved than I want to spend time on now. And even if it is implemented, I'd guess that being able to reference the current / immediate vale of a meter would still be useful.

Another idea: "value = Value(Target.TargetIndusty)".

As now, just "Value" would be the immediate value of whatever is being modified by an effect. Wrapping another reference in "Value()" would get the immediate value of whatever it contains.

User avatar
Dilvish
AI Lead and Programmer Emeritus
Posts: 4768
Joined: Sat Sep 22, 2012 6:25 pm

Re: SetMeter Effect Current vs. Initial Value

#6 Post by Dilvish »

Geoff the Medio wrote:Another idea: "value = Value(Target.TargetIndusty)".
That looks like a good idea to me.
If I provided any code, scripts or other content here, it's released under GPL 2.0 and CC-BY-SA 3.0

User avatar
Geoff the Medio
Programming, Design, Admin
Posts: 13587
Joined: Wed Oct 08, 2003 1:33 am
Location: Munich

Re: SetMeter Effect Current vs. Initial Value

#7 Post by Geoff the Medio »

Dilvish wrote:
Geoff the Medio wrote:Another idea: "value = Value(Target.TargetIndusty)".
That looks like a good idea to me.
This is implemented in the branch. Most meter-modifications are also moved into scripted effects, excluding some ship resource meters that I'm not sure where to put in scripts. Some testing to see what this has broken would be helpful.

Post Reply