RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

server crash

rathraven

Traveler
Using daat99's newest owltr.
A player turned in a bod, and the server crashed.
Exception:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Server.Engines.BulkOrders.SmithRewardCalculator.ComputeGold(Int32 quantity, Boolean exceptional, BulkMaterialType material, Int32 itemCount, Type type) in c:\2.3\Scripts\Engines\BulkOrders\Rewards.cs:line 511
at Server.Engines.BulkOrders.RewardCalculator.ComputeGold(LargeBOD bod) in c:\2.3\Scripts\Engines\BulkOrders\Rewards.cs:line 145
at Server.Engines.BulkOrders.LargeSmithBOD.ComputeGold() in c:\2.3\Scripts\Engines\BulkOrders\LargeSmithBOD.cs:line 40
at Server.Engines.BulkOrders.LargeBOD.GetRewards(Item& reward, Int32& gold, Int32& fame) in c:\2.3\Scripts\Engines\BulkOrders\LargeBOD.cs:line 50
at Server.Mobiles.BaseVendor.OnDragDrop(Mobile from, Item dropped) in c:\2.3\Scripts\Mobiles\Vendors\BaseVendor.cs:line 786
at Server.Item.DropToMobile(Mobile from, Mobile target, Point3D p)
at Server.Mobile.Drop(Mobile to, Point3D loc)
at Server.Network.PacketHandlers.DropReq6017(NetState state, PacketReader pvSrc)
at Server.Network.MessagePump.HandleReceive(NetState ns)
at Server.Network.MessagePump.Slice()
at Server.Core.Main(String[] args)


Code:
using System;
using Server;
using Server.Items;
 
namespace Server.Engines.BulkOrders
{
    public delegate Item ConstructCallback( int type );
 
    public sealed class RewardType
    {
        private int m_Points;
        private Type[] m_Types;
 
        public int Points{ get{ return m_Points; } }
        public Type[] Types{ get{ return m_Types; } }
 
        public RewardType( int points, params Type[] types )
        {
            m_Points = points;
            m_Types = types;
        }
 
        public bool Contains( Type type )
        {
            for ( int i = 0; i < m_Types.Length; ++i )
            {
                if ( m_Types[i] == type )
                    return true;
            }
 
            return false;
        }
    }
 
    public sealed class RewardItem
    {
        private int m_Weight;
        private ConstructCallback m_Constructor;
        private int m_Type;
 
        public int Weight{ get{ return m_Weight; } }
        public ConstructCallback Constructor{ get{ return m_Constructor; } }
        public int Type{ get{ return m_Type; } }
 
        public RewardItem( int weight, ConstructCallback constructor ) : this( weight, constructor, 0 )
        {
        }
 
        public RewardItem( int weight, ConstructCallback constructor, int type )
        {
            m_Weight = weight;
            m_Constructor = constructor;
            m_Type = type;
        }
 
        public Item Construct()
        {
            try{ return m_Constructor( m_Type ); }
            catch{ return null; }
        }
    }
 
    public sealed class RewardGroup
    {
        private int m_Points;
        private RewardItem[] m_Items;
 
        public int Points{ get{ return m_Points; } }
        public RewardItem[] Items{ get{ return m_Items; } }
 
        public RewardGroup( int points, params RewardItem[] items )
        {
            m_Points = points;
            m_Items = items;
        }
 
        public RewardItem AcquireItem()
        {
            if ( m_Items.Length == 0 )
                return null;
            else if ( m_Items.Length == 1 )
                return m_Items[0];
 
            int totalWeight = 0;
 
            for ( int i = 0; i < m_Items.Length; ++i )
                totalWeight += m_Items[i].Weight;
 
            int randomWeight = Utility.Random( totalWeight );
 
            for ( int i = 0; i < m_Items.Length; ++i )
            {
                RewardItem item = m_Items[i];
 
                if ( randomWeight < item.Weight )
                    return item;
 
                randomWeight -= item.Weight;
            }
 
            return null;
        }
    }
 
    public abstract class RewardCalculator
    {
        private RewardGroup[] m_Groups;
 
        public RewardGroup[] Groups{ get{ return m_Groups; } set{ m_Groups = value; } }
 
        public abstract int ComputePoints( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type );
        public abstract int ComputeGold( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type );
 
        public virtual int ComputeFame( SmallBOD bod )
        {
            int points = ComputePoints( bod ) / 50;
 
            return points * points;
        }
 
        public virtual int ComputeFame( LargeBOD bod )
        {
            int points = ComputePoints( bod ) / 50;
 
            return points * points;
        }
 
        public virtual int ComputePoints( SmallBOD bod )
        {
            return ComputePoints( bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type );
        }
 
        public virtual int ComputePoints( LargeBOD bod )
        {
            return ComputePoints( bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length, bod.Entries[0].Details.Type );
        }
 
        public virtual int ComputeGold( SmallBOD bod )
        {
            return ComputeGold( bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type );
        }
 
        public virtual int ComputeGold( LargeBOD bod )
        {
            return ComputeGold( bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length, bod.Entries[0].Details.Type );
        }
 
        public virtual RewardGroup LookupRewards( int points )
        {
            for ( int i = m_Groups.Length - 1; i >= 1; --i )
            {
                RewardGroup group = m_Groups[i];
 
                if ( points >= group.Points )
                    return group;
            }
 
            return m_Groups[0];
        }
 
        public virtual int LookupTypePoints( RewardType[] types, Type type )
        {
            for ( int i = 0; i < types.Length; ++i )
            {
                if ( types[i].Contains( type ) )
                    return types[i].Points;
            }
 
            return 0;
        }
 
        public RewardCalculator()
        {
        }
    }
 
    public sealed class SmithRewardCalculator : RewardCalculator
    {
        #region Constructors
        private static readonly ConstructCallback SturdyShovel = new ConstructCallback( CreateSturdyShovel );
        private static readonly ConstructCallback SturdyPickaxe = new ConstructCallback( CreateSturdyPickaxe );
        private static readonly ConstructCallback MiningGloves = new ConstructCallback( CreateMiningGloves );
        private static readonly ConstructCallback GargoylesPickaxe = new ConstructCallback( CreateGargoylesPickaxe );
        private static readonly ConstructCallback ProspectorsTool = new ConstructCallback( CreateProspectorsTool );
        private static readonly ConstructCallback PowderOfTemperament = new ConstructCallback( CreatePowderOfTemperament );
        private static readonly ConstructCallback RunicHammer = new ConstructCallback( CreateRunicHammer );
        private static readonly ConstructCallback PowerScroll = new ConstructCallback( CreatePowerScroll );
        private static readonly ConstructCallback ColoredAnvil = new ConstructCallback( CreateColoredAnvil );
        private static readonly ConstructCallback AncientHammer = new ConstructCallback( CreateAncientHammer );
        //daat99 OWLTR start - bod rewards
        private static readonly ConstructCallback Deco = new ConstructCallback( CreateDeco );
        private static readonly ConstructCallback SturdySmithHammer = new ConstructCallback( CreateSturdySmithHammer );
        private static readonly ConstructCallback SmithersProtector = new ConstructCallback( CreateSmithersProtector );
        private static readonly ConstructCallback SharpeningBlade = new ConstructCallback( CreateSharpeningBlade );
        private static readonly ConstructCallback ColoredForgeDeed = new ConstructCallback( CreateColoredForgeDeed );
        private static readonly ConstructCallback ChargedDyeTub = new ConstructCallback( CreateChargedDyeTub );
        private static readonly ConstructCallback BagOfResources = new ConstructCallback( CreateBagOfResources );
        private static readonly ConstructCallback ArmorOfCrafting = new ConstructCallback( CreateArmorOfCrafting );
 
        private static Item CreateDeco( int type )
        {
            switch (type)
            {
                case 0: default: return new Deco( 5053, "Chainmail Tunic" );
                case 1: return new Deco( 5052, "chainmail Leggings" );
                case 2: return new Deco( 5402, "Decorative Armor" );
                case 3: return new Deco( 5509, "Decorative Shield and Sword" );
                case 4: return new Deco( 7110, "Decorative Scale Shield" );
                case 5: return new Deco( 10324, "Sword Display" );
            }
        }
       
        private static Item CreateSturdySmithHammer( int type )
        {
            return new SturdySmithHammer();
        }
       
        private static Item CreateSmithersProtector( int type )
        {
            return new SmithersProtector();
        }
       
        private static Item CreateSharpeningBlade( int type )
        {
            return new SharpeningBlade();
        }
       
        private static Item CreateColoredForgeDeed( int type )
        {
            return new ColoredForgeDeed( CraftResources.GetHue( (CraftResource)Utility.RandomMinMax( (int)CraftResource.DullCopper, (int)CraftResource.Platinum ) ) );
        }
 
        private static Item CreateChargedDyeTub( int type )
        {
            return new ChargedDyeTub( 10, type );
        }
 
 
        private static Item CreateBagOfResources( int type )
        {
            return new BagOfResources();
        }
       
        private static Item CreateArmorOfCrafting( int type )
        {
            switch (type)
            {
                case 1: default: return new ArmorOfCrafting( 1, 5062, Utility.Random(2)); //gloves
                case 2: return new ArmorOfCrafting( 1, 7609, Utility.Random(2)); //cap
                case 3: return new ArmorOfCrafting( 1, 5068, Utility.Random(2)); //tunic
                case 4: return new ArmorOfCrafting( 1, 5063, Utility.Random(2)); //gorget
                case 5: return new ArmorOfCrafting( 1, 5069, Utility.Random(2)); //arms
                case 6: return new ArmorOfCrafting( 1, 5067, Utility.Random(2)); //leggings
                case 7: return new ArmorOfCrafting( 3, 5062, Utility.Random(2)); //gloves
                case 8: return new ArmorOfCrafting( 3, 7609, Utility.Random(2)); //cap
                case 9: return new ArmorOfCrafting( 3, 5068, Utility.Random(2)); //tunic
                case 10: return new ArmorOfCrafting( 3, 5063, Utility.Random(2)); //gorget
                case 11: return new ArmorOfCrafting( 3, 5069, Utility.Random(2)); //arms
                case 12: return new ArmorOfCrafting( 3, 5067, Utility.Random(2)); //leggings
                case 13: return new ArmorOfCrafting( 5, 5062, Utility.Random(2)); //gloves
                case 14: return new ArmorOfCrafting( 5, 7609, Utility.Random(2)); //cap
                case 15: return new ArmorOfCrafting( 5, 5068, Utility.Random(2)); //tunic
                case 16: return new ArmorOfCrafting( 5, 5063, Utility.Random(2)); //gorget
                case 17: return new ArmorOfCrafting( 5, 5069, Utility.Random(2)); //arms
                case 18: return new ArmorOfCrafting( 5, 5067, Utility.Random(2)); //leggings
            }
        }
        //daat99 OWLTR end - bod rewards
 
        private static Item CreateSturdyShovel( int type )
        {
            return new SturdyShovel();
        }
 
        private static Item CreateSturdyPickaxe( int type )
        {
            return new SturdyPickaxe();
        }
 
        private static Item CreateMiningGloves( int type )
        {
            if ( type == 1 )
                return new LeatherGlovesOfMining( 1 );
            else if ( type == 3 )
                return new StuddedGlovesOfMining( 3 );
            else if ( type == 5 )
                return new RingmailGlovesOfMining( 5 );
 
            throw new InvalidOperationException();
        }
 
        private static Item CreateGargoylesPickaxe( int type )
        {
            return new GargoylesPickaxe();
        }
 
        private static Item CreateProspectorsTool( int type )
        {
            return new ProspectorsTool();
        }
 
        private static Item CreatePowderOfTemperament( int type )
        {
            return new PowderOfTemperament();
        }
 
        private static Item CreateRunicHammer( int type )
        {
            if ( type >= 1 && type <= 8 )
                return new RunicHammer( CraftResource.Iron + type, Core.AOS ? ( 55 - (type*5) ) : 50 );
 
            throw new InvalidOperationException();
        }
 
        private static Item CreatePowerScroll( int type )
        {
            if ( type == 5 || type == 10 || type == 15 || type == 20 )
                return new PowerScroll( SkillName.Blacksmith, 100 + type );
 
            throw new InvalidOperationException();
        }
 
        private static Item CreateColoredAnvil( int type )
        {
            // Generate an anvil deed, not an actual anvil.
            //return new ColoredAnvilDeed();
 
            return new ColoredAnvil();
        }
 
        private static Item CreateAncientHammer( int type )
        {
            if ( type == 10 || type == 15 || type == 30 || type == 60 )
                return new AncientSmithyHammer( type );
 
            throw new InvalidOperationException();
        }
        #endregion
 
        public static readonly SmithRewardCalculator Instance = new SmithRewardCalculator();
 
        private RewardType[] m_Types = new RewardType[]
            {
                // Armors
                new RewardType( 200, typeof( RingmailGloves ), typeof( RingmailChest ), typeof( RingmailArms ), typeof( RingmailLegs ) ),
                new RewardType( 300, typeof( ChainCoif ), typeof( ChainLegs ), typeof( ChainChest ) ),
                new RewardType( 400, typeof( PlateArms ), typeof( PlateLegs ), typeof( PlateHelm ), typeof( PlateGorget ), typeof( PlateGloves ), typeof( PlateChest ) ),
 
                // Weapons
                new RewardType( 200, typeof( Bardiche ), typeof( Halberd ) ),
                new RewardType( 300, typeof( Dagger ), typeof( ShortSpear ), typeof( Spear ), typeof( WarFork ), typeof( Kryss ) ),    //OSI put the dagger in there.  Odd, ain't it.
                new RewardType( 350, typeof( Axe ), typeof( BattleAxe ), typeof( DoubleAxe ), typeof( ExecutionersAxe ), typeof( LargeBattleAxe ), typeof( TwoHandedAxe ) ),
                new RewardType( 350, typeof( Broadsword ), typeof( Cutlass ), typeof( Katana ), typeof( Longsword ), typeof( Scimitar ), /*typeof( ThinLongsword ),*/ typeof( VikingSword ) ),
                new RewardType( 350, typeof( WarAxe ), typeof( HammerPick ), typeof( Mace ), typeof( Maul ), typeof( WarHammer ), typeof( WarMace ) )
            };
 
        public override int ComputePoints( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type )
        {
            int points = 0;
 
            if ( quantity == 10 )
                points += 10;
            else if ( quantity == 15 )
                points += 25;
            else if ( quantity == 20 )
                points += 50;
 
            if ( exceptional )
                points += 200;
 
            if ( itemCount > 1 )
                points += LookupTypePoints( m_Types, type );
 
            //daat99 OWLTR start - custom resources
            if ( material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Platinum )
            //daat99 OWLTR end - custom resources
                points += 200 + (50 * (material - BulkMaterialType.DullCopper));
 
            return points;
        }
 
