DISCLAIMER: I am not a developer for SD. I don't really know exactly how they're processing the calculation elements. I'm inferring this behavior from numerous experiments with settings, variable names, and spell definitions. It's entirely possible that my "why" is a little off on a few technical details. But the fix works.
There are two critical things you need to know to see how the bug happened:
1. <Calculate/> elements in the xml (Better tutorial on that HERE)
These are used all over the place to figure out (for example) how much damage something does as a percentage of a stat.
I'm being loose with my terminology below. I know that the xml isn't actually creating/storing variables, obviously. All that talk is referring to whatever is "processing" the various calculation tags.
Calculate.InternalName = A "local" variable name you're creating to refer to the value we're storing. It's a little unclear where the value actually lives. I'm thinking of this more like a pointer or reference.
Calculate.ValueOwner = One of a few set strings that tell the processor where to go to get the values for variables in your expression. If a variable name doesn't belong to the specified ValueOwner, it appears to use "local" variables. This is usually left blank (for local) or set to CastingUnit or TargetUnit. It seems like there is a default setting for this property that isn't NULL. I'm guessing it's set differently in the Tactical combat vs. AutoResolve logic, and that's why we're seeing the different results.
Calculate.Expression = Defines an atomic or binary algebraic expression that appears to accept the operators *, /, +, and -. Either or both of the arguments can be variables (that both belong to the ValueOwner specified) or constants (double/float/int).
2. UnitStat_NumFireShards (Water/Air/Earth, also)
This value apparently has a default value of 1. This is important. When you build a new shrine, it's increased by 1. This means when you have 2 shrines, you have "3" NumFireShards. I'm guessing they did this so they could multiply by NumXXXShards without having to add one first.
So here's how it goes down in the xml:
(This is from the core Fireball spell definition)
Code: xml
- <GameModifier InternalName="FireballModifier">
- <ModType>Unit</ModType>
- <Attribute>DefendableDamage</Attribute>
- <Calculate InternalName="AttackerIntelligence" ValueOwner="CastingUnit">
- <Expression><![CDATA[[UnitStat_Intelligence]]]></Expression>
- </Calculate>
- <Calculate InternalName="Value" ValueOwner="CastingUnit">
- <Expression><![CDATA[[AttackerIntelligence] * -1.0]]></Expression>
- </Calculate>
- <Calculate InternalName="Value">
- <Expression><![CDATA[[Value] * [UnitStat_NumFireShards]]]></Expression>
- </Calculate>
- </GameModifier>
So what happens here?
Calculate #1: We assign the
UnitStat_Intelligence value from "CastingUnit" to a new
local variable named
AttackerIntelligence.
Calculate #2: We assign negative the calculated
AttackerIntelligence value (from step 1) to "Value." This is the first place where things get a little iffy. Where is Value being set? "Locally" as the value of the Expression that's being parsed, or to the property of the same name on "CastingUnit?" Honestly, it's just a tad sloppy.
Calculate #3: This is where it's definitely off course. In this expression, they reference
UnitStat_NumFireShards. But... the ValueOwner is blank, meaning that it's unclear where this value is actually coming from. It doesn't completely bomb, though, because the default value for NumXXXShards is 1, remember? So even when it grabs the wrong source (which is seems to do in tactical combat), it doesn't cause an obvious "Oh look it's broken!" effect.
And how do we fix it?
Pretty easily, actually. Just clean up the unclear references:
Code: xml
- <GameModifier InternalName="FireballModifier">
- <ModType>Unit</ModType>
- <Attribute>DefendableDamage</Attribute>
- <Calculate InternalName="EffectStrength" ValueOwner="CastingUnit">
- <Expression><![CDATA[[UnitStat_Intelligence]*[UnitStat_NumFireShards]]]></Expression>
- </Calculate>
- <Calculate InternalName="CalculatedDamage">
- <Expression><![CDATA[[EffectStrength] * -1.0]]></Expression>
- </Calculate>
- <Calculate InternalName="Value">
- <Expression><![CDATA[[CalculatedDamage]]]></Expression>
- </Calculate>
- </GameModifier>
Calculate #1: We assign the
EffectStrength as Int*NumXShards. Both of these values belong to CastingUnit, so it works great.
Calculate #2: We multiply the damage by -1 to make sure it
hurts the target. This could have been rolled into step 3, but it's better to keep it alone where we can tweak the damage multiplier by itself.
Calculate #3: Just assigns the calculated damage to the "Value" element of the modifier.
Gnilbert