Greetings all,

I'd like to sell some scrolls of transcendence in a vendor, using its SB sales list. The issue I am having is that the InternalBuyInfo list is looking for an item type, and the random method to generate a scroll with a random skill is as follows

C#:
        public static ScrollofTranscendence CreateRandom( int min, int max )
        {
            SkillName skill = (SkillName)Utility.Random( SkillInfo.Table.Length );

            return new ScrollofTranscendence(skill, Utility.RandomMinMax(min, max) * 0.1);
        }

its needless for me to say that putting

Add( new GenericBuyInfo( typeof( ScrollofTranscendence.CreateRandom(1, 3) ), 10000, 10, 0x14F0, 0 ) );

in the internal buy info doesn't work. Is there an easy way to code this in the vendor's sale list?
 
here an example when I played around with the source of odyssey ;)
C#:
Add(new GenericBuyInfo(typeof(PowerScroll), 80000, 20, 0x14F0, 0x481, new object[] { SkillName.Alchemy, 120 }));
 
so that is for a powerscroll of archery, what if you wanted to sell a random powerscroll?

im trying to make it a lottery-type of thing where the player doesn't know what scroll hes getting.
 
The clostest thing to that directly would be something like this
C#:
Add(new GenericBuyInfo(typeof(PowerScroll), 80000, 20, 0x14F0, 0x481, new object[] { PowerScroll.Skills[Utility.Random(PowerScroll.Skills.Count)], 100 + Utility.Random(1, 20) }));

but that just randomizes on restock and per vendor.
What you could do though is make either an item that on use gives you an random powerscroll or an bag that gets an random powerscroll added in the constructor
 
The bag / item that on use gives you a scroll is the only way if i don't want the players to see what it is they are buying (e.g. scroll of chilvalry). I want them to see "scroll", and once bought, see what they got.
having a bag is the only way to do this hunh? I was hoping i'd be able to call on the createrandom method somehow...
 
You can make an item with the below code and sell that instead. It has the same appearance/hue as a powerscroll but has additional text underneath the name "Power Scroll" so players know what to do with it. You can then also use this for other things like loot.

C#:
using System;
using Server;
using Server.Network;
using System.Text;
using Server.Items;
using Server.Mobiles;

namespace Server.Items
{
    public class RandomPowerScroll : Item
    {
        [Constructable]
        public RandomPowerScroll() : base( 0x14F0 )
        {
            Name = "power scroll";
            Hue = 0x481;
            Weight = 1.0;
        }

        public RandomPowerScroll( Serial serial ) : base( serial )
        {
        }

