Gnilbert Gnilbert

[BUG/FIX] Why Shards don't increase magic damage (as coded)... and how to fix it

[BUG/FIX] Why Shards don't increase magic damage (as coded)... and how to fix it

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
  1.   &lt;GameModifier InternalName="FireballModifier"&gt;
  2.    &lt;ModType&gt;Unit&lt;/ModType&gt;
  3.    &lt;Attribute&gt;DefendableDamage&lt;/Attribute&gt;
  4.    &lt;Calculate InternalName="AttackerIntelligence" ValueOwner="CastingUnit"&gt;
  5.     &lt;Expression&gt;&lt;![CDATA[[UnitStat_Intelligence]]]&gt;&lt;/Expression&gt;
  6.    &lt;/Calculate&gt;
  7.    &lt;Calculate InternalName="Value" ValueOwner="CastingUnit"&gt;
  8.     &lt;Expression&gt;&lt;![CDATA[[AttackerIntelligence] * -1.0]]&gt;&lt;/Expression&gt;
  9.    &lt;/Calculate&gt;
  10.       &lt;Calculate InternalName="Value"&gt;
  11.       &lt;Expression&gt;&lt;![CDATA[[Value] * [UnitStat_NumFireShards]]]&gt;&lt;/Expression&gt;
  12.       &lt;/Calculate&gt;
  13.   &lt;/GameModifier&gt;


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
  1.   &lt;GameModifier InternalName="FireballModifier"&gt;
  2.    &lt;ModType&gt;Unit&lt;/ModType&gt;
  3.    &lt;Attribute&gt;DefendableDamage&lt;/Attribute&gt;
  4.    &lt;Calculate InternalName="EffectStrength" ValueOwner="CastingUnit"&gt;
  5.     &lt;Expression&gt;&lt;![CDATA[[UnitStat_Intelligence]*[UnitStat_NumFireShards]]]&gt;&lt;/Expression&gt;
  6.    &lt;/Calculate&gt;
  7.    &lt;Calculate InternalName="CalculatedDamage"&gt;
  8.     &lt;Expression&gt;&lt;![CDATA[[EffectStrength] * -1.0]]&gt;&lt;/Expression&gt;
  9.    &lt;/Calculate&gt;
  10.    &lt;Calculate InternalName="Value"&gt;
  11.    &lt;Expression&gt;&lt;![CDATA[[CalculatedDamage]]]&gt;&lt;/Expression&gt;
  12.    &lt;/Calculate&gt;
  13.   &lt;/GameModifier&gt;


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

30,440 views 30 replies
Reply #26 Top

I was just messing around and did similar fix pack to shard scaling:

http://dl.dropbox.com/u/10706980/SpellDamageFix.xml

It only includes damage spells. And yes, it's pretty much mirrors same thing as Heavenfall's work, but with no fixes to morale or drain spells. And no edit to heal spell either, since it appears to work without any modifications.

But what the heck, if I already did it for personal use, why not share it? :grin:

Reply #27 Top

I'm just curious - how in the world did the game launch with all these broken spells?  Was there no internal testing at all of magic in the internal beta??  For a game that's called War of Magic, you'd think testing the functionality of spells and nodes would be, ya know, kinda a priority?

Reply #28 Top

Quoting Heavenfall, reply 23
I noticed the same thing, however Bravery still didn't work (its attribute isn't accurate) If you want to look at a core spell that actually can change morale, look at Rallying Cry or Fear

I fixed everything except Shield of Fire and Burning Blade (I just can't get them to work right without being able to overwrite core gamemodifiers)

http://thedyinggrounds.com/Elemental/HF106_spell_Shardproof.xml

 

 

Just to note that opening XML in Firefox gives parsing error. So there must be some error in the code.

 

 

XML Parsing Error: mismatched tag. Expected: </Spells>.
Location: http://thedyinggrounds.com/Elemental/HF106_spell_Shardproof.xml
Line Number 611, Column 4:    </SpellDef></Spells>
----------^

Reply #29 Top

Quoting dawgs4ever, reply 27
I'm just curious - how in the world did the game launch with all these broken spells?  Was there no internal testing at all of magic in the internal beta??  For a game that's called War of Magic, you'd think testing the functionality of spells and nodes would be, ya know, kinda a priority?
it sounds like spells work in auto resolve?  So perhaps they didn't test spells in tactical battles?

Reply #30 Top

Quoting p22, reply 28

Quoting Heavenfall, reply 23I noticed the same thing, however Bravery still didn't work (its attribute isn't accurate) If you want to look at a core spell that actually can change morale, look at Rallying Cry or Fear

I fixed everything except Shield of Fire and Burning Blade (I just can't get them to work right without being able to overwrite core gamemodifiers)

http://thedyinggrounds.com/Elemental/HF106_spell_Shardproof.xml

 
 

Just to note that opening XML in Firefox gives parsing error. So there must be some error in the code.

 

 

XML Parsing Error: mismatched tag. Expected: </Spells>.
Location: http://thedyinggrounds.com/Elemental/HF106_spell_Shardproof.xml
Line Number 611, Column 4:    </SpellDef></Spells>
----------^

 

Damn, I knew it was a bad idea to upload it separately =)

You can find an updated version in the bugfix mod.