Example #1
0
    public static ItemClass GetItemClassBySpecifier(string specifier)
    {
        specifier = specifier.Trim().ToLower();
        string commonspecifier = "common " + specifier;

        foreach (ItemClass cls in Classes)
        {
            string sname = cls.ServerName.ToLower();
            if (sname == specifier || sname == commonspecifier)
            {
                return(cls);
            }
        }

        // try to guess based on specifier. this is used in world.res
        string[] specSplit = specifier.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
        string   searchFor; // this is reused
        // first off, if last word is "shield", then we're looking for something in Templates.Shields
        int gSlot = -1;

        Templates.TplArmor gOption = null;
        int gOptionId = -1;

        if (specSplit[specSplit.Length - 1] == "shield")
        {
            searchFor = "";
            for (int j = 1; j >= 0; j--)
            {
                if (specSplit.Length - 1 - j < 0)
                {
                    continue;
                }

                searchFor = string.Join(" ", specSplit.Skip(specSplit.Length - 1 - j).Take(j + 1).ToArray());
                for (int i = 0; i < TemplateLoader.Templates.Shields.Count; i++)
                {
                    Templates.TplArmor shieldKind = TemplateLoader.Templates.Shields[i];
                    if (shieldKind.Name.ToLower() == searchFor)
                    {
                        gOption   = shieldKind;
                        gOptionId = i;
                        gSlot     = shieldKind.Slot;
                        break;
                    }
                }

                if (gOption != null)
                {
                    // remove the option specifier (leaving only class and material)
                    specSplit = specSplit.Take(specSplit.Length - (j + 2)).ToArray();
                    break;
                }
            }
        }
        // otherwise search in weapons and armor.
        else
        {
            searchFor = "";
            for (int j = 1; j >= 0; j--)
            {
                if (specSplit.Length - 1 - j < 0)
                {
                    continue;
                }

                searchFor = string.Join(" ", specSplit.Skip(specSplit.Length - 1 - j).Take(j + 1).ToArray());
                for (int i = 0; i < TemplateLoader.Templates.Weapons.Count; i++)
                {
                    Templates.TplArmor weaponKind = TemplateLoader.Templates.Weapons[i];
                    if (weaponKind.Name.ToLower() == searchFor)
                    {
                        gOption   = weaponKind;
                        gOptionId = i;
                        gSlot     = weaponKind.Slot;
                        break;
                    }
                }

                if (gOption == null)
                {
                    for (int i = 0; i < TemplateLoader.Templates.Armor.Count; i++)
                    {
                        Templates.TplArmor armorKind = TemplateLoader.Templates.Armor[i];
                        if (armorKind.Name.ToLower() == searchFor)
                        {
                            gOption   = armorKind;
                            gOptionId = i;
                            gSlot     = armorKind.Slot;
                            break;
                        }
                    }
                }

                if (gOption != null)
                {
                    specSplit = specSplit.Take(specSplit.Length - (j + 1)).ToArray();
                    break;
                }
            }
        }

        // here we either have gOption and gSlot or the item is not found.
        if (gOption == null || gSlot < 0)
        {
            return(null);
        }

        // now find material
        int gMaterial = -1;

        searchFor = "";
        for (int j = 1; j >= 0; j--)
        {
            if (specSplit.Length - 1 - j < 0)
            {
                continue;
            }

            searchFor = string.Join(" ", specSplit.Skip(specSplit.Length - 1 - j).Take(j + 1).ToArray());
            for (int i = 0; i < TemplateLoader.Templates.Materials.Count; i++)
            {
                Templates.TplMaterial fmat = TemplateLoader.Templates.Materials[i];
                if (fmat.Name.ToLower() == searchFor)
                {
                    gMaterial = i;
                    break;
                }
            }

            if (gMaterial >= 0)
            {
                specSplit = specSplit.Take(specSplit.Length - (j + 1)).ToArray();
                break;
            }
        }

        if (gMaterial < 0)
        {
            // check if option has "none" material allowed (aka 15)
            if (gOption.IsAllowed(-1, 15))
            {
                gMaterial = 15;
            }
            else
            {
                // there are very special items like "Sonic Beam" that have ONLY option in them
                ItemClass newCls = new ItemClass();
                newCls.ServerName    = gOption.Name;
                newCls.VisualName    = newCls.ServerName;
                newCls.Option        = gOption;
                newCls.IsMagic       = false;
                newCls.IsSpecial     = true;
                newCls.ItemID        = (ushort)gOptionId;
                newCls.UsableMage    = false;
                newCls.UsableFighter = false;
                newCls.Price         = 0;
                return(newCls);
            }
        }

        int gClass = -1; // common by default

        searchFor = string.Join(" ", specSplit);
        for (int i = 0; i < TemplateLoader.Templates.Classes.Count; i++)
        {
            Templates.TplClass fcls = TemplateLoader.Templates.Classes[i];
            if (fcls.Name.ToLower() == searchFor)
            {
                gClass = i;
                break;
            }
        }

        if (gClass < 0)
        {
            gClass = 0;             // default is common. the only default here.
        }
        // how try to find required item.
        Templates.TplClass    reqClass    = TemplateLoader.GetClassById(gClass);
        Templates.TplMaterial reqMaterial = TemplateLoader.GetMaterialById(gMaterial);
        Templates.TplArmor    reqOption;
        if (reqClass == null || reqMaterial == null) // this shouldnt happen tbh
        {
            return(null);
        }

        // do option remap for shields. nival did NOT write "soft helm" or "soft large shield". instead they just wrote "helm" and "large shield".
        reqOption = gOption;

        int oldOptionId = gOptionId;

        if (reqMaterial.Name.ToLower().Contains("wood") && !reqOption.IsAllowed(gClass, gMaterial))
        {
            gOptionId += 2; // small/large -> wooden small/wooden large
        }
        else if (reqMaterial.Name.ToLower().Contains("leather") && !reqOption.IsAllowed(gClass, gMaterial))
        {
            gOptionId += 1; // small/large -> soft small/soft large
        }
        if (oldOptionId != gOptionId)
        {
            reqOption = TemplateLoader.GetOptionByIdAndSlot(gOptionId, gSlot);
            if (reqOption == null)
            {
                return(null);
            }
        }

        for (int i = 0; i < Classes.Count; i++)
        {
            if (Classes[i].Class == reqClass &&
                Classes[i].Material == reqMaterial &&
                Classes[i].Option == reqOption)
            {
                return(Classes[i]);
            }
        }

        return(null);
    }