        public override void OnDoubleClick( Mobile from )
        {
            if ( !IsChildOf( from.Backpack ) )
            {
                from.SendMessage( "This must be in your backpack to read." );
                return;
            }
            else
            {
                from.PrivateOverheadMessage(MessageType.Regular, 0x14C, false, "You read the scroll and its true text is in your backpack.", from.NetState);

                switch ( Utility.RandomMinMax( 0, 47 ) )
                {
                    case 0: from.AddToBackpack ( new DJ_SP_Alchemy() ); break;
                    case 1: from.AddToBackpack ( new DJ_SP_Anatomy() ); break;
                    case 2: from.AddToBackpack ( new DJ_SP_AnimalLore() ); break;
                    case 3: from.AddToBackpack ( new DJ_SP_AnimalTaming() ); break;
                    case 4: from.AddToBackpack ( new DJ_SP_Archery() ); break;
                    case 5: from.AddToBackpack ( new DJ_SP_ArmsLore() ); break;
                    case 6: from.AddToBackpack ( new DJ_SP_Blacksmith() ); break;
                    case 7: from.AddToBackpack ( new DJ_SP_Bushido() ); break;
                    case 8: from.AddToBackpack ( new DJ_SP_Carpentry() ); break;
                    case 9: from.AddToBackpack ( new DJ_SP_Cartography() ); break;
                    case 10: from.AddToBackpack ( new DJ_SP_Chivalry() ); break;
                    case 11: from.AddToBackpack ( new DJ_SP_Cooking() ); break;
                    case 12: from.AddToBackpack ( new DJ_SP_DetectHidden() ); break;
                    case 13: from.AddToBackpack ( new DJ_SP_Discordance() ); break;
                    case 14: from.AddToBackpack ( new DJ_SP_EvalInt() ); break;
                    case 15: from.AddToBackpack ( new DJ_SP_Fencing() ); break;
                    case 16: from.AddToBackpack ( new DJ_SP_Fishing() ); break;
                    case 17: from.AddToBackpack ( new DJ_SP_Fletching() ); break;
                    case 18: from.AddToBackpack ( new DJ_SP_Focus() ); break;
                    case 19: from.AddToBackpack ( new DJ_SP_Healing() ); break;
                    case 20: from.AddToBackpack ( new DJ_SP_Hiding() ); break;
                    case 21: from.AddToBackpack ( new DJ_SP_Inscribe() ); break;
                    case 22: from.AddToBackpack ( new DJ_SP_Lockpicking() ); break;
                    case 23: from.AddToBackpack ( new DJ_SP_Lumberjacking() ); break;
                    case 24: from.AddToBackpack ( new DJ_SP_Macing() ); break;
                    case 25: from.AddToBackpack ( new DJ_SP_Magery() ); break;
                    case 26: from.AddToBackpack ( new DJ_SP_MagicResist() ); break;
                    case 27: from.AddToBackpack ( new DJ_SP_Meditation() ); break;
                    case 28: from.AddToBackpack ( new DJ_SP_Mining() ); break;
                    case 29: from.AddToBackpack ( new DJ_SP_Musicianship() ); break;
                    case 30: from.AddToBackpack ( new DJ_SP_Necromancy() ); break;
                    case 31: from.AddToBackpack ( new DJ_SP_Ninjitsu() ); break;
                    case 32: from.AddToBackpack ( new DJ_SP_Parry() ); break;
                    case 33: from.AddToBackpack ( new DJ_SP_Peacemaking() ); break;
                    case 34: from.AddToBackpack ( new DJ_SP_Poisoning() ); break;
                    case 35: from.AddToBackpack ( new DJ_SP_Provocation() ); break;
                    case 36: from.AddToBackpack ( new DJ_SP_RemoveTrap() ); break;
                    case 37: from.AddToBackpack ( new DJ_SP_Snooping() ); break;
                    case 38: from.AddToBackpack ( new DJ_SP_SpiritSpeak() ); break;
                    case 39: from.AddToBackpack ( new DJ_SP_Stealing() ); break;
                    case 40: from.AddToBackpack ( new DJ_SP_Stealth() ); break;
                    case 41: from.AddToBackpack ( new DJ_SP_Swords() ); break;
                    case 42: from.AddToBackpack ( new DJ_SP_Tactics() ); break;
                    case 43: from.AddToBackpack ( new DJ_SP_Tailoring() ); break;
                    case 44: from.AddToBackpack ( new DJ_SP_Tinkering() ); break;
                    case 45: from.AddToBackpack ( new DJ_SP_Tracking() ); break;
                    case 46: from.AddToBackpack ( new DJ_SP_Veterinary() ); break;
                    case 47: from.AddToBackpack ( new DJ_SP_Wrestling() ); break;
                }
                this.Delete();
            }
        }

        public override void AddNameProperties(ObjectPropertyList list)
        {
            base.AddNameProperties(list);
            list.Add( 1049644, "Read To Determine The Type");
        }

        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();
        }
    }
}
 
Last edited:
another way but kinda hacky :D is this:

C#:
Add(new GenericBuyInfo(typeof(RandomPowerScroll), 80000, 20, 0x14F0, 0x481, new object[] { 5, 20, true }));
Add(new GenericBuyInfo(typeof(RandomPowerScroll), 80000, 20, 0x14F0, 0x481, new object[] { 5, 20, false }));

C#:
using Server.Items;

namespace Server.Customs.Items
{
    public class RandomPowerScroll : PowerScroll
    {
        private int min, max;
        private bool craft, exploitProtection;

        public RandomPowerScroll(int min, int max, bool craft) : base()
        {
            this.min = min;
            this.max = max;
            this.craft = craft;
        }

        public override void AddNameProperty(ObjectPropertyList list)
        {
            if (craft)
                list.Add("Random Power Scroll with Crafts");
            else
                list.Add("Random Power Scroll without Crafts");
        }

        public override void OnAdded(object parent)
        {
            base.OnAdded(parent);
            if (exploitProtection || parent is Container && (ItemID == 0 || Map == Map.Internal)) return;

            PowerScroll scroll = null;
            if (craft)
                scroll = PowerScroll.CreateRandom(min, max);
            else
                scroll = PowerScroll.CreateRandomNoCraft(min, max);

            if (Parent is Item)
            {
                ((Container)Parent).DropItem(scroll);
            }
            else
            {
                scroll.MoveToWorld(Location, Map);
            }
            Delete();
            exploitProtection = true;
        }

        public RandomPowerScroll(Serial serial) : base(serial)
        { }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);
            writer.Write(0);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            reader.ReadInt();
        }
    }
}
 
thats what i was trying to do by using the createrandom method in scroll of transcendence.

ill copy the randompowerscroll example to create a randomscrolloftranscendence item, which the vendor can then sell
 
Seems to work so far, thanks Pyro for simple workaround. unsure if the new random scroll will pop to the ground more often then not, but that's a detail at this point.

for anyone else wanting to do this for scrolls of transcendence:
C#:
using Server.Items;

