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!

Owltr ver. 3.0.0

Hammerhand

Knight
I'd say its more than likely this line thats causing the issues.
Code:
                if (pm != null && pm.GemMining && pm.ToggleMiningGem && from.Skills[SkillName.Mining].Base >= 100.0 && 0.1 > Utility.RandomDouble())
                    return Loot.RandomGem().GetType();  << this line here
Personally I would just comment out those 2 lines & adjust the following area.
Lines 140 to 146..
Code:
                    new BonusHarvestResource(0, 99.4, null, null), //Nothing
                    new BonusHarvestResource(100, .1, 1072562, typeof(BlueDiamond)),
                    new BonusHarvestResource(100, .1, 1072567, typeof(DarkSapphire)),
                    new BonusHarvestResource(100, .1, 1072570, typeof(EcruCitrine)),
                    new BonusHarvestResource(100, .1, 1072564, typeof(FireRuby)),
                    new BonusHarvestResource(100, .1, 1072566, typeof(PerfectEmerald)),
                    new BonusHarvestResource(100, .1, 1072568, typeof(Turquoise))
Changing the numbers in here can increase the chances of getting the bonus resources (gems) without resorting to toggling for mining gems. See the 99.4? That means that 99.4 times out of 100 you will get nothing. By changing that & the .1 numbers, you can increase the chances. BUT.. they HAVE to equal 100, no more, no less. ex:
Code:
                    new BonusHarvestResource(0, 49.0, null, null), //Nothing
                    new BonusHarvestResource(100, 8.5, 1072562, typeof(BlueDiamond)),
                    new BonusHarvestResource(100, 8.5, 1072567, typeof(DarkSapphire)),
                    new BonusHarvestResource(100, 8.5, 1072570, typeof(EcruCitrine)),
                    new BonusHarvestResource(100, 8.5, 1072564, typeof(FireRuby)),
                    new BonusHarvestResource(100, 8.5, 1072566, typeof(PerfectEmerald)),
                    new BonusHarvestResource(100, 8.5, 1072568, typeof(Turquoise))
8.5 x 6 = 51 + 49 = 100 So 49 times out of 100... nothing.. 51 times out of 100 you have a 1 in 6 chance of getting one of the 6 gems. And that happens as the player is mining for ore. No toggling, no crash. ;)
 

sec_goat

Squire
Sounds Good HammerHand I will try that!

In the meantime I am looking into MyLumberjacking problem and it looks like there might be a typo in the Daat99's OWLTR LOG.cs around line 151 i think

Code:
    public override bool Axe(Mobile from, BaseAxe axe)
        {
            if (!TryCreateBoards(from, 95, new Board()))
                return false;
 
            return true;
        }
    }

this in the class Log : BaseLog. Basically means players cannot make logs at all until they are practically GMED. I changed mine down to 0 and it seems to be working now.

I will report back On the mining front, I think you are correct and this will probably at least keep the server from crashing.However I know that in terms of SA mining the ToggleGemMining allows players to mine the small gems which is used with imbuing.

This is the problem with using a SA fork, it adds so much complexity that no one is really ready for, and that I certainley do not fully understand.

Thanks again for your help!
 

sec_goat

Squire
I gave it a shot, other than changing the drop rate for large gems and I still get the same issue, something funky I have done in merging maybe, either way it is crashing in harvestSystem / Daats Resource helper.

It appears that when of the some ore is dug up line 67 of ResourceHelper has some null returns?

Code:
CraftResourceInfo info = CraftResources.GetInfo(resultCraftResource);

it works fine for a while but then the info on line 67 turns up as NULL.

So I take it back, not a gem mining problem, goes back to a bad merge most likely!

If you have any suggestions I am glad to take them :)

Thanks again for all your work and help!


HUGE EDIT:

HammerHand thanks for all your help I finally tracked down the culprit using Cosnole.WriteLine

I had to edit my GetType in ResourceInfo.cs to account for the new material types
Line 1314 in mine was only accounting for the OSI types.

Looks good so far!

Code:
 public static CraftResourceType GetType(CraftResource resource)
        {
            if (resource >= CraftResource.Iron && resource <= CraftResource.Platinum)
                return CraftResourceType.Metal;
 
            if (resource >= CraftResource.RegularLeather && resource <= CraftResource.EtherealLeather)
                return CraftResourceType.Leather;
 
            if (resource >= CraftResource.RedScales && resource <= CraftResource.GoldScales)
                return CraftResourceType.Scales;
 
            if (resource >= CraftResource.RegularWood && resource <= CraftResource.Petrified)
                return CraftResourceType.Wood;
 
            return CraftResourceType.None;
        }
 

daat99

Moderator
Staff member
Can you post these files in code tags please?
crash log said:
at daat99.ResourceHelper.GetDaat99HarvestedType(Type originalType, Boolean prospected, Double skill) in c:\RunUO\Scripts\Custom Systems\OWLTR 3.01.00\New\Resource Helper.cs:line 70
at Server.Engines.Harvest.HarvestSystem.FinishHarvesting(Mobile from, Item tool, HarvestDefinition def, Object toHarvest, Object locked) in c:\RunUO\Scripts\Services\Harvest\Core\HarvestSystem.cs:line 161
at Server.Engines.Harvest.HarvestSoundTimer.OnTick() in c:\RunUO\Scripts\Services\Harvest\Core\HarvestSoundTimer.cs:line 31
 

sec_goat

Squire
Sure thing daat99 I think I have resolved it but I would be more than happy to have you look it over ;)

Here is ResourceHelper.cs

Code:
using System;
using System.Collections.Generic;
using Server.Items;
using Server.Engines.Craft;
using Server;
 
namespace daat99
{
    public static class ResourceHelper
    {
        private static readonly int CANT_CRAFT_METAL = 1044268;
        private static readonly int CANT_CRAFT_STONE_GRANITE = 1044526;
        //private static readonly int CANT_CRAFT_STONE_OTHERS = 1044527;
        private static readonly int CANT_CRAFT_WOOD = 1044268;
        private static readonly int CANT_CRAFT_SCALE = 1044268;
        private static readonly int CANT_CRAFT_LEATHER = 1044462;
 
        private static Dictionary<CraftResource, double> craftResourceMinSkill;
        public static Dictionary<CraftResource, double> CraftResourceMinSkill
        {
            get
            {
                if (craftResourceMinSkill == null)
                {
                    craftResourceMinSkill = new Dictionary<CraftResource, double>();
                    foreach (ResourceData data in Resources)
                    {
                        try
                        {
                            if (!craftResourceMinSkill.ContainsKey(data.CraftResource))
                                craftResourceMinSkill.Add(data.CraftResource, data.MinSkill);
                        }
                        catch { }
                    }
                }
                return craftResourceMinSkill;
            }
        }
 
        public static Type GetDaat99HarvestedType(Type originalType, bool prospected, double skill)
        {
 
            double MAX_SKILL = 130.0;
            if (skill > MAX_SKILL)
                skill = MAX_SKILL;
            double chance = Utility.RandomMinMax(1, (int)(skill*10))/10.0 + (prospected ? 10 : 0);
 
            CraftResource originalCraftResource = CraftResources.GetFromType(originalType);
            CraftResource firstCraftResource = GetFirstCraftResourceFromType(originalCraftResource);
            CraftResource resultCraftResource = firstCraftResource;
 
 
            if ( Utility.RandomDouble() < 0.3 )
            {
                CraftResource check = GetLastCraftResourceFromType(originalCraftResource);
                double diff = MAX_SKILL/((int)check - (int)firstCraftResource + 1);
               
                for ( ; check > firstCraftResource; check = (CraftResource)((int)check - 1) )
                {
                    double minSkill = GetMinSkill(check);
                    if ( skill < minSkill )
                        continue;
                    if (chance > minSkill - diff)
                    {
                        resultCraftResource = check;
                        break;
                    }
                }
            }
            CraftResourceInfo info = CraftResources.GetInfo(resultCraftResource);
            if (originalType.IsSubclassOf(typeof(BaseGranite)) && info.ResourceTypes.Length > 2)
                return info.ResourceTypes[2];
            if (info.ResourceTypes.Length > 1)
                return info.ResourceTypes[1];
            return info.ResourceTypes[0];
        }
 
        private static Dictionary<CraftResource, ResourceData> craftResourceDataList;
        public static Dictionary<CraftResource, ResourceData> CraftResourceDataList
        {
            get
            {
                if (craftResourceDataList == null)
                {
                    craftResourceDataList = new Dictionary<CraftResource, ResourceData>();
                    foreach (ResourceData data in Resources)
                    {
                        try
                        {
                            if (!craftResourceDataList.ContainsKey(data.CraftResource))
                                craftResourceDataList.Add(data.CraftResource, data);
                        }
                        catch { }
                    }
                }
                return craftResourceDataList;
            }
        }
 