Example #2
0
    public static void InitClasses()
    {
        if (ClassesLoaded)
        {
            return;
        }
        ClassesLoaded = true;

        MemoryStream ms = ResourceManager.OpenRead("world/data/itemname.pkt");

        if (ms == null)
        {
            Core.Abort("Couldn't load \"world/data/itemname.pkt\"!");
            return;
        }

        ms.Position = 3;
        BinaryReader br = new BinaryReader(ms);

        try
        {
            uint item_count = br.ReadUInt32();
            ms.Position += 2;

            for (uint i = 0; i < item_count; i++)
            {
                ItemClass cls = new ItemClass();
                cls.ItemID     = br.ReadUInt16();
                cls.ServerName = Locale.ItemServ[(int)i];
                cls.VisualName = Locale.ItemName[(int)i];
                ms.Position   += 2;           // some unknown info (usually 0x01 0x00)
                byte flags = br.ReadByte();
                if (flags == 2 || flags == 6) // usablefighter
                {
                    cls.UsableFighter = true;
                }
                if (flags == 4 || flags == 6) // usablemage
                {
                    cls.UsableMage = true;
                }
                byte count_mods = br.ReadByte();
                ms.Position += 2; // size of modifier array in bytes (i.e. 0x0B) + id of price (0x01)
                cls.Price    = br.ReadUInt32();
                count_mods--;
                for (byte j = 0; j < count_mods; j++)
                {
                    ItemEffect effect   = new ItemEffect();
                    byte       r_effect = br.ReadByte();
                    sbyte      r_value  = br.ReadSByte();
                    effect.Type1  = (ItemEffect.Effects)r_effect;
                    effect.Value1 = r_value;
                    cls.Effects.Add(effect);
                }

                // done reading. init auxiliary fields.
                int materialId = (cls.ItemID & 0xF000) >> 12;
                int slotId     = (cls.ItemID & 0x0F00) >> 8;
                int classId    = (cls.ItemID & 0x0070) >> 5;
                int optionId   = (cls.ItemID & 0x001F);

                if (materialId == 0 && slotId == 14) // 0x0E##
                {
                    cls.IsMagic = true;
                    cls.MagicID = (cls.ItemID & 0xFF) - 1;
                    optionId    = cls.MagicID + 1;
                    classId     = 0;
                    materialId  = 0;
                }
                else
                {
                    cls.IsMagic = false;
                    cls.MagicID = -1;
                }

                cls.IsSpecial = false;

                cls.Material = TemplateLoader.GetMaterialById(materialId);
                cls.Class    = TemplateLoader.GetClassById(classId);
                cls.Option   = TemplateLoader.GetOptionByIdAndSlot(optionId, slotId);

                string imageNameBase = string.Format("{0:D2}{1:D2}{2}{3:D2}", materialId, slotId, classId, optionId);
                cls.File_Pack = new ItemPackFile("graphics/inventory/" + imageNameBase + ".16a");

                if (cls.UsableFighter)
                {
                    cls.File_BodyMF1 = new ItemFile("graphics/equipment/mfighter/primary/" + imageNameBase + ".256");
                    cls.File_BodyFF1 = new ItemFile("graphics/equipment/ffighter/primary/" + imageNameBase + ".256");
                    cls.File_BodyMF2 = new ItemFile("graphics/equipment/mfighter/secondary/" + imageNameBase + ".256");
                    cls.File_BodyFF2 = new ItemFile("graphics/equipment/ffighter/secondary/" + imageNameBase + ".256");
                }

                if (cls.UsableMage)
                {
                    cls.File_BodyMM1 = new ItemFile("graphics/equipment/mmage/primary/" + imageNameBase + ".256");
                    cls.File_BodyFM1 = new ItemFile("graphics/equipment/fmage/primary/" + imageNameBase + ".256");
                    cls.File_BodyMM2 = new ItemFile("graphics/equipment/mmage/secondary/" + imageNameBase + ".256");
                    cls.File_BodyFM2 = new ItemFile("graphics/equipment/fmage/secondary/" + imageNameBase + ".256");
                }

                Classes.Add(cls);
            }

            // create a fake item with ID=0xFFFF
            // "gold"
            ItemClass gcls = new ItemClass();
            gcls.ServerName    = "Gold";
            gcls.VisualName    = "Gold";
            gcls.Price         = 1;
            gcls.ItemID        = 0xFFFF;
            gcls.IsMagic       = false;
            gcls.MagicID       = -1;
            gcls.IsSpecial     = false;
            gcls.IsMoney       = true;
            gcls.UsableFighter = true;
            gcls.UsableMage    = true;
            gcls.File_Pack     = new ItemPackFile("graphics/interface/money/money.16a");
            Classes.Add(gcls);
        }
        finally
        {
            ms.Close();
        }
    }
