I think the way to handle the light/heavy shield question is to set the class to ignore spell failure from shields, manually calculate the chance of spell failure from heavy shields, and add that in to the class.
Alright, let's begin by calculating what the arcane failure chance is from heavy shields.
Purchase a heavy shield, a light shield, a buckler, and some other piece of armor for a blank character. In the develop menu, make sure that the first option, "Enable Data File Debugging" is checked, and then for each of those armors and shields, right-click on it, and select "Show Debug Tags for XXX".
Compare those tag lists to each other. The first thing you're looking for is a component tag that is specific to shields - it looks like component.BaseArmor is as close as we're going to get, but that's shared by the armors, too, so also look for a tag that's specific to shields, like EquipType.Shield.
The second thing you're looking for is how light shields are distinguished from heavy shields. Looks like you've got ShldClass.Buckler, ShldClass.Light, and ShldClass.Heavy.
The third thing you're looking for is how to determine whether armor is equipped or not. While watching the list of tags for a shield, equip it and unequip it, and watch how the tags change as you do. Looks like Helper.CurrShield is assigned to a shield once it's equipped - that's even more specific than EquipType.Shield.
Now, to figure out how the arcane failure chance is stored. Close all the tag windows, and right-click each of the shields and armors again, this time selecting "Show Debug Fields for XXX". Look through the list of fields to figure out how arcane failure chances are stored - it's field[arArcFail].value.
We'll start writing our script by searching through all the armor on the hero, looking for those that are equipped shields and heavy shields:
Code:
var arcfail as number
foreach pick in hero from BaseArmor where "Helper.CurrShield & ShldClass.Heavy"
For each pick we find, we'll add its arcane failure chance to a variable (and close out the search):
Code:
arcfail += eachpick.field[arArcFail].value
nexteach
Now, let's look at the class to figure out how it records arcane failure chances. Add a level or two of a class to the character (it actually doesn't even matter if the class has a chance of arcane spell failure, but you might as well use your new class).
Go to the develop menu, to the "Floating Info Windows" option, and choose "Show Selection Fields". In the list of picks that pops up, find your class - you'll see that there's one copy of the class level for each level you've added - they'll all look like "cSorcerer" - "c" & the class tag. You'll also see one copy of the class helper - it'll look like "cHelpSor" - "cHelp" and the three-letter abbreviation. Select the class helper in this list, and press OK.
Now, look through the fields until you find where the arcane failure chance is stored. It may help to equip enough armor and shields that the class has a % that you can look for. You'll find that it's "cArcFail".
Now, back to the script. We've told the class to ignore arcane spell failure from all shields, and we've totaled up the arcane failure chance from heavy shields, so we'll add what we've calculated to the classes own chance:
Code:
field[cArcFail].value += arcfail
For the timing, you probably wouldn't be able to figure this out, but a class calculates its cArcFail at Final/10000, so you want to modify that immediately after, say Final/10500.
Collecting the script together for easy copying (and adding a few comments, so we can understand the script 6 months from now):
Location: an Eval Script on the Class tab, Timing: Final/10500
Code:
var arcfail as number
~find all equipped heavy shields, and total their arcane failure chance
foreach pick in hero from BaseArmor where "Helper.CurrShield & ShldClass.Heavy"
arcfail += eachpick.field[arArcFail].value
nexteach
~the class is currently set to ignore arcane failure chances from shields,
~but we want to add the chance from heavy shields back in
field[cArcFail].value += arcfail