        public static double GetMinSkill(CraftResource resource)
        {
            if (CraftResourceMinSkill.ContainsKey(resource))
                return CraftResourceMinSkill[resource];
            return 0.0;
        }
 
        private static List<ResourceData> resources;
        private static List<ResourceData> Resources
        {
            get
            {
                if ( resources == null )
                {
                    resources = new List<ResourceData>();
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Iron,            "Iron",            typeof(IronIngot),            typeof(IronOre),          00.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.DullCopper,        "Dull Copper",        typeof(DullCopperIngot),    typeof(DullCopperOre),      20.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.ShadowIron,        "Shadow Iron",        typeof(ShadowIronIngot),    typeof(ShadowIronOre),      30.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Copper,            "Copper",            typeof(CopperIngot),        typeof(CopperOre),          40.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Bronze,            "Bronze",            typeof(BronzeIngot),        typeof(BronzeOre),          50.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Gold,            "Gold",            typeof(GoldIngot),            typeof(GoldOre),          60.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Agapite,            "Agapite",            typeof(AgapiteIngot),        typeof(AgapiteOre),      70.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Verite,            "Verite",            typeof(VeriteIngot),        typeof(VeriteOre),          80.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Valorite,        "Valorite",        typeof(ValoriteIngot),        typeof(ValoriteOre),      90.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Blaze,            "Blaze",            typeof(BlazeIngot),        typeof(BlazeOre),        100.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Ice,                "Ice",                typeof(IceIngot),            typeof(IceOre),        105.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Toxic,            "Toxic",            typeof(ToxicIngot),        typeof(ToxicOre),        110.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Electrum,        "Electrum",        typeof(ElectrumIngot),        typeof(ElectrumOre),    115.0, CANT_CRAFT_METAL));
                    resources.Add( new ResourceData(CraftResourceType.Metal,    CraftResource.Platinum,        "Platinum",        typeof(PlatinumIngot),        typeof(PlatinumOre),    119.0, CANT_CRAFT_METAL));
                   
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.RegularWood,        "Log",                typeof(Board),                typeof(Log),              00.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.OakWood,            "Oak",                typeof(OakBoard),            typeof(OakLog),          20.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.AshWood,            "Ash",                typeof(AshBoard),            typeof(AshLog),          30.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.YewWood,            "Yew",                typeof(YewBoard),            typeof(YewLog),          40.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.Heartwood,        "Heartwood",        typeof(HeartwoodBoard),    typeof(HeartwoodLog),      50.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.Bloodwood,        "Bloodwood",        typeof(BloodwoodBoard),    typeof(BloodwoodLog),      60.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.Frostwood,        "Frostwood",        typeof(FrostwoodBoard),    typeof(FrostwoodLog),      70.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.Ebony,            "Ebony",            typeof(EbonyBoard),        typeof(EbonyLog),          80.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.Bamboo,            "Bamboo",            typeof(BambooBoard),        typeof(BambooLog),          90.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.PurpleHeart,        "PurpleHeart",        typeof(PurpleHeartBoard),    typeof(PurpleHeartLog), 100.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.Redwood,            "Redwood",            typeof(RedwoodBoard),        typeof(RedwoodLog),    110.0, CANT_CRAFT_WOOD));
                    resources.Add( new ResourceData(CraftResourceType.Wood,    CraftResource.Petrified,        "Petrified",        typeof(PetrifiedBoard),    typeof(PetrifiedLog),    119.0, CANT_CRAFT_WOOD));
                   
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.RegularLeather,    "Regular Leather",    typeof(Leather),            typeof(Hides),              00.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.SpinedLeather,    "Spined Leather",    typeof(SpinedLeather),        typeof(SpinedHides),      20.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.HornedLeather,    "Horned Leather",    typeof(HornedLeather),        typeof(HornedHides),      35.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.BarbedLeather,    "Barbed Leather",    typeof(BarbedLeather),        typeof(BarbedHides),      50.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.PolarLeather,      "Polar Leather",    typeof(PolarLeather),        typeof(PolarHides),      60.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.SyntheticLeather,    "Synthetic Leather",typeof(SyntheticLeather),    typeof(SyntheticHides),  70.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.BlazeLeather,        "Blaze Leather",    typeof(BlazeLeather),        typeof(BlazeHides),      80.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.DaemonicLeather,    "Daemonic Leather",    typeof(DaemonicLeather),    typeof(DaemonicHides),      90.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.ShadowLeather,    "Shadow Leather",    typeof(ShadowLeather),        typeof(ShadowHides),    100.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.FrostLeather,        "Frost Leather",    typeof(FrostLeather),        typeof(FrostHides),    110.0, CANT_CRAFT_LEATHER));
                    resources.Add( new ResourceData(CraftResourceType.Leather,    CraftResource.EtherealLeather,    "Ethereal Leather", typeof(EtherealLeather),    typeof(EtherealHides),    119.0, CANT_CRAFT_LEATHER));                   
                   
                    resources.Add( new ResourceData(CraftResourceType.Scales,    CraftResource.RedScales,        "Red Scales",        typeof(RedScales),            typeof(RedScales),          00.0, CANT_CRAFT_SCALE));
                    resources.Add( new ResourceData(CraftResourceType.Scales,    CraftResource.YellowScales,        "Yellow Scales",    typeof(YellowScales),        typeof(YellowScales),    00.0, CANT_CRAFT_SCALE));
                    resources.Add( new ResourceData(CraftResourceType.Scales,    CraftResource.BlackScales,        "Black Scales",        typeof(BlackScales),        typeof(BlackScales),      00.0, CANT_CRAFT_SCALE));
                    resources.Add( new ResourceData(CraftResourceType.Scales,    CraftResource.GreenScales,        "Green Scales",        typeof(GreenScales),        typeof(GreenScales),      00.0, CANT_CRAFT_SCALE));
                    resources.Add( new ResourceData(CraftResourceType.Scales,    CraftResource.WhiteScales,        "White Scales",        typeof(WhiteScales),        typeof(WhiteScales),      00.0, CANT_CRAFT_SCALE));
                    resources.Add( new ResourceData(CraftResourceType.Scales,    CraftResource.BlueScales,        "Blue Scales",        typeof(BlueScales),        typeof(BlueScales),      00.0, CANT_CRAFT_SCALE));
                    resources.Add( new ResourceData(CraftResourceType.Scales,    CraftResource.CopperScales,        "Copper Scales",    typeof(CopperScales),        typeof(CopperScales),      00.0, CANT_CRAFT_SCALE));
                    resources.Add( new ResourceData(CraftResourceType.Scales,    CraftResource.SilverScales,        "Silver Scales",    typeof(SilverScales),        typeof(SilverScales),      00.0, CANT_CRAFT_SCALE));
                    resources.Add( new ResourceData(CraftResourceType.Scales,    CraftResource.GoldScales,        "Gold Scales",        typeof(GoldScales),        typeof(GoldScales),      00.0, CANT_CRAFT_SCALE));
                   
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Iron,            "Granite",            typeof(Granite),            typeof(Granite),          00.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.DullCopper,        "Dull Copper",        typeof(DullCopperGranite),    typeof(DullCopperGranite),20.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.ShadowIron,        "Shadow Iron",        typeof(ShadowIronGranite),    typeof(ShadowIronGranite),30.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Copper,            "Copper",            typeof(CopperGranite),        typeof(CopperGranite),      40.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Bronze,            "Bronze",            typeof(BronzeGranite),        typeof(BronzeGranite),      50.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Gold,            "Gold",            typeof(GoldGranite),        typeof(GoldGranite),      60.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Agapite,            "Agapite",            typeof(AgapiteGranite),    typeof(AgapiteGranite),  70.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Verite,            "Verite",            typeof(VeriteGranite),        typeof(VeriteGranite),      80.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Valorite,        "Valorite",        typeof(ValoriteGranite),    typeof(ValoriteGranite), 90.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Blaze,            "Blaze",            typeof(BlazeGranite),        typeof(BlazeGranite),    100.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Ice,                "Ice",                typeof(IceGranite),        typeof(IceGranite),    105.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Toxic,            "Toxic",            typeof(ToxicGranite),        typeof(ToxicGranite),    110.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Electrum,        "Electrum",        typeof(ElectrumGranite),    typeof(ElectrumGranite),115.0, CANT_CRAFT_STONE_GRANITE));
                    resources.Add( new ResourceData(CraftResourceType.None,    CraftResource.Platinum,        "Platinum",        typeof(PlatinumGranite),    typeof(PlatinumGranite),119.0, CANT_CRAFT_STONE_GRANITE));
                }
                return resources;
            }
        }
 
        #region AddCraftingResources
        //daat99.ResourceHelper.AddMetalResources(this);
        public static void AddMetalResources(CraftSystem system)
        {
            bool first = true;
            foreach ( ResourceData data in Resources )
            {
                if ( data.ResourceType == CraftResourceType.Metal )
                {
                    if ( first )
                    {
                        system.SetSubRes( data.ItemType, data.Name );
                        first = false;
                    }
                    system.AddSubRes( data.ItemType, data.Name, data.MinSkill, data.CantCraftMessage );
                }
            }
        }
       
        //daat99.ResourceHelper.AddStoneResources(this);
        public static void AddStoneResources(CraftSystem system)
        {   
            bool first = true;
            foreach ( ResourceData data in Resources )
            {
                if ( data.ResourceType == CraftResourceType.None )
                {
                    if ( first )
                    {
                        system.SetSubRes( data.ItemType, data.Name );
                        first = false;
                    }
                    system.AddSubRes( data.ItemType, data.Name, data.MinSkill, data.CantCraftMessage );
                }
            }
        }
 
        //daat99.ResourceHelper.AddWoodResources(this);
        public static void AddWoodResources(CraftSystem system)
        {
            bool first = true;
            foreach ( ResourceData data in Resources )
            {
                if ( data.ResourceType == CraftResourceType.Wood )
                {
                    if ( first )
                    {
                        system.SetSubRes( data.RawType, data.Name );
                        first = false;
                    }
                    system.AddSubRes( data.RawType, data.Name, data.MinSkill, data.CantCraftMessage );
                }
            }
        }
       
        //daat99.ResourceHelper.AddScaleResources(this);
        public static void AddScaleResources(CraftSystem system)
        {   
            bool first = true;
            foreach ( ResourceData data in Resources )
            {
                if ( data.ResourceType == CraftResourceType.Scales )
                {
                    if ( first )
                    {
                        system.SetSubRes2( data.ItemType, data.Name );
                        first = false;
                    }
                    system.AddSubRes2( data.ItemType, data.Name, data.MinSkill, data.CantCraftMessage );
                }
            }
        }
       
        //daat99.ResourceHelper.AddTailorResources(this);
        public static void AddTailorResources(CraftSystem system)
        {
            bool first = true;
            foreach ( ResourceData data in Resources )
            {
                if ( data.ResourceType == CraftResourceType.Leather )
                {
                    if ( first )
                    {
                        system.SetSubRes( data.ItemType, data.Name );
                        first = false;
                    }
                    system.AddSubRes( data.ItemType, data.Name, data.MinSkill, data.CantCraftMessage );
                }
            }
        }
        #endregion AddCraftingResources
 
        public class ResourceData
        {
            public static ResourceData EMPTY = new ResourceData(CraftResourceType.None, CraftResource.None, "", null, null, 0.0, 0);
            public CraftResource CraftResource;
            public string Name;
            public double MinSkill;
            public int CantCraftMessage;
            public Type RawType;
            public Type ItemType;
            public CraftResourceType ResourceType;
            public int Level;
           
            public ResourceData( CraftResourceType resourceType, CraftResource craftResource, string name, Type itemType, Type raw, double minSkill, int cantCraftMessage)
            {
                this.ResourceType = resourceType;
                this.CraftResource = craftResource;
                this.Name = name;
                this.RawType = raw;
                this.ItemType = itemType;
                this.MinSkill = minSkill;
                this.CantCraftMessage = cantCraftMessage;
                this.Level = (int)craftResource;
            }
        }
 
        public static CraftResource GetLastCraftResourceFromType(CraftResource resource)
        {
            switch (CraftResources.GetType(resource))
            {
                case CraftResourceType.Metal:
                    return CraftResource.Platinum;
                case CraftResourceType.Leather:
                    return CraftResource.EtherealLeather;
                case CraftResourceType.Wood:
                    return CraftResource.Petrified;
                case CraftResourceType.Scales:
                    return CraftResource.GoldScales;
            }
            return CraftResource.None;
        }
 
        public static CraftResource GetFirstCraftResourceFromType(CraftResource resource)
        {
            switch (CraftResources.GetType(resource))
            {
                case CraftResourceType.Metal:
                    return CraftResource.Iron;
                case CraftResourceType.Leather:
                    return CraftResource.RegularLeather;
                case CraftResourceType.Wood:
                    return CraftResource.RegularWood;
                case CraftResourceType.Scales:
                    return CraftResource.RedScales;
            }
            return CraftResource.None;
        }
 
        public static Type[][] GetTypesTable()
        {
            return new Type[][]
            {
                //OSI woods
                new Type[]{ typeof( Log ),                typeof( Board ) },
                new Type[]{ typeof( OakLog ),            typeof( OakBoard ) },
                new Type[]{ typeof( AshLog ),            typeof( AshBoard ) },
                new Type[]{ typeof( YewLog ),            typeof( YewBoard ) },
                new Type[]{ typeof( HeartwoodLog ),    typeof( HeartwoodBoard ) },
                new Type[]{ typeof( BloodwoodLog ),    typeof( BloodwoodBoard ) },
                new Type[]{ typeof( FrostwoodLog ),    typeof( FrostwoodBoard ) },
                //OWLTR custom woods
                new Type[]{ typeof( EbonyLog ),        typeof( EbonyBoard ) },
                new Type[]{ typeof( BambooLog ),        typeof( BambooBoard ) },
                new Type[]{ typeof( PurpleHeartLog ),    typeof( PurpleHeartBoard ) },
                new Type[]{ typeof( RedwoodLog ),        typeof( RedwoodBoard ) },
                new Type[]{ typeof( PetrifiedLog ),    typeof( PetrifiedBoard ) },
                //OSI leathers
                new Type[]{ typeof( Leather ),            typeof( Hides ) },
                new Type[]{ typeof( SpinedLeather ),    typeof( SpinedHides ) },
                new Type[]{ typeof( HornedLeather ),    typeof( HornedHides ) },
                new Type[]{ typeof( BarbedLeather ),    typeof( BarbedHides ) },
                //OWLTR leathers
                new Type[]{ typeof( PolarLeather ),    typeof( PolarHides ) },
                new Type[]{ typeof( SyntheticLeather ), typeof( SyntheticHides ) },
                new Type[]{ typeof( BlazeLeather ),    typeof( BlazeHides ) },
                new Type[]{ typeof( DaemonicLeather ),    typeof( DaemonicHides ) },
                new Type[]{ typeof( ShadowLeather ),    typeof( ShadowHides ) },
                new Type[]{ typeof( FrostLeather ),    typeof( FrostHides ) },
                new Type[]{ typeof( EtherealLeather ),    typeof( EtherealHides ) },
                //OSI other items
                new Type[]{ typeof( BlankMap ),        typeof( BlankScroll ) },
                new Type[]{ typeof( Cloth ),            typeof( UncutCloth ) },
                new Type[]{ typeof( CheeseWheel ),        typeof( CheeseWedge ) },
                new Type[]{ typeof( Pumpkin ),            typeof( SmallPumpkin ) },
                new Type[]{ typeof( WoodenBowlOfPeas ), typeof( PewterBowlOfPeas ) }
            };
        }
    }
}

HarevestSystem.cs

Code:
using System;
using System.Collections;
using System.Collections.Generic;
using Server;
using Server.Items;
using Server.Targeting;
using daat99;
 
namespace Server.Engines.Harvest
{
    public abstract class HarvestSystem
    {
        private List<HarvestDefinition> m_Definitions;
        public List<HarvestDefinition> Definitions { get { return m_Definitions; } }
        public HarvestSystem()
        {
            m_Definitions = new List<HarvestDefinition>();
        }
 
        public virtual bool CheckTool(Mobile from, Item tool)
        {
            bool wornOut = (tool == null || tool.Deleted || (tool is IUsesRemaining && ((IUsesRemaining)tool).UsesRemaining <= 0));
 
            if (wornOut)
                from.SendLocalizedMessage(1044038); // You have worn out your tool!
 
            return !wornOut;
        }
 
        public virtual bool CheckHarvest(Mobile from, Item tool)
        {
            return CheckTool( from, tool );
        }
 
        public virtual bool CheckHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
        {
            return CheckTool( from, tool );
        }
 
        public virtual bool CheckRange(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed)
        {
            bool inRange = (from.Map == map && from.InRange(loc, def.MaxRange));
 
            if (!inRange)
                def.SendMessageTo(from, timed ? def.TimedOutOfRangeMessage : def.OutOfRangeMessage);
 
            return inRange;
        }
 
        public virtual bool CheckResources(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, bool timed)
        {
            HarvestBank bank = def.GetBank(map, loc.X, loc.Y);
            bool available = (bank != null && bank.Current >= def.ConsumedPerHarvest);
 
            if (!available)
                def.SendMessageTo(from, timed ? def.DoubleHarvestMessage : def.NoResourcesMessage);
 
            return available;
        }
 