Example #3
0
        public Shelf(AllodsMap.AlmShop.AlmShopShelf rules)
        {
            // basic props
            PriceMin    = rules.PriceMin;
            PriceMax    = rules.PriceMax;
            MaxItems    = rules.MaxItems;
            MaxSameType = rules.MaxSameItems;

            // get list of classes supported for the item.
            var Materials = new List <Templates.TplMaterial>();
            var Classes   = new List <Templates.TplClass>();
            var Types     = new List <Templates.TplArmor>();

            //
            ItemClasses        = new List <ItemClass>();
            SpecialItemClasses = new List <ItemClass>();

            //
            AllowMagic  = rules.ItemExtras.HasFlag(AllodsMap.AlmShop.AlmShopItemExtra.Magic);
            AllowCommon = AllowMagic ? rules.ItemExtras.HasFlag(AllodsMap.AlmShop.AlmShopItemExtra.Common) : true;

            AllowSpecial = rules.ItemTypes.HasFlag(AllodsMap.AlmShop.AlmShopItemType.Other);

            // this currently abuses the fact that there is a hardcoded list of materials.
            // will need to be changed if we extend it.
            for (int i = 0; i < 15; i++)
            {
                uint flag  = 1u << i;
                uint value = (uint)rules.ItemMaterials;
                if ((flag & value) != 0)
                {
                    Materials.Add(TemplateLoader.GetMaterialById(i));
                }
            }

            // same goes for classes.
            for (int i = 0; i < 7; i++)
            {
                uint flag  = 1u << i;
                uint value = ((uint)rules.ItemClasses) >> 15;
                if ((flag & value) != 0)
                {
                    Classes.Add(TemplateLoader.GetClassById(i));
                }
            }

            // types are a bit more complicated, because there is no direct mapping for this.
            // we use "slot"
            // note that there is also separation between mage and warrior armor here.

            // add weapons
            if (rules.ItemTypes.HasFlag(AllodsMap.AlmShop.AlmShopItemType.Weapon))
            {
                foreach (Templates.TplArmor weapon in TemplateLoader.Templates.Weapons)
                {
                    if (!CheckArmorShapeAllowed(weapon, rules))
                    {
                        continue;
                    }
                    if (weapon.SuitableFor == 1)
                    {
                        Types.Add(weapon);
                    }
                }
            }

            if (rules.ItemTypes.HasFlag(AllodsMap.AlmShop.AlmShopItemType.Wands))
            {
                foreach (Templates.TplArmor weapon in TemplateLoader.Templates.Weapons)
                {
                    if (!CheckArmorShapeAllowed(weapon, rules))
                    {
                        continue;
                    }
                    if (weapon.SuitableFor == 2)
                    {
                        Types.Add(weapon);
                    }
                }
            }

            // add armor
            if (rules.ItemTypes.HasFlag(AllodsMap.AlmShop.AlmShopItemType.Armor))
            {
                foreach (Templates.TplArmor armor in TemplateLoader.Templates.Armor)
                {
                    if (!CheckArmorShapeAllowed(armor, rules))
                    {
                        continue;
                    }
                    if (armor.SuitableFor == 1)
                    {
                        Types.Add(armor);
                    }
                }
            }

            if (rules.ItemTypes.HasFlag(AllodsMap.AlmShop.AlmShopItemType.ArmorMage))
            {
                foreach (Templates.TplArmor armor in TemplateLoader.Templates.Armor)
                {
                    if (!CheckArmorShapeAllowed(armor, rules))
                    {
                        continue;
                    }
                    if (armor.SuitableFor == 2)
                    {
                        Types.Add(armor);
                    }
                }
            }

            // add armor suitable for everyone (e.g. rings)
            if (rules.ItemTypes.HasFlag(AllodsMap.AlmShop.AlmShopItemType.Armor) || rules.ItemTypes.HasFlag(AllodsMap.AlmShop.AlmShopItemType.ArmorMage))
            {
                foreach (Templates.TplArmor armor in TemplateLoader.Templates.Armor)
                {
                    if (!CheckArmorShapeAllowed(armor, rules))
                    {
                        continue;
                    }
                    if (armor.SuitableFor == 3)
                    {
                        Types.Add(armor);
                    }
                }
            }

            // add shields
            if (rules.ItemTypes.HasFlag(AllodsMap.AlmShop.AlmShopItemType.Shield))
            {
                foreach (Templates.TplArmor shield in TemplateLoader.Templates.Shields)
                {
                    if (!CheckArmorShapeAllowed(shield, rules))
                    {
                        continue;
                    }
                    Types.Add(shield);
                }
            }

            // add special (other)
            // copy the list (we may want to skip some items later)
            if (rules.ItemTypes.HasFlag(AllodsMap.AlmShop.AlmShopItemType.Other))
            {
                // generate id for scroll.
                for (ushort i = 6; i <= 0x3F; i++)
                {
                    ushort    itemId = (ushort)(0x0E00 | i);
                    ItemClass cls    = ItemClassLoader.GetItemClassById(itemId);
                    if (cls == null)
                    {
                        continue;
                    }
                    if (cls.Price < PriceMin || cls.Price > PriceMax)
                    {
                        continue;
                    }
                    SpecialItemClasses.Add(cls);
                }
            }

            // now that we have all the allowed combinations, let's populate items!
            // note that not all possible IDs are valid -- we need to check this
            foreach (Templates.TplArmor armor in Types)
            {
                // class id
                for (int i = 0; i < 7; i++)
                {
                    // material id
                    for (int j = 0; j < 15; j++)
                    {
                        // check if allowed
                        if ((armor.ClassesAllowed[i] & (1 << j)) == 0)
                        {
                            continue;
                        }
                        ushort    itemId = (ushort)((i << 5) | (j << 12) | (armor.Slot << 8) | (armor.Index));
                        ItemClass cls    = ItemClassLoader.GetItemClassById(itemId);
                        if (cls == null)
                        {
                            continue;
                        }
                        if (cls.Price > PriceMax || (!AllowMagic && cls.Price < PriceMin))
                        {
                            continue;
                        }
                        ItemClasses.Add(cls);
                    }
                }
            }

            Items = new ItemPack();
            GenerateItems();
        }