Devblog:

I think a lot of folk misunderstand the amount of work that has to go into taking a stock RunUO install and paring it down to the T2A or Renaissance era with any degree of fidelity. With AOS and its wacky new protection stats system, anyone developing a pre-AOS server really needs to pick through the source rather meticulously. RunUO is littered with conditionals for Core.AOS and in some cases the focus on the later eras has meant that the non-AOS cases have fallen by the wayside.

Case in point: Protection.

public override void OnCast()  
{
    if ( Core.AOS )
    {
        if ( CheckSequence() )
            Toggle( Caster, Caster );
        FinishSequence();
    }
    else
    {
        if ( m_Registry.ContainsKey( Caster ) )
        {
            Caster.SendLocalizedMessage( 1005559 ); // This spell is already in effect.
        }
        else if ( !Caster.CanBeginAction( typeof( DefensiveSpell ) ) )
        {
            Caster.SendLocalizedMessage( 1005385 ); // The spell will not adhere to you at this time.
        }
        else if ( CheckSequence() )
        {
            if ( Caster.BeginAction( typeof( DefensiveSpell ) ) )
            {
                double value = (int)(Caster.Skills[SkillName.EvalInt].Value + Caster.Skills[SkillName.Meditation].Value + Caster.Skills[SkillName.Inscribe].Value);
                value /= 4;
                if ( value < 0 ) {
                    value = 0;
                }
                else if ( value > 75 ) 
                {
                    value = 75.0;
                }
                Registry.Add( Caster, value );
                new InternalTimer( Caster ).Start();
                Caster.FixedParticles( 0x375A, 9, 20, 5016, EffectLayer.Waist );
                Caster.PlaySound( 0x1ED );
            }
            else
            {
                Caster.SendLocalizedMessage( 1005385 ); // The spell will not adhere to you at this time.
            }
        }
        FinishSequence();
    }
}

The above snippet is from the Protection Spell. If you look closely, you'll see that if Core.AOS is false (which it is for our server), then the Toggle() function never gets called. Instead, it does a few checks, adds the spell object to the registry, starts a timer.... and then does nothing. There is no armor bonus granted when using this spell. Arch Protection works; and if you poke at the code you'll see it has its own, different logic.

Daleron and I also spent some time digging into just how exactly one's armour rating or AR is calculated. It's something I'd always sort of glossed over; one of those things that just works in the background and you never bother with it. Turns out it's pretty simple in RunUO, though some of it seems pretty arbitrary:

The AR summation is so that different pieces contribute a different amount. Gorgets and gloves contribute 7%, helmets contribute 14%, arms/pauldrons contribute 15%, legs 22%, chestplates 35%, and finally shields contribute 100% of their AR rating to your total.

Conveniently, the Zulu Archive tells me that a suit of Ryous provides 100 AR. Based on the RunUO internals it should work out something like this:

Ryous

In POL, it's hilariously buggy. first of all, in the itemdesc.cfg the Ryous items are all set for an AR of 70, not 100. More on that later. Now, In my copy of ZHF, built with POL093, every item has an equipscript and an unequipscript that live under scripts/control/. After some digging I found the relevant functions.

When equipping:

function DoArMods( who , item )
    var ar := Cint(GetObjProperty( item, "ArBonus" ));
    if( ar )
        who.ar_mod := who.ar_mod + Cint(ar/2);
    endif   
endfunction

When unequipping (irrelevant stuff removed):

program unequip( who, it )
[...]
    temp := Cint(GetObjProperty( it, "ArBonus" ));
    if( temp )
        who.ar_mod := who.ar_mod - Cint(temp/2);
    endif
[...]
endprogram

Let's just take a sec and list the actual armor values I got from ingame testing, one piece at a time.

Tallying these numbers gets you 97.

The ArBonus and ar_mod CProps get set when you equip items with a bonus to armor, such as a helmet of hardening. Unfortunately POL093 does AR processing in the core which is closed-source, and documentation is hard to find these days. As best I can tell, though, it's all fucked up.

What if you equip the gloves and then the legs, you should have 13 AR, right?

Wrong. You have 14. Because POL.

The Ryous shield on its own bestows a mighty 32 AR. Well, if I equipped the legs and the gloves for a total of 4 + 9 = 14, then maybe I will get even more than 36!.

No. Fuck you. You get 33. The gloves only count for 1 if you have a shield on.

Well what about all 3? It should be, er.... well it should be 45.

Wrong again! It's 43.

How about just the legs and the arms? 18? Nope, 19.

It goes on and on, but basically the pieces give different ratings depending on when you equip them. The whole suit, irrespective of order, eventually reaches 99 AR with the shield. That's not 100 (info vault), it's not 70 (itemdesc.cfg), and it's not 97 (grade 3 math). The funniest part to me was that if you equip everything but the shield you get 69 AR, and then get ripped off for that last 2 AR when you put the shield on and only get 99, not 101.

Somebody, somewhere, wrote some really funky code in the old POL core(s).

And this is why all serious UO development has moved to RunUO.

As always, get at me on IRC.