        public virtual void OnBadHarvestTarget(Mobile from, Item tool, object toHarvest)
        {
        }
 
        public virtual object GetLock(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
        {
            /* Here we prevent multiple harvesting.
            *
            * Some options:
            *  - 'return tool;' : This will allow the player to harvest more than once concurrently, but only if they use multiple tools. This seems to be as OSI.
            *  - 'return GetType();' : This will disallow multiple harvesting of the same type. That is, we couldn't mine more than once concurrently, but we could be both mining and lumberjacking.
            *  - 'return typeof( HarvestSystem );' : This will completely restrict concurrent harvesting.
            */
            return tool;
        }
 
        public virtual void OnConcurrentHarvest(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
        {
        }
 
        public virtual void OnHarvestStarted(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
        {
        }
 
        public virtual bool BeginHarvesting(Mobile from, Item tool)
        {
            if ( !CheckHarvest( from, tool ) )
                return false;
 
            from.Target = new HarvestTarget(tool, this);
            return true;
        }
 
        public virtual void FinishHarvesting(Mobile from, Item tool, HarvestDefinition def, object toHarvest, object locked)
        {
            from.EndAction(locked);
 
            if ( !CheckHarvest( from, tool ) )
                return;
 
            int tileID;
            Map map;
            Point3D loc;
 
            if ( !GetHarvestDetails( from, tool, toHarvest, out tileID, out map, out loc ) )
            {
                OnBadHarvestTarget( from, tool, toHarvest );
                return;
            }
            else if (!def.Validate(tileID))
            {
                OnBadHarvestTarget( from, tool, toHarvest );
                return;
            }
           
            if ( !CheckRange( from, tool, def, map, loc, true ) )
                return;
            else if ( !CheckResources( from, tool, def, map, loc, true ) )
                return;
            else if ( !CheckHarvest( from, tool, def, toHarvest ) )
                return;
 
            if ( SpecialHarvest( from, tool, def, map, loc ) )
                return;
 
            HarvestBank bank = def.GetBank(map, loc.X, loc.Y);
 
            if (bank == null)
                return;
 
            HarvestVein vein = bank.Vein;
 
            if (vein != null)
                vein = MutateVein( from, tool, def, bank, toHarvest, vein );
 
            if (vein == null)
                return;
 
            HarvestResource primary = vein.PrimaryResource;
            HarvestResource fallback = vein.FallbackResource;
            HarvestResource resource = MutateResource( from, tool, def, map, loc, vein, primary, fallback );
 
            double skillBase = from.Skills[def.Skill].Base;
            double skillValue = from.Skills[def.Skill].Value;
 
            Type type = null;
            //daat99 OWLTR start - daat99 harvesting
            type = GetResourceType(from, tool, def, map, loc, resource);
            bool daatHarvesting = false;
            if (daat99.OWLTROptionsManager.IsEnabled(daat99.OWLTROptionsManager.OPTIONS_ENUM.DAAT99_MINING) && (type.IsSubclassOf(typeof(BaseOre)) || type.IsSubclassOf(typeof(BaseGranite))))
                daatHarvesting = true;
            else if (daat99.OWLTROptionsManager.IsEnabled(daat99.OWLTROptionsManager.OPTIONS_ENUM.DAAT99_LUMBERJACKING) && type.IsSubclassOf(typeof(BaseLog)))
                daatHarvesting = true;
            if ( daatHarvesting || (skillBase >= resource.ReqSkill && from.CheckSkill( def.Skill, resource.MinSkill, resource.MaxSkill )) )
            {
 
                if (type != null)
                    type = MutateType( type, from, tool, def, map, loc, resource );
                if (daatHarvesting)
                {
                    type = ResourceHelper.GetDaat99HarvestedType(type, bank.Vein.IsProspected, skillValue);
                    //type = GetResourceType(from, tool, def, map, loc, resource);
                    from.CheckSkill(def.Skill, 0.0, from.Skills[def.Skill].Cap + (vein.IsProspected?10.0:0.0));
                }
                //daat99 OWLTR end - daat99 harvesting
 
                if (type != null)
                {
                    Item item = Construct( type, from );
 
                    if (item == null)
                    {
                        type = null;
                    }
                    else
                    {
                        //The whole harvest system is kludgy and I'm sure this is just adding to it.
                        if (item.Stackable)
                        {
                            int amount = def.ConsumedPerHarvest;
                            int feluccaAmount = def.ConsumedPerFeluccaHarvest;
 
                            int racialAmount = (int)Math.Ceiling(amount * 1.1);
                            int feluccaRacialAmount = (int)Math.Ceiling(feluccaAmount * 1.1);
 
                            bool eligableForRacialBonus = (def.RaceBonus && from.Race == Race.Human);
                            bool inFelucca = (map == Map.Felucca);
 
                            if (eligableForRacialBonus && inFelucca && bank.Current >= feluccaRacialAmount && 0.1 > Utility.RandomDouble())
                                item.Amount = feluccaRacialAmount;
                            else if (inFelucca && bank.Current >= feluccaAmount)
                                item.Amount = feluccaAmount;
                            else if (eligableForRacialBonus && bank.Current >= racialAmount && 0.1 > Utility.RandomDouble())
                                item.Amount = racialAmount;
                            else
                                item.Amount = amount;
                        }
 
                        bank.Consume(item.Amount, from);
                        //daat99 OWLTR start - custom harvesting
                        CraftResource craftResourceFromType = CraftResources.GetFromType(type);
                        string s_Type = "UNKNOWN";
                        int i_Tokens = 1;
                        if (craftResourceFromType != CraftResource.None)
                        {
                            s_Type = CraftResources.GetInfo(craftResourceFromType).Name;
                            i_Tokens = CraftResources.GetIndex(craftResourceFromType) + 1;
                        }
                        if (craftResourceFromType != CraftResource.None && daat99.OWLTROptionsManager.IsEnabled(daat99.OWLTROptionsManager.OPTIONS_ENUM.DAAT99_MINING) && def.Skill == SkillName.Mining && (type.IsSubclassOf(typeof(Server.Items.BaseOre)) || type.IsSubclassOf(typeof(Server.Items.BaseGranite))))
                        {
                            if (type.IsSubclassOf(typeof(Server.Items.BaseOre)))
                            {
                                if ( Give( from, item, def.PlaceAtFeetIfFull ) )
                                    from.SendMessage("You dig some {0} ore and placed it in your backpack.", s_Type);
                                else
                        {
                                    from.SendMessage("Your backpack is full, so the ore you mined is lost.");
                                    item.Delete();
                                }
                            }
                            else
                            {
                                if ( Give( from, item, def.PlaceAtFeetIfFull ) )
                                    from.SendMessage("You carefully extract some workable stone from the ore vein.");
                                else
                                {
                                    from.SendMessage("Your backpack is full, so the ore you mined is lost.");
                                    item.Delete();
                                }
                            }
                        }
                        else if (craftResourceFromType != CraftResource.None && OWLTROptionsManager.IsEnabled(OWLTROptionsManager.OPTIONS_ENUM.DAAT99_LUMBERJACKING) && def.Skill == SkillName.Lumberjacking)
                        {
                            if ( Give( from, item, def.PlaceAtFeetIfFull ) )
                                from.SendMessage("You placed some {0} logs in your backpack.", s_Type);
                            else
                            {
                                from.SendMessage("You can't place any wood into your backpack!");
                                item.Delete();
                            }
                        }
                        else
                        {
                        //daat99 OWLTR end - custom harvesting
                            if ( Give( from, item, def.PlaceAtFeetIfFull ) )
                            {
                                SendSuccessTo( from, item, resource );
                        }
                        else
                        {
                                SendPackFullTo( from, item, def, resource );
                            item.Delete();
                        }
                        //daat99 OWLTR start - custom harvesting
                        }
                        if (from.Map == Map.Felucca)
                            i_Tokens = (int)(i_Tokens*1.5);
                        if ( OWLTROptionsManager.IsEnabled(OWLTROptionsManager.OPTIONS_ENUM.HARVEST_GIVE_TOKENS) )
                            TokenSystem.GiveTokensToPlayer(from as Server.Mobiles.PlayerMobile, i_Tokens);
                        //daat99 OWLTR end - custom harvesting
 
                        BonusHarvestResource bonus = def.GetBonusResource();
 
                        if (bonus != null && bonus.Type != null && skillBase >= bonus.ReqSkill)
                        {
                            Item bonusItem = Construct( bonus.Type, from );
 
                            if ( Give( from, bonusItem, true ) )    //Bonuses always allow placing at feet, even if pack is full irregrdless of def
                            {
                                bonus.SendSuccessTo(from);
                            }
                            else
                            {
                                item.Delete();
                            }
                        }
 
                        if (tool is IUsesRemaining)
                        {
                            IUsesRemaining toolWithUses = (IUsesRemaining)tool;
 
                            toolWithUses.ShowUsesRemaining = true;
 
                            if (toolWithUses.UsesRemaining > 0)
                                --toolWithUses.UsesRemaining;
 
                            if (toolWithUses.UsesRemaining < 1)
                            {
                                tool.Delete();
                                def.SendMessageTo(from, def.ToolBrokeMessage);
                            }
                        }
                    }
                }
            }
 
            if (type == null)
                def.SendMessageTo(from, def.FailMessage);
 
            //daat99 OWLTR start - custom harvesting
            if ( this is Lumberjacking || this is Mining )
                OnHarvestFinished( from, tool, def, vein, bank, resource, toHarvest, type );
            else
            //daat99 OWLTR end - custom harvesting
            OnHarvestFinished( from, tool, def, vein, bank, resource, toHarvest );
        }
 
        //daat99 OWLTR start - custom resources
        public virtual void OnHarvestFinished( Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, HarvestBank bank, HarvestResource resource, object harvested, Type type )
        {
        }
        //daat99 OWLTR end - custom resources
        public virtual void OnHarvestFinished(Mobile from, Item tool, HarvestDefinition def, HarvestVein vein, HarvestBank bank, HarvestResource resource, object harvested)
        {
        }
 
        public virtual bool SpecialHarvest(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc)
        {
            return false;
        }
 
        public virtual Item Construct(Type type, Mobile from)
        {
            try{ return Activator.CreateInstance( type ) as Item; }
            catch{ return null; }
        }
 
        public virtual HarvestVein MutateVein(Mobile from, Item tool, HarvestDefinition def, HarvestBank bank, object toHarvest, HarvestVein vein)
        {
            return vein;
        }
 
        public virtual void SendSuccessTo(Mobile from, Item item, HarvestResource resource)
        {
            resource.SendSuccessTo(from);
        }
 
        public virtual void SendPackFullTo(Mobile from, Item item, HarvestDefinition def, HarvestResource resource)
        {
            def.SendMessageTo(from, def.PackFullMessage);
        }
 
        public virtual bool Give(Mobile m, Item item, bool placeAtFeet)
        {
            if (m.PlaceInBackpack(item))
                return true;
 
            if (!placeAtFeet)
                return false;
 
            Map map = m.Map;
 
            if (map == null)
                return false;
 
            List<Item> atFeet = new List<Item>();
 
            foreach (Item obj in m.GetItemsInRange(0))
                atFeet.Add(obj);
 
            for (int i = 0; i < atFeet.Count; ++i)
            {
                Item check = atFeet[i];
 
                if (check.StackWith(m, item, false))
                    return true;
            }
 
            item.MoveToWorld(m.Location, map);
            return true;
        }
 
        public virtual Type MutateType(Type type, Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestResource resource)
        {
            return from.Region.GetResource(type);
        }
 
        public virtual Type GetResourceType(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestResource resource)
        {
            if (resource.Types.Length > 0)
                return resource.Types[Utility.Random(resource.Types.Length)];
 
            return null;
        }
 
        public virtual HarvestResource MutateResource(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc, HarvestVein vein, HarvestResource primary, HarvestResource fallback)
        {
            bool racialBonus = (def.RaceBonus && from.Race == Race.Elf);
 
            if (vein.ChanceToFallback > (Utility.RandomDouble() + (racialBonus ? .20 : 0)))
                return fallback;
 
            double skillValue = from.Skills[def.Skill].Value;
 
            if (fallback != null && (skillValue < primary.ReqSkill || skillValue < primary.MinSkill))
                return fallback;
 
            return primary;
        }
 
        public virtual bool OnHarvesting(Mobile from, Item tool, HarvestDefinition def, object toHarvest, object locked, bool last)
        {
            if ( !CheckHarvest( from, tool ) )
            {
                from.EndAction(locked);
                return false;
            }
 
            int tileID;
            Map map;
            Point3D loc;
 
            if ( !GetHarvestDetails( from, tool, toHarvest, out tileID, out map, out loc ) )
            {
                from.EndAction(locked);
                OnBadHarvestTarget( from, tool, toHarvest );
                return false;
            }
            else if (!def.Validate(tileID))
            {
                from.EndAction(locked);
                OnBadHarvestTarget( from, tool, toHarvest );
                return false;
            }
            else if ( !CheckRange( from, tool, def, map, loc, true ) )
            {
                from.EndAction(locked);
                return false;
            }
            else if ( !CheckResources( from, tool, def, map, loc, true ) )
            {
                from.EndAction(locked);
                return false;
            }
            else if ( !CheckHarvest( from, tool, def, toHarvest ) )
            {
                from.EndAction(locked);
                return false;
            }
 
            DoHarvestingEffect( from, tool, def, map, loc );
 
            new HarvestSoundTimer(from, tool, this, def, toHarvest, locked, last).Start();
 
            return !last;
        }
 
        public virtual void DoHarvestingSound(Mobile from, Item tool, HarvestDefinition def, object toHarvest)
        {
            if (def.EffectSounds.Length > 0)
                from.PlaySound(Utility.RandomList(def.EffectSounds));
        }
 
        public virtual void DoHarvestingEffect(Mobile from, Item tool, HarvestDefinition def, Map map, Point3D loc)
        {
            from.Direction = from.GetDirectionTo(loc);
 
            if (!from.Mounted)
                from.Animate(Utility.RandomList(def.EffectActions), 5, 1, true, false, 0);
        }
 
        public virtual HarvestDefinition GetDefinition(int tileID)
        {
            HarvestDefinition def = null;
 
            for ( int i = 0; def == null && i < m_Definitions.Count; ++i )
            {
                HarvestDefinition check = m_Definitions[i];
 
                if (check.Validate(tileID))
                    def = check;
            }
 
            return def;
        }
 
        public virtual void StartHarvesting(Mobile from, Item tool, object toHarvest)
        {
            if ( !CheckHarvest( from, tool ) )
                return;
 
            int tileID;
            Map map;
            Point3D loc;
 
            if ( !GetHarvestDetails( from, tool, toHarvest, out tileID, out map, out loc ) )
            {
                OnBadHarvestTarget( from, tool, toHarvest );
                return;
            }
 
            HarvestDefinition def = GetDefinition( tileID );
 
            if (def == null)
            {
                OnBadHarvestTarget( from, tool, toHarvest );
                return;
            }
 
            if ( !CheckRange( from, tool, def, map, loc, false ) )
                return;
            else if ( !CheckResources( from, tool, def, map, loc, false ) )
                return;
            else if ( !CheckHarvest( from, tool, def, toHarvest ) )
                return;
 
            object toLock = GetLock( from, tool, def, toHarvest );
 
            if (!from.BeginAction(toLock))
            {
                OnConcurrentHarvest( from, tool, def, toHarvest );
                return;
            }
 
            new HarvestTimer(from, tool, this, def, toHarvest, toLock).Start();
            OnHarvestStarted( from, tool, def, toHarvest );
        }
 
        public virtual bool GetHarvestDetails(Mobile from, Item tool, object toHarvest, out int tileID, out Map map, out Point3D loc)
        {
            if (toHarvest is Static && !((Static)toHarvest).Movable)
            {
                Static obj = (Static)toHarvest;
 
                tileID = (obj.ItemID & 0x3FFF) | 0x4000;
                map = obj.Map;
                loc = obj.GetWorldLocation();
            }
            else if (toHarvest is StaticTarget)
            {
                StaticTarget obj = (StaticTarget)toHarvest;
 
                tileID = (obj.ItemID & 0x3FFF) | 0x4000;
                map = from.Map;
                loc = obj.Location;
            }
            else if (toHarvest is LandTarget)
            {
                LandTarget obj = (LandTarget)toHarvest;
 
                tileID = obj.TileID;
                map = from.Map;
                loc = obj.Location;
            }
            else
            {
                tileID = 0;
                map = null;
                loc = Point3D.Zero;
                return false;
            }
 
            return (map != null && map != Map.Internal);
        }
    }
}
 
namespace Server
{
    public interface IChopable
    {
        void OnChop(Mobile from);
    }
 
    [AttributeUsage(AttributeTargets.Class)]
    public class FurnitureAttribute : Attribute
    {
        public static bool Check( Item item )
        {
            return ( item != null && item.GetType().IsDefined( typeof( FurnitureAttribute ), false ) );
        }
 
        public FurnitureAttribute()
        {
        }
    }
}


HarvestSoundTimer.cs

Code:
using System;
 
namespace Server.Engines.Harvest
{
    public class HarvestSoundTimer : Timer
    {
        private readonly Mobile m_From;
        private readonly Item m_Tool;
        private readonly HarvestSystem m_System;
        private readonly HarvestDefinition m_Definition;
        private readonly object m_ToHarvest;
        private readonly object m_Locked;
        private readonly bool m_Last;
        public HarvestSoundTimer(Mobile from, Item tool, HarvestSystem system, HarvestDefinition def, object toHarvest, object locked, bool last)
            : base(def.EffectSoundDelay)
        {
            this.m_From = from;
            this.m_Tool = tool;
            this.m_System = system;
            this.m_Definition = def;
            this.m_ToHarvest = toHarvest;
            this.m_Locked = locked;
            this.m_Last = last;
        }
 
        protected override void OnTick()
        {
            this.m_System.DoHarvestingSound(this.m_From, this.m_Tool, this.m_Definition, this.m_ToHarvest);
 
            if (this.m_Last)
                this.m_System.FinishHarvesting(this.m_From, this.m_Tool, this.m_Definition, this.m_ToHarvest, this.m_Locked);
        }
    }
}
 

Hammerhand

Knight
Think I found at least part of the issue, its in the HarvestSoundTimer.cs Or at least might be an issue..
Yours..
Code:
        private readonly Mobile m_From;
      private readonly Item m_Tool;
        private readonly HarvestSystem m_System;
        private readonly HarvestDefinition m_Definition;
        private readonly object m_ToHarvest;
        private readonly object m_Locked;
        private readonly bool m_Last;

Daat99 OWLTR..
Code:
        private Mobile m_From;
        private Item m_Tool;
        private HarvestSystem m_System;
        private HarvestDefinition m_Definition;
        private object m_ToHarvest, m_Locked;
        private bool m_Last;

Missed merge there... OWLTR doesnt have the readonly. Actually.. just looked at a stock 2.3.. it doesnt have the readonly either, just the ForkUO/ServUO servers... ;)
 

sec_goat

Squire
Yes sir, it looks like I am in fact using ServUO. I guess I forgot to mention that, I do apologize! Thank you for helping me out! I think things are lookign pretty good on my end, getting custom ores and all that, just need to figure out how to use the rest of the system now! :D
 

daat99

Moderator
Staff member
If you solved it than it doesn't matter but if you didn't please change this:
Code:
CraftResource check = GetLastCraftResourceFromType(originalCraftResource);
double diff = MAX_SKILL/((int)check - (int)firstCraftResource + 1);
to this:
Code:
CraftResource check = GetLastCraftResourceFromType(originalCraftResource);
Console.WriteLine("Check is null? {0}, originalCraftResource: {1}", check == null, originalCraftResource);
double diff = MAX_SKILL/((int)check - (int)firstCraftResource + 1);
Let me know what it prints in the console using the problematic resources.
 

sec_goat

Squire
If you solved it than it doesn't matter but if you didn't please change this:
Code:
CraftResource check = GetLastCraftResourceFromType(originalCraftResource);
double diff = MAX_SKILL/((int)check - (int)firstCraftResource + 1);
to this:
Code:
CraftResource check = GetLastCraftResourceFromType(originalCraftResource);
Console.WriteLine("Check is null? {0}, originalCraftResource: {1}", check == null, originalCraftResource);
double diff = MAX_SKILL/((int)check - (int)firstCraftResource + 1);
Let me know what it prints in the console using the problematic resources.

daat99 you are a smart man! this is almost exactly what I did to fix it, my writeline was a tad different. That indeed was the problem. I had missed a merge where I accounted for the new resource types and it was in one section or another returning ResourceType = None which in turn left some variable null, which caused the crash.

I just wanted to say thank you to both you and Hammerhand for all the assistance, you guys are amazing!
 

sec_goat

Squire
Guess who? :D

I appear to be having some issues with large bod rewards:
I turn in a large bod for 10 Exceptional Iron Weapons and the ComputeGold Funtion returns a Type index of 15 which crashes the server obviously!

It looks like in the ComputeType(Type type int ItemCount) it is sendin g the wrong item count, this is a bod of item count 10 and this function is gettign an item count of 6

I was wondering if you guys could take a look and see what I am missing?

here is my crash report:



Server Crash Report
===================

RunUO Version 0.4, Build 4990.11336
Operating System: Microsoft Windows NT 6.1.7601 Service Pack 1
.NET Framework: 4.0.30319.18052
Time: 9/13/2013 7:49:13 AM
Mobiles: 25858
Items: 146784
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:\RunUO\Scripts\Services\BulkOrders\Rewards.cs:line 565
at Server.Engines.BulkOrders.RewardCalculator.ComputeGold(LargeBOD bod) in c:\RunUO\Scripts\Services\BulkOrders\Rewards.cs:line 205
at Server.Engines.BulkOrders.LargeSmithBOD.ComputeGold() in c:\RunUO\Scripts\Services\BulkOrders\LargeSmithBOD.cs:line 108
at Server.Engines.BulkOrders.LargeBOD.GetRewards(Item& reward, Int32& gold, Int32& fame) in c:\RunUO\Scripts\Services\BulkOrders\LargeBOD.cs:line 133
at Server.Mobiles.BaseVendor.OnDragDrop(Mobile from, Item dropped) in c:\RunUO\Scripts\Mobiles\Vendors\BaseVendor.cs:line 1021
at Server.Item.DropToMobile(Mobile from, Mobile target, Point3D p) in c:\RunUO\Server\Item.cs:line 4111
at Server.Mobile.Drop(Mobile to, Point3D loc) in c:\RunUO\Server\Mobile.cs:line 5246
at Server.Network.PacketHandlers.DropReq6017(NetState state, PacketReader pvSrc) in c:\RunUO\Server\Network\PacketHandlers.cs:line 1021
at Server.Network.MessagePump.HandleReceive(NetState ns) in c:\RunUO\Server\Network\MessagePump.cs:line 272
at Server.Network.MessagePump.Slice() in c:\RunUO\Server\Network\MessagePump.cs:line 126
at Server.Core.Main(String[] args) in c:\RunUO\Server\Main.cs:line 678

here is my console write lines obviously returning an index that doesn't exist:


09:48:11 Rewards.cs line 523 ComputeType
09:48:11 Type: Server.Items.Broadsword itemCount: 6
09:48:11 m_Types.Length: 8
09:48:11 Rewards.Cs l;ine 539 if (this.m_Types[typeIdx].Contains(type))
09:48:11 typeIDx: 6 this.m_Types[typeIdx]: Server.Engines.BulkOrders.RewardType
09:48:11 Rewards.cs line 554: return (typeIdx + 1) * 2
09:48:11 return (typeIdx + 1) * 2: 14
09:48:11 Reward.cs line 561:
09:48:11 typeindex: 15 quanIndex: 0 mtrIndex: 0
09:48:11 Error:



Rewards.cs

Code:
using System;
using Server;
using Server.Items;
 
namespace Server.Engines.BulkOrders
{
    public delegate Item ConstructCallback(int type);
 
    public sealed class RewardType
    {
        private readonly int m_Points;
        private readonly Type[] m_Types;
 
        public int Points
        {
            get
            {
                return this.m_Points;
            }
        }
        public Type[] Types
        {
            get
            {
                return this.m_Types;
            }
        }
 
        public RewardType(int points, params Type[] types)
        {
            this.m_Points = points;
            this.m_Types = types;
        }
 
        public bool Contains(Type type)
        {
            for (int i = 0; i < this.m_Types.Length; ++i)
            {
                if (this.m_Types[i] == type)
                    return true;
            }
 
            return false;
        }
    }
 
    public sealed class RewardItem
    {
        private readonly int m_Weight;
        private readonly ConstructCallback m_Constructor;
        private readonly int m_Type;
 
        public int Weight
        {
            get
            {
                return this.m_Weight;
            }
        }
        public ConstructCallback Constructor
        {
            get
            {
                return this.m_Constructor;
            }
        }
        public int Type
        {
            get
            {
                return this.m_Type;
            }
        }
 
        public RewardItem(int weight, ConstructCallback constructor)
            : this(weight, constructor, 0)
        {
        }
 
        public RewardItem(int weight, ConstructCallback constructor, int type)
        {
            this.m_Weight = weight;
            this.m_Constructor = constructor;
            this.m_Type = type;
        }
 