namespace Server.Items
{
    public class RandomTranscendence : ScrollofTranscendence
    {

        public RandomTranscendence() : base()
        {
        }

        public override void OnAdded(object parent)
        {
            base.OnAdded(parent);

            ScrollofTranscendence scroll = null;

            scroll = ScrollofTranscendence.CreateRandom(1, 3);


            if (Parent is Item)
            {
                ((Container)Parent).DropItem(scroll);
            }
            else
            {
                scroll.MoveToWorld(Location, Map);
            }
            Delete();

        }

        public RandomTranscendence(Serial serial) : base(serial)
        { }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);
            writer.Write(0);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            reader.ReadInt();
        }
    }
}

In the vendor sales list, add "RandomTranscendence" as a new list item.
 
The clostest thing to that directly would be something like this
C#:
Add(new GenericBuyInfo(typeof(PowerScroll), 80000, 20, 0x14F0, 0x481, new object[] { PowerScroll.Skills[Utility.Random(PowerScroll.Skills.Count)], 100 + Utility.Random(1, 20) }));

but that just randomizes on restock and per vendor.
What you could do though is make either an item that on use gives you an random powerscroll or an bag that gets an random powerscroll added in the constructor
Pyro, as a newbie to servuo, how would one make such a bag?! I’m highly interested.
Post automatically merged:

 
idk just something basic like

Code:
namespace Server.Items.Custom
{
    public class BagOfRandomPowerScroll : Bag
    {
        public override string DefaultName { get { return "bag of random power scroll"; } }

        [Constructable]
        public BagOfRandomPowerScroll() : base()
        {
            Hue = 1129;
            DropItem(new PowerScroll(PowerScroll.Skills[Utility.Random(PowerScroll.Skills.Count)], 100 + Utility.Random(1, 20)));
        }

        public BagOfRandomPowerScroll(Serial serial) : base(serial)
        { }

        public override void Serialize(GenericWriter writer)
        {
            base.Serialize(writer);
            writer.Write(0);
        }

        public override void Deserialize(GenericReader reader)
        {
            base.Deserialize(reader);
            reader.ReadInt(); // version Number
        }
    }
}

Or you can use the CreateRandom functions from PowerScroll itself, but then it is in increments of 5
 
Last edited:
@PyrO

I tried what you suggested and the Compiler ran with no error. However, when trying to add, im seeing this message:

20:46:02 System.MemberAccessException: Cannot create an instance of Server.Items.Custom.PSBag because it is an abstract class.
at System.Reflection.RuntimeConstructorInfo.CheckCanCreateInstance(Type declaringType, Boolean isVarArg)
at System.Reflection.RuntimeConstructorInfo.ThrowNoInvokeException()
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Server.Commands.Add.Build(Mobile from, ConstructorInfo ctor, Object[] values, String[,] props, PropertyInfo[] realProps, Boolean& sendError)
at Server.Commands.Add.Build(Mobile from, Point3D start, Point3D end, ConstructorInfo ctor, Object[] values, String[,] props, PropertyInfo[] realProps, List`1 packs, Boolean outline, Boolean mapAvg)

any ideas?
 
@PyrO

I tried what you suggested and the Compiler ran with no error. However, when trying to add, im seeing this message:

20:46:02 System.MemberAccessException: Cannot create an instance of Server.Items.Custom.PSBag because it is an abstract class.
at System.Reflection.RuntimeConstructorInfo.CheckCanCreateInstance(Type declaringType, Boolean isVarArg)
at System.Reflection.RuntimeConstructorInfo.ThrowNoInvokeException()
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Server.Commands.Add.Build(Mobile from, ConstructorInfo ctor, Object[] values, String[,] props, PropertyInfo[] realProps, Boolean& sendError)
at Server.Commands.Add.Build(Mobile from, Point3D start, Point3D end, ConstructorInfo ctor, Object[] values, String[,] props, PropertyInfo[] realProps, List`1 packs, Boolean outline, Boolean mapAvg)

any ideas?
You need to remove abstract keyword from your class.
Change
C#:
 public abstract class BagOfRandomPowerScroll : Bag
to
C#:
 public class BagOfRandomPowerScroll : Bag
 
Alternative would be to use GenericBuyInfo which specifies the name such that it just indicates the "scroll of transcendence".
And have the default constructor generate a random scroll instead of the alchemy scroll with 0.0 skill.

untested, but something like:
C#:
Add( new GenericBuyInfo("scroll of transcendence", typeof( ScrollofTranscendence ), 10000, 10, 0x14F0, 0 ) );
C#:
public ScrollOfTranscendence()  : this(PowerScroll.Skills[Utility.Random(PowerScroll.Skills.Count)], Utility.RandomDouble()*5)  { }
 
Back