        private static int[][][] m_GoldTable = new int[][][]
        {
            //daat99 OWLTR start - custom gold reward
            new int[][] // 1-part (regular)
            {
                new int[]{ 100, 200, 300,  400,  500,  600,  700,  800,  900, 1000, 1100, 1200, 1300, 1400 },
                new int[]{ 200, 400, 600,  800, 1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 2800 },
                new int[]{ 300, 600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600, 3900, 4200 }
            },
            new int[][] // 1-part (exceptional)
            {
                new int[]{ 250, 500,  750, 1000, 1250, 1500, 1750, 2000,  2250, 2500, 2750, 3000, 3250, 3500 },
                new int[]{ 350, 700, 1050, 1400, 1750, 2100, 2450, 2800,  3150, 3500, 3850, 4200, 4550, 4900 },
                new int[]{ 450, 900, 1350, 1800, 2250, 2700, 3150, 3600,  4050, 4500, 4950, 5400, 5850, 6300 }
            },
            new int[][] // Ringmail (regular)
            {
                new int[]{ 2000, 4000,  6000,  8000, 10000, 12000, 14000, 16000, 18000, 20000, 22000, 24000, 26000, 28000 },
                new int[]{ 3000, 6000,  9000, 12000, 15000, 18000, 21000, 24000, 27000, 30000, 33000, 36000, 39000, 42000 },
                new int[]{ 4000, 8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000, 48000, 52000, 56000 }
            },
            new int[][] // Ringmail (exceptional)
            {
                new int[]{ 4000,  8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000, 48000,  52000,  56000 },
                new int[]{ 6000, 12000, 18000, 24000, 30000, 36000, 42000, 48000, 54000, 60000, 66000, 72000,  78000,  84000 },
                new int[]{ 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000, 96000, 104000, 112000 }
            },
            new int[][] // Chainmail (regular)
            {
                new int[]{ 4000,  8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000, 48000,  52000,  56000 },
                new int[]{ 6000, 12000, 18000, 24000, 30000, 36000, 42000, 48000, 54000, 60000, 66000, 72000,  78000,  84000 },
                new int[]{ 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000, 96000, 104000, 112000 }
            },
            new int[][] // Chainmail (exceptional)
            {
                new int[]{  7000, 14000, 21000, 28000, 35000, 42000,  49000,  56000,  63000,  70000,  77000,  84000,  91000,  98000 },
                new int[]{ 10000, 20000, 30000, 40000, 50000, 60000,  70000,  80000,  90000, 100000, 110000, 120000, 130000, 140000 },
                new int[]{ 15000, 30000, 45000, 60000, 75000, 90000, 105000, 120000, 135000, 150000, 165000, 180000, 195000, 210000 }
            },
            new int[][] // Platemail (regular)
            {
                new int[]{  5000, 10000, 15000, 20000, 25000, 30000,  35000,  40000,  45000,  50000,  55000,  60000,  65000,  70000 },
                new int[]{  7500, 15000, 22500, 30000, 37500, 45000,  52500,  60000,  67500,  75000,  82500,  90000,  97500, 105000 },
                new int[]{ 10000, 20000, 30000, 40000, 50000, 60000,  70000,  80000,  90000, 100000, 110000, 120000, 130000, 140000 }
            },
            new int[][] // Platemail (exceptional)
            {
                new int[]{ 10000, 20000, 30000, 40000,  50000,  60000,  70000,  80000,  90000, 100000, 110000, 120000, 130000, 140000 },
                new int[]{ 15000, 30000, 45000, 60000,  75000,  90000, 105000, 120000, 135000, 150000, 165000, 180000, 195000, 210000 },
                new int[]{ 20000, 40000, 60000, 80000, 100000, 120000, 140000, 160000, 180000, 200000, 220000, 240000, 260000, 280000 }
            },
            new int[][] // 2-part weapons (regular)
            {
                new int[]{ 3000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 4500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 6000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 2-part weapons (exceptional)
            {
                new int[]{ 5000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 7500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 10000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 5-part weapons (regular)
            {
                new int[]{ 4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 6000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 8000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 5-part weapons (exceptional)
            {
                new int[]{ 7500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 11250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 15000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 6-part weapons (regular)
            {
                new int[]{ 4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 6000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 10000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 6-part weapons (exceptional)
            {
                new int[]{ 7500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 11250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 15000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            }
            //daat99 OWLTR start - custom gold reward
        };
 
        private int ComputeType( Type type, int itemCount )
        {
            // Item count of 1 means it's a small BOD.
            if ( itemCount == 1 )
                return 0;
 
            int typeIdx;
 
            // Loop through the RewardTypes defined earlier and find the correct one.
            //daat99 OWLTR start - don't use magic numbers...
            for ( typeIdx = 0; typeIdx < m_Types.Length; ++typeIdx )
            //daat99 OWLTR end - don't use magic numbers...
            {
                if ( m_Types[typeIdx].Contains( type ) )
                    break;
            }
 
            //daat99 OWLTR start - custom bods
            //daat99 note: make it last 3 types, not specific index!
            // Types 5, 6 and 7 are Large Weapon BODs with the same rewards.
            if ( typeIdx > m_Types.Length-2 )
                typeIdx = m_Types.Length-2;
            //daat99 OWLTR end - custom bods
 
            return ( typeIdx + 1 ) * 2;
        }
        public override int ComputeGold( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type )
        {
            int[][][] goldTable = m_GoldTable;
 
            int typeIndex = ComputeType( type, itemCount );
            int quanIndex = ( quantity == 20 ? 2 : quantity == 15 ? 1 : 0 );
            //daat99 OWLTR start - custom resource
            int mtrlIndex = ( material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Platinum ) ? 1 + (int)(material - BulkMaterialType.DullCopper) : 0;
            //daat99 OWLTR end - custom resource
 
            if ( exceptional )
                typeIndex++;
 
            int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
 
            int min = (gold * 9) / 10;
            int max = (gold * 10) / 9;
 
            return Utility.RandomMinMax( min, max );
        }
 
        public SmithRewardCalculator()
        {
            Groups = new RewardGroup[]
            {
                //daat99 OWLTR start - bod reward
                new RewardGroup(    0, new RewardItem( 1, SturdyShovel ), new RewardItem( 1, SturdySmithHammer ) ),
                new RewardGroup(  25, new RewardItem( 1, SturdyPickaxe ), new RewardItem( 1, SturdySmithHammer ) ),
                new RewardGroup(  50, new RewardItem( 90, SturdyShovel ), new RewardItem( 10, ArmorOfCrafting, Utility.RandomMinMax(1,6) ) ),
                new RewardGroup(  200, new RewardItem( 90, SturdyPickaxe ), new RewardItem( 10, ArmorOfCrafting, Utility.RandomMinMax(1,6) ) ),
                new RewardGroup(  400, new RewardItem( 90, ProspectorsTool ), new RewardItem( 10, ArmorOfCrafting, Utility.RandomMinMax(1,6) ) ),
                new RewardGroup(  450, new RewardItem( 2, PowderOfTemperament ), new RewardItem( 1, GargoylesPickaxe ), new RewardItem( 1, Deco, Utility.Random(6) ) ),
                new RewardGroup(  500, new RewardItem( 1, RunicHammer, 1 ), new RewardItem( 1, GargoylesPickaxe ), new RewardItem( 1, Deco, Utility.Random(6) ) ),
                new RewardGroup(  550, new RewardItem( 3, RunicHammer, 1 ), new RewardItem( 2, RunicHammer, 2 ) ),
                new RewardGroup(  600, new RewardItem( 1, RunicHammer, 2 ), new RewardItem( 1, ColoredForgeDeed ) ),
                new RewardGroup(  625, new RewardItem( 3, RunicHammer, 2 ), new RewardItem( 1, ColoredAnvil ) ),
                new RewardGroup(  650, new RewardItem( 1, RunicHammer, 3 ), new RewardItem( 1, Deco, Utility.Random(6) ) ),
                new RewardGroup(  675, new RewardItem( 1, ColoredAnvil ), new RewardItem( 3, RunicHammer, 3 ) ),
                new RewardGroup(  700, new RewardItem( 1, RunicHammer, 4 ), new RewardItem( 1, Deco, Utility.Random(6) ) ),
                new RewardGroup(  750, new RewardItem( 1, AncientHammer, 10 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  800, new RewardItem( 1, GargoylesPickaxe ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  850, new RewardItem( 1, AncientHammer, 15 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  900, new RewardItem( 1, RunicHammer, 5 ), new RewardItem( 1, ChargedDyeTub, Utility.RandomMinMax(1,2) ) ),
                new RewardGroup(  950, new RewardItem( 1, RunicHammer, 5 ), new RewardItem( 1, ChargedDyeTub, Utility.RandomMinMax(1,2) ) ),
                new RewardGroup( 1000, new RewardItem( 1, AncientHammer, 30 ), new RewardItem( 1, ChargedDyeTub, Utility.RandomMinMax(1,2) ) ),
                new RewardGroup( 1050, new RewardItem( 1, RunicHammer, 6 ), new RewardItem( 1, SmithersProtector ) ),
                new RewardGroup( 1100, new RewardItem( 1, AncientHammer, 60 ), new RewardItem( 1, SmithersProtector ) ),
                new RewardGroup( 1150, new RewardItem( 1, RunicHammer, 7 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1200, new RewardItem( 1, RunicHammer, 8 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1250, new RewardItem( 1, RunicHammer, 9 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1300, new RewardItem( 1, RunicHammer, 10 ), new RewardItem( 1, BagOfResources ) ),
                new RewardGroup( 1350, new RewardItem( 1, RunicHammer, 11 ), new RewardItem( 1, BagOfResources ) ),
                new RewardGroup( 1400, new RewardItem( 1, RunicHammer, 12 ), new RewardItem( 1, SharpeningBlade ) ),
                new RewardGroup( 1450, new RewardItem( 1, RunicHammer, 13 ), new RewardItem( 1, SharpeningBlade ) )
                //daat99 OWLTR end - bod reward
            };
        }
    }
 
    public sealed class TailorRewardCalculator : RewardCalculator
    {
        #region Constructors
        private static readonly ConstructCallback Cloth = new ConstructCallback( CreateCloth );
        private static readonly ConstructCallback Sandals = new ConstructCallback( CreateSandals );
        private static readonly ConstructCallback StretchedHide = new ConstructCallback( CreateStretchedHide );
        private static readonly ConstructCallback RunicKit = new ConstructCallback( CreateRunicKit );
        private static readonly ConstructCallback Tapestry = new ConstructCallback( CreateTapestry );
        private static readonly ConstructCallback PowerScroll = new ConstructCallback( CreatePowerScroll );
        private static readonly ConstructCallback BearRug = new ConstructCallback( CreateBearRug );
        private static readonly ConstructCallback ClothingBlessDeed = new ConstructCallback( CreateCBD );
        //daat99 OWLTR start - bod reward
        private static readonly ConstructCallback ArmorOfCrafting = new ConstructCallback( CreateArmorOfCrafting );
        private static readonly ConstructCallback TailorsProtector = new ConstructCallback( CreateTailorsProtector );
        private static readonly ConstructCallback SturdySewingKit = new ConstructCallback( CreateSturdySewingKit );
        private static readonly ConstructCallback MastersKnife = new ConstructCallback( CreateMastersKnife );
        private static readonly ConstructCallback GargoylesKnife = new ConstructCallback( CreateGargoylesKnife );
        private static readonly ConstructCallback ColoredScissors = new ConstructCallback( CreateColoredScissors );
        private static readonly ConstructCallback ColoredLoom = new ConstructCallback( CreateColoredLoom );
        private static readonly ConstructCallback ChargedDyeTub = new ConstructCallback( CreateChargedDyeTub );
        private static readonly ConstructCallback BagOfResources = new ConstructCallback( CreateBagOfResources );
        private static readonly ConstructCallback Deco = new ConstructCallback( CreateDeco );
       
        private static Item CreateArmorOfCrafting( int type )
        {
            switch (type)
            {
                case 1: default: return new ArmorOfCrafting( 1, 5062, 2 ); //gloves
                case 2: return new ArmorOfCrafting( 1, 7609, 2 ); //cap
                case 3: return new ArmorOfCrafting( 1, 5068, 2 ); //tunic
                case 4: return new ArmorOfCrafting( 1, 5063, 2 ); //gorget
                case 5: return new ArmorOfCrafting( 1, 5069, 2 ); //arms
                case 6: return new ArmorOfCrafting( 1, 5067, 2 ); //leggings
                case 7: return new ArmorOfCrafting( 3, 5062, 2 ); //gloves
                case 8: return new ArmorOfCrafting( 3, 7609, 2 ); //cap
                case 9: return new ArmorOfCrafting( 3, 5068, 2 ); //tunic
                case 10: return new ArmorOfCrafting( 3, 5063, 2 ); //gorget
                case 11: return new ArmorOfCrafting( 3, 5069, 2 ); //arms
                case 12: return new ArmorOfCrafting( 3, 5067, 2 ); //leggings
                case 13: return new ArmorOfCrafting( 5, 5062, 2 ); //gloves
                case 14: return new ArmorOfCrafting( 5, 7609, 2 ); //cap
                case 15: return new ArmorOfCrafting( 5, 5068, 2 ); //tunic
                case 16: return new ArmorOfCrafting( 5, 5063, 2 ); //gorget
                case 17: return new ArmorOfCrafting( 5, 5069, 2 ); //arms
                case 18: return new ArmorOfCrafting( 5, 5067, 2 ); //leggings
            }
        }
       
        private static Item CreateTailorsProtector( int type )
        {
            return new TailorsProtector();
        }
 
        private static Item CreateSturdySewingKit( int type )
        {
            return new SturdySewingKit();
        }
 
        private static Item CreateGargoylesKnife( int type )
        {
            return new GargoylesKnife();
        }
 
        private static Item CreateMastersKnife( int type )
        {
            return new MastersKnife();
        }
 
        private static Item CreateColoredScissors( int type )
        {
            return new ColoredScissors( CraftResources.GetHue( (CraftResource)Utility.RandomMinMax( (int)CraftResource.SpinedLeather, (int)CraftResource.EtherealLeather ) ), 25 );
        }
       
        private static Item CreateColoredLoom( int type )
        {
            if (Utility.Random(2) == 1)
                return new ColoredLoomSouthDeed( CraftResources.GetHue( (CraftResource)Utility.RandomMinMax( (int)CraftResource.SpinedLeather, (int)CraftResource.EtherealLeather ) ) );
            else
                return new ColoredLoomEastDeed( CraftResources.GetHue( (CraftResource)Utility.RandomMinMax( (int)CraftResource.SpinedLeather, (int)CraftResource.EtherealLeather ) ) );
        }
       
        private static Item CreateChargedDyeTub( int type )
        {
            return new ChargedDyeTub( 0 );
        }
       
        private static Item CreateBagOfResources( int type )
        {
            return new BagOfResources();
        }
 
        private static Item CreateDeco( int type )
        {
            switch (type)
            {
                case 0: default: return new Deco( 4054, "Tapestry" );
                case 1: return new Deco( 9036, "Rose of Trinsic" );
                case 2: return new Deco( 15721, "Deer Corspe" );
                case 3: return new Deco( 5610, "Banner" );
            }
        }
        //daat99 OWLTR end - bod reward
       
        private static int[][] m_ClothHues = new int[][]
            {
                new int[]{ 0x483, 0x48C, 0x488, 0x48A },
                new int[]{ 0x495, 0x48B, 0x486, 0x485 },
                new int[]{ 0x48D, 0x490, 0x48E, 0x491 },
                new int[]{ 0x48F, 0x494, 0x484, 0x497 },
                new int[]{ 0x489, 0x47F, 0x482, 0x47E }
            };
 
        private static Item CreateCloth( int type )
        {
            if ( type >= 0 && type < m_ClothHues.Length )
            {
                UncutCloth cloth = new UncutCloth( 100 );
                cloth.Hue = m_ClothHues[type][Utility.Random( m_ClothHues[type].Length )];
                return cloth;
            }
 
            throw new InvalidOperationException();
        }
 
        private static int[] m_SandalHues = new int[]
            {
                0x489, 0x47F, 0x482,
                0x47E, 0x48F, 0x494,
                0x484, 0x497
            };
 
        private static Item CreateSandals( int type )
        {
            return new Sandals( m_SandalHues[Utility.Random( m_SandalHues.Length )] );
        }
 
        private static Item CreateStretchedHide( int type )
        {
            switch ( Utility.Random( 4 ) )
            {
                default:
                case 0:    return new SmallStretchedHideEastDeed();
                case 1: return new SmallStretchedHideSouthDeed();
                case 2: return new MediumStretchedHideEastDeed();
                case 3: return new MediumStretchedHideSouthDeed();
            }
        }
 
        private static Item CreateTapestry( int type )
        {
            switch ( Utility.Random( 4 ) )
            {
                default:
                case 0:    return new LightFlowerTapestryEastDeed();
                case 1: return new LightFlowerTapestrySouthDeed();
                case 2: return new DarkFlowerTapestryEastDeed();
                case 3: return new DarkFlowerTapestrySouthDeed();
            }
        }
 
        private static Item CreateBearRug( int type )
        {
            switch ( Utility.Random( 4 ) )
            {
                default:
                case 0:    return new BrownBearRugEastDeed();
                case 1: return new BrownBearRugSouthDeed();
                case 2: return new PolarBearRugEastDeed();
                case 3: return new PolarBearRugSouthDeed();
            }
        }
 
        private static Item CreateRunicKit( int type )
        {
            //daat99 OWLTR start - bod reward
            if ( type >= 1 && type <= 10 )
                return new RunicSewingKit( CraftResource.RegularLeather + type, 100 - (type*5) );
            //daat99 OWLTR end - bod reward
 
            throw new InvalidOperationException();
        }
 
        private static Item CreatePowerScroll( int type )
        {
            if ( type == 5 || type == 10 || type == 15 || type == 20 )
                return new PowerScroll( SkillName.Tailoring, 100 + type );
 
            throw new InvalidOperationException();
        }
 
        private static Item CreateCBD( int type )
        {
            return new ClothingBlessDeed();
        }
        #endregion
 
        public static readonly TailorRewardCalculator Instance = new TailorRewardCalculator();
 
        public override int ComputePoints( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type )
        {
            int points = 0;
 
            if ( quantity == 10 )
                points += 10;
            else if ( quantity == 15 )
                points += 25;
            else if ( quantity == 20 )
                points += 50;
 
            if ( exceptional )
                points += 100;
 
            if ( itemCount == 4 )
                points += 300;
            else if ( itemCount == 5 )
                points += 400;
            else if ( itemCount == 6 )
                points += 500;
            //daat99 OWLTR start - bod rewards
            if ( material >= BulkMaterialType.Spined && material <= BulkMaterialType.Ethereal )
                points += 50 + (50 * (material - BulkMaterialType.Spined));
            //daat99 OWLTR end - bod rewards
           
            return points;
        }
 
        //daat99 OWLTR start - gold reward
        private static int[][][] m_AosGoldTable = new int[][][]
            {
                    new int[][] // 1-part (regular)
                {
                    new int[]{ 100, 200, 300,  400,  500,  600,  700,  800,  900, 1000, 1100 },
                    new int[]{ 200, 400, 600,  800, 1000, 1200, 1400, 1600, 1800, 2000, 2200 },
                    new int[]{ 300, 600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300 }
                },
                new int[][] // 1-part (exceptional)
                {
                    new int[]{ 250, 500,  750, 1000, 1250, 1500, 1750, 2000,  2250, 2500, 2750 },
                    new int[]{ 350, 700, 1050, 1400, 1750, 2100, 2450, 2800,  3150, 3500, 3850 },
                    new int[]{ 450, 900, 1350, 1800, 2250, 2700, 3150, 3600,  4050, 4500, 4950 }
                },
                new int[][] // 4-part (regular)
                {
                    new int[]{ 2000, 4000,  6000,  8000, 10000, 12000, 14000, 16000, 18000, 20000, 22000 },
                    new int[]{ 3000, 6000,  9000, 12000, 15000, 18000, 21000, 24000, 27000, 30000, 33000 },
                    new int[]{ 4000, 8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000 }
                },
                new int[][] // 4-part (exceptional)
                {
                    new int[]{ 4000,  8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000 },
                    new int[]{ 6000, 12000, 18000, 24000, 30000, 36000, 42000, 48000, 54000, 60000, 66000 },
                    new int[]{ 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000 }
                },
                new int[][] // 5-part (regular)
                {
                    new int[]{ 4000,  8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000 },
                    new int[]{ 6000, 12000, 18000, 24000, 30000, 36000, 42000, 48000, 54000, 60000, 66000 },
                    new int[]{ 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000 }
                },
                new int[][] // 5-part (exceptional)
                {
                    new int[]{  7000, 14000, 21000, 28000, 35000, 42000,  49000,  56000,  63000,  70000,  77000 },
                    new int[]{ 10000, 20000, 30000, 40000, 50000, 60000,  70000,  80000,  90000, 100000, 110000 },
                    new int[]{ 15000, 30000, 45000, 60000, 75000, 90000, 105000, 120000, 135000, 150000, 165000 }
                },
                new int[][] // 6-part (regular)
                {
                    new int[]{  5000, 10000, 15000, 20000, 25000, 30000,  35000,  40000,  45000,  50000,  55000 },
                    new int[]{  7500, 15000, 22500, 30000, 37500, 45000,  52500,  60000,  67500,  75000,  82500 },
                    new int[]{ 10000, 20000, 30000, 40000, 50000, 60000,  70000,  80000,  90000, 100000, 110000 }
                },
                new int[][] // 6-part (exceptional)
                {
                    new int[]{ 10000, 20000, 30000, 40000,  50000,  60000,  70000,  80000,  90000, 100000, 110000 },
                    new int[]{ 15000, 30000, 45000, 60000,  75000,  90000, 105000, 120000, 135000, 150000, 165000 },
                    new int[]{ 20000, 40000, 60000, 80000, 100000, 120000, 140000, 160000, 180000, 200000, 220000 }
                }
            };
 
        private static int[][][] m_OldGoldTable = m_AosGoldTable;
        //daat99 OWLTR end - gold reward
 
        public override int ComputeGold( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type )
        {
            int[][][] goldTable = ( Core.AOS ? m_AosGoldTable : m_OldGoldTable );
 
            int typeIndex = (( itemCount == 6 ? 3 : itemCount == 5 ? 2 : itemCount == 4 ? 1 : 0 ) * 2) + (exceptional ? 1 : 0);
            int quanIndex = ( quantity == 20 ? 2 : quantity == 15 ? 1 : 0 );
            //daat99 OWLTR start - bod material
            int mtrlIndex = ( material >= BulkMaterialType.Spined && material <= BulkMaterialType.Ethereal ) ? 1 + (int)(material - BulkMaterialType.Spined) : 0;
            //daat99 OWLTR end - bod material
 
            int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
 
            int min = (gold * 9) / 10;
            int max = (gold * 10) / 9;
 
            return Utility.RandomMinMax( min, max );
        }
 
        public TailorRewardCalculator()
        {
            Groups = new RewardGroup[]
            //daat99 OWLTR start - bod reward
            {
                new RewardGroup(    0, new RewardItem( 1, Cloth, 0 ), new RewardItem( 1, ColoredLoom ) ),
                new RewardGroup(  50, new RewardItem( 1, Cloth, 1 ), new RewardItem( 1, ColoredLoom ) ),
                new RewardGroup(  100, new RewardItem( 1, Cloth, 2 ), new RewardItem( 1, Sandals ) ),
                new RewardGroup(  150, new RewardItem( 6, Cloth, 3 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(1,6) ), new RewardItem( 3, Sandals ) ),
                new RewardGroup(  200, new RewardItem( 2, Cloth, 4 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(1,6) ), new RewardItem( 2, Sandals ) ),
                new RewardGroup(  300, new RewardItem( 1, StretchedHide ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(1,6) ), new RewardItem( 1, ColoredScissors ) ),
                new RewardGroup(  350, new RewardItem( 1, RunicKit, 1 ), new RewardItem( 1, ColoredScissors ) ),
                new RewardGroup(  400, new RewardItem( 3, Tapestry ), new RewardItem( 1, SturdySewingKit ), new RewardItem( 1, ColoredScissors ) ),
                new RewardGroup(  450, new RewardItem( 1, BearRug ), new RewardItem( 1, SturdySewingKit ) ),
                new RewardGroup(  500, new RewardItem( 1, Deco, Utility.Random(4) ), new RewardItem( 1, MastersKnife ) ),
                new RewardGroup(  550, new RewardItem( 1, ClothingBlessDeed ), new RewardItem( 1, Deco, Utility.Random(4) ), new RewardItem( 1, MastersKnife ) ),
                new RewardGroup(  600, new RewardItem( 1, RunicKit, 2 ), new RewardItem( 1, MastersKnife ) ),
                new RewardGroup(  650, new RewardItem( 1, RunicKit, 2 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  700, new RewardItem( 1, RunicKit, 3 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  750, new RewardItem( 1, RunicKit, 3 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ), new RewardItem( 1, GargoylesKnife ) ),
                new RewardGroup(  800, new RewardItem( 1, RunicKit, 4 ), new RewardItem( 1, ChargedDyeTub ), new RewardItem( 1, GargoylesKnife ) ),
                new RewardGroup(  850, new RewardItem( 1, RunicKit, 4 ), new RewardItem( 1, ChargedDyeTub ) ),
                new RewardGroup(  900, new RewardItem( 1, RunicKit, 5 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup(  950, new RewardItem( 1, RunicKit, 6 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1000, new RewardItem( 1, RunicKit, 7 ), new RewardItem( 1, TailorsProtector ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1050, new RewardItem( 1, RunicKit, 8 ), new RewardItem( 1, TailorsProtector ) ),
                new RewardGroup( 1100, new RewardItem( 1, RunicKit, 9 ), new RewardItem( 1, BagOfResources ) ),
                new RewardGroup( 1150, new RewardItem( 1, RunicKit, 10 ), new RewardItem( 1, BagOfResources ) ),
            };
            //daat99 OWLTR end - bod reward
        }
    }
}
 

rathraven

Traveler
it happens when player turns in a completed bod large 20....he can turn in 10s no problems...but the 20s is when the crash happens
 

daat99

Moderator
Staff member
Please add the following code before the "gold = goldTable[..][..][..]" line:
Code:
Console.Write("Params[{0},{1},{2}], ", typeIndex, quanIndex, mtrlIndex);
typeIndex = typeIndex >= goldTable.Length ? goldTable.Length -1 : typeIndex;
quanIndex = quanIndex >= goldTable[typeIndex].Length ? goldTable[typeIndex].Length -1 : quanIndex;
mtrlIndex = mtrlIndex >= goldTable[typeIndex][quanIndex].Length ? goldTable[typeIndex][quanIndex].Length -1 : mtrlIndex;
Console.Write("Fixed Params[{0},{1},{2}], ", typeIndex, quanIndex, mtrlIndex);
Console.WriteLine("goldTable[{0},{1},{2}]", goldTable.Length, goldTable[typeIndex].Length , goldTable[typeIndex][quanIndex].Length);
Let me know what happen in the console when your players try the same thing (it should fix the crash but it's not an official fix!).

Also, if you can tell if it happens using specific resources or using all the resources it'll help a lot.

NOTE:
You may need to change the word "Length" with the word "Count" all over this code snippet.
 

rathraven

Traveler
first one I turned in was a 20 large regular iron Chainmail armor
console msg:
Params[5,2,0], Fixed Params[5,2,0], goldTable[14,3,14]

second one I turned in was a 20 large verite ringmail armor
console msg:
Params[3,2,7], Fixed Params[3,2,7], goldTable[14,3,14]
 

rathraven

Traveler
just attempted to turnin 20 large smith regular iron weapons

and it crashed again...
Exception:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at Server.Engines.BulkOrders.SmithRewardCalculator.ComputeGold(Int32 quantity, Boolean exceptional, BulkMaterialType material, Int32 itemCount, Type type) in c:\2.3\Scripts\Engines\BulkOrders\Rewards.cs:line 511
at Server.Engines.BulkOrders.RewardCalculator.ComputeGold(LargeBOD bod) in c:\2.3\Scripts\Engines\BulkOrders\Rewards.cs:line 145
at Server.Engines.BulkOrders.LargeSmithBOD.ComputeGold() in c:\2.3\Scripts\Engines\BulkOrders\LargeSmithBOD.cs:line 40
at Server.Engines.BulkOrders.LargeBOD.GetRewards(Item& reward, Int32& gold, Int32& fame) in c:\2.3\Scripts\Engines\BulkOrders\LargeBOD.cs:line 50
at Server.Mobiles.BaseVendor.OnDragDrop(Mobile from, Item dropped) in c:\2.3\Scripts\Mobiles\Vendors\BaseVendor.cs:line 786
at Server.Item.DropToMobile(Mobile from, Mobile target, Point3D p)
at Server.Mobile.Drop(Mobile to, Point3D loc)
at Server.Network.PacketHandlers.DropReq6017(NetState state, PacketReader pvSrc)
at Server.Network.MessagePump.HandleReceive(NetState ns)
at Server.Network.MessagePump.Slice()
at Server.Core.Main(String[] args)
 

rathraven

Traveler
line 511 is
int gold = goldTable[typeIndex][quanIndex][mtrlIndex];

reward.cs
Code:
using System;
using Server;
using Server.Items;
 
namespace Server.Engines.BulkOrders
{
    public delegate Item ConstructCallback( int type );
 
    public sealed class RewardType
    {
        private int m_Points;
        private Type[] m_Types;
 
        public int Points{ get{ return m_Points; } }
        public Type[] Types{ get{ return m_Types; } }
 
        public RewardType( int points, params Type[] types )
        {
            m_Points = points;
            m_Types = types;
        }
 
        public bool Contains( Type type )
        {
            for ( int i = 0; i < m_Types.Length; ++i )
            {
                if ( m_Types[i] == type )
                    return true;
            }
 
            return false;
        }
    }
 
    public sealed class RewardItem
    {
        private int m_Weight;
        private ConstructCallback m_Constructor;
        private int m_Type;
 
        public int Weight{ get{ return m_Weight; } }
        public ConstructCallback Constructor{ get{ return m_Constructor; } }
        public int Type{ get{ return m_Type; } }
 
        public RewardItem( int weight, ConstructCallback constructor ) : this( weight, constructor, 0 )
        {
        }
 
        public RewardItem( int weight, ConstructCallback constructor, int type )
        {
            m_Weight = weight;
            m_Constructor = constructor;
            m_Type = type;
        }
 
        public Item Construct()
        {
            try{ return m_Constructor( m_Type ); }
            catch{ return null; }
        }
    }
 
    public sealed class RewardGroup
    {
        private int m_Points;
        private RewardItem[] m_Items;
 
        public int Points{ get{ return m_Points; } }
        public RewardItem[] Items{ get{ return m_Items; } }
 
        public RewardGroup( int points, params RewardItem[] items )
        {
            m_Points = points;
            m_Items = items;
        }
 
        public RewardItem AcquireItem()
        {
            if ( m_Items.Length == 0 )
                return null;
            else if ( m_Items.Length == 1 )
                return m_Items[0];
 
            int totalWeight = 0;
 
            for ( int i = 0; i < m_Items.Length; ++i )
                totalWeight += m_Items[i].Weight;
 
            int randomWeight = Utility.Random( totalWeight );
 
            for ( int i = 0; i < m_Items.Length; ++i )
            {
                RewardItem item = m_Items[i];
 
                if ( randomWeight < item.Weight )
                    return item;
 
                randomWeight -= item.Weight;
            }
 
            return null;
        }
    }
 
    public abstract class RewardCalculator
    {
        private RewardGroup[] m_Groups;
 
        public RewardGroup[] Groups{ get{ return m_Groups; } set{ m_Groups = value; } }
 
        public abstract int ComputePoints( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type );
        public abstract int ComputeGold( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type );
 
        public virtual int ComputeFame( SmallBOD bod )
        {
            int points = ComputePoints( bod ) / 50;
 
            return points * points;
        }
 
        public virtual int ComputeFame( LargeBOD bod )
        {
            int points = ComputePoints( bod ) / 50;
 
            return points * points;
        }
 
        public virtual int ComputePoints( SmallBOD bod )
        {
            return ComputePoints( bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type );
        }
 
        public virtual int ComputePoints( LargeBOD bod )
        {
            return ComputePoints( bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length, bod.Entries[0].Details.Type );
        }
 
        public virtual int ComputeGold( SmallBOD bod )
        {
            return ComputeGold( bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type );
        }
 
        public virtual int ComputeGold( LargeBOD bod )
        {
            return ComputeGold( bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length, bod.Entries[0].Details.Type );
        }
 
        public virtual RewardGroup LookupRewards( int points )
        {
            for ( int i = m_Groups.Length - 1; i >= 1; --i )
            {
                RewardGroup group = m_Groups[i];
 
                if ( points >= group.Points )
                    return group;
            }
 
            return m_Groups[0];
        }
 
        public virtual int LookupTypePoints( RewardType[] types, Type type )
        {
            for ( int i = 0; i < types.Length; ++i )
            {
                if ( types[i].Contains( type ) )
                    return types[i].Points;
            }
 
            return 0;
        }
 
        public RewardCalculator()
        {
        }
    }
 
    public sealed class SmithRewardCalculator : RewardCalculator
    {
        #region Constructors
        private static readonly ConstructCallback SturdyShovel = new ConstructCallback( CreateSturdyShovel );
        private static readonly ConstructCallback SturdyPickaxe = new ConstructCallback( CreateSturdyPickaxe );
        private static readonly ConstructCallback MiningGloves = new ConstructCallback( CreateMiningGloves );
        private static readonly ConstructCallback GargoylesPickaxe = new ConstructCallback( CreateGargoylesPickaxe );
        private static readonly ConstructCallback ProspectorsTool = new ConstructCallback( CreateProspectorsTool );
        private static readonly ConstructCallback PowderOfTemperament = new ConstructCallback( CreatePowderOfTemperament );
        private static readonly ConstructCallback RunicHammer = new ConstructCallback( CreateRunicHammer );
        private static readonly ConstructCallback PowerScroll = new ConstructCallback( CreatePowerScroll );
        private static readonly ConstructCallback ColoredAnvil = new ConstructCallback( CreateColoredAnvil );
        private static readonly ConstructCallback AncientHammer = new ConstructCallback( CreateAncientHammer );
        //daat99 OWLTR start - bod rewards
        private static readonly ConstructCallback Deco = new ConstructCallback( CreateDeco );
        private static readonly ConstructCallback SturdySmithHammer = new ConstructCallback( CreateSturdySmithHammer );
        private static readonly ConstructCallback SmithersProtector = new ConstructCallback( CreateSmithersProtector );
        private static readonly ConstructCallback SharpeningBlade = new ConstructCallback( CreateSharpeningBlade );
        private static readonly ConstructCallback ColoredForgeDeed = new ConstructCallback( CreateColoredForgeDeed );
        private static readonly ConstructCallback ChargedDyeTub = new ConstructCallback( CreateChargedDyeTub );
        private static readonly ConstructCallback BagOfResources = new ConstructCallback( CreateBagOfResources );
        private static readonly ConstructCallback ArmorOfCrafting = new ConstructCallback( CreateArmorOfCrafting );
 
        private static Item CreateDeco( int type )
        {
            switch (type)
            {
                case 0: default: return new Deco( 5053, "Chainmail Tunic" );
                case 1: return new Deco( 5052, "chainmail Leggings" );
                case 2: return new Deco( 5402, "Decorative Armor" );
                case 3: return new Deco( 5509, "Decorative Shield and Sword" );
                case 4: return new Deco( 7110, "Decorative Scale Shield" );
                case 5: return new Deco( 10324, "Sword Display" );
            }
        }
       
        private static Item CreateSturdySmithHammer( int type )
        {
            return new SturdySmithHammer();
        }
       
        private static Item CreateSmithersProtector( int type )
        {
            return new SmithersProtector();
        }
       
        private static Item CreateSharpeningBlade( int type )
        {
            return new SharpeningBlade();
        }
       
        private static Item CreateColoredForgeDeed( int type )
        {
            return new ColoredForgeDeed( CraftResources.GetHue( (CraftResource)Utility.RandomMinMax( (int)CraftResource.DullCopper, (int)CraftResource.Platinum ) ) );
        }
 
        private static Item CreateChargedDyeTub( int type )
        {
            return new ChargedDyeTub( 10, type );
        }
 
 
        private static Item CreateBagOfResources( int type )
        {
            return new BagOfResources();
        }
       
        private static Item CreateArmorOfCrafting( int type )
        {
            switch (type)
            {
                case 1: default: return new ArmorOfCrafting( 1, 5062, Utility.Random(2)); //gloves
                case 2: return new ArmorOfCrafting( 1, 7609, Utility.Random(2)); //cap
                case 3: return new ArmorOfCrafting( 1, 5068, Utility.Random(2)); //tunic
                case 4: return new ArmorOfCrafting( 1, 5063, Utility.Random(2)); //gorget
                case 5: return new ArmorOfCrafting( 1, 5069, Utility.Random(2)); //arms
                case 6: return new ArmorOfCrafting( 1, 5067, Utility.Random(2)); //leggings
                case 7: return new ArmorOfCrafting( 3, 5062, Utility.Random(2)); //gloves
                case 8: return new ArmorOfCrafting( 3, 7609, Utility.Random(2)); //cap
                case 9: return new ArmorOfCrafting( 3, 5068, Utility.Random(2)); //tunic
                case 10: return new ArmorOfCrafting( 3, 5063, Utility.Random(2)); //gorget
                case 11: return new ArmorOfCrafting( 3, 5069, Utility.Random(2)); //arms
                case 12: return new ArmorOfCrafting( 3, 5067, Utility.Random(2)); //leggings
                case 13: return new ArmorOfCrafting( 5, 5062, Utility.Random(2)); //gloves
                case 14: return new ArmorOfCrafting( 5, 7609, Utility.Random(2)); //cap
                case 15: return new ArmorOfCrafting( 5, 5068, Utility.Random(2)); //tunic
                case 16: return new ArmorOfCrafting( 5, 5063, Utility.Random(2)); //gorget
                case 17: return new ArmorOfCrafting( 5, 5069, Utility.Random(2)); //arms
                case 18: return new ArmorOfCrafting( 5, 5067, Utility.Random(2)); //leggings
            }
        }
        //daat99 OWLTR end - bod rewards
 
        private static Item CreateSturdyShovel( int type )
        {
            return new SturdyShovel();
        }
 
        private static Item CreateSturdyPickaxe( int type )
        {
            return new SturdyPickaxe();
        }
 
        private static Item CreateMiningGloves( int type )
        {
            if ( type == 1 )
                return new LeatherGlovesOfMining( 1 );
            else if ( type == 3 )
                return new StuddedGlovesOfMining( 3 );
            else if ( type == 5 )
                return new RingmailGlovesOfMining( 5 );
 
            throw new InvalidOperationException();
        }
 
        private static Item CreateGargoylesPickaxe( int type )
        {
            return new GargoylesPickaxe();
        }
 
        private static Item CreateProspectorsTool( int type )
        {
            return new ProspectorsTool();
        }
 
        private static Item CreatePowderOfTemperament( int type )
        {
            return new PowderOfTemperament();
        }
 
        private static Item CreateRunicHammer( int type )
        {
            if ( type >= 1 && type <= 8 )
                return new RunicHammer( CraftResource.Iron + type, Core.AOS ? ( 55 - (type*5) ) : 50 );
 
            throw new InvalidOperationException();
        }
 
        private static Item CreatePowerScroll( int type )
        {
            if ( type == 5 || type == 10 || type == 15 || type == 20 )
                return new PowerScroll( SkillName.Blacksmith, 100 + type );
 
            throw new InvalidOperationException();
        }
 
        private static Item CreateColoredAnvil( int type )
        {
            // Generate an anvil deed, not an actual anvil.
            //return new ColoredAnvilDeed();
 
            return new ColoredAnvil();
        }
 
        private static Item CreateAncientHammer( int type )
        {
            if ( type == 10 || type == 15 || type == 30 || type == 60 )
                return new AncientSmithyHammer( type );
 
            throw new InvalidOperationException();
        }
        #endregion
 
        public static readonly SmithRewardCalculator Instance = new SmithRewardCalculator();
 
        private RewardType[] m_Types = new RewardType[]
            {
                // Armors
                new RewardType( 200, typeof( RingmailGloves ), typeof( RingmailChest ), typeof( RingmailArms ), typeof( RingmailLegs ) ),
                new RewardType( 300, typeof( ChainCoif ), typeof( ChainLegs ), typeof( ChainChest ) ),
                new RewardType( 400, typeof( PlateArms ), typeof( PlateLegs ), typeof( PlateHelm ), typeof( PlateGorget ), typeof( PlateGloves ), typeof( PlateChest ) ),
 
                // Weapons
                new RewardType( 200, typeof( Bardiche ), typeof( Halberd ) ),
                new RewardType( 300, typeof( Dagger ), typeof( ShortSpear ), typeof( Spear ), typeof( WarFork ), typeof( Kryss ) ),    //OSI put the dagger in there.  Odd, ain't it.
                new RewardType( 350, typeof( Axe ), typeof( BattleAxe ), typeof( DoubleAxe ), typeof( ExecutionersAxe ), typeof( LargeBattleAxe ), typeof( TwoHandedAxe ) ),
                new RewardType( 350, typeof( Broadsword ), typeof( Cutlass ), typeof( Katana ), typeof( Longsword ), typeof( Scimitar ), /*typeof( ThinLongsword ),*/ typeof( VikingSword ) ),
                new RewardType( 350, typeof( WarAxe ), typeof( HammerPick ), typeof( Mace ), typeof( Maul ), typeof( WarHammer ), typeof( WarMace ) )
            };
 
        public override int ComputePoints( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type )
        {
            int points = 0;
 
            if ( quantity == 10 )
                points += 10;
            else if ( quantity == 15 )
                points += 25;
            else if ( quantity == 20 )
                points += 50;
 
            if ( exceptional )
                points += 200;
 
            if ( itemCount > 1 )
                points += LookupTypePoints( m_Types, type );
 
            //daat99 OWLTR start - custom resources
            if ( material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Platinum )
            //daat99 OWLTR end - custom resources
                points += 200 + (50 * (material - BulkMaterialType.DullCopper));
 
            return points;
        }
 
        private static int[][][] m_GoldTable = new int[][][]
        {
            //daat99 OWLTR start - custom gold reward
            new int[][] // 1-part (regular)
            {
                new int[]{ 100, 200, 300,  400,  500,  600,  700,  800,  900, 1000, 1100, 1200, 1300, 1400 },
                new int[]{ 200, 400, 600,  800, 1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 2800 },
                new int[]{ 300, 600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300, 3600, 3900, 4200 }
            },
            new int[][] // 1-part (exceptional)
            {
                new int[]{ 250, 500,  750, 1000, 1250, 1500, 1750, 2000,  2250, 2500, 2750, 3000, 3250, 3500 },
                new int[]{ 350, 700, 1050, 1400, 1750, 2100, 2450, 2800,  3150, 3500, 3850, 4200, 4550, 4900 },
                new int[]{ 450, 900, 1350, 1800, 2250, 2700, 3150, 3600,  4050, 4500, 4950, 5400, 5850, 6300 }
            },
            new int[][] // Ringmail (regular)
            {
                new int[]{ 2000, 4000,  6000,  8000, 10000, 12000, 14000, 16000, 18000, 20000, 22000, 24000, 26000, 28000 },
                new int[]{ 3000, 6000,  9000, 12000, 15000, 18000, 21000, 24000, 27000, 30000, 33000, 36000, 39000, 42000 },
                new int[]{ 4000, 8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000, 48000, 52000, 56000 }
            },
            new int[][] // Ringmail (exceptional)
            {
                new int[]{ 4000,  8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000, 48000,  52000,  56000 },
                new int[]{ 6000, 12000, 18000, 24000, 30000, 36000, 42000, 48000, 54000, 60000, 66000, 72000,  78000,  84000 },
                new int[]{ 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000, 96000, 104000, 112000 }
            },
            new int[][] // Chainmail (regular)
            {
                new int[]{ 4000,  8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000, 48000,  52000,  56000 },
                new int[]{ 6000, 12000, 18000, 24000, 30000, 36000, 42000, 48000, 54000, 60000, 66000, 72000,  78000,  84000 },
                new int[]{ 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000, 96000, 104000, 112000 }
            },
            new int[][] // Chainmail (exceptional)
            {
                new int[]{  7000, 14000, 21000, 28000, 35000, 42000,  49000,  56000,  63000,  70000,  77000,  84000,  91000,  98000 },
                new int[]{ 10000, 20000, 30000, 40000, 50000, 60000,  70000,  80000,  90000, 100000, 110000, 120000, 130000, 140000 },
                new int[]{ 15000, 30000, 45000, 60000, 75000, 90000, 105000, 120000, 135000, 150000, 165000, 180000, 195000, 210000 }
            },
            new int[][] // Platemail (regular)
            {
                new int[]{  5000, 10000, 15000, 20000, 25000, 30000,  35000,  40000,  45000,  50000,  55000,  60000,  65000,  70000 },
                new int[]{  7500, 15000, 22500, 30000, 37500, 45000,  52500,  60000,  67500,  75000,  82500,  90000,  97500, 105000 },
                new int[]{ 10000, 20000, 30000, 40000, 50000, 60000,  70000,  80000,  90000, 100000, 110000, 120000, 130000, 140000 }
            },
            new int[][] // Platemail (exceptional)
            {
                new int[]{ 10000, 20000, 30000, 40000,  50000,  60000,  70000,  80000,  90000, 100000, 110000, 120000, 130000, 140000 },
                new int[]{ 15000, 30000, 45000, 60000,  75000,  90000, 105000, 120000, 135000, 150000, 165000, 180000, 195000, 210000 },
                new int[]{ 20000, 40000, 60000, 80000, 100000, 120000, 140000, 160000, 180000, 200000, 220000, 240000, 260000, 280000 }
            },
            new int[][] // 2-part weapons (regular)
            {
                new int[]{ 3000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 4500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 6000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 2-part weapons (exceptional)
            {
                new int[]{ 5000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 7500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 10000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 5-part weapons (regular)
            {
                new int[]{ 4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 6000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 8000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 5-part weapons (exceptional)
            {
                new int[]{ 7500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 11250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 15000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 6-part weapons (regular)
            {
                new int[]{ 4000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 6000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 10000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            },
            new int[][] // 6-part weapons (exceptional)
            {
                new int[]{ 7500, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 11250, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                new int[]{ 15000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
            }
            //daat99 OWLTR start - custom gold reward
        };
 
        private int ComputeType( Type type, int itemCount )
        {
            // Item count of 1 means it's a small BOD.
            if ( itemCount == 1 )
                return 0;
 
            int typeIdx;
 
            // Loop through the RewardTypes defined earlier and find the correct one.
            //daat99 OWLTR start - don't use magic numbers...
            for ( typeIdx = 0; typeIdx < m_Types.Length; ++typeIdx )
            //daat99 OWLTR end - don't use magic numbers...
            {
                if ( m_Types[typeIdx].Contains( type ) )
                    break;
            }
 
            //daat99 OWLTR start - custom bods
            //daat99 note: make it last 3 types, not specific index!
            // Types 5, 6 and 7 are Large Weapon BODs with the same rewards.
            if ( typeIdx > m_Types.Length-2 )
                typeIdx = m_Types.Length-2;
            //daat99 OWLTR end - custom bods
 
            return ( typeIdx + 1 ) * 2;
        }
        public override int ComputeGold( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type )
        {
            int[][][] goldTable = m_GoldTable;
 
            int typeIndex = ComputeType( type, itemCount );
            int quanIndex = ( quantity == 20 ? 2 : quantity == 15 ? 1 : 0 );
            //daat99 OWLTR start - custom resource
            int mtrlIndex = ( material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Platinum ) ? 1 + (int)(material - BulkMaterialType.DullCopper) : 0;
            //daat99 OWLTR end - custom resource
 
            if ( exceptional )
                typeIndex++;
 
            int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
//test changes
Console.Write("Params[{0},{1},{2}], ", typeIndex, quanIndex, mtrlIndex);
typeIndex = typeIndex >= goldTable.Length ? goldTable.Length -1 : typeIndex;
quanIndex = quanIndex >= goldTable[typeIndex].Length ? goldTable[typeIndex].Length -1 : quanIndex;
mtrlIndex = mtrlIndex >= goldTable[typeIndex][quanIndex].Length ? goldTable[typeIndex][quanIndex].Length -1 : mtrlIndex;
Console.Write("Fixed Params[{0},{1},{2}], ", typeIndex, quanIndex, mtrlIndex);
Console.WriteLine("goldTable[{0},{1},{2}]", goldTable.Length, goldTable[typeIndex].Length , goldTable[typeIndex][quanIndex].Length);
//end test changes
 
            int min = (gold * 9) / 10;
            int max = (gold * 10) / 9;
 
            return Utility.RandomMinMax( min, max );
        }
 
        public SmithRewardCalculator()
        {
            Groups = new RewardGroup[]
            {
                //daat99 OWLTR start - bod reward
                new RewardGroup(    0, new RewardItem( 1, SturdyShovel ), new RewardItem( 1, SturdySmithHammer ) ),
                new RewardGroup(  25, new RewardItem( 1, SturdyPickaxe ), new RewardItem( 1, SturdySmithHammer ) ),
                new RewardGroup(  50, new RewardItem( 90, SturdyShovel ), new RewardItem( 10, ArmorOfCrafting, Utility.RandomMinMax(1,6) ) ),
                new RewardGroup(  200, new RewardItem( 90, SturdyPickaxe ), new RewardItem( 10, ArmorOfCrafting, Utility.RandomMinMax(1,6) ) ),
                new RewardGroup(  400, new RewardItem( 90, ProspectorsTool ), new RewardItem( 10, ArmorOfCrafting, Utility.RandomMinMax(1,6) ) ),
                new RewardGroup(  450, new RewardItem( 2, PowderOfTemperament ), new RewardItem( 1, GargoylesPickaxe ), new RewardItem( 1, Deco, Utility.Random(6) ) ),
                new RewardGroup(  500, new RewardItem( 1, RunicHammer, 1 ), new RewardItem( 1, GargoylesPickaxe ), new RewardItem( 1, Deco, Utility.Random(6) ) ),
                new RewardGroup(  550, new RewardItem( 3, RunicHammer, 1 ), new RewardItem( 2, RunicHammer, 2 ) ),
                new RewardGroup(  600, new RewardItem( 1, RunicHammer, 2 ), new RewardItem( 1, ColoredForgeDeed ) ),
                new RewardGroup(  625, new RewardItem( 3, RunicHammer, 2 ), new RewardItem( 1, ColoredAnvil ) ),
                new RewardGroup(  650, new RewardItem( 1, RunicHammer, 3 ), new RewardItem( 1, Deco, Utility.Random(6) ) ),
                new RewardGroup(  675, new RewardItem( 1, ColoredAnvil ), new RewardItem( 3, RunicHammer, 3 ) ),
                new RewardGroup(  700, new RewardItem( 1, RunicHammer, 4 ), new RewardItem( 1, Deco, Utility.Random(6) ) ),
                new RewardGroup(  750, new RewardItem( 1, AncientHammer, 10 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  800, new RewardItem( 1, GargoylesPickaxe ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  850, new RewardItem( 1, AncientHammer, 15 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  900, new RewardItem( 1, RunicHammer, 5 ), new RewardItem( 1, ChargedDyeTub, Utility.RandomMinMax(1,2) ) ),
                new RewardGroup(  950, new RewardItem( 1, RunicHammer, 5 ), new RewardItem( 1, ChargedDyeTub, Utility.RandomMinMax(1,2) ) ),
                new RewardGroup( 1000, new RewardItem( 1, AncientHammer, 30 ), new RewardItem( 1, ChargedDyeTub, Utility.RandomMinMax(1,2) ) ),
                new RewardGroup( 1050, new RewardItem( 1, RunicHammer, 6 ), new RewardItem( 1, SmithersProtector ) ),
                new RewardGroup( 1100, new RewardItem( 1, AncientHammer, 60 ), new RewardItem( 1, SmithersProtector ) ),
                new RewardGroup( 1150, new RewardItem( 1, RunicHammer, 7 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1200, new RewardItem( 1, RunicHammer, 8 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1250, new RewardItem( 1, RunicHammer, 9 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1300, new RewardItem( 1, RunicHammer, 10 ), new RewardItem( 1, BagOfResources ) ),
                new RewardGroup( 1350, new RewardItem( 1, RunicHammer, 11 ), new RewardItem( 1, BagOfResources ) ),
                new RewardGroup( 1400, new RewardItem( 1, RunicHammer, 12 ), new RewardItem( 1, SharpeningBlade ) ),
                new RewardGroup( 1450, new RewardItem( 1, RunicHammer, 13 ), new RewardItem( 1, SharpeningBlade ) )
                //daat99 OWLTR end - bod reward
            };
        }
    }
 
    public sealed class TailorRewardCalculator : RewardCalculator
    {
        #region Constructors
        private static readonly ConstructCallback Cloth = new ConstructCallback( CreateCloth );
        private static readonly ConstructCallback Sandals = new ConstructCallback( CreateSandals );
        private static readonly ConstructCallback StretchedHide = new ConstructCallback( CreateStretchedHide );
        private static readonly ConstructCallback RunicKit = new ConstructCallback( CreateRunicKit );
        private static readonly ConstructCallback Tapestry = new ConstructCallback( CreateTapestry );
        private static readonly ConstructCallback PowerScroll = new ConstructCallback( CreatePowerScroll );
        private static readonly ConstructCallback BearRug = new ConstructCallback( CreateBearRug );
        private static readonly ConstructCallback ClothingBlessDeed = new ConstructCallback( CreateCBD );
        //daat99 OWLTR start - bod reward
        private static readonly ConstructCallback ArmorOfCrafting = new ConstructCallback( CreateArmorOfCrafting );
        private static readonly ConstructCallback TailorsProtector = new ConstructCallback( CreateTailorsProtector );
        private static readonly ConstructCallback SturdySewingKit = new ConstructCallback( CreateSturdySewingKit );
        private static readonly ConstructCallback MastersKnife = new ConstructCallback( CreateMastersKnife );
        private static readonly ConstructCallback GargoylesKnife = new ConstructCallback( CreateGargoylesKnife );
        private static readonly ConstructCallback ColoredScissors = new ConstructCallback( CreateColoredScissors );
        private static readonly ConstructCallback ColoredLoom = new ConstructCallback( CreateColoredLoom );
        private static readonly ConstructCallback ChargedDyeTub = new ConstructCallback( CreateChargedDyeTub );
        private static readonly ConstructCallback BagOfResources = new ConstructCallback( CreateBagOfResources );
        private static readonly ConstructCallback Deco = new ConstructCallback( CreateDeco );
       
        private static Item CreateArmorOfCrafting( int type )
        {
            switch (type)
            {
                case 1: default: return new ArmorOfCrafting( 1, 5062, 2 ); //gloves
                case 2: return new ArmorOfCrafting( 1, 7609, 2 ); //cap
                case 3: return new ArmorOfCrafting( 1, 5068, 2 ); //tunic
                case 4: return new ArmorOfCrafting( 1, 5063, 2 ); //gorget
                case 5: return new ArmorOfCrafting( 1, 5069, 2 ); //arms
                case 6: return new ArmorOfCrafting( 1, 5067, 2 ); //leggings
                case 7: return new ArmorOfCrafting( 3, 5062, 2 ); //gloves
                case 8: return new ArmorOfCrafting( 3, 7609, 2 ); //cap
                case 9: return new ArmorOfCrafting( 3, 5068, 2 ); //tunic
                case 10: return new ArmorOfCrafting( 3, 5063, 2 ); //gorget
                case 11: return new ArmorOfCrafting( 3, 5069, 2 ); //arms
                case 12: return new ArmorOfCrafting( 3, 5067, 2 ); //leggings
                case 13: return new ArmorOfCrafting( 5, 5062, 2 ); //gloves
                case 14: return new ArmorOfCrafting( 5, 7609, 2 ); //cap
                case 15: return new ArmorOfCrafting( 5, 5068, 2 ); //tunic
                case 16: return new ArmorOfCrafting( 5, 5063, 2 ); //gorget
                case 17: return new ArmorOfCrafting( 5, 5069, 2 ); //arms
                case 18: return new ArmorOfCrafting( 5, 5067, 2 ); //leggings
            }
        }
       
        private static Item CreateTailorsProtector( int type )
        {
            return new TailorsProtector();
        }
 
        private static Item CreateSturdySewingKit( int type )
        {
            return new SturdySewingKit();
        }
 
        private static Item CreateGargoylesKnife( int type )
        {
            return new GargoylesKnife();
        }
 
        private static Item CreateMastersKnife( int type )
        {
            return new MastersKnife();
        }
 
        private static Item CreateColoredScissors( int type )
        {
            return new ColoredScissors( CraftResources.GetHue( (CraftResource)Utility.RandomMinMax( (int)CraftResource.SpinedLeather, (int)CraftResource.EtherealLeather ) ), 25 );
        }
       
        private static Item CreateColoredLoom( int type )
        {
            if (Utility.Random(2) == 1)
                return new ColoredLoomSouthDeed( CraftResources.GetHue( (CraftResource)Utility.RandomMinMax( (int)CraftResource.SpinedLeather, (int)CraftResource.EtherealLeather ) ) );
            else
                return new ColoredLoomEastDeed( CraftResources.GetHue( (CraftResource)Utility.RandomMinMax( (int)CraftResource.SpinedLeather, (int)CraftResource.EtherealLeather ) ) );
        }
       
        private static Item CreateChargedDyeTub( int type )
        {
            return new ChargedDyeTub( 0 );
        }
       
        private static Item CreateBagOfResources( int type )
        {
            return new BagOfResources();
        }
 
        private static Item CreateDeco( int type )
        {
            switch (type)
            {
                case 0: default: return new Deco( 4054, "Tapestry" );
                case 1: return new Deco( 9036, "Rose of Trinsic" );
                case 2: return new Deco( 15721, "Deer Corspe" );
                case 3: return new Deco( 5610, "Banner" );
            }
        }
        //daat99 OWLTR end - bod reward
       
        private static int[][] m_ClothHues = new int[][]
            {
                new int[]{ 0x483, 0x48C, 0x488, 0x48A },
                new int[]{ 0x495, 0x48B, 0x486, 0x485 },
                new int[]{ 0x48D, 0x490, 0x48E, 0x491 },
                new int[]{ 0x48F, 0x494, 0x484, 0x497 },
                new int[]{ 0x489, 0x47F, 0x482, 0x47E }
            };
 
        private static Item CreateCloth( int type )
        {
            if ( type >= 0 && type < m_ClothHues.Length )
            {
                UncutCloth cloth = new UncutCloth( 100 );
                cloth.Hue = m_ClothHues[type][Utility.Random( m_ClothHues[type].Length )];
                return cloth;
            }
 
            throw new InvalidOperationException();
        }
 
        private static int[] m_SandalHues = new int[]
            {
                0x489, 0x47F, 0x482,
                0x47E, 0x48F, 0x494,
                0x484, 0x497
            };
 
        private static Item CreateSandals( int type )
        {
            return new Sandals( m_SandalHues[Utility.Random( m_SandalHues.Length )] );
        }
 
        private static Item CreateStretchedHide( int type )
        {
            switch ( Utility.Random( 4 ) )
            {
                default:
                case 0:    return new SmallStretchedHideEastDeed();
                case 1: return new SmallStretchedHideSouthDeed();
                case 2: return new MediumStretchedHideEastDeed();
                case 3: return new MediumStretchedHideSouthDeed();
            }
        }
 
        private static Item CreateTapestry( int type )
        {
            switch ( Utility.Random( 4 ) )
            {
                default:
                case 0:    return new LightFlowerTapestryEastDeed();
                case 1: return new LightFlowerTapestrySouthDeed();
                case 2: return new DarkFlowerTapestryEastDeed();
                case 3: return new DarkFlowerTapestrySouthDeed();
            }
        }
 
        private static Item CreateBearRug( int type )
        {
            switch ( Utility.Random( 4 ) )
            {
                default:
                case 0:    return new BrownBearRugEastDeed();
                case 1: return new BrownBearRugSouthDeed();
                case 2: return new PolarBearRugEastDeed();
                case 3: return new PolarBearRugSouthDeed();
            }
        }
 
        private static Item CreateRunicKit( int type )
        {
            //daat99 OWLTR start - bod reward
            if ( type >= 1 && type <= 10 )
                return new RunicSewingKit( CraftResource.RegularLeather + type, 100 - (type*5) );
            //daat99 OWLTR end - bod reward
 
            throw new InvalidOperationException();
        }
 
        private static Item CreatePowerScroll( int type )
        {
            if ( type == 5 || type == 10 || type == 15 || type == 20 )
                return new PowerScroll( SkillName.Tailoring, 100 + type );
 
            throw new InvalidOperationException();
        }
 
        private static Item CreateCBD( int type )
        {
            return new ClothingBlessDeed();
        }
        #endregion
 
        public static readonly TailorRewardCalculator Instance = new TailorRewardCalculator();
 
        public override int ComputePoints( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type )
        {
            int points = 0;
 
            if ( quantity == 10 )
                points += 10;
            else if ( quantity == 15 )
                points += 25;
            else if ( quantity == 20 )
                points += 50;
 
            if ( exceptional )
                points += 100;
 
            if ( itemCount == 4 )
                points += 300;
            else if ( itemCount == 5 )
                points += 400;
            else if ( itemCount == 6 )
                points += 500;
            //daat99 OWLTR start - bod rewards
            if ( material >= BulkMaterialType.Spined && material <= BulkMaterialType.Ethereal )
                points += 50 + (50 * (material - BulkMaterialType.Spined));
            //daat99 OWLTR end - bod rewards
           
            return points;
        }
 
        //daat99 OWLTR start - gold reward
        private static int[][][] m_AosGoldTable = new int[][][]
            {
                    new int[][] // 1-part (regular)
                {
                    new int[]{ 100, 200, 300,  400,  500,  600,  700,  800,  900, 1000, 1100 },
                    new int[]{ 200, 400, 600,  800, 1000, 1200, 1400, 1600, 1800, 2000, 2200 },
                    new int[]{ 300, 600, 900, 1200, 1500, 1800, 2100, 2400, 2700, 3000, 3300 }
                },
                new int[][] // 1-part (exceptional)
                {
                    new int[]{ 250, 500,  750, 1000, 1250, 1500, 1750, 2000,  2250, 2500, 2750 },
                    new int[]{ 350, 700, 1050, 1400, 1750, 2100, 2450, 2800,  3150, 3500, 3850 },
                    new int[]{ 450, 900, 1350, 1800, 2250, 2700, 3150, 3600,  4050, 4500, 4950 }
                },
                new int[][] // 4-part (regular)
                {
                    new int[]{ 2000, 4000,  6000,  8000, 10000, 12000, 14000, 16000, 18000, 20000, 22000 },
                    new int[]{ 3000, 6000,  9000, 12000, 15000, 18000, 21000, 24000, 27000, 30000, 33000 },
                    new int[]{ 4000, 8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000 }
                },
                new int[][] // 4-part (exceptional)
                {
                    new int[]{ 4000,  8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000 },
                    new int[]{ 6000, 12000, 18000, 24000, 30000, 36000, 42000, 48000, 54000, 60000, 66000 },
                    new int[]{ 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000 }
                },
                new int[][] // 5-part (regular)
                {
                    new int[]{ 4000,  8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000 },
                    new int[]{ 6000, 12000, 18000, 24000, 30000, 36000, 42000, 48000, 54000, 60000, 66000 },
                    new int[]{ 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000 }
                },
                new int[][] // 5-part (exceptional)
                {
                    new int[]{  7000, 14000, 21000, 28000, 35000, 42000,  49000,  56000,  63000,  70000,  77000 },
                    new int[]{ 10000, 20000, 30000, 40000, 50000, 60000,  70000,  80000,  90000, 100000, 110000 },
                    new int[]{ 15000, 30000, 45000, 60000, 75000, 90000, 105000, 120000, 135000, 150000, 165000 }
                },
                new int[][] // 6-part (regular)
                {
                    new int[]{  5000, 10000, 15000, 20000, 25000, 30000,  35000,  40000,  45000,  50000,  55000 },
                    new int[]{  7500, 15000, 22500, 30000, 37500, 45000,  52500,  60000,  67500,  75000,  82500 },
                    new int[]{ 10000, 20000, 30000, 40000, 50000, 60000,  70000,  80000,  90000, 100000, 110000 }
                },
                new int[][] // 6-part (exceptional)
                {
                    new int[]{ 10000, 20000, 30000, 40000,  50000,  60000,  70000,  80000,  90000, 100000, 110000 },
                    new int[]{ 15000, 30000, 45000, 60000,  75000,  90000, 105000, 120000, 135000, 150000, 165000 },
                    new int[]{ 20000, 40000, 60000, 80000, 100000, 120000, 140000, 160000, 180000, 200000, 220000 }
                }
            };
 
        private static int[][][] m_OldGoldTable = m_AosGoldTable;
        //daat99 OWLTR end - gold reward
 
        public override int ComputeGold( int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type )
        {
            int[][][] goldTable = ( Core.AOS ? m_AosGoldTable : m_OldGoldTable );
 
            int typeIndex = (( itemCount == 6 ? 3 : itemCount == 5 ? 2 : itemCount == 4 ? 1 : 0 ) * 2) + (exceptional ? 1 : 0);
            int quanIndex = ( quantity == 20 ? 2 : quantity == 15 ? 1 : 0 );
            //daat99 OWLTR start - bod material
            int mtrlIndex = ( material >= BulkMaterialType.Spined && material <= BulkMaterialType.Ethereal ) ? 1 + (int)(material - BulkMaterialType.Spined) : 0;
            //daat99 OWLTR end - bod material
 
            int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
 
            int min = (gold * 9) / 10;
            int max = (gold * 10) / 9;
 
            return Utility.RandomMinMax( min, max );
        }
 
        public TailorRewardCalculator()
        {
            Groups = new RewardGroup[]
            //daat99 OWLTR start - bod reward
            {
                new RewardGroup(    0, new RewardItem( 1, Cloth, 0 ), new RewardItem( 1, ColoredLoom ) ),
                new RewardGroup(  50, new RewardItem( 1, Cloth, 1 ), new RewardItem( 1, ColoredLoom ) ),
                new RewardGroup(  100, new RewardItem( 1, Cloth, 2 ), new RewardItem( 1, Sandals ) ),
                new RewardGroup(  150, new RewardItem( 6, Cloth, 3 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(1,6) ), new RewardItem( 3, Sandals ) ),
                new RewardGroup(  200, new RewardItem( 2, Cloth, 4 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(1,6) ), new RewardItem( 2, Sandals ) ),
                new RewardGroup(  300, new RewardItem( 1, StretchedHide ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(1,6) ), new RewardItem( 1, ColoredScissors ) ),
                new RewardGroup(  350, new RewardItem( 1, RunicKit, 1 ), new RewardItem( 1, ColoredScissors ) ),
                new RewardGroup(  400, new RewardItem( 3, Tapestry ), new RewardItem( 1, SturdySewingKit ), new RewardItem( 1, ColoredScissors ) ),
                new RewardGroup(  450, new RewardItem( 1, BearRug ), new RewardItem( 1, SturdySewingKit ) ),
                new RewardGroup(  500, new RewardItem( 1, Deco, Utility.Random(4) ), new RewardItem( 1, MastersKnife ) ),
                new RewardGroup(  550, new RewardItem( 1, ClothingBlessDeed ), new RewardItem( 1, Deco, Utility.Random(4) ), new RewardItem( 1, MastersKnife ) ),
                new RewardGroup(  600, new RewardItem( 1, RunicKit, 2 ), new RewardItem( 1, MastersKnife ) ),
                new RewardGroup(  650, new RewardItem( 1, RunicKit, 2 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  700, new RewardItem( 1, RunicKit, 3 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ) ),
                new RewardGroup(  750, new RewardItem( 1, RunicKit, 3 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(7,12) ), new RewardItem( 1, GargoylesKnife ) ),
                new RewardGroup(  800, new RewardItem( 1, RunicKit, 4 ), new RewardItem( 1, ChargedDyeTub ), new RewardItem( 1, GargoylesKnife ) ),
                new RewardGroup(  850, new RewardItem( 1, RunicKit, 4 ), new RewardItem( 1, ChargedDyeTub ) ),
                new RewardGroup(  900, new RewardItem( 1, RunicKit, 5 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup(  950, new RewardItem( 1, RunicKit, 6 ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1000, new RewardItem( 1, RunicKit, 7 ), new RewardItem( 1, TailorsProtector ), new RewardItem( 1, ArmorOfCrafting, Utility.RandomMinMax(13,18) ) ),
                new RewardGroup( 1050, new RewardItem( 1, RunicKit, 8 ), new RewardItem( 1, TailorsProtector ) ),
                new RewardGroup( 1100, new RewardItem( 1, RunicKit, 9 ), new RewardItem( 1, BagOfResources ) ),
                new RewardGroup( 1150, new RewardItem( 1, RunicKit, 10 ), new RewardItem( 1, BagOfResources ) ),
            };
            //daat99 OWLTR end - bod reward
        }
    }
}
 

rathraven

Traveler
largesmithbod.cs
Code:
using System;
using System.Collections;
using Server;
using Server.Items;
using Mat = Server.Engines.BulkOrders.BulkMaterialType;
using System.Collections.Generic;
 
namespace Server.Engines.BulkOrders
{
    [TypeAlias( "Scripts.Engines.BulkOrders.LargeSmithBOD" )]
    public class LargeSmithBOD : LargeBOD
    {
        public static double[] m_BlacksmithMaterialChances = new double[]
            {
                //daat99 OWLTR start - custom resources
                0.120, // None
                0.100, // Dull Copper
                0.090, // Shadow Iron
                0.090, // Copper
                0.080, // Bronze
                0.080, // Gold
                0.070, // Agapite
                0.070, // Verite
                0.060, // Valorite
                0.060, // Blaze
                0.050, // Ice
                0.050, // Toxic
                0.040, // Electrum
                0.040  // Platinum
                //daat99 OWLTR end - custom resources
            };
 
        public override int ComputeFame()
        {
            return SmithRewardCalculator.Instance.ComputeFame( this );
        }
 
        public override int ComputeGold()
        {
            return SmithRewardCalculator.Instance.ComputeGold( this );
        }
 
        [Constructable]
        public LargeSmithBOD()
        {
            LargeBulkEntry[] entries;
            bool useMaterials = true;
           
            int rand = Utility.Random( 8 );
 
            switch ( rand )
            {
                default:
                case  0: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeRing );      break;
                case  1: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargePlate );    break;
                case  2: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeChain );    break;
                case  3: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeAxes );        break;
                case  4: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeFencing );    break;
                case  5: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeMaces );    break;
                case  6: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargePolearms );    break;
                case  7: entries = LargeBulkEntry.ConvertEntries( this, LargeBulkEntry.LargeSwords );    break;
            }
           
            if( rand > 2 && rand < 8 )
                useMaterials = false;
 
            int hue = 0x44E;
            int amountMax = Utility.RandomList( 10, 15, 20, 20 );
            bool reqExceptional = ( 0.825 > Utility.RandomDouble() );
 
            BulkMaterialType material;
 
            if ( useMaterials )
                material = GetRandomMaterial( BulkMaterialType.DullCopper, m_BlacksmithMaterialChances );
            else
                material = BulkMaterialType.None;
 
            this.Hue = hue;
            this.AmountMax = amountMax;
            this.Entries = entries;
            this.RequireExceptional = reqExceptional;
            this.Material = material;
        }
 
        public LargeSmithBOD( int amountMax, bool reqExceptional, BulkMaterialType mat, LargeBulkEntry[] entries )
        {
            this.Hue = 0x44E;
            this.AmountMax = amountMax;
            this.Entries = entries;
            this.RequireExceptional = reqExceptional;
            this.Material = mat;
        }
 
        public override List<Item> ComputeRewards( bool full )
        {
            List<Item> list = new List<Item>();
 
            RewardGroup rewardGroup = SmithRewardCalculator.Instance.LookupRewards( SmithRewardCalculator.Instance.ComputePoints( this ) );
 
            if ( rewardGroup != null )
            {
                if ( full )
                {
                    for ( int i = 0; i < rewardGroup.Items.Length; ++i )
                    {
                        Item item = rewardGroup.Items[i].Construct();
 
                        if ( item != null )
                            list.Add( item );
                    }
                }
                else
                {
                    RewardItem rewardItem = rewardGroup.AcquireItem();
 
                    if ( rewardItem != null )
                    {
                        Item item = rewardItem.Construct();
 
                        if ( item != null )
                            list.Add( item );
                    }
                }
            }
 
            return list;
        }
 
        public LargeSmithBOD( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
        }
    }
}

largebod.cs
Code:
using System;
using System.Collections;
using Server;
using Server.Items;
using System.Collections.Generic;
 
namespace Server.Engines.BulkOrders
{
    [TypeAlias( "Scripts.Engines.BulkOrders.LargeBOD" )]
    public abstract class LargeBOD : Item
    {
        private int m_AmountMax;
        private bool m_RequireExceptional;
        private BulkMaterialType m_Material;
        private LargeBulkEntry[] m_Entries;
 
        [CommandProperty( AccessLevel.GameMaster )]
        public int AmountMax{ get{ return m_AmountMax; } set{ m_AmountMax = value; InvalidateProperties(); } }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool RequireExceptional{ get{ return m_RequireExceptional; } set{ m_RequireExceptional = value; InvalidateProperties(); } }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public BulkMaterialType Material{ get{ return m_Material; } set{ m_Material = value; InvalidateProperties(); } }
 
        public LargeBulkEntry[] Entries{ get{ return m_Entries; } set{ m_Entries = value; InvalidateProperties(); } }
 
        [CommandProperty( AccessLevel.GameMaster )]
        public bool Complete
        {
            get
            {
                for ( int i = 0; i < m_Entries.Length; ++i )
                {
                    if ( m_Entries[i].Amount < m_AmountMax )
                        return false;
                }
 
                return true;
            }
        }
 
        public abstract List<Item> ComputeRewards( bool full );
        public abstract int ComputeGold();
        public abstract int ComputeFame();
 
        public virtual void GetRewards( out Item reward, out int gold, out int fame )
        {
            reward = null;
            gold = ComputeGold();
            fame = ComputeFame();
 
            List<Item> rewards = ComputeRewards( false );
 
            if ( rewards.Count > 0 )
            {
                reward = rewards[Utility.Random( rewards.Count )];
 
                for ( int i = 0; i < rewards.Count; ++i )
                {
                    if ( rewards[i] != reward )
                        rewards[i].Delete();
                }
            }
        }
 
        public static BulkMaterialType GetRandomMaterial( BulkMaterialType start, double[] chances )
        {
            double random = Utility.RandomDouble();
 
            for ( int i = 0; i < chances.Length; ++i )
            {
                if ( random < chances[i] )
                    return ( i == 0 ? BulkMaterialType.None : start + (i - 1) );
 
                random -= chances[i];
            }
 
            return BulkMaterialType.None;
        }
 
        public override int LabelNumber{ get{ return 1045151; } } // a bulk order deed
 
        public LargeBOD( int hue, int amountMax, bool requireExeptional, BulkMaterialType material, LargeBulkEntry[] entries ) : base( Core.AOS ? 0x2258 : 0x14EF )
        {
            Weight = 1.0;
            Hue = hue; // Blacksmith: 0x44E; Tailoring: 0x483
            LootType = LootType.Blessed;
 
            m_AmountMax = amountMax;
            m_RequireExceptional = requireExeptional;
            m_Material = material;
            m_Entries = entries;
        }
 
        public LargeBOD() : base( Core.AOS ? 0x2258 : 0x14EF )
        {
            Weight = 1.0;
            LootType = LootType.Blessed;
        }
 
        public override void GetProperties( ObjectPropertyList list )
        {
            base.GetProperties( list );
 
            list.Add( 1060655 ); // large bulk order
 
            if ( m_RequireExceptional )
                list.Add( 1045141 ); // All items must be exceptional.
 
            //daat99 OWLTR start - custom resource
            if ( m_Material != BulkMaterialType.None )
                list.Add( "All items must be crafted with " + LargeBODGump.GetMaterialStringFor( m_Material ) ); // All items must be made with x material.
            //daat99 OWLTR end - custom resource
 
            list.Add( 1060656, m_AmountMax.ToString() ); // amount to make: ~1_val~
 
            for ( int i = 0; i < m_Entries.Length; ++i )
                list.Add( 1060658 + i, "#{0}\t{1}", m_Entries[i].Details.Number, m_Entries[i].Amount ); // ~1_val~: ~2_val~
        }
 
        public override void OnDoubleClick( Mobile from )
        {
            if ( IsChildOf( from.Backpack ) )
                from.SendGump( new LargeBODGump( from, this ) );
            else
                from.SendLocalizedMessage( 1045156 ); // You must have the deed in your backpack to use it.
        }
 
        public void BeginCombine( Mobile from )
        {
            if ( !Complete )
                from.Target = new LargeBODTarget( this );
            else
                from.SendLocalizedMessage( 1045166 ); // The maximum amount of requested items have already been combined to this deed.
        }
 
        public void EndCombine( Mobile from, object o )
        {
            if ( o is Item && ((Item)o).IsChildOf( from.Backpack ) )
            {
                if ( o is SmallBOD )
                {
                    SmallBOD small = (SmallBOD)o;
 
                    LargeBulkEntry entry = null;
 
                    for ( int i = 0; entry == null && i < m_Entries.Length; ++i )
                    {
                        if ( m_Entries[i].Details.Type == small.Type )
                            entry = m_Entries[i];
                    }
 
                    if ( entry == null )
                    {
                        from.SendLocalizedMessage( 1045160 ); // That is not a bulk order for this large request.
                    }
                    else if ( m_RequireExceptional && !small.RequireExceptional )
                    {
                        from.SendLocalizedMessage( 1045161 ); // Both orders must be of exceptional quality.
                    }
                    //daat99 OWLTR start - custom ores
                    else if ( m_Material >= BulkMaterialType.DullCopper && m_Material <= BulkMaterialType.Platinum && small.Material != m_Material )
                    //daat99 OWLTR end - custom ores
                    {
                        from.SendLocalizedMessage( 1045162 ); // Both orders must use the same ore type.
                    }
                    //daat99 OWLTR start - custom leather
                    else if ( m_Material >= BulkMaterialType.Spined && m_Material <= BulkMaterialType.Ethereal && small.Material != m_Material )
                    //daat99 OWLTR end - custom leather
                    {
                        from.SendLocalizedMessage( 1049351 ); // Both orders must use the same leather type.
                    }
                    //daat99 OWLTR start - custom wood
                    else if ( m_Material >= BulkMaterialType.Heartwood && m_Material <= BulkMaterialType.Petrified && small.Material != m_Material )
                    {
                        from.SendMessage( "Both orders must use the same wood type." ); // Both orders must use the same leather type.
                    }
                    //daat99 OWLTR end - custom wood
                    else if ( m_AmountMax != small.AmountMax )
                    {
                        from.SendLocalizedMessage( 1045163 ); // The two orders have different requested amounts and cannot be combined.
                    }
                    else if ( small.AmountCur < small.AmountMax )
                    {
                        from.SendLocalizedMessage( 1045164 ); // The order to combine with is not completed.
                    }
                    else if ( entry.Amount >= m_AmountMax )
                    {
                        from.SendLocalizedMessage( 1045166 ); // The maximum amount of requested items have already been combined to this deed.
                    }
                    else
                    {
                        entry.Amount += small.AmountCur;
                        small.Delete();
 
                        from.SendLocalizedMessage( 1045165 ); // The orders have been combined.
 
                        from.SendGump( new LargeBODGump( from, this ) );
 
                        if ( !Complete )
                            BeginCombine( from );
                    }
                }
                else
                {
                    from.SendLocalizedMessage( 1045159 ); // That is not a bulk order.
                }
            }
            else
            {
                from.SendLocalizedMessage( 1045158 ); // You must have the item in your backpack to target it.
            }
        }
 
        public LargeBOD( Serial serial ) : base( serial )
        {
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int) 0 ); // version
 
            writer.Write( m_AmountMax );
            writer.Write( m_RequireExceptional );
            writer.Write( (int) m_Material );
 
            writer.Write( (int) m_Entries.Length );
 
            for ( int i = 0; i < m_Entries.Length; ++i )
                m_Entries[i].Serialize( writer );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            switch ( version )
            {
                case 0:
                {
                    m_AmountMax = reader.ReadInt();
                    m_RequireExceptional = reader.ReadBool();
                    m_Material = (BulkMaterialType)reader.ReadInt();
 
                    m_Entries = new LargeBulkEntry[reader.ReadInt()];
 
                    for ( int i = 0; i < m_Entries.Length; ++i )
                        m_Entries[i] = new LargeBulkEntry( this, reader );
 
                    break;
                }
            }
 
            if ( Weight == 0.0 )
                Weight = 1.0;
 
            if ( Core.AOS && ItemID == 0x14EF )
                ItemID = 0x2258;
 
            if ( Parent == null && Map == Map.Internal && Location == Point3D.Zero )
                Delete();
        }
    }
}


basevendor.cs
Code:
using System;
using System.Collections;
using System.Collections.Generic;
using Server.Items;
using Server.Network;
using Server.ContextMenus;
using Server.Mobiles;
using Server.Misc;
using Server.Engines.BulkOrders;
using Server.Regions;
using Server.Factions;
using daat99;
 
namespace Server.Mobiles
{
    public enum VendorShoeType
    {
        None,
        Shoes,
        Boots,
        Sandals,
        ThighBoots
    }
 
    public abstract class BaseVendor : BaseCreature, IVendor
    {
        private const int MaxSell = 10;
 
        protected abstract List<SBInfo> SBInfos { get; }
 
        private ArrayList m_ArmorBuyInfo = new ArrayList();
        private ArrayList m_ArmorSellInfo = new ArrayList();
 
        private DateTime m_LastRestock;
 
        private DateTime m_NextTrickOrTreat;
 
        public override bool CanTeach { get { return true; } }
 
        public override bool BardImmune { get { return true; } }
 
        public override bool PlayerRangeSensitive { get { return true; } }
 
        public virtual bool IsActiveVendor { get { return true; } }
        public virtual bool IsActiveBuyer { get { return IsActiveVendor; } } // response to vendor SELL
        public virtual bool IsActiveSeller { get { return IsActiveVendor; } } // repsonse to vendor BUY
 
        public virtual NpcGuild NpcGuild { get { return NpcGuild.None; } }
 
        public virtual bool IsInvulnerable { get { return true; } }
 
        public virtual DateTime NextTrickOrTreat { get { return m_NextTrickOrTreat; } set { m_NextTrickOrTreat = value; } }
 
        public override bool ShowFameTitle { get { return false; } }
 
        public virtual bool IsValidBulkOrder( Item item )
        {
            return false;
        }
 
        public virtual Item CreateBulkOrder( Mobile from, bool fromContextMenu )
        {
            return null;
        }
 
        public virtual bool SupportsBulkOrders( Mobile from )
        {
            return false;
        }
 
        public virtual TimeSpan GetNextBulkOrder( Mobile from )
        {
            return TimeSpan.Zero;
        }
 
        public virtual void OnSuccessfulBulkOrderReceive( Mobile from )
        {
        }
 
        #region Faction
        public virtual int GetPriceScalar()
        {
            Town town = Town.FromRegion( this.Region );
 
            if ( town != null )
                return ( 100 + town.Tax );
 
            return 100;
        }
 
        public void UpdateBuyInfo()
        {
            int priceScalar = GetPriceScalar();
 
            IBuyItemInfo[] buyinfo = (IBuyItemInfo[])m_ArmorBuyInfo.ToArray( typeof( IBuyItemInfo ) );
 
            if ( buyinfo != null )
            {
                foreach ( IBuyItemInfo info in buyinfo )
                    info.PriceScalar = priceScalar;
            }
        }
        #endregion
 
        private class BulkOrderInfoEntry : ContextMenuEntry
        {
            private Mobile m_From;
            private BaseVendor m_Vendor;
 
            public BulkOrderInfoEntry( Mobile from, BaseVendor vendor )
                : base( 6152 )
            {
                m_From = from;
                m_Vendor = vendor;
            }
 
            public override void OnClick()
            {
                if ( m_Vendor.SupportsBulkOrders( m_From ) )
                {
                    TimeSpan ts = m_Vendor.GetNextBulkOrder( m_From );
 
                    int totalSeconds = (int)ts.TotalSeconds;
                    int totalHours = ( totalSeconds + 3599 ) / 3600;
                    int totalMinutes = ( totalSeconds + 59 ) / 60;
 
                    if ( ( ( Core.SE ) ? totalMinutes == 0 : totalHours == 0 ) )
                    {
                        m_From.SendLocalizedMessage( 1049038 ); // You can get an order now.
 
                        if ( Core.AOS )
                        {
                            Item bulkOrder = m_Vendor.CreateBulkOrder( m_From, true );
 
                            if ( bulkOrder is LargeBOD )
                                m_From.SendGump( new LargeBODAcceptGump( m_From, (LargeBOD)bulkOrder ) );
                            else if ( bulkOrder is SmallBOD )
                                m_From.SendGump( new SmallBODAcceptGump( m_From, (SmallBOD)bulkOrder ) );
                        }
                    }
                    else
                    {
                        int oldSpeechHue = m_Vendor.SpeechHue;
                        m_Vendor.SpeechHue = 0x3B2;
 
                        if ( Core.SE )
                            m_Vendor.SayTo( m_From, 1072058, totalMinutes.ToString() ); // An offer may be available in about ~1_minutes~ minutes.
                        else
                            m_Vendor.SayTo( m_From, 1049039, totalHours.ToString() ); // An offer may be available in about ~1_hours~ hours.
 
                        m_Vendor.SpeechHue = oldSpeechHue;
                    }
                }
            }
        }
 
        public BaseVendor( string title )
            : base( AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2 )
        {
            LoadSBInfo();
 
            this.Title = title;
            InitBody();
            InitOutfit();
 
            Container pack;
            //these packs MUST exist, or the client will crash when the packets are sent
            pack = new Backpack();
            pack.Layer = Layer.ShopBuy;
            pack.Movable = false;
            pack.Visible = false;
            AddItem( pack );
 
            pack = new Backpack();
            pack.Layer = Layer.ShopResale;
            pack.Movable = false;
            pack.Visible = false;
            AddItem( pack );
 
            m_LastRestock = DateTime.Now;
        }
 
        public BaseVendor( Serial serial )
            : base( serial )
        {
        }
 
        public DateTime LastRestock
        {
            get
            {
                return m_LastRestock;
            }
            set
            {
                m_LastRestock = value;
            }
        }
 
        public virtual TimeSpan RestockDelay
        {
            get
            {
                return TimeSpan.FromHours( 1 );
            }
        }
 
        public Container BuyPack
        {
            get
            {
                Container pack = FindItemOnLayer( Layer.ShopBuy ) as Container;
 
                if ( pack == null )
                {
                    pack = new Backpack();
                    pack.Layer = Layer.ShopBuy;
                    pack.Visible = false;
                    AddItem( pack );
                }
 
                return pack;
            }
        }
 
        public abstract void InitSBInfo();
 
        public virtual bool IsTokunoVendor { get { return ( Map == Map.Tokuno ); } }
 
        protected void LoadSBInfo()
        {
            m_LastRestock = DateTime.Now;
 
            for ( int i = 0; i < m_ArmorBuyInfo.Count; ++i )
            {
                GenericBuyInfo buy = m_ArmorBuyInfo[i] as GenericBuyInfo;
 
                if ( buy != null )
                    buy.DeleteDisplayEntity();
            }
 
            SBInfos.Clear();
 
            InitSBInfo();
 
            m_ArmorBuyInfo.Clear();
            m_ArmorSellInfo.Clear();
 
            for ( int i = 0; i < SBInfos.Count; i++ )
            {
                SBInfo sbInfo = (SBInfo)SBInfos[i];
                m_ArmorBuyInfo.AddRange( sbInfo.BuyInfo );
                m_ArmorSellInfo.Add( sbInfo.SellInfo );
            }
        }
 
        public virtual bool GetGender()
        {
            return Utility.RandomBool();
        }
 
        public virtual void InitBody()
        {
            InitStats( 100, 100, 25 );
 
            SpeechHue = Utility.RandomDyedHue();
            Hue = Utility.RandomSkinHue();
 
            if ( IsInvulnerable && !Core.AOS )
                NameHue = 0x35;
 
            if ( Female = GetGender() )
            {
                Body = 0x191;
                Name = NameList.RandomName( "female" );
            }
            else
            {
                Body = 0x190;
                Name = NameList.RandomName( "male" );
            }
        }
 
        public virtual int GetRandomHue()
        {
            switch ( Utility.Random( 5 ) )
            {
                default:
                case 0: return Utility.RandomBlueHue();
                case 1: return Utility.RandomGreenHue();
                case 2: return Utility.RandomRedHue();
                case 3: return Utility.RandomYellowHue();
                case 4: return Utility.RandomNeutralHue();
            }
        }
 
        public virtual int GetShoeHue()
        {
            if ( 0.1 > Utility.RandomDouble() )
                return 0;
 
            return Utility.RandomNeutralHue();
        }
 
        public virtual VendorShoeType ShoeType
        {
            get { return VendorShoeType.Shoes; }
        }
 
        public virtual int RandomBrightHue()
        {
            if ( 0.1 > Utility.RandomDouble() )
                return Utility.RandomList( 0x62, 0x71 );
 
            return Utility.RandomList( 0x03, 0x0D, 0x13, 0x1C, 0x21, 0x30, 0x37, 0x3A, 0x44, 0x59 );
        }
 
        public virtual void CheckMorph()
        {
            if ( CheckGargoyle() )
                return;
 
            if ( CheckNecromancer() )
                return;
 
            CheckTokuno();
        }
 
        public virtual bool CheckTokuno()
        {
            if ( this.Map != Map.Tokuno )
                return false;
 
            NameList n;
 
            if ( Female )
                n = NameList.GetNameList( "tokuno female" );
            else
                n = NameList.GetNameList( "tokuno male" );
 
            if ( !n.ContainsName( this.Name ) )
                TurnToTokuno();
 
            return true;
        }
 
        public virtual void TurnToTokuno()
        {
            if ( Female )
                this.Name = NameList.RandomName( "tokuno female" );
            else
                this.Name = NameList.RandomName( "tokuno male" );
        }
 
        public virtual bool CheckGargoyle()
        {
            Map map = this.Map;
 
            if ( map != Map.Ilshenar )
                return false;
 
            if ( !Region.IsPartOf( "Gargoyle City" ) )
                return false;
 
            if ( Body != 0x2F6 || ( Hue & 0x8000 ) == 0 )
                TurnToGargoyle();
 
            return true;
        }
 
        public virtual bool CheckNecromancer()
        {
            Map map = this.Map;
 
            if ( map != Map.Malas )
                return false;
 
            if ( !Region.IsPartOf( "Umbra" ) )
                return false;
 
            if ( Hue != 0x83E8 )
                TurnToNecromancer();
 
            return true;
        }
 
        public override void OnAfterSpawn()
        {
            CheckMorph();
        }
 
        protected override void OnMapChange( Map oldMap )
        {
            base.OnMapChange( oldMap );
 
            CheckMorph();
 
            LoadSBInfo();
        }
 
        public virtual int GetRandomNecromancerHue()
        {
            switch ( Utility.Random( 20 ) )
            {
                case 0: return 0;
                case 1: return 0x4E9;
                default: return Utility.RandomList( 0x485, 0x497 );
            }
        }
 
        public virtual void TurnToNecromancer()
        {
            for ( int i = 0; i < this.Items.Count; ++i )
            {
                Item item = this.Items[i];
 
                if ( item is Hair || item is Beard )
                    item.Hue = 0;
                else if ( item is BaseClothing || item is BaseWeapon || item is BaseArmor || item is BaseTool )
                    item.Hue = GetRandomNecromancerHue();
            }
 
            HairHue = 0;
            FacialHairHue = 0;
 
            Hue = 0x83E8;
        }
 
        public virtual void TurnToGargoyle()
        {
            for ( int i = 0; i < this.Items.Count; ++i )
            {
                Item item = this.Items[i];
 
                if ( item is BaseClothing || item is Hair || item is Beard )
                    item.Delete();
            }
 
            HairItemID = 0;
            FacialHairItemID = 0;
 
            Body = 0x2F6;
            Hue = RandomBrightHue() | 0x8000;
            Name = NameList.RandomName( "gargoyle vendor" );
 
            CapitalizeTitle();
        }
 
        public virtual void CapitalizeTitle()
        {
            string title = this.Title;
 
            if ( title == null )
                return;
 
            string[] split = title.Split( ' ' );
 
            for ( int i = 0; i < split.Length; ++i )
            {
                if ( Insensitive.Equals( split[i], "the" ) )
                    continue;
 
                if ( split[i].Length > 1 )
                    split[i] = Char.ToUpper( split[i][0] ) + split[i].Substring( 1 );
                else if ( split[i].Length > 0 )
                    split[i] = Char.ToUpper( split[i][0] ).ToString();
            }
 
            this.Title = String.Join( " ", split );
        }
 
        public virtual int GetHairHue()
        {
            return Utility.RandomHairHue();
        }
 
        public virtual void InitOutfit()
        {
            switch ( Utility.Random( 3 ) )
            {
                case 0: AddItem( new FancyShirt( GetRandomHue() ) ); break;
                case 1: AddItem( new Doublet( GetRandomHue() ) ); break;
                case 2: AddItem( new Shirt( GetRandomHue() ) ); break;
            }
 
            switch ( ShoeType )
            {
                case VendorShoeType.Shoes: AddItem( new Shoes( GetShoeHue() ) ); break;
                case VendorShoeType.Boots: AddItem( new Boots( GetShoeHue() ) ); break;
                case VendorShoeType.Sandals: AddItem( new Sandals( GetShoeHue() ) ); break;
                case VendorShoeType.ThighBoots: AddItem( new ThighBoots( GetShoeHue() ) ); break;
            }
 
            int hairHue = GetHairHue();
 
            Utility.AssignRandomHair( this, hairHue );
            Utility.AssignRandomFacialHair( this, hairHue );
 
            if ( Female )
            {
                switch ( Utility.Random( 6 ) )
                {
                    case 0: AddItem( new ShortPants( GetRandomHue() ) ); break;
                    case 1:
                    case 2: AddItem( new Kilt( GetRandomHue() ) ); break;
                    case 3:
                    case 4:
                    case 5: AddItem( new Skirt( GetRandomHue() ) ); break;
                }
            }
            else
            {
                switch ( Utility.Random( 2 ) )
                {
                    case 0: AddItem( new LongPants( GetRandomHue() ) ); break;
                    case 1: AddItem( new ShortPants( GetRandomHue() ) ); break;
                }
            }
 
            PackGold( 100, 200 );
        }
 
        public virtual void Restock()
        {
            m_LastRestock = DateTime.Now;
 
            IBuyItemInfo[] buyInfo = this.GetBuyInfo();
 
            foreach ( IBuyItemInfo bii in buyInfo )
                bii.OnRestock();
        }
 
        private static TimeSpan InventoryDecayTime = TimeSpan.FromHours( 1.0 );
 
        public virtual void VendorBuy( Mobile from )
        {
            if ( !IsActiveSeller )
                return;
 
            if ( !from.CheckAlive() )
                return;
 
            if ( !CheckVendorAccess( from ) )
            {
                Say( 501522 ); // I shall not treat with scum like thee!
                return;
            }
 
            if ( DateTime.Now - m_LastRestock > RestockDelay )
                Restock();
 
            UpdateBuyInfo();
 
            int count = 0;
            List<BuyItemState> list;
            IBuyItemInfo[] buyInfo = this.GetBuyInfo();
            IShopSellInfo[] sellInfo = this.GetSellInfo();
 
            list = new List<BuyItemState>( buyInfo.Length );
            Container cont = this.BuyPack;
 
            List<ObjectPropertyList> opls = null;
 
            for ( int idx = 0; idx < buyInfo.Length; idx++ )
            {
                IBuyItemInfo buyItem = (IBuyItemInfo)buyInfo[idx];
 
                if ( buyItem.Amount <= 0 || list.Count >= 250 )
                    continue;
 
                // NOTE: Only GBI supported; if you use another implementation of IBuyItemInfo, this will crash
                GenericBuyInfo gbi = (GenericBuyInfo)buyItem;
                IEntity disp = gbi.GetDisplayEntity();
 
                list.Add( new BuyItemState( buyItem.Name, cont.Serial, disp == null ? (Serial)0x7FC0FFEE : disp.Serial, buyItem.Price, buyItem.Amount, buyItem.ItemID, buyItem.Hue ) );
                count++;
 
                if ( opls == null ) {
                    opls = new List<ObjectPropertyList>();
                }
 
                if ( disp is Item ) {
                    opls.Add( ( ( Item ) disp ).PropertyList );
                } else if ( disp is Mobile ) {
                    opls.Add( ( ( Mobile ) disp ).PropertyList );
                }
            }
 
            List<Item> playerItems = cont.Items;
 
            for ( int i = playerItems.Count - 1; i >= 0; --i )
            {
                if ( i >= playerItems.Count )
                    continue;
 
                Item item = playerItems[i];
 
                if ( ( item.LastMoved + InventoryDecayTime ) <= DateTime.Now )
                    item.Delete();
            }
 
            for ( int i = 0; i < playerItems.Count; ++i )
            {
                Item item = playerItems[i];
 
                int price = 0;
                string name = null;
 
                foreach ( IShopSellInfo ssi in sellInfo )
                {
                    if ( ssi.IsSellable( item ) )
                    {
                        price = ssi.GetBuyPriceFor( item );
                        name = ssi.GetNameFor( item );
                        break;
                    }
                }
 
                if ( name != null && list.Count < 250 )
                {
                    list.Add( new BuyItemState( name, cont.Serial, item.Serial, price, item.Amount, item.ItemID, item.Hue ) );
                    count++;
 
                    if ( opls == null ) {
                        opls = new List<ObjectPropertyList>();
                    }
 
                    opls.Add( item.PropertyList );
                }
            }
 
            //one (not all) of the packets uses a byte to describe number of items in the list.  Osi = dumb.
            //if ( list.Count > 255 )
            //    Console.WriteLine( "Vendor Warning: Vendor {0} has more than 255 buy items, may cause client errors!", this );
 
            if ( list.Count > 0 )
            {
                list.Sort( new BuyItemStateComparer() );
 
                SendPacksTo( from );
 
                NetState ns = from.NetState;
 
                if ( ns == null )
                    return;
 
                if ( ns.ContainerGridLines )
                    from.Send( new VendorBuyContent6017( list ) );
                else
                    from.Send( new VendorBuyContent( list ) );
 
                from.Send( new VendorBuyList( this, list ) );
 
                if ( ns.HighSeas )
                    from.Send( new DisplayBuyListHS( this ) );
                else
                    from.Send( new DisplayBuyList( this ) );
 
                from.Send( new MobileStatusExtended( from ) );//make sure their gold amount is sent
 
                if ( opls != null ) {
                    for ( int i = 0; i < opls.Count; ++i ) {
                        from.Send( opls[i] );
                    }
                }
 
                SayTo( from, 500186 ); // Greetings.  Have a look around.
            }
        }
 
        public virtual void SendPacksTo( Mobile from )
        {
            Item pack = FindItemOnLayer( Layer.ShopBuy );
 
            if ( pack == null )
            {
                pack = new Backpack();
                pack.Layer = Layer.ShopBuy;
                pack.Movable = false;
                pack.Visible = false;
                AddItem( pack );
            }
 
            from.Send( new EquipUpdate( pack ) );
 
            pack = FindItemOnLayer( Layer.ShopSell );
 
            if ( pack != null )
                from.Send( new EquipUpdate( pack ) );
 
            pack = FindItemOnLayer( Layer.ShopResale );
 
            if ( pack == null )
            {
                pack = new Backpack();
                pack.Layer = Layer.ShopResale;
                pack.Movable = false;
                pack.Visible = false;
                AddItem( pack );
            }
 
            from.Send( new EquipUpdate( pack ) );
        }
 
        public virtual void VendorSell( Mobile from )
        {
            if ( !IsActiveBuyer )
                return;
 
            if ( !from.CheckAlive() )
                return;
 
            if ( !CheckVendorAccess( from ) )
            {
                Say( 501522 ); // I shall not treat with scum like thee!
                return;
            }
 
            Container pack = from.Backpack;
 
            if ( pack != null )
            {
                IShopSellInfo[] info = GetSellInfo();
 
                Hashtable table = new Hashtable();
 
                foreach ( IShopSellInfo ssi in info )
                {
                    Item[] items = pack.FindItemsByType( ssi.Types );
 
                    foreach ( Item item in items )
                    {
                        if ( item is Container && ( (Container)item ).Items.Count != 0 )
                            continue;
 
                        if ( item.IsStandardLoot() && item.Movable && ssi.IsSellable( item ) )
                            table[item] = new SellItemState( item, ssi.GetSellPriceFor( item ), ssi.GetNameFor( item ) );
                    }
                }
 
                if ( table.Count > 0 )
                {
                    SendPacksTo( from );
 
                    from.Send( new VendorSellList( this, table ) );
                }
                else
                {
                    Say( true, "You have nothing I would be interested in." );
                }
            }
        }
 
        public override bool OnDragDrop( Mobile from, Item dropped )
        {
            /* TODO: Thou art giving me? and fame/karma for gold gifts */
 
            if ( dropped is SmallBOD || dropped is LargeBOD )
            {
                if( Core.ML )
                {
                    if( ((PlayerMobile)from).NextBODTurnInTime > DateTime.Now )
                    {
                        SayTo( from, 1079976 );    //
                        return false;
                    }
                }
 
                if ( !IsValidBulkOrder( dropped ) || !SupportsBulkOrders( from ) )
                {
                    SayTo( from, 1045130 ); // That order is for some other shopkeeper.
                    return false;
                }
                else if ( ( dropped is SmallBOD && !( (SmallBOD)dropped ).Complete ) || ( dropped is LargeBOD && !( (LargeBOD)dropped ).Complete ) )
                {
                    SayTo( from, 1045131 ); // You have not completed the order yet.
                    return false;
                }
 
                Item reward;
                int gold, fame;
 
                if ( dropped is SmallBOD )
                    ( (SmallBOD)dropped ).GetRewards( out reward, out gold, out fame );
                else
                    ( (LargeBOD)dropped ).GetRewards( out reward, out gold, out fame );
 
                from.SendSound( 0x3D );
 
                SayTo( from, 1045132 ); // Thank you so much!  Here is a reward for your effort.
 
                if ( reward != null )
                    from.AddToBackpack( reward );
 
                if ( gold > 1000 )
                    from.AddToBackpack( new BankCheck( gold ) );
                else if ( gold > 0 )
                    from.AddToBackpack( new Gold( gold ) );
                //daat99 OWLTR start - give tokens for bods
                if (OWLTROptionsManager.IsEnabled(OWLTROptionsManager.OPTIONS_ENUM.BOD_GIVE_TOKENS) && gold > 100)
                    TokenSystem.GiveTokensToPlayer(from as PlayerMobile, (int)(gold / 100));
                //daat99 OWLTR end - give tokens for bods
 
                Titles.AwardFame( from, fame, true );
 
                OnSuccessfulBulkOrderReceive( from );
 
                if( Core.ML )
                {
                    ((PlayerMobile)from).NextBODTurnInTime = DateTime.Now + TimeSpan.FromSeconds( 10.0 );
                }
 
                dropped.Delete();
                return true;
            }
 
            return base.OnDragDrop( from, dropped );
        }
 
        private GenericBuyInfo LookupDisplayObject( object obj )
        {
            IBuyItemInfo[] buyInfo = this.GetBuyInfo();
 
            for ( int i = 0; i < buyInfo.Length; ++i ) {
                GenericBuyInfo gbi = (GenericBuyInfo)buyInfo[i];
 
                if ( gbi.GetDisplayEntity() == obj )
                    return gbi;
            }
 
            return null;
        }
 
        private void ProcessSinglePurchase( BuyItemResponse buy, IBuyItemInfo bii, List<BuyItemResponse> validBuy, ref int controlSlots, ref bool fullPurchase, ref int totalCost )
        {
            int amount = buy.Amount;
 
            if ( amount > bii.Amount )
                amount = bii.Amount;
 
            if ( amount <= 0 )
                return;
 
            int slots = bii.ControlSlots * amount;
 
            if ( controlSlots >= slots )
            {
                controlSlots -= slots;
            }
            else
            {
                fullPurchase = false;
                return;
            }
 
            totalCost += bii.Price * amount;
            validBuy.Add( buy );
        }
 
        private void ProcessValidPurchase( int amount, IBuyItemInfo bii, Mobile buyer, Container cont )
        {
            if ( amount > bii.Amount )
                amount = bii.Amount;
 
            if ( amount < 1 )
                return;
 
            bii.Amount -= amount;
 
            IEntity o = bii.GetEntity();
 
            if ( o is Item )
            {
                Item item = (Item)o;
 
                if ( item.Stackable )
                {
                    item.Amount = amount;
 
                    if ( cont == null || !cont.TryDropItem( buyer, item, false ) )
                        item.MoveToWorld( buyer.Location, buyer.Map );
                }
                else
                {
                    item.Amount = 1;
 
                    if ( cont == null || !cont.TryDropItem( buyer, item, false ) )
                        item.MoveToWorld( buyer.Location, buyer.Map );
 
                    for ( int i = 1; i < amount; i++ )
                    {
                        item = bii.GetEntity() as Item;
 
                        if ( item != null )
                        {
                            item.Amount = 1;
 
                            if ( cont == null || !cont.TryDropItem( buyer, item, false ) )
                                item.MoveToWorld( buyer.Location, buyer.Map );
                        }
                    }
                }
            }
            else if ( o is Mobile )
            {
                Mobile m = (Mobile)o;
 
                m.Direction = (Direction)Utility.Random( 8 );
                m.MoveToWorld( buyer.Location, buyer.Map );
                m.PlaySound( m.GetIdleSound() );
 
                if ( m is BaseCreature )
                    ( (BaseCreature)m ).SetControlMaster( buyer );
 
                for ( int i = 1; i < amount; ++i )
                {
                    m = bii.GetEntity() as Mobile;
 
                    if ( m != null )
                    {
                        m.Direction = (Direction)Utility.Random( 8 );
                        m.MoveToWorld( buyer.Location, buyer.Map );
 
                        if ( m is BaseCreature )
                            ( (BaseCreature)m ).SetControlMaster( buyer );
                    }
                }
            }
        }
 
        public virtual bool OnBuyItems( Mobile buyer, List<BuyItemResponse> list )
        {
            if ( !IsActiveSeller )
                return false;
 
            if ( !buyer.CheckAlive() )
                return false;
 
            if ( !CheckVendorAccess( buyer ) )
            {
                Say( 501522 ); // I shall not treat with scum like thee!
                return false;
            }
 
            UpdateBuyInfo();
 
            IBuyItemInfo[] buyInfo = this.GetBuyInfo();
            IShopSellInfo[] info = GetSellInfo();
            int totalCost = 0;
            List<BuyItemResponse> validBuy = new List<BuyItemResponse>( list.Count );
            Container cont;
            bool bought = false;
            bool fromBank = false;
            bool fullPurchase = true;
            int controlSlots = buyer.FollowersMax - buyer.Followers;
 
            foreach ( BuyItemResponse buy in list )
            {
                Serial ser = buy.Serial;
                int amount = buy.Amount;
 
                if ( ser.IsItem )
                {
                    Item item = World.FindItem( ser );
 
                    if ( item == null )
                        continue;
 
                    GenericBuyInfo gbi = LookupDisplayObject( item );
 
                    if ( gbi != null )
                    {
                        ProcessSinglePurchase( buy, gbi, validBuy, ref controlSlots, ref fullPurchase, ref totalCost );
                    }
                    else if ( item != this.BuyPack && item.IsChildOf( this.BuyPack ) )
                    {
                        if ( amount > item.Amount )
                            amount = item.Amount;
 
                        if ( amount <= 0 )
                            continue;
 
                        foreach ( IShopSellInfo ssi in info )
                        {
                            if ( ssi.IsSellable( item ) )
                            {
                                if ( ssi.IsResellable( item ) )
                                {
                                    totalCost += ssi.GetBuyPriceFor( item ) * amount;
                                    validBuy.Add( buy );
                                    break;
                                }
                            }
                        }
                    }
                }
                else if ( ser.IsMobile )
                {
                    Mobile mob = World.FindMobile( ser );
 
                    if ( mob == null )
                        continue;
 
                    GenericBuyInfo gbi = LookupDisplayObject( mob );
 
                    if ( gbi != null )
                        ProcessSinglePurchase( buy, gbi, validBuy, ref controlSlots, ref fullPurchase, ref totalCost );
                }
            }//foreach
 
            if ( fullPurchase && validBuy.Count == 0 )
                SayTo( buyer, 500190 ); // Thou hast bought nothing!
            else if ( validBuy.Count == 0 )
                SayTo( buyer, 500187 ); // Your order cannot be fulfilled, please try again.
 
            if ( validBuy.Count == 0 )
                return false;
 
            bought = ( buyer.AccessLevel >= AccessLevel.GameMaster );
 
            cont = buyer.Backpack;
            if ( !bought && cont != null )
            {
                if ( cont.ConsumeTotal( typeof( Gold ), totalCost ) )
                    bought = true;
                else if ( totalCost < 2000 )
                    SayTo( buyer, 500192 );//Begging thy pardon, but thou casnt afford that.
            }
 
            if ( !bought && totalCost >= 2000 )
            {
                cont = buyer.FindBankNoCreate();
                if ( cont != null && cont.ConsumeTotal( typeof( Gold ), totalCost ) )
                {
                    bought = true;
                    fromBank = true;
                }
                else
                {
                    SayTo( buyer, 500191 ); //Begging thy pardon, but thy bank account lacks these funds.
                }
            }
 
            if ( !bought )
                return false;
            else
                buyer.PlaySound( 0x32 );
 
            cont = buyer.Backpack;
            if ( cont == null )
                cont = buyer.BankBox;
 
            foreach ( BuyItemResponse buy in validBuy )
            {
                Serial ser = buy.Serial;
                int amount = buy.Amount;
 
                if ( amount < 1 )
                    continue;
 
                if ( ser.IsItem )
                {
                    Item item = World.FindItem( ser );
 
                    if ( item == null )
                        continue;
 
                    GenericBuyInfo gbi = LookupDisplayObject( item );
 
                    if ( gbi != null )
                    {
                        ProcessValidPurchase( amount, gbi, buyer, cont );
                    }
                    else
                    {
                        if ( amount > item.Amount )
                            amount = item.Amount;
 
                        foreach ( IShopSellInfo ssi in info )
                        {
                            if ( ssi.IsSellable( item ) )
                            {
                                if ( ssi.IsResellable( item ) )
                                {
                                    Item buyItem;
                                    if ( amount >= item.Amount )
                                    {
                                        buyItem = item;
                                    }
                                    else
                                    {
                                        buyItem = Mobile.LiftItemDupe( item, item.Amount - amount );
 
                                        if ( buyItem == null )
                                            buyItem = item;
                                    }
 
                                    if ( cont == null || !cont.TryDropItem( buyer, buyItem, false ) )
                                        buyItem.MoveToWorld( buyer.Location, buyer.Map );
 
                                    break;
                                }
                            }
                        }
                    }
                }
                else if ( ser.IsMobile )
                {
                    Mobile mob = World.FindMobile( ser );
 
                    if ( mob == null )
                        continue;
 
                    GenericBuyInfo gbi = LookupDisplayObject( mob );
 
                    if ( gbi != null )
                        ProcessValidPurchase( amount, gbi, buyer, cont );
                }
            }//foreach
 
            if ( fullPurchase )
            {
                if ( buyer.AccessLevel >= AccessLevel.GameMaster )
                    SayTo( buyer, true, "I would not presume to charge thee anything.  Here are the goods you requested." );
                else if ( fromBank )
                    SayTo( buyer, true, "The total of thy purchase is {0} gold, which has been withdrawn from your bank account.  My thanks for the patronage.", totalCost );
                else
                    SayTo( buyer, true, "The total of thy purchase is {0} gold.  My thanks for the patronage.", totalCost );
            }
            else
            {
                if ( buyer.AccessLevel >= AccessLevel.GameMaster )
                    SayTo( buyer, true, "I would not presume to charge thee anything.  Unfortunately, I could not sell you all the goods you requested." );
                else if ( fromBank )
                    SayTo( buyer, true, "The total of thy purchase is {0} gold, which has been withdrawn from your bank account.  My thanks for the patronage.  Unfortunately, I could not sell you all the goods you requested.", totalCost );
                else
                    SayTo( buyer, true, "The total of thy purchase is {0} gold.  My thanks for the patronage.  Unfortunately, I could not sell you all the goods you requested.", totalCost );
            }
 
            return true;
        }
 
        public virtual bool CheckVendorAccess( Mobile from )
        {
            GuardedRegion reg = (GuardedRegion)this.Region.GetRegion( typeof( GuardedRegion ) );
 
            if ( reg != null && !reg.CheckVendorAccess( this, from ) )
                return false;
 
            if ( this.Region != from.Region )
            {
                reg = (GuardedRegion)from.Region.GetRegion( typeof( GuardedRegion ) );
 
                if ( reg != null && !reg.CheckVendorAccess( this, from ) )
                    return false;
            }
 
            return true;
        }
 
        public virtual bool OnSellItems( Mobile seller, List<SellItemResponse> list )
        {
            if ( !IsActiveBuyer )
                return false;
 
            if ( !seller.CheckAlive() )
                return false;
 
            if ( !CheckVendorAccess( seller ) )
            {
                Say( 501522 ); // I shall not treat with scum like thee!
                return false;
            }
 
            seller.PlaySound( 0x32 );
 
            IShopSellInfo[] info = GetSellInfo();
            IBuyItemInfo[] buyInfo = this.GetBuyInfo();
            int GiveGold = 0;
            int Sold = 0;
            Container cont;
 
            foreach ( SellItemResponse resp in list )
            {
                if ( resp.Item.RootParent != seller || resp.Amount <= 0 || !resp.Item.IsStandardLoot() || !resp.Item.Movable || ( resp.Item is Container && ( (Container)resp.Item ).Items.Count != 0 ) )
                    continue;
 
                foreach ( IShopSellInfo ssi in info )
                {
                    if ( ssi.IsSellable( resp.Item ) )
                    {
                        Sold++;
                        break;
                    }
                }
            }
 
            if ( Sold > MaxSell )
            {
                SayTo( seller, true, "You may only sell {0} items at a time!", MaxSell );
                return false;
            }
            else if ( Sold == 0 )
            {
                return true;
            }
 
            foreach ( SellItemResponse resp in list )
            {
                if ( resp.Item.RootParent != seller || resp.Amount <= 0 || !resp.Item.IsStandardLoot() || !resp.Item.Movable || ( resp.Item is Container && ( (Container)resp.Item ).Items.Count != 0 ) )
                    continue;
 
                foreach ( IShopSellInfo ssi in info )
                {
                    if ( ssi.IsSellable( resp.Item ) )
                    {
                        int amount = resp.Amount;
 
                        if ( amount > resp.Item.Amount )
                            amount = resp.Item.Amount;
 
                        if ( ssi.IsResellable( resp.Item ) )
                        {
                            bool found = false;
 
                            foreach ( IBuyItemInfo bii in buyInfo )
                            {
                                if ( bii.Restock( resp.Item, amount ) )
                                {
                                    resp.Item.Consume( amount );
                                    found = true;
 
                                    break;
                                }
                            }
 
                            if ( !found )
                            {
                                cont = this.BuyPack;
 
                                if ( amount < resp.Item.Amount )
                                {
                                    Item item = Mobile.LiftItemDupe( resp.Item, resp.Item.Amount - amount );
 
                                    if ( item != null )
                                    {
                                        item.SetLastMoved();
                                        cont.DropItem( item );
                                    }
                                    else
                                    {
                                        resp.Item.SetLastMoved();
                                        cont.DropItem( resp.Item );
                                    }
                                }
                                else
                                {
                                    resp.Item.SetLastMoved();
                                    cont.DropItem( resp.Item );
                                }
                            }
                        }
                        else
                        {
                            if ( amount < resp.Item.Amount )
                                resp.Item.Amount -= amount;
                            else
                                resp.Item.Delete();
                        }
 
                        GiveGold += ssi.GetSellPriceFor( resp.Item ) * amount;
                        break;
                    }
                }
            }
 
            if ( GiveGold > 0 )
            {
                while ( GiveGold > 60000 )
                {
                    seller.AddToBackpack( new Gold( 60000 ) );
                    GiveGold -= 60000;
                }
 
                seller.AddToBackpack( new Gold( GiveGold ) );
 
                seller.PlaySound( 0x0037 );//Gold dropping sound
 
                if ( SupportsBulkOrders( seller ) )
                {
                    Item bulkOrder = CreateBulkOrder( seller, false );
 
                    if ( bulkOrder is LargeBOD )
                        seller.SendGump( new LargeBODAcceptGump( seller, (LargeBOD)bulkOrder ) );
                    else if ( bulkOrder is SmallBOD )
                        seller.SendGump( new SmallBODAcceptGump( seller, (SmallBOD)bulkOrder ) );
                }
            }
            //no cliloc for this?
            //SayTo( seller, true, "Thank you! I bought {0} item{1}. Here is your {2}gp.", Sold, (Sold > 1 ? "s" : ""), GiveGold );
 
            return true;
        }
 
        public override void Serialize( GenericWriter writer )
        {
            base.Serialize( writer );
 
            writer.Write( (int)1 ); // version
 
            List<SBInfo> sbInfos = this.SBInfos;
 
            for ( int i = 0; sbInfos != null && i < sbInfos.Count; ++i )
            {
                SBInfo sbInfo = sbInfos[i];
                List<GenericBuyInfo> buyInfo = sbInfo.BuyInfo;
 
                for ( int j = 0; buyInfo != null && j < buyInfo.Count; ++j )
                {
                    GenericBuyInfo gbi = (GenericBuyInfo)buyInfo[j];
 
                    int maxAmount = gbi.MaxAmount;
                    int doubled = 0;
 
                    switch ( maxAmount )
                    {
                        case  40: doubled = 1; break;
                        case  80: doubled = 2; break;
                        case 160: doubled = 3; break;
                        case 320: doubled = 4; break;
                        case 640: doubled = 5; break;
                        case 999: doubled = 6; break;
                    }
 
                    if ( doubled > 0 )
                    {
                        writer.WriteEncodedInt( 1 + ( ( j * sbInfos.Count ) + i ) );
                        writer.WriteEncodedInt( doubled );
                    }
                }
            }
 
            writer.WriteEncodedInt( 0 );
        }
 
        public override void Deserialize( GenericReader reader )
        {
            base.Deserialize( reader );
 
            int version = reader.ReadInt();
 
            LoadSBInfo();
 
            List<SBInfo> sbInfos = this.SBInfos;
 
            switch ( version )
            {
                case 1:
                    {
                        int index;
 
                        while ( ( index = reader.ReadEncodedInt() ) > 0 )
                        {
                            int doubled = reader.ReadEncodedInt();
 
                            if ( sbInfos != null )
                            {
                                index -= 1;
                                int sbInfoIndex = index % sbInfos.Count;
                                int buyInfoIndex = index / sbInfos.Count;
 
                                if ( sbInfoIndex >= 0 && sbInfoIndex < sbInfos.Count )
                                {
                                    SBInfo sbInfo = sbInfos[sbInfoIndex];
                                    List<GenericBuyInfo> buyInfo = sbInfo.BuyInfo;
 
                                    if ( buyInfo != null && buyInfoIndex >= 0 && buyInfoIndex < buyInfo.Count )
                                    {
                                        GenericBuyInfo gbi = (GenericBuyInfo)buyInfo[buyInfoIndex];
 
                                        int amount = 20;
 
                                        switch ( doubled )
                                        {
                                            case 1: amount = 40; break;
                                            case 2: amount = 80; break;
                                            case 3: amount = 160; break;
                                            case 4: amount = 320; break;
                                            case 5: amount = 640; break;
                                            case 6: amount = 999; break;
                                        }
 
                                        gbi.Amount = gbi.MaxAmount = amount;
                                    }
                                }
                            }
                        }
 
                        break;
                    }
            }
 
            if ( IsParagon )
                IsParagon = false;
 
            if ( Core.AOS && NameHue == 0x35 )
                NameHue = -1;
 
            Timer.DelayCall( TimeSpan.Zero, new TimerCallback( CheckMorph ) );
        }
 
        public override void AddCustomContextEntries( Mobile from, List<ContextMenuEntry> list )
        {
            if ( from.Alive && IsActiveVendor )
            {
                if ( SupportsBulkOrders( from ) )
                    list.Add( new BulkOrderInfoEntry( from, this ) );
               
                if ( IsActiveSeller )
                    list.Add( new VendorBuyEntry( from, this ) );
 
                if ( IsActiveBuyer )
                    list.Add( new VendorSellEntry( from, this ) );
            }
 
            base.AddCustomContextEntries( from, list );
        }
 
        public virtual IShopSellInfo[] GetSellInfo()
        {
            return (IShopSellInfo[])m_ArmorSellInfo.ToArray( typeof( IShopSellInfo ) );
        }
 
        public virtual IBuyItemInfo[] GetBuyInfo()
        {
            return (IBuyItemInfo[])m_ArmorBuyInfo.ToArray( typeof( IBuyItemInfo ) );
        }
 
        public override bool CanBeDamaged()
        {
            return !IsInvulnerable;
        }
    }
}
 
namespace Server.ContextMenus
{
    public class VendorBuyEntry : ContextMenuEntry
    {
        private BaseVendor m_Vendor;
 
        public VendorBuyEntry( Mobile from, BaseVendor vendor )
            : base( 6103, 8 )
        {
            m_Vendor = vendor;
            Enabled = vendor.CheckVendorAccess( from );
        }
 
        public override void OnClick()
        {
            m_Vendor.VendorBuy( this.Owner.From );
        }
    }
 
    public class VendorSellEntry : ContextMenuEntry
    {
        private BaseVendor m_Vendor;
 
        public VendorSellEntry( Mobile from, BaseVendor vendor )
            : base( 6104, 8 )
        {
            m_Vendor = vendor;
            Enabled = vendor.CheckVendorAccess( from );
        }
 
        public override void OnClick()
        {
            m_Vendor.VendorSell( this.Owner.From );
        }
    }
}
 
namespace Server
{
    public interface IShopSellInfo
    {
        //get display name for an item
        string GetNameFor( Item item );
 
        //get price for an item which the player is selling
        int GetSellPriceFor( Item item );
 
        //get price for an item which the player is buying
        int GetBuyPriceFor( Item item );
 
        //can we sell this item to this vendor?
        bool IsSellable( Item item );
 
        //What do we sell?
        Type[] Types { get; }
 
        //does the vendor resell this item?
        bool IsResellable( Item item );
    }
 
    public interface IBuyItemInfo
    {
        //get a new instance of an object (we just bought it)
        IEntity GetEntity();
 
        int ControlSlots { get; }
 
        int PriceScalar { get; set; }
 
        //display price of the item
        int Price { get; }
 
        //display name of the item
        string Name { get; }
 
        //display hue
        int Hue { get; }
 
        //display id
        int ItemID { get; }
 
        //amount in stock
        int Amount { get; set; }
 
        //max amount in stock
        int MaxAmount { get; }
 
        //Attempt to restock with item, (return true if restock sucessful)
        bool Restock( Item item, int amount );
 
        //called when its time for the whole shop to restock
        void OnRestock();
    }
}
 

rathraven

Traveler
Did some more testing. The crash doesn't happen when turning in large armor bods, only when turning in large weapon bods. It crashes when turning in the bods that have 5 to 6 different weapons needed.

I tested tailoring also, and its working fine no crash issues with tailoring bods.
 

daat99

Moderator
Staff member
Please move line 511 to after the code I asked you to add and try again to use 20 weapon bod.
Then let me know what happens in the console (without the crash this time).

PS
I meant to say "before" and not "below" when I original posted, my bad :(
 

rathraven

Traveler
Ok moved it and this is what happening in the console.

Params[13,0,0], Fixed Params[13,0,0], goldTable[14,3,15]
Params[10,2,0], Fixed Params[10,2,0], goldTable[14,3,15]
Params[15,2,0], Fixed Params[13,2,0], goldTable[14,3,15]
Params[13,1,0], Fixed Params[13,1,0], goldTable[14,3,15]
Params[15,1,0], Fixed Params[13,1,0], goldTable[14,3,15]

no crashes so far
 

daat99

Moderator
Staff member
Can you tell me which numbers the following bods gets you please?
1-part (regular)
1-part (exceptional)
Ringmail (regular)
Ringmail (exceptional)
Chainmail (regular)
Chainmail (exceptional)
Platemail (regular)
Platemail (exceptional)
2-part weapons (regular)
2-part weapons (exceptional)
5-part weapons (regular)
5-part weapons (exceptional)
6-part weapons (regular)
6-part weapons (exceptional)
They should be 0-13 (in the order posted above).
If they aren't I'm probably missing at least 2 types of bods and I would appreciate it if you can tell me which ones and what their numbers are.
 

rathraven

Traveler
1-part (regular)
Params[0,2,0], Fixed Params[0,2,0], goldTable[14,3,14]

1-part (exceptional)
Params[1,2,0], Fixed Params[1,2,0], goldTable[14,3,14]

Ringmail (regular)
Params[2,2,5], Fixed Params[2,2,5], goldTable[14,3,14]

Ringmail (exceptional)
Params[3,2,5], Fixed Params[2,2,5], goldTable[14,3,14]

Chainmail (regular)
Params[4,2,9], Fixed Params[4,2,9], goldTable[14,3,14]

Chainmail (exceptional)
Params[5,2,9], Fixed Params[5,2,9], goldTable[14,3,14]

Platemail (regular)
Params[6,2,6], Fixed Params[6,2,6], goldTable[14,3,14]

Platemail (exceptional)
Params[7,2,6], Fixed Params[7,2,6], goldTable[14,3,14]

2-part weapons (regular)
Params[8,2,0], Fixed Params[8,2,0], goldTable[14,3,15]

2-part weapons (exceptional)
Params[9,2,0], Fixed Params[9,2,0], goldTable[14,3,15]

5-part weapons (regular)
Params[10,2,0], Fixed Params[10,2,0], goldTable[14,3,15]

5-part weapons (exceptional)
Params[11,2,0], Fixed Params[11,2,0], goldTable[14,3,15]

6-part weapons (regular)
Params[14,2,0], Fixed Params[13,2,0], goldTable[14,3,15]

6-part weapons (exceptional)
Params[15,2,0], Fixed Params[13,2,0], goldTable[14,3,15]

12 and 13 im unsure of what they are...
 

daat99

Moderator
Staff member
@Hammerhand: Do you have any idea which bod types are missing from the list and are marked as 12 and 13?

@rathraven: did you add any bod related system other than the OWLTR to your server?

Please change this line:
Code:
typeIndex = typeIndex >= goldTable.Length ? goldTable.Length -1 : typeIndex;
to this:
Code:
typeIndex -= typeIndex >= goldTable.Length ? 2 : 0;
typeIndex = typeIndex >= goldTable.Length ? goldTable.Length -1 : typeIndex;

The above change will fix the crash and distribute the gold reward as originally intended.
 

daat99

Moderator
Staff member
@ rathraven, Thanks.
@ Hammerhand, Can you please check if we have this crash in our copy using the weapon bods as well (from BitBucket)?
If you can test this with the write line code it'll be great :)
 

Hammerhand

Knight
My files are the same as whats on BitBucket. I'm seeing differences between mine & Rathravens files though. Looks like it could be a couple missed edits..
Section starting at line 122 in LargeBOD.cs missing..
public override void OnDoubleClickNotAccessible( Mobile from )
{
OnDoubleClick( from );
}
public override void OnDoubleClickSecureTrade( Mobile from )
{
OnDoubleClick( from );
}
------------------------------------
BaseVendor.cs line 760 in mine

PlayerMobile pm = from as PlayerMobile;
if ( Core.ML && pm != null && pm.NextBODTurnInTime > DateTime.Now )

His has at line 767 Line count differences are due to spacing only..

if(Core.ML)
{
if(((PlayerMobile)from).NextBODTurnInTime > DateTime.Now)
 
Top