        public Item Construct()
        {
            try
            {
                return this.m_Constructor(this.m_Type);
            }
            catch
            {
                return null;
            }
        }
    }
 
    public sealed class RewardGroup
    {
        private readonly int m_Points;
        private readonly RewardItem[] m_Items;
 
        public int Points
        {
            get
            {
                return this.m_Points;
            }
        }
        public RewardItem[] Items
        {
            get
            {
                return this.m_Items;
            }
        }
 
        public RewardGroup(int points, params RewardItem[] items)
        {
            this.m_Points = points;
            this.m_Items = items;
        }
 
        public RewardItem AcquireItem()
        {
            if (this.m_Items.Length == 0)
                return null;
            else if (this.m_Items.Length == 1)
                return this.m_Items[0];
 
            int totalWeight = 0;
 
            for (int i = 0; i < this.m_Items.Length; ++i)
                totalWeight += this.m_Items[i].Weight;
 
            int randomWeight = Utility.Random(totalWeight);
 
            for (int i = 0; i < this.m_Items.Length; ++i)
            {
                RewardItem item = this.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 this.m_Groups;
            }
            set
            {
                this.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 = this.ComputePoints(bod) / 50;
 
            return points * points;
        }
 
        public virtual int ComputeFame(LargeBOD bod)
        {
            int points = this.ComputePoints(bod) / 50;
 
            return points * points;
        }
 
        public virtual int ComputePoints(SmallBOD bod)
        {
            return this.ComputePoints(bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type);
        }
 
        public virtual int ComputePoints(LargeBOD bod)
        {
            return this.ComputePoints(bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length, bod.Entries[0].Details.Type);
        }
 
        public virtual int ComputeGold(SmallBOD bod)
        {
            return this.ComputeGold(bod.AmountMax, bod.RequireExceptional, bod.Material, 1, bod.Type);
        }
 
        public virtual int ComputeGold(LargeBOD bod)
        {
            return this.ComputeGold(bod.AmountMax, bod.RequireExceptional, bod.Material, bod.Entries.Length, bod.Entries[0].Details.Type);
        }
 
        public virtual RewardGroup LookupRewards(int points)
        {
            for (int i = this.m_Groups.Length - 1; i >= 1; --i)
            {
                RewardGroup group = this.m_Groups[i];
 
                if (points >= group.Points)
                    return group;
            }
 
            return this.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 DaatsBagOfResources = new ConstructCallback( CreateDaatsBagOfResources );
        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 CreateDaatsBagOfResources( int type )
        {
            return new DaatsBagOfResources();
        }
        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 readonly 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 += this.LookupTypePoints(this.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 (this.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 = this.ComputeType(type, itemCount);
            int quanIndex = (quantity == 20 ? 2 : quantity == 15 ? 1 : 0);
            int mtrlIndex = (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Platinum) ? 1 + (int)(material - BulkMaterialType.DullCopper) : 0;
 
            if (exceptional)
                typeIndex++;
            Console.WriteLine("Reward.cs line 561: ");
       
            Console.WriteLine("typeindex: " + typeIndex + " quanIndex: " + quanIndex + " mtrIndex: " + mtrlIndex);
            Console.WriteLine(goldTable[typeIndex][quanIndex][mtrlIndex]);
 
            int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
 
            int min = (gold * 9) / 10;
            int max = (gold * 10) / 9;
 
            return Utility.RandomMinMax(min, max);
        }
 
        public SmithRewardCalculator()
        {
            this.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, DaatsBagOfResources ) ),
                new RewardGroup( 1350, new RewardItem( 1, RunicHammer, 11 ), new RewardItem( 1, DaatsBagOfResources ) ),
                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 readonly 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 readonly 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 readonly 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[][] // 5-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[][] // 6-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[][] // 6-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[][] // 1-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[][] // 4-part (regular)
            {
                    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[][] // 4-part (exceptional)
            {
                    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[][] // 5-part (regular)
            {
                    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()
        {
            this.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
        }
    }
}

LargeBOD.cs

Code:
using System;
using System.Collections;
using Server;
using Server.Items;
using System.Collections.Generic;
using Server.Mobiles;
 
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;
        public LargeBOD(int hue, int amountMax, bool requireExeptional, BulkMaterialType material, LargeBulkEntry[] entries)
            : base(Core.AOS ? 0x2258 : 0x14EF)
        {
            this.Weight = 1.0;
            this.Hue = hue; // Blacksmith: 0x44E; Tailoring: 0x483
            this.LootType = LootType.Blessed;
 
            this.m_AmountMax = amountMax;
            this.m_RequireExceptional = requireExeptional;
            this.m_Material = material;
            this.m_Entries = entries;
        }
 
        public LargeBOD()
            : base(Core.AOS ? 0x2258 : 0x14EF)
        {
            this.Weight = 1.0;
            this.LootType = LootType.Blessed;
        }
 
        [CommandProperty(AccessLevel.GameMaster)]
        public int AmountMax
        {
            get
            {
                return this.m_AmountMax;
            }
            set
            {
                this.m_AmountMax = value;
                this.InvalidateProperties();
            }
        }
        [CommandProperty(AccessLevel.GameMaster)]
        public bool RequireExceptional
        {
            get
            {
                return this.m_RequireExceptional;
            }
            set
            {
                this.m_RequireExceptional = value;
                this.InvalidateProperties();
            }
        }
        [CommandProperty(AccessLevel.GameMaster)]
        public BulkMaterialType Material
        {
            get
            {
                return this.m_Material;
            }
            set
            {
                this.m_Material = value;
                this.InvalidateProperties();
            }
        }
        public LargeBulkEntry[] Entries
        {
            get
            {
                return this.m_Entries;
            }
            set
            {
                this.m_Entries = value;
                this.InvalidateProperties();
            }
        }
        [CommandProperty(AccessLevel.GameMaster)]
        public bool Complete
        {
            get
            {
                for (int i = 0; i < this.m_Entries.Length; ++i)
                {
                    if (this.m_Entries[i].Amount < this.m_AmountMax)
                        return false;
                }
 
                return true;
            }
        }
        public override int LabelNumber
        {
            get
            {
                return 1045151;
            }
        }// a bulk order deed
        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 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 = this.ComputeGold();
            fame = this.ComputeFame();
 
            List<Item> rewards = this.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 override void GetProperties(ObjectPropertyList list)
        {
            base.GetProperties(list);
 
            list.Add(1060655); // large bulk order
 
            if (this.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, this.m_AmountMax.ToString()); // amount to make: ~1_val~
 
            for (int i = 0; i < this.m_Entries.Length; ++i)
                list.Add(1060658 + i, "#{0}\t{1}", this.m_Entries[i].Details.Number, this.m_Entries[i].Amount); // ~1_val~: ~2_val~
        }
 
        public override void OnDoubleClickNotAccessible(Mobile from)
        {
            this.OnDoubleClick(from);
        }
 
        public override void OnDoubleClickSecureTrade(Mobile from)
        {
            this.OnDoubleClick(from);
        }
 
        public override void OnDoubleClick(Mobile from)
        {
            if (this.IsChildOf(from.Backpack) || this.InSecureTrade || this.RootParent is PlayerVendor)
                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 (!this.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 < this.m_Entries.Length; ++i)
                    {
                        if (this.m_Entries[i].Details.Type == small.Type)
                            entry = this.m_Entries[i];
                    }
 
                    if (entry == null)
                    {
                        from.SendLocalizedMessage(1045160); // That is not a bulk order for this large request.
                    }
                    else if (this.m_RequireExceptional && !small.RequireExceptional)
                    {
                        from.SendLocalizedMessage(1045161); // Both orders must be of exceptional quality.
                    }
                    else if (this.m_Material >= BulkMaterialType.DullCopper && this.m_Material <= BulkMaterialType.Valorite && small.Material != this.m_Material)
                    {
                        from.SendLocalizedMessage(1045162); // Both orders must use the same ore type.
                    }
                    else if (this.m_Material >= BulkMaterialType.Spined && this.m_Material <= BulkMaterialType.Barbed && small.Material != this.m_Material)
                    {
                        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 (this.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 >= this.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 (!this.Complete)
                            this.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(this.m_AmountMax);
            writer.Write(this.m_RequireExceptional);
            writer.Write((int)this.m_Material);
 
            writer.Write((int)this.m_Entries.Length);
 
            for (int i = 0; i < this.m_Entries.Length; ++i)
                this.m_Entries[i].Serialize(writer);
        }
 
        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
 
            int version = reader.ReadInt();
 
            switch ( version )
            {
                case 0:
                    {
                        this.m_AmountMax = reader.ReadInt();
                        this.m_RequireExceptional = reader.ReadBool();
                        this.m_Material = (BulkMaterialType)reader.ReadInt();
 
                        this.m_Entries = new LargeBulkEntry[reader.ReadInt()];
 
                        for (int i = 0; i < this.m_Entries.Length; ++i)
                            this.m_Entries[i] = new LargeBulkEntry(this, reader);
 
                        break;
                    }
            }
 
            if (this.Weight == 0.0)
                this.Weight = 1.0;
 
            if (Core.AOS && this.ItemID == 0x14EF)
                this.ItemID = 0x2258;
 
            if (this.Parent == null && this.Map == Map.Internal && this.Location == Point3D.Zero)
                this.Delete();
        }
    }
}


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
        };
        [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 int ComputeFame()
        {
            return SmithRewardCalculator.Instance.ComputeFame(this);
        }
 
        public override int ComputeGold()
        {
            return SmithRewardCalculator.Instance.ComputeGold(this);
        }
 
        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();
        }
    }
}
 

Hammerhand

Knight
Uuummm... yeah.. your LargeBOD.cs.. not good. You're missing chunks of the OWLTR edit and the ServUO script has extra stuff in it.
 

sec_goat

Squire
Uuummm... yeah.. your LargeBOD.cs.. not good. You're missing chunks of the OWLTR edit and the ServUO script has extra stuff in it.
Replace LargeBod Entirley with the one from the OWLTR download, and no changes, same crash, same lines and same index that's just too dman high :D

It has something to do with item count begin off it seems and that returning an index from ComputeType that does not exist.

For some reason it seems AmountMax in LargwSmithBod is returning 6 an feeding that into ComputeType, and since 6 isn't a valid bod amount number if messes up the rest of the calculations.

Reward.cs line 562
int typeIndex = this.ComputeType(type, itemCount);
Code:
 public override int ComputeGold(int quantity, bool exceptional, BulkMaterialType material, int itemCount, Type type)
        {
            int[][][] goldTable = m_GoldTable;
 
            int typeIndex = this.ComputeType(type, itemCount);
            int quanIndex = (quantity == 20 ? 2 : quantity == 15 ? 1 : 0);
            int mtrlIndex = (material >= BulkMaterialType.DullCopper && material <= BulkMaterialType.Platinum) ? 1 + (int)(material - BulkMaterialType.DullCopper) : 0;
 
            if (exceptional)
                typeIndex++;
            Console.WriteLine("Reward.cs line 561: ");
   
            Console.WriteLine("typeindex: " + typeIndex + " quanIndex: " + quanIndex + " mtrIndex: " + mtrlIndex);
            Console.WriteLine(goldTable[typeIndex][quanIndex][mtrlIndex]);
 
            int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
 
            int min = (gold * 9) / 10;
            int max = (gold * 10) / 9;
 
            return Utility.RandomMinMax(min, max);
        }

Reward.csline 523
Code:
 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...
            Console.WriteLine("Rewards.cs line 523 ComputeType");
            Console.WriteLine("Type: " + type + " itemCount: " + itemCount);
            Console.WriteLine("m_Types.Length: " + m_Types.Length);
            for ( typeIdx = 0; typeIdx < m_Types.Length; ++typeIdx )
            //daat99 OWLTR end - don't use magic numbers...
            {
                if (this.m_Types[typeIdx].Contains(type))
                {
                    Console.WriteLine("Rewards.Cs l;ine 539 if (this.m_Types[typeIdx].Contains(type))");
                    Console.WriteLine("typeIDx: " + typeIdx + " this.m_Types[typeIdx]: " + this.m_Types[typeIdx]);
                    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
            Console.WriteLine("Rewards.cs line 554: return (typeIdx + 1) * 2");
            Console.WriteLine("return (typeIdx + 1) * 2: " + (typeIdx + 1) * 2);
            return (typeIdx + 1) * 2;
        }


I will go ahead and replace LArgeSmithBod and Rewards.cs fully from the OWLTR download and see if that helps.
 

sec_goat

Squire
Hammerhand I replace Rewards.cs, LargeBod.cs and LargeSmithBod.CS directly from the OWLTR download And I still get the same error as before:

Code:
Server Crash Report
===================
 
RunUO Version 0.4, Build 4990.11336
Operating System: Microsoft Windows NT 6.1.7601 Service Pack 1
.NET Framework: 4.0.30319.18052
Time: 9/13/2013 3:44:48 PM
Mobiles: 25840
Items: 146796
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:\RunUO\Scripts\Services\BulkOrders\Rewards.cs:line 514
  at Server.Engines.BulkOrders.RewardCalculator.ComputeGold(LargeBOD bod) in c:\RunUO\Scripts\Services\BulkOrders\Rewards.cs:line 146
  at Server.Engines.RunOrders.LargeSmithBOD.ComputeGold() in c:\RunUO\Scripts\Services\BulkOrders\LargeSmithBOD.cs:line 40
  at Server.Engines.BulkOrders.LargeBOD.GetRewards(Item& reward, Int32& gold, Int32& fame) in c:\RunUO\Scripts\Services\BulkOrders\LargeBOD.cs:line 50
  at Server.Mobiles.BaseVendor.OnDragDrop(Mobile from, Item dropped) in c:\RunUO\Scripts\Mobiles\Vendors\BaseVendor.cs:line 1021
  at Server.Item.DropToMobile(Mobile from, Mobile target, Point3D p) in c:\RunUO\Server\Item.cs:line 4111
  at Server.Mobile.Drop(Mobile to, Point3D loc) in c:\RunUO\Server\Mobile.cs:line 5246
  at Server.Network.PacketHandlers.DropReq6017(NetState state, PacketReader pvSrc) in c:\RunUO\Server\Network\PacketHandlers.cs:line 1021
  at Server.Network.MessagePump.HandleReceive(NetState ns) in c:\RunUO\Server\Network\MessagePump.cs:line 272
  at Server.Network.MessagePump.Slice() in c:\RunUO\Server\Network\MessagePump.cs:line 126
  at Server.Core.Main(String[] args) in c:\RunUO\Server\Main.cs:line 678
 

Hammerhand

Knight
You really should be merging the files, not replacing them. Your Rewards.cs was a bad merge. By just replacing the files, you remove anything new that was in the ServUO server.. ie: some ML & SA content that could be there.
 

sec_goat

Squire
You really should be merging the files, not replacing them. Your Rewards.cs was a bad merge. By just replacing the files, you remove anything new that was in the ServUO server.. ie: some ML & SA content that could be there.
I was only trying to trouble shoot a bit, I think this means that It was not the merge that is cause the issue, at least not in these particular files. Also looking at ServUO rewards.cs next to OWLTR rewards.cs the big difference is that ServUO uses this and readonly that and daat's owltr seems to remove powerscrolls as reward items and changes the amount of gold rewarded.
Either way the computations in both daat's and ServUOs files are the same for ComputeGold and ComputeType ( at least in theory!)

I've got some theories on how to fix this, at least to cobble together a fix. I am not sure how to tell if this is a deeper issue than a bad OWLTR / Custom.

Either way I appreciate the Guidance Hammerhand, Thanks!


EDIT: this appears to work but doe not fix the underlying issue. So I am not sure if this is a complete fix or not, but I added a check to make sure Typeindex wasn't too large, and if it was set it back to it's largest possible.

Code:
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++;
 
         [COLOR=#ffff00]   if (typeIndex >= goldTable.GetUpperBound(0))[/COLOR]
[COLOR=#ffff00]                typeIndex = goldTable.GetUpperBound(0);[/COLOR]
 
            int gold = goldTable[typeIndex][quanIndex][mtrlIndex];
 
            int min = (gold * 9) / 10;
            int max = (gold * 10) / 9;
 
            return Utility.RandomMinMax(min, max);
        }
 

daat99

Moderator
Staff member
This is actually a problem someone else encountered as well so it might be OWLTR issue.
Can you please take a look at this thread:
http://www.runuo.com/community/threads/server-crash.534303/#post-3972663

I didn't had any time to look into it but if you can figure out what makes the large weapon bods return index 14 and 15 instead of 12 and 13 it'll be great.
As for a temporary fix I would do this:
C#:
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);
If you keep the console writes than you'll see the index each bod returns.

From what I know either large weapon bods should be 12 and 13 or I'm missing 2 types of bods.
 

Hammerhand

Knight
The biggest problem with merging anything with the ForkUO/ServUO server are these 2 things... as shown in a single snippet of code.
RunUO 2.3 and pretty much any other version.. 5 lines..
Code:
        [CommandProperty( AccessLevel.GameMaster )]
        public bool ConfinedRoaming
        {
            get { return m_ConfinedRoaming; }
            set { m_ConfinedRoaming = value; }
        }
ForkUO/ServUO.. same script, same snippet.. 11 lines & the addition of this. to everything.
Code:
        [CommandProperty(AccessLevel.GameMaster)]
        public bool ConfinedRoaming
        {
            get
            {
                return this.m_ConfinedRoaming;
            }
            set
            {
                this.m_ConfinedRoaming = value;
            }
        }
Makes merging anything almost impossible because the "this." alone generates differences as does the carriage returns I think they're called. PlayerMobile.cs alone showed over 1k differences when trying to merge OWLTR in. And that was with ignore whitespace checked. I spent 2 hours going through that one script with both versions open (OWLTR & ForkUO) trying to match up lines to insert the edits. The entire project could take several days to get right, if its even possible.
 
Top