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!

FS Animal Taming Systems

Dave1969

Wanderer
How would i go about doing this. Ive looked everywhere

stormwolff said:
Changing the way it collects the gold perhaps or just having it look for 0 gold.


Ive looked all over for the file that has the command to set the gold in it and found nothing
 

Arcanagirl

Wanderer
well for some reason the difference in animaltrainer and my evos by removing the spaces allowed my shard to work now...I dont know why but thats what happened to mine. This fix was for the merging or non merging issue of FS wanting to delete items or mobiles.
 

Scripture

Wanderer
The create bulk order method is at the begginning. Although I don't see what activates it handing out the actually BOD, simply the conditions in how long it'll take depending on your skill for the frequency of bods. The only thing I see that'd be remotely close is
#region Bulk Orders
public override Item CreateBulkOrder( Mobile from, bool fromContextMenu )

But the only thing from the single click menu on animal trainers is Bulk Order Info, which does nothing but tell you there is a BoD available.


Code:
using System;
using System.Collections;
using Server;
using Server.Gumps;
using Server.Items;
using Server.Network;
using Server.Targeting;
using Server.ContextMenus;
using Server.Engines.BulkOrders;

namespace Server.Mobiles
{
	public class AnimalTrainer : BaseVendor
	{
		private ArrayList m_SBInfos = new ArrayList();
		protected override ArrayList SBInfos{ get { return m_SBInfos; } }

		[Constructable]
		public AnimalTrainer() : base( "the animal trainer" )
		{
			SetSkill( SkillName.AnimalLore, 64.0, 100.0 );
			SetSkill( SkillName.AnimalTaming, 90.0, 100.0 );
			SetSkill( SkillName.Veterinary, 65.0, 88.0 );
		}

		public override void InitSBInfo()
		{
			m_SBInfos.Add( new SBAnimalTrainer() );
		}

		public override VendorShoeType ShoeType
		{
			get{ return Female ? VendorShoeType.ThighBoots : VendorShoeType.Boots; }
		}

		#region Bulk Orders
		public override Item CreateBulkOrder( Mobile from, bool fromContextMenu )
		{
			PlayerMobile pm = from as PlayerMobile;

			if ( pm != null && pm.NextTamingBulkOrder == TimeSpan.Zero && (fromContextMenu || 0.2 > Utility.RandomDouble()) )
			{
				double theirSkill = pm.Skills[SkillName.AnimalTaming].Base;

				if ( theirSkill >= 70.1 )
					pm.NextTamingBulkOrder = TimeSpan.FromHours( 3.0 );
				else if ( theirSkill >= 50.1 )
					pm.NextTamingBulkOrder = TimeSpan.FromHours( 2.0 );
				else
					pm.NextTamingBulkOrder = TimeSpan.FromHours( 1.0 );

				if ( theirSkill >= 70.1 && ((theirSkill - 40.0) / 300.0) > Utility.RandomDouble() )
					return new LargeTamingBOD();

				return SmallTamingBOD.CreateRandomFor( from );
			}

			return null;
		}

		public override bool IsValidBulkOrder( Item item )
		{
			return ( item is SmallTamingBOD || item is LargeTamingBOD );
		}

		public override bool SupportsBulkOrders( Mobile from )
		{
			return ( from is PlayerMobile && from.Skills[SkillName.AnimalTaming].Base > 0 && FSATS.EnableTamingBODs == true );
		}

		public override TimeSpan GetNextBulkOrder( Mobile from )
		{
			if ( from is PlayerMobile )
				return ((PlayerMobile)from).NextTamingBulkOrder;

			return TimeSpan.Zero;
		}
		#endregion

		public override int GetShoeHue()
		{
			return 0;
		}

		public override void InitOutfit()
		{
			base.InitOutfit();

			AddItem( Utility.RandomBool() ? (Item)new QuarterStaff() : (Item)new ShepherdsCrook() );
		}

		private class StableEntry : ContextMenuEntry
		{
			private AnimalTrainer m_Trainer;
			private Mobile m_From;

			public StableEntry( AnimalTrainer trainer, Mobile from ) : base( 6126, 12 )
			{
				m_Trainer = trainer;
				m_From = from;
			}

			public override void OnClick()
			{
				m_Trainer.BeginStable( m_From );
			}
		}

		private class ClaimListGump : Gump
		{
			private AnimalTrainer m_Trainer;
			private Mobile m_From;
			private ArrayList m_List;

			public ClaimListGump( AnimalTrainer trainer, Mobile from, ArrayList list ) : base( 50, 50 )
			{
				m_Trainer = trainer;
				m_From = from;
				m_List = list;

				from.CloseGump( typeof( ClaimListGump ) );

				AddPage( 0 );

				AddBackground( 0, 0, 325, 50 + (list.Count * 20), 9250 );
				AddAlphaRegion( 5, 5, 315, 40 + (list.Count * 20) );

				AddHtml( 15, 15, 275, 20, "<BASEFONT COLOR=#FFFFFF>Select a pet to retrieve from the stables:</BASEFONT>", false, false );

				for ( int i = 0; i < list.Count; ++i )
				{
					BaseCreature pet = list[i] as BaseCreature;

					if ( pet == null || pet.Deleted )
						continue;

					AddButton( 15, 39 + (i * 20), 10006, 10006, i + 1, GumpButtonType.Reply, 0 );
					AddHtml( 32, 35 + (i * 20), 275, 18, String.Format( "<BASEFONT COLOR=#C0C0EE>{0}</BASEFONT>", pet.Name ), false, false );
				}
			}

			public override void OnResponse( NetState sender, RelayInfo info )
			{
				int index = info.ButtonID - 1;

				if ( index >= 0 && index < m_List.Count )
					m_Trainer.EndClaimList( m_From, m_List[index] as BaseCreature );
			}
		}

		private class ClaimAllEntry : ContextMenuEntry
		{
			private AnimalTrainer m_Trainer;
			private Mobile m_From;

			public ClaimAllEntry( AnimalTrainer trainer, Mobile from ) : base( 6127, 12 )
			{
				m_Trainer = trainer;
				m_From = from;
			}

			public override void OnClick()
			{
				m_Trainer.Claim( m_From );
			}
		}

		public override void AddCustomContextEntries( Mobile from, ArrayList list )
		{
			if ( from.Alive )
			{
				list.Add( new StableEntry( this, from ) );

				if ( from.Stabled.Count > 0 )
					list.Add( new ClaimAllEntry( this, from ) );
			}

			base.AddCustomContextEntries( from, list );
		}

		public static int GetMaxStabled( Mobile from )
		{
			double taming = from.Skills[SkillName.AnimalTaming].Value;
			double anlore = from.Skills[SkillName.AnimalLore].Value;
			double vetern = from.Skills[SkillName.Veterinary].Value;
			double sklsum = taming + anlore + vetern;

			int max;

			if ( sklsum >= 240.0 )
				max = 5;
			else if ( sklsum >= 200.0 )
				max = 4;
			else if ( sklsum >= 160.0 )
				max = 3;
			else
				max = 2;

			if ( taming >= 100.0 )
				max += (int)((taming - 90.0) / 10);

			if ( anlore >= 100.0 )
				max += (int)((anlore - 90.0) / 10);

			if ( vetern >= 100.0 )
				max += (int)((vetern - 90.0) / 10);

			return max;
		}

		private class StableTarget : Target
		{
			private AnimalTrainer m_Trainer;

			public StableTarget( AnimalTrainer trainer ) : base( 12, false, TargetFlags.None )
			{
				m_Trainer = trainer;
			}

			protected override void OnTarget( Mobile from, object targeted )
			{
				if ( targeted is BaseCreature )
					m_Trainer.EndStable( from, (BaseCreature)targeted );
				else if ( targeted == from )
					m_Trainer.SayTo( from, 502672 ); // HA HA HA! Sorry, I am not an inn.
				else
					m_Trainer.SayTo( from, 1048053 ); // You can't stable that!
			}
		}

		public void BeginClaimList( Mobile from )
		{
			if ( Deleted || !from.CheckAlive() )
				return;

			ArrayList list = new ArrayList();

			for ( int i = 0; i < from.Stabled.Count; ++i )
			{
				BaseCreature pet = from.Stabled[i] as BaseCreature;

				if ( pet == null || pet.Deleted )
				{
					pet.IsStabled = false;
					from.Stabled.RemoveAt( i );
					--i;
					continue;
				}

				list.Add( pet );
			}

			if ( list.Count > 0 )
				from.SendGump( new ClaimListGump( this, from, list ) );
			else
				SayTo( from, 502671 ); // But I have no animals stabled with me at the moment!
		}

		public void EndClaimList( Mobile from, BaseCreature pet )
		{
			if ( pet == null || pet.Deleted || from.Map != this.Map || !from.InRange( this, 14 ) || !from.Stabled.Contains( pet ) || !from.CheckAlive() )
				return;

			if ( (from.Followers + pet.ControlSlots) <= from.FollowersMax )
			{
				pet.SetControlMaster( from );

				if ( pet.Summoned )
					pet.SummonMaster = from;

				pet.ControlTarget = from;
				pet.ControlOrder = OrderType.Follow;

				pet.MoveToWorld( from.Location, from.Map );

				pet.IsStabled = false;
				from.Stabled.Remove( pet );

				SayTo( from, 1042559 ); // Here you go... and good day to you!
			}
			else
			{
				SayTo( from, 1049612, pet.Name ); // ~1_NAME~ remained in the stables because you have too many followers.
			}
		}

		public void BeginStable( Mobile from )
		{
			if ( Deleted || !from.CheckAlive() )
				return;

			if ( from.Stabled.Count >= GetMaxStabled( from ) )
			{
				SayTo( from, 1042565 ); // You have too many pets in the stables!
			}
			else
			{
				SayTo( from, 1042558 ); /* I charge 30 gold per pet for a real week's stable time.
										 * I will withdraw it from thy bank account.
										 * Which animal wouldst thou like to stable here?
										 */

				from.Target = new StableTarget( this );
			}
		}

		public void EndStable( Mobile from, BaseCreature pet )
		{
			if ( Deleted || !from.CheckAlive() )
				return;

			if ( !pet.Controled || pet.ControlMaster != from )
			{
				SayTo( from, 1042562 ); // You do not own that pet!
			}
			else if ( pet.IsDeadPet )
			{
				SayTo( from, 1049668 ); // Living pets only, please.
			}
			else if ( pet.Summoned )
			{
				SayTo( from, 502673 ); // I can not stable summoned creatures.
			}
			else if ( pet.Body.IsHuman )
			{
				SayTo( from, 502672 ); // HA HA HA! Sorry, I am not an inn.
			}
			else if ( (pet is PackLlama || pet is PackHorse || pet is Beetle) && (pet.Backpack != null && pet.Backpack.Items.Count > 0) )
			{
				SayTo( from, 1042563 ); // You need to unload your pet.
			}
			else if ( pet.Combatant != null && pet.InRange( pet.Combatant, 12 ) && pet.Map == pet.Combatant.Map )
			{
				SayTo( from, 1042564 ); // I'm sorry.  Your pet seems to be busy.
			}
			else if ( from.Stabled.Count >= GetMaxStabled( from ) )
			{
				SayTo( from, 1042565 ); // You have too many pets in the stables!
			}
			else
			{
				Container bank = from.BankBox;

				if ( bank != null && bank.ConsumeTotal( typeof( Gold ), 30 ) )
				{
					pet.ControlTarget = null;
					pet.ControlOrder = OrderType.Stay;
					pet.Internalize();

					pet.SetControlMaster( null );
					pet.SummonMaster = null;

					pet.IsStabled = true;
					from.Stabled.Add( pet );

					SayTo( from, 502679 ); // Very well, thy pet is stabled. Thou mayst recover it by saying 'claim' to me. In one real world week, I shall sell it off if it is not claimed!
				}
				else
				{
					SayTo( from, 502677 ); // But thou hast not the funds in thy bank account!
				}
			}
		}

		public void Claim( Mobile from )
		{
			if ( Deleted || !from.CheckAlive() )
				return;

			bool claimed = false;
			int stabled = 0;

			for ( int i = 0; i < from.Stabled.Count; ++i )
			{
				BaseCreature pet = from.Stabled[i] as BaseCreature;

				if ( pet == null || pet.Deleted )
				{
					pet.IsStabled = false;
					from.Stabled.RemoveAt( i );
					--i;
					continue;
				}

				++stabled;

				if ( (from.Followers + pet.ControlSlots) <= from.FollowersMax )
				{
					pet.SetControlMaster( from );

					if ( pet.Summoned )
						pet.SummonMaster = from;

					pet.ControlTarget = from;
					pet.ControlOrder = OrderType.Follow;

					pet.MoveToWorld( from.Location, from.Map );

					pet.IsStabled = false;
					from.Stabled.RemoveAt( i );
					--i;

					claimed = true;
				}
				else
				{
					SayTo( from, 1049612, pet.Name ); // ~1_NAME~ remained in the stables because you have too many followers.
				}
			}

			if ( claimed )
				SayTo( from, 1042559 ); // Here you go... and good day to you!
			else if ( stabled == 0 )
				SayTo( from, 502671 ); // But I have no animals stabled with me at the moment!
		}

		public override bool HandlesOnSpeech( Mobile from )
		{
			return true;
		}

		public override void OnSpeech( SpeechEventArgs e )
		{
			if ( !e.Handled && e.HasKeyword( 0x0008 ) )
			{
				e.Handled = true;
				BeginStable( e.Mobile );
			}
			else if ( !e.Handled && e.HasKeyword( 0x0009 ) )
			{
				e.Handled = true;

				if ( !Insensitive.Equals( e.Speech, "claim" ) )
					BeginClaimList( e.Mobile );
				else
					Claim( e.Mobile );
			}
			else
			{
				base.OnSpeech( e );
			}
		}

		public AnimalTrainer( 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();
		}
	}
}
 

stormwolff

Knight
Dave1969 said:
Ive looked all over for the file that has the command to set the gold in it and found nothing
Code:
								if ( Banker.Withdraw( from, pct.Price ) )
								{
									from.SendLocalizedMessage( 1060398, pct.Price.ToString() );
									from.SendLocalizedMessage( 1060022, Banker.GetBalance( from ).ToString() );

I guess you would have to find out where it sets the price or figure out how to restructure the code around that so it errors out before giving a new generation 1 pet to the stable.

Code:
if ( dropped is PetClaimTicket )
			{
				PetClaimTicket pct = (PetClaimTicket)dropped;
				if ( pct.Time <= DateTime.Now )
				{
					if ( pct.Pet == null )
					{
						from.SendMessage( "Error! Contact Gamemaster" );
						return false;
					}
					else if ( from.Followers == 0 )
					{
						Type pettype = pct.Pet.GetType();
						BaseCreature bc = (BaseCreature)pct.Pet;

						bc.IsStabled = true;
						from.Stabled.Add( bc );
						this.SayTo( from, "I have put your pet that was mating in the stable under you name." );

						BaseCreature baby = null;
	
						if ( pettype != null )
						{
							object o = Activator.CreateInstance( pettype );
        						baby = o as BaseCreature;
						}

						if ( baby == null )
						{
							from.SendMessage( 38, "There was an internal error and breeding has failed due to lack of type, Please contact a member of the staff." );
							return false;
						}
						else
						{
							if ( from == pct.Owner )
							{
								if ( Banker.Withdraw( from, pct.Price ) )
								{
									from.SendLocalizedMessage( 1060398, pct.Price.ToString() );
									from.SendLocalizedMessage( 1060022, Banker.GetBalance( from ).ToString() );

									baby.Str = pct.Str;
									baby.Dex = pct.Dex;
									baby.Int = pct.Int;
									baby.HitsMaxSeed = pct.Hits;
									baby.StamMaxSeed = pct.Stam;
									baby.ManaMaxSeed = pct.Mana;
									baby.PhysicalResistanceSeed = pct.Phys;
									baby.FireResistSeed = pct.Fire;
									baby.ColdResistSeed = pct.Cold;
									baby.EnergyResistSeed = pct.Nrgy;
									baby.PoisonResistSeed = pct.Pois;
									baby.DamageMin = pct.Dmin;
									baby.DamageMax = pct.Dmax;
									baby.MaxLevel = pct.Mlev;
									baby.Generation = pct.Gen + 1;

        								baby.Controled = true;
        								baby.ControlMaster = from;
        								baby.Location = from.Location;
									baby.ControlOrder = OrderType.Follow;
									baby.ControlTarget = from;
        								baby.Map = from.Map;
									baby.Name = baby.Name + " baby";

									if ( pct.AI == 1 )
										baby.AI = AIType.AI_Mage;
									else if ( pct.AI == 2 )
										baby.AI = AIType.AI_Melee;

        								World.AddMobile( baby );

									pct.Delete();

									return true;
								}
								else
								{
									this.SayTo( from, "Hey! you tring to cheat me! This anit for free buddy." );
									from.SendMessage( "You lack the gold in your banking account to do this." );
									return false;
								}
							}
							else
							{
								this.SayTo( from, "You are not the owner of this deed." );
								return false;
							}
						}
					}
					else
					{
						this.SayTo( from, "Please stable or shrink all your pets before we go on." );
						return false;
					}
				}
				else
				{
					if ( pct.Pet != null )
					{
						this.SayTo( from, "Your pet {0} is not done mating yet, Please check back later.", pct.Pet.Name );
						return false;
					}
					else
					{
						from.SendMessage( "Error in your (Pet Claim Ticket) please contact the staff." );
						return false;
					}
				}
			}
			else
			{
				return false;
			}
 

Hellsbane

Wanderer
Scripture said:
Is this a fix for just the merging of Daats script and this one? And I thought that the amount of spaces had no effect on how the script compiles (between parenthesis at least)


Are you sure it wouldn't create an incompatability issue? If one script is done one way and another script done another way, wouldn't they conflict?
 

Arcanagirl

Wanderer
it is possible, cause look at the case sensitive issue. this.name = ""; would cause 4 to 5 errors..

When the correst for is this.Name = "";

So really runuo is very picky about how each script is programed. I think its cause if all the scripts use the same form, like spaces. it would work fine but if a system has one part spaces and the other part non spaces, it may cause the issue I had and others had. Cuase my shard isnt crashing or deleting mobiles or items anymore. I finally respawned the shard up.
 

Greystar

Wanderer
Arcanagirl said:
it is possible, cause look at the case sensitive issue. this.name = ""; would cause 4 to 5 errors..

When the correst for is this.Name = "";

So really runuo is very picky about how each script is programed. I think its cause if all the scripts use the same form, like spaces. it would work fine but if a system has one part spaces and the other part non spaces, it may cause the issue I had and others had. Cuase my shard isnt crashing or deleting mobiles or items anymore. I finally respawned the shard up.

its not runuo thats picky... I just figured I'd clairify this. Its almost any HighLevel programming language. (except VB who as long as you spell the variable right changes its case to match the way it was originally defined as long as its a global variable, but then again I'm not sure if they call VB a high level language or not). Almost any Language name != Name and Friend != friend the value of the capital letter is different then the value of the lower case. So you could in theory use both Upper and lower case variables with the same name and be fine although very confusing. Just my little rant for the moment, since individuals keep saying runuo is pick when its not RunUO its the code it's written in.
 

Scripture

Wanderer
So no one has any idea on how I can claim a BoD from the animal trainer though? The context menu doesnt have anything on it that lets me claim a bod, only check to see if I COULD get one now. And the animal trainer doesnt let me sell him anything. Any idea's?

I'm guessing that it's different for me from everyone else because I have AoS and SE disabled.
 

Freya

Wanderer
Ok, I got the problem fixed where it now gives the taming BOD to players, BUT now it won't accept them when they're full... It just puts the BOD back in the players backpack when they try to drop on the animal trainer... so there's no way to turn them in... any ideas?
 

Arvoreen

Sorceror
Freya said:
Ok, I got the problem fixed where it now gives the taming BOD to players, BUT now it won't accept them when they're full... It just puts the BOD back in the players backpack when they try to drop on the animal trainer... so there's no way to turn them in... any ideas?

Does your AnimalTrainer.cs have a IsValidBulkOrder override? If not, you'll need to add one and make it return true if it's a SmallMobileBOD or LargeMobileBOD.

Do you have the FS Taming System install instructions? I thought that it gave instructions for how to modify your distro scripts. :)

Hope this helps!
 

Freya

Wanderer
Yes, thats all in there... I was able to replace the animaltrainer.cs w/the one provided w/this system since it was put in on a fresh RunUO install... =) And it does have that override method in there, set to true... I've been trying to figure out where I could have gone wrong... but I'm stumped :confused: Thanks for response =)
 

Arvoreen

Sorceror
Freya said:
Yes, thats all in there... I was able to replace the animaltrainer.cs w/the one provided w/this system since it was put in on a fresh RunUO install... =) And it does have that override method in there, set to true... I've been trying to figure out where I could have gone wrong... but I'm stumped :confused: Thanks for response =)

The next thing to check is the OnDragDrop in BaseVendor.

Make sure that it checks for SmallMobileBOD and LargeMobileBOD in there, in addition to SmallBOD and LargeBOD.
 

Freya

Wanderer
Ok, I found part of the problem, it was something I missed including in the BaseVendor.cs since I have Daat's OWLTR system in also, I was a bit confused on fusing the differences in the systems in some scripts... Problem is now when you drop a BOD on the animal trainer it says "This isn't an acceptable bod"... :confused: Here is my BaseVendor.cs below... I am thinking the problem is somewhere in it, but not sure, Thanks again for helping!

Code:
using System;
using System.Collections;
using Server.Items;
using Server.Network;
using Server.ContextMenus;
using Server.Mobiles;
using Server.Misc;
using Server.Engines.BulkOrders;
using Server.Regions;
using Server.Factions;

namespace Server.Mobiles
{
	public enum VendorShoeType
	{
		None,
		Shoes,
		Boots,
		Sandals,
		ThighBoots
	}

	public abstract class BaseVendor : BaseCreature, IVendor
	{
		private const int MaxSell = 500;

		protected abstract ArrayList SBInfos{ get; }

		private ArrayList m_ArmorBuyInfo = new ArrayList();
		private ArrayList m_ArmorSellInfo = new ArrayList();

		private DateTime m_LastRestock;

		public override bool CanTeach{ get{ return true; } }

		public override bool PlayerRangeSensitive{ get{ return true; } }

		public virtual bool IsActiveVendor{ get{ return true; } }
		public virtual bool IsActiveBuyer{ get{ return IsActiveVendor; } } // response to vendor SELL
		public virtual bool IsActiveSeller{ get{ return IsActiveVendor; } } // repsonse to vendor BUY

		public virtual NpcGuild NpcGuild{ get{ return NpcGuild.None; } }

		public virtual bool IsInvulnerable{ get{ return true; } }

		public override bool ShowFameTitle{ get{ return false; } }

		public virtual bool IsValidBulkOrder( Item item )
		{
			return false;
		}

		public virtual Item CreateBulkOrder( Mobile from, bool fromContextMenu )
		{
			return null;
		}

		public virtual bool SupportsBulkOrders( Mobile from )
		{
			return false;
		}

		public virtual TimeSpan GetNextBulkOrder( Mobile from )
		{
			return TimeSpan.Zero;
		}

		#region Faction
		public virtual int GetPriceScalar()
		{
			Town town = Town.FromRegion( this.Region );

			if ( town != null )
				return (100 + town.Tax);

			return 100;
		}

		public void UpdateBuyInfo()
		{
			int priceScalar = GetPriceScalar();
			
			IBuyItemInfo[] buyinfo = (IBuyItemInfo[])m_ArmorBuyInfo.ToArray( typeof( IBuyItemInfo ) );

			if ( buyinfo != null )
			{
				foreach ( IBuyItemInfo info in buyinfo )
					info.PriceScalar = priceScalar;
			}
		}
		#endregion

		private class BulkOrderInfoEntry : ContextMenuEntry
		{
			private Mobile m_From;
			private BaseVendor m_Vendor;

			public BulkOrderInfoEntry( Mobile from, BaseVendor vendor ) : base( 6152, 6 )
			{
				m_From = from;
				m_Vendor = vendor;
			}

			public override void OnClick()
			{
				if ( m_Vendor.SupportsBulkOrders( m_From ) )
				{
					TimeSpan ts = m_Vendor.GetNextBulkOrder( m_From );

					int totalSeconds = (int)ts.TotalSeconds;
					int totalHours = (totalSeconds + 3599) / 3600;

					if ( totalHours == 0 )
					{
						m_From.SendLocalizedMessage( 1049038 ); // You can get an order now.

						if ( Core.AOS )
						{
							Item bulkOrder = m_Vendor.CreateBulkOrder( m_From, true );

							if ( bulkOrder is SmallMobileBOD )
								m_From.SendGump( new SmallMobileBODAcceptGump( m_From, (SmallMobileBOD)bulkOrder ) );
							else if ( bulkOrder is LargeMobileBOD )
								m_From.SendGump( new LargeMobileBODAcceptGump( m_From, (LargeMobileBOD)bulkOrder ) );
							else if ( bulkOrder is LargeBOD )
								m_From.SendGump( new LargeBODAcceptGump( m_From, (LargeBOD)bulkOrder ) );
							else if ( bulkOrder is SmallBOD )
								m_From.SendGump( new SmallBODAcceptGump( m_From, (SmallBOD)bulkOrder ) );
						}
					}
					else
					{
						int oldSpeechHue = m_Vendor.SpeechHue;
						m_Vendor.SpeechHue = 0x3B2;
						m_Vendor.SayTo( m_From, 1049039, totalHours.ToString() ); // An offer may be available in about ~1_hours~ hours.
						m_Vendor.SpeechHue = oldSpeechHue;
					}
				}
			}
		}

		public BaseVendor( string title ) : base( AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2 )
		{
			LoadSBInfo();

			this.Title = title;
			InitBody();
			InitOutfit();

			Container pack;
			//these packs MUST exist, or the client will crash when the packets are sent
			pack = new Backpack();
			pack.Layer = Layer.ShopBuy;
			pack.Movable = false;
			pack.Visible = false;
			AddItem( pack );

			pack = new Backpack();
			pack.Layer = Layer.ShopResale;
			pack.Movable = false;
			pack.Visible = false;
			AddItem( pack );

			m_LastRestock = DateTime.Now;
		}
		
		public BaseVendor( Serial serial ) : base( serial )
		{
		}

		public DateTime LastRestock
		{
			get
			{
				return m_LastRestock;
			}
			set
			{
				m_LastRestock = value;
			}
		}

		public virtual TimeSpan RestockDelay
		{
			get
			{
				return TimeSpan.FromHours( 1 );
			}
		}

		public Container BuyPack
		{
			get
			{
				Container pack = FindItemOnLayer( Layer.ShopBuy ) as Container;

				if ( pack == null )
				{
					pack = new Backpack();
					pack.Layer = Layer.ShopBuy;
					pack.Visible = false;
					AddItem( pack );
				}

				return pack;
			}
		}

		public abstract void InitSBInfo();

		protected void LoadSBInfo()
		{
			m_LastRestock = DateTime.Now;

			InitSBInfo();

			m_ArmorBuyInfo.Clear();
			m_ArmorSellInfo.Clear();

			for ( int i = 0; i < SBInfos.Count; i++ )
			{
				SBInfo sbInfo = (SBInfo)SBInfos[i];
				m_ArmorBuyInfo.AddRange( sbInfo.BuyInfo );
				m_ArmorSellInfo.Add( sbInfo.SellInfo );
			}
		}

		public virtual bool GetGender()
		{
			return Utility.RandomBool();
		}

		public virtual void InitBody()
		{
			InitStats( 100, 100, 25 );

			SpeechHue = Utility.RandomDyedHue();
			Hue = Utility.RandomSkinHue();

			if ( IsInvulnerable && !Core.AOS )
				NameHue = 0x35;

			if ( Female = GetGender() )
			{
				Body = 0x191;
				Name = NameList.RandomName( "female" );
			}
			else
			{
				Body = 0x190;
				Name = NameList.RandomName( "male" );
			}
		}

		public virtual int GetRandomHue()
		{
			switch ( Utility.Random( 5 ) )
			{
				default:
				case 0: return Utility.RandomBlueHue();
				case 1: return Utility.RandomGreenHue();
				case 2: return Utility.RandomRedHue();
				case 3: return Utility.RandomYellowHue();
				case 4: return Utility.RandomNeutralHue();
			}
		}

		public virtual int GetShoeHue()
		{
			if ( 0.1 > Utility.RandomDouble() )
				return 0;

			return Utility.RandomNeutralHue();
		}

		public virtual VendorShoeType ShoeType
		{
			get{ return VendorShoeType.Shoes; }
		}

		public virtual int RandomBrightHue()
		{
			if ( 0.1 > Utility.RandomDouble() )
				return Utility.RandomList( 0x62, 0x71 );

			return Utility.RandomList( 0x03, 0x0D, 0x13, 0x1C, 0x21, 0x30, 0x37, 0x3A, 0x44, 0x59 );
		}

		public virtual void CheckMorph()
		{
			if ( CheckGargoyle() )
				return;

			CheckNecromancer();
		}

		public virtual bool CheckGargoyle()
		{
			Map map = this.Map;

			if ( map != Map.Ilshenar )
				return false;

			if ( Region.Name != "Gargoyle City" )
				return false;

			if ( Body != 0x2F6 || (Hue & 0x8000) == 0 )
				TurnToGargoyle();

			return true;
		}

		public virtual bool CheckNecromancer()
		{
			Map map = this.Map;

			if ( map != Map.Malas )
				return false;

			if ( Region.Name != "Umbra" )
				return false;

			if ( Hue != 0x83E8 )
				TurnToNecromancer();

			return true;
		}

		public override void OnAfterSpawn()
		{
			CheckMorph();
		}

		protected override void OnMapChange( Map oldMap )
		{
			base.OnMapChange( oldMap );

			CheckMorph();
		}

		public virtual int GetRandomNecromancerHue()
		{
			switch ( Utility.Random( 20 ) )
			{
				case 0: return 0;
				case 1: return 0x4E9;
				default: return Utility.RandomList( 0x485, 0x497 );
			}
		}

		public virtual void TurnToNecromancer()
		{
			ArrayList items = new ArrayList( this.Items );

			for ( int i = 0; i < items.Count; ++i )
			{
				Item item = (Item)items[i];

				if ( item is Hair || item is Beard )
					item.Hue = 0;
				else if ( item is BaseClothing || item is BaseWeapon || item is BaseArmor || item is BaseTool )
					item.Hue = GetRandomNecromancerHue();
			}

			Hue = 0x83E8;
		}

		public virtual void TurnToGargoyle()
		{
			ArrayList items = new ArrayList( this.Items );

			for ( int i = 0; i < items.Count; ++i )
			{
				Item item = (Item)items[i];

				if ( item is BaseClothing || item is Hair || item is Beard )
					item.Delete();
			}

			Body = 0x2F6;
			Hue = RandomBrightHue() | 0x8000;
			Name = NameList.RandomName( "gargoyle vendor" );

			CapitalizeTitle();
		}

		public virtual void CapitalizeTitle()
		{
			string title = this.Title;

			if ( title == null )
				return;

			string[] split = title.Split( ' ' );

			for ( int i = 0; i < split.Length; ++i )
			{
				if ( Insensitive.Equals( split[i], "the" ) )
					continue;

				if ( split[i].Length > 1 )
					split[i] = Char.ToUpper( split[i][0] ) + split[i].Substring( 1 );
				else if ( split[i].Length > 0 )
					split[i] = Char.ToUpper( split[i][0] ).ToString();
			}

			this.Title = String.Join( " ", split );
		}

		public virtual int GetHairHue()
		{
			return Utility.RandomHairHue();
		}

		public virtual void InitOutfit()
		{
			switch ( Utility.Random( 3 ) )
			{
				case 0: AddItem( new FancyShirt( GetRandomHue() ) ); break;
				case 1: AddItem( new Doublet( GetRandomHue() ) ); break;
				case 2: AddItem( new Shirt( GetRandomHue() ) ); break;
			}

			switch ( ShoeType )
			{
				case VendorShoeType.Shoes: AddItem( new Shoes( GetShoeHue() ) ); break;
				case VendorShoeType.Boots: AddItem( new Boots( GetShoeHue() ) ); break;
				case VendorShoeType.Sandals: AddItem( new Sandals( GetShoeHue() ) ); break;
				case VendorShoeType.ThighBoots: AddItem( new ThighBoots( GetShoeHue() ) ); break;
			}

			int hairHue = GetHairHue();

			AddItem( Server.Items.Hair.GetRandomHair( Female, hairHue ) );

			if ( Female )
			{
				switch ( Utility.Random( 6 ) )
				{
					case 0: AddItem( new ShortPants( GetRandomHue() ) ); break;
					case 1:
					case 2: AddItem( new Kilt( GetRandomHue() ) ); break;
					case 3:
					case 4:
					case 5: AddItem( new Skirt( GetRandomHue() ) ); break;
				}
			}
			else
			{
				switch ( Utility.Random( 2 ) )
				{
					case 0: AddItem( new LongPants( GetRandomHue() ) ); break;
					case 1: AddItem( new ShortPants( GetRandomHue() ) ); break;
				}

				switch ( Utility.Random( 5 ) )
				{
					case 0: AddItem( new LongBeard( hairHue ) ); break;
					case 1: AddItem( new MediumLongBeard( hairHue ) ); break;
					case 2: AddItem( new Vandyke( hairHue ) ); break;
					case 3: AddItem( new Mustache( hairHue ) ); break;
					case 4: AddItem( new Goatee( hairHue ) ); break;
				}
			}

			PackGold( 100, 200 );
		}

		public virtual void Restock()
		{
			m_LastRestock = DateTime.Now;

			IBuyItemInfo[] buyInfo = this.GetBuyInfo();

			foreach ( IBuyItemInfo bii in buyInfo )
				bii.OnRestock();
		}

		private static TimeSpan InventoryDecayTime = TimeSpan.FromHours( 1.0 );

		public virtual void VendorBuy( Mobile from )
		{
			if ( !IsActiveSeller )
				return;

			if ( !from.CheckAlive() )
				return;

			if ( !CheckVendorAccess( from ) )
			{
				Say( 501522 ); // I shall not treat with scum like thee!
				return;
			}

			if ( DateTime.Now - m_LastRestock > RestockDelay )
				Restock();

			UpdateBuyInfo();

			int count = 0;
			ArrayList list;
			IBuyItemInfo[] buyInfo = this.GetBuyInfo();
			IShopSellInfo[] sellInfo = this.GetSellInfo();

			list = new ArrayList( buyInfo.Length );
			Container cont = this.BuyPack;

			ArrayList opls = new ArrayList();

			for (int idx=0;idx<buyInfo.Length;idx++)
			{
				IBuyItemInfo buyItem = (IBuyItemInfo)buyInfo[idx];

				if ( buyItem.Amount <= 0 || list.Count >= 250 )
					continue;

				// NOTE: Only GBI supported; if you use another implementation of IBuyItemInfo, this will crash
				GenericBuyInfo gbi = (GenericBuyInfo) buyItem;
				IEntity disp = gbi.GetDisplayObject() as IEntity;

				list.Add( new BuyItemState( buyItem.Name, cont.Serial, disp == null ? (Serial) 0x7FC0FFEE : disp.Serial, buyItem.Price, buyItem.Amount, buyItem.ItemID, buyItem.Hue ) );
				count++;

				if ( disp is Item )
					opls.Add( (disp as Item).PropertyList );
				else if ( disp is Mobile )
					opls.Add( (disp as Mobile).PropertyList );
			}

			ArrayList playerItems = cont.Items;

			for ( int i = playerItems.Count - 1; i >= 0; --i )
			{
				if ( i >= playerItems.Count )
					continue;

				Item item = (Item)playerItems[i];

				if ( (item.LastMoved + InventoryDecayTime) <= DateTime.Now )
					item.Delete();
			}

			for ( int i = 0; i < playerItems.Count; ++i )
			{
				Item item = (Item)playerItems[i];

				int price = 0;
				string name = null;

				foreach( IShopSellInfo ssi in sellInfo )
				{
					if ( ssi.IsSellable( item ) )
					{
						price = ssi.GetBuyPriceFor( item );
						name = ssi.GetNameFor( item );
						break;
					}
				}

				if ( name != null && list.Count < 250 )
				{
					list.Add( new BuyItemState( name, cont.Serial, item.Serial, price, item.Amount, item.ItemID, item.Hue ) );
					count++;

					opls.Add( item.PropertyList );
				}
			}

			//one (not all) of the packets uses a byte to describe number of items in the list.  Osi = dumb.
			//if ( list.Count > 255 )
			//	Console.WriteLine( "Vendor Warning: Vendor {0} has more than 255 buy items, may cause client errors!", this );

			if ( list.Count > 0 )
			{
				list.Sort( new BuyItemStateComparer() );

				SendPacksTo( from );
				
				from.Send( new VendorBuyContent( list ) );
				from.Send( new VendorBuyList( this, list ) );
				from.Send( new DisplayBuyList( this ) );
				from.Send( new MobileStatusExtended( from ) );//make sure their gold amount is sent

				for ( int i = 0; i < opls.Count; ++i )
					from.Send( opls[i] as Packet );

				SayTo( from, 500186 ); // Greetings.  Have a look around.
			}
		}

		public virtual void SendPacksTo( Mobile from )
		{
			Item pack = FindItemOnLayer( Layer.ShopBuy );

			if ( pack == null )
			{
				pack = new Backpack();
				pack.Layer = Layer.ShopBuy;
				pack.Movable = false;
				pack.Visible = false;
				AddItem( pack );
			}

			from.Send( new EquipUpdate( pack ) );

			pack = FindItemOnLayer( Layer.ShopSell );

			if ( pack != null )
				from.Send( new EquipUpdate( pack ) );

			pack = FindItemOnLayer( Layer.ShopResale );

			if ( pack == null )
			{
				pack = new Backpack();
				pack.Layer = Layer.ShopResale;
				pack.Movable = false;
				pack.Visible = false;
				AddItem( pack );
			}

			from.Send( new EquipUpdate( pack ) );
		}

		public virtual void VendorSell( Mobile from )
		{
			if ( !IsActiveBuyer )
				return;

			if ( !from.CheckAlive() )
				return;

			if ( !CheckVendorAccess( from ) )
			{
				Say( 501522 ); // I shall not treat with scum like thee!
				return;
			}

			Container pack = from.Backpack;

			if ( pack != null )
			{
				IShopSellInfo[] info = GetSellInfo();

				Hashtable table = new Hashtable();

				foreach ( IShopSellInfo ssi in info )
				{
					Item[] items = pack.FindItemsByType( ssi.Types );

					foreach ( Item item in items )
					{
						if ( item is Container && ((Container)item).Items.Count != 0 )
							continue;

						if ( item.IsStandardLoot() && item.Movable && ssi.IsSellable( item ) )
							table[item] = new SellItemState( item, ssi.GetSellPriceFor( item ), ssi.GetNameFor( item ) );
					}
				}

				if ( table.Count > 0 )
				{
					SendPacksTo( from );

					from.Send( new VendorSellList( this, table ) );
				}
				else
				{
					Say( true, "You have nothing I would be interested in." );
				}
			}
		}

		public override bool OnDragDrop( Mobile from, Item dropped )
		{
			if ( dropped is SmallBOD || dropped is LargeBOD || dropped is SmallMobileBOD || dropped is LargeMobileBOD )
				daat99.daat99.ClaimBods( from, dropped );
/*			if ( dropped is SmallBOD || dropped is LargeBOD )
			{
				if ( !IsValidBulkOrder( dropped ) || !SupportsBulkOrders( from ) )
				{
					SayTo( from, 1045130 ); // That order is for some other shopkeeper.
					return false;
				}
				else if ( (dropped is SmallBOD && !((SmallBOD)dropped).Complete) || (dropped is LargeBOD && !((LargeBOD)dropped).Complete) || (dropped is SmallMobileBOD && !((SmallMobileBOD)dropped).Complete) || (dropped is LargeMobileBOD && !((LargeMobileBOD)dropped).Complete) )
				{
					SayTo( from, 1045131 ); // You have not completed the order yet.
					return false;
				}

				Item reward;
				int gold, fame;

				if ( dropped is SmallBOD )
					((SmallBOD)dropped).GetRewards( out reward, out gold, out fame );
				else
					((LargeBOD)dropped).GetRewards( out reward, out gold, out fame );
				else if ( dropped is LargeMobileBOD )
					((LargeMobileBOD)dropped).GetRewards( out reward, out gold, out fame );
				else
					((SmallMobileBOD)dropped).GetRewards( out reward, out gold, out fame );

				from.SendSound( 0x3D );

				SayTo( from, 1045132 ); // Thank you so much!  Here is a reward for your effort.

				if ( reward != null )
					from.AddToBackpack( reward );

				if ( gold > 1000 )
					from.AddToBackpack( new BankCheck( gold ) );
				else if ( gold > 0 )
					from.AddToBackpack( new Gold( gold ) );
				
				//start daat99 tokens for bods 1/1
				bool b_BodTokens = daat99.OWLTR.BodGiveTokens;
				if (daat99.Daat99OWLTR.Ops != null)
					b_BodTokens = daat99.Daat99OWLTR.Ops[14].Setting;

				if (b_BodTokens == true && gold > 100)
					GiveTokens.RewardTokens(from, (int)(gold/100));
				//end daat99 tokens for bods 1/1

				Titles.AwardFame( from, fame, true );

				dropped.Delete();
				return true;
			}
*/
			return base.OnDragDrop( from, dropped );
		}

		private GenericBuyInfo LookupDisplayObject( object obj )
		{
			IBuyItemInfo[] buyInfo = this.GetBuyInfo();

			for ( int i = 0; i < buyInfo.Length; ++i )
			{
				GenericBuyInfo gbi = buyInfo[i] as GenericBuyInfo;

				if ( gbi.GetDisplayObject() == obj )
					return gbi;
			}

			return null;
		}

		private void ProcessSinglePurchase( BuyItemResponse buy, IBuyItemInfo bii, ArrayList validBuy, ref int controlSlots, ref bool fullPurchase, ref int totalCost )
		{
			int amount = buy.Amount;

			if ( amount > bii.Amount )
				amount = bii.Amount;

			if ( amount <= 0 )
				return;

			int slots = bii.ControlSlots * amount;

			if ( controlSlots >= slots )
			{
				controlSlots -= slots;
			}
			else
			{
				fullPurchase = false;
				return;
			}

			totalCost += bii.Price * amount;
			validBuy.Add( buy );
		}

		private void ProcessValidPurchase( int amount, IBuyItemInfo bii, Mobile buyer, Container cont )
		{
			if ( amount > bii.Amount )
				amount = bii.Amount;

			if ( amount < 1 )
				return;

			bii.Amount -= amount;

			object o = bii.GetObject();

			if ( o is Item )
			{
				Item item = (Item)o;

				if ( item.Stackable )
				{
					item.Amount = amount;

					if ( cont == null || !cont.TryDropItem( buyer, item, false ) )
						item.MoveToWorld( buyer.Location, buyer.Map );
				}
				else
				{
					item.Amount = 1;

					if ( cont == null || !cont.TryDropItem( buyer, item, false ) )
						item.MoveToWorld( buyer.Location, buyer.Map );

					for (int i=1;i<amount;i++)
					{
						item = bii.GetObject() as Item;

						if ( item != null )
						{
							item.Amount = 1;

							if ( cont == null || !cont.TryDropItem( buyer, item, false ) )
								item.MoveToWorld( buyer.Location, buyer.Map );
						}
					}
				}
			}
			else if ( o is Mobile )
			{
				Mobile m = (Mobile)o;

				m.Direction = (Direction)Utility.Random( 8 );
				m.MoveToWorld( buyer.Location, buyer.Map );
				m.PlaySound( m.GetIdleSound() );

				if ( m is BaseCreature )
					((BaseCreature)m).SetControlMaster( buyer );

				for ( int i = 1; i < amount; ++i )
				{
					m = bii.GetObject() as Mobile;

					if ( m != null )
					{
						m.Direction = (Direction)Utility.Random( 8 );
						m.MoveToWorld( buyer.Location, buyer.Map );

						if ( m is BaseCreature )
							((BaseCreature)m).SetControlMaster( buyer );
					}
				}
			}
		}

		public virtual bool OnBuyItems( Mobile buyer, ArrayList list )
		{
			if ( !IsActiveSeller )
				return false;

			if ( !buyer.CheckAlive() )
				return false;

			if ( !CheckVendorAccess( buyer ) )
			{
				Say( 501522 ); // I shall not treat with scum like thee!
				return false;
			}

			UpdateBuyInfo();

			IBuyItemInfo[] buyInfo = this.GetBuyInfo();
			IShopSellInfo[] info = GetSellInfo();
			int totalCost = 0;
			ArrayList validBuy = new ArrayList( list.Count );
			Container cont;
			bool bought = false;
			bool fromBank = false;
			bool fullPurchase = true;
			int controlSlots = buyer.FollowersMax - buyer.Followers;

			foreach ( BuyItemResponse buy in list )
			{
				Serial ser = buy.Serial;
				int amount = buy.Amount;

				if ( ser.IsItem )
				{
					Item item = World.FindItem( ser );

					if ( item == null )
						continue;

					GenericBuyInfo gbi = LookupDisplayObject( item );

					if ( gbi != null )
					{
						ProcessSinglePurchase( buy, gbi, validBuy, ref controlSlots, ref fullPurchase, ref totalCost );
					}
					else if ( item.RootParent == this )
					{
						if ( amount > item.Amount )
							amount = item.Amount;

						if ( amount <= 0 )
							continue;

						foreach ( IShopSellInfo ssi in info )
						{
							if ( ssi.IsSellable( item ) )
							{
								if ( ssi.IsResellable( item ) )
								{
									totalCost += ssi.GetBuyPriceFor( item ) * amount;
									validBuy.Add( buy );
									break;
								}
							}
						}
					}
				}
				else if ( ser.IsMobile )
				{
					Mobile mob = World.FindMobile( ser );

					if ( mob == null )
						continue;

					GenericBuyInfo gbi = LookupDisplayObject( mob );

					if ( gbi != null )
						ProcessSinglePurchase( buy, gbi, validBuy, ref controlSlots, ref fullPurchase, ref totalCost );
				}
			}//foreach

			if ( fullPurchase && validBuy.Count == 0 )
				SayTo( buyer, 500190 ); // Thou hast bought nothing!
			else if ( validBuy.Count == 0 )
				SayTo( buyer, 500187 ); // Your order cannot be fulfilled, please try again.

			if ( validBuy.Count == 0 )
				return false;

			bought = ( buyer.AccessLevel >= AccessLevel.GameMaster );

			cont = buyer.Backpack;
			if ( !bought && cont != null )
			{
				if ( cont.ConsumeTotal( typeof( Gold ), totalCost ) )
					bought = true;
				else if ( totalCost < 2000 )
					SayTo( buyer, 500192 );//Begging thy pardon, but thou casnt afford that.
			}

			if ( !bought && totalCost >= 2000 )
			{
				cont = buyer.BankBox;
				if ( cont != null && cont.ConsumeTotal( typeof( Gold ), totalCost ) )
				{
					bought = true;
					fromBank = true;
				}
				else
				{
					SayTo( buyer, 500191 ); //Begging thy pardon, but thy bank account lacks these funds.
				}
			}

			if ( !bought )
				return false;
			else
				buyer.PlaySound( 0x32 );

			cont = buyer.Backpack;
			if ( cont == null )
				cont = buyer.BankBox;

			foreach ( BuyItemResponse buy in validBuy )
			{
				Serial ser = buy.Serial;
				int amount = buy.Amount;

				if ( amount < 1 )
					continue;

				if ( ser.IsItem )
				{
					Item item = World.FindItem( ser );

					if ( item == null )
						continue;

					GenericBuyInfo gbi = LookupDisplayObject( item );

					if ( gbi != null )
					{
						ProcessValidPurchase( amount, gbi, buyer, cont );
					}
					else
					{
						if ( amount > item.Amount )
							amount = item.Amount;

						foreach ( IShopSellInfo ssi in info )
						{
							if ( ssi.IsSellable( item ) )
							{
								if ( ssi.IsResellable( item ) )
								{
									Item buyItem;
									if ( amount >= item.Amount )
									{
										buyItem = item;
									}
									else
									{
										buyItem = item.Dupe( amount );
										item.Amount -= amount;
									}

									if ( cont == null || !cont.TryDropItem( buyer, buyItem, false ) )
										buyItem.MoveToWorld( buyer.Location, buyer.Map );

									break;
								}
							}
						}
					}
				}
				else if ( ser.IsMobile )
				{
					Mobile mob = World.FindMobile( ser );

					if ( mob == null )
						continue;

					GenericBuyInfo gbi = LookupDisplayObject( mob );

					if ( gbi != null )
						ProcessValidPurchase( amount, gbi, buyer, cont );
				}

				/*if ( ser >= 0 && ser <= buyInfo.Length )
				{
					IBuyItemInfo bii = buyInfo[ser];

				}
				else
				{
					Item item = World.FindItem( buy.Serial );

					if ( item == null )
						continue;

					if ( amount > item.Amount )
						amount = item.Amount;

					foreach( IShopSellInfo ssi in info )
					{
						if ( ssi.IsSellable( item ) )
						{
							if ( ssi.IsResellable( item ) )
							{
								Item buyItem;
								if ( amount >= item.Amount )
								{
									buyItem = item;
								}
								else
								{
									buyItem = item.Dupe( amount );
									item.Amount -= amount;
								}

								if ( cont == null || !cont.TryDropItem( buyer, buyItem, false ) )
									buyItem.MoveToWorld( buyer.Location, buyer.Map );

								break;
							}
						}
					}
				}*/
			}//foreach

			if ( fullPurchase )
			{
				if ( buyer.AccessLevel >= AccessLevel.GameMaster )
					SayTo( buyer, true, "I would not presume to charge thee anything.  Here are the goods you requested." );
				else if ( fromBank )
					SayTo( buyer, true, "The total of thy purchase is {0} gold, which has been withdrawn from your bank account.  My thanks for the patronage.", totalCost );
				else
					SayTo( buyer, true, "The total of thy purchase is {0} gold.  My thanks for the patronage.", totalCost );
			}
			else
			{
				if ( buyer.AccessLevel >= AccessLevel.GameMaster )
					SayTo( buyer, true, "I would not presume to charge thee anything.  Unfortunately, I could not sell you all the goods you requested." );
				else if ( fromBank )
					SayTo( buyer, true, "The total of thy purchase is {0} gold, which has been withdrawn from your bank account.  My thanks for the patronage.  Unfortunately, I could not sell you all the goods you requested.", totalCost );
				else
					SayTo( buyer, true, "The total of thy purchase is {0} gold.  My thanks for the patronage.  Unfortunately, I could not sell you all the goods you requested.", totalCost );
			}

			return true;
		}

		public virtual bool CheckVendorAccess( Mobile from )
		{
			GuardedRegion reg = this.Region as GuardedRegion;

			if ( reg != null && !reg.CheckVendorAccess( this, from ) )
				return false;

			if ( this.Region != from.Region )
			{
				reg = from.Region as GuardedRegion;

				if ( reg != null && !reg.CheckVendorAccess( this, from ) )
					return false;
			}

			return true;
		}

		public virtual bool OnSellItems( Mobile seller, ArrayList list )
		{
			if ( !IsActiveBuyer )
				return false;

			if ( !seller.CheckAlive() )
				return false;

			if ( !CheckVendorAccess( seller ) )
			{
				Say( 501522 ); // I shall not treat with scum like thee!
				return false;
			}

			seller.PlaySound( 0x32 );

			IShopSellInfo[] info = GetSellInfo();
			IBuyItemInfo[] buyInfo = this.GetBuyInfo();
			int GiveGold = 0;
			int Sold = 0;
			Container cont;
			ArrayList delete = new ArrayList();
			ArrayList drop = new ArrayList();

			foreach ( SellItemResponse resp in list )
			{
				if ( resp.Item.RootParent != seller || resp.Amount <= 0 )
					continue;

				foreach( IShopSellInfo ssi in info )
				{
					if ( ssi.IsSellable( resp.Item ) )
					{
						Sold++;
						break;
					}
				}
			}

			if ( Sold > MaxSell )
			{
				SayTo( seller, true, "You may only sell {0} items at a time!", MaxSell );
				return false;
			} 
			else if ( Sold == 0 )
			{
				return true;
			}

			foreach ( SellItemResponse resp in list )
			{
				if ( resp.Item.RootParent != seller || resp.Amount <= 0 )
					continue;

				foreach( IShopSellInfo ssi in info )
				{
					if ( ssi.IsSellable( resp.Item ) )
					{
						int amount = resp.Amount;

						if ( amount > resp.Item.Amount )
							amount = resp.Item.Amount;

						if ( ssi.IsResellable( resp.Item ) )
						{
							bool found = false;

							foreach ( IBuyItemInfo bii in buyInfo )
							{
								if ( bii.Restock( resp.Item, amount ) )
								{
									resp.Item.Consume( amount );
									found = true;

									break;
								}
							}

							if ( !found )
							{
								cont = this.BuyPack;

								if ( amount < resp.Item.Amount )
								{
									resp.Item.Amount -= amount;
									Item item = resp.Item.Dupe( amount );
									item.SetLastMoved();
									cont.DropItem( item );
								}
								else
								{
									resp.Item.SetLastMoved();
									cont.DropItem( resp.Item );
								}
							}
						}
						else
						{
							if ( amount < resp.Item.Amount )
								resp.Item.Amount -= amount;
							else
								resp.Item.Delete();
						}

						GiveGold += ssi.GetSellPriceFor( resp.Item )*amount;
						break;
					}
				}
			}

			if ( GiveGold > 0 )
			{
				while ( GiveGold > 60000 )
				{
					seller.AddToBackpack( new Gold( 60000 ) );
					GiveGold -= 60000;
				}

				seller.AddToBackpack( new Gold( GiveGold ) );

				seller.PlaySound( 0x0037 );//Gold dropping sound

				if ( SupportsBulkOrders( seller ) )
				{
					Item bulkOrder = CreateBulkOrder( seller, false );

					if ( bulkOrder is LargeBOD )
						seller.SendGump( new LargeBODAcceptGump( seller, (LargeBOD)bulkOrder ) );
					else if ( bulkOrder is SmallBOD )
						seller.SendGump( new SmallBODAcceptGump( seller, (SmallBOD)bulkOrder ) );
					else if ( bulkOrder is SmallMobileBOD )
						seller.SendGump( new SmallMobileBODAcceptGump( seller, (SmallMobileBOD)bulkOrder ) );
					else if ( bulkOrder is LargeMobileBOD )
						seller.SendGump( new LargeMobileBODAcceptGump( seller, (LargeMobileBOD)bulkOrder ) );
				}
			}
			//no cliloc for this?
			//SayTo( seller, true, "Thank you! I bought {0} item{1}. Here is your {2}gp.", Sold, (Sold > 1 ? "s" : ""), GiveGold );
			
			return true;
		}

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

			writer.Write( (int) 1 ); // version

			ArrayList sbInfos = this.SBInfos;

			for ( int i = 0; sbInfos != null && i < sbInfos.Count; ++i )
			{
				SBInfo sbInfo = (SBInfo)sbInfos[i];
				ArrayList buyInfo = sbInfo.BuyInfo;

				for ( int j = 0; buyInfo != null && j < buyInfo.Count; ++j )
				{
					GenericBuyInfo gbi = (GenericBuyInfo)buyInfo[j];

					int maxAmount = gbi.MaxAmount;
					int doubled = 0;

					switch ( maxAmount )
					{
						case  40: doubled = 1; break;
						case  80: doubled = 2; break;
						case 160: doubled = 3; break;
						case 320: doubled = 4; break;
						case 640: doubled = 5; break;
						case 999: doubled = 6; break;
					}

					if ( doubled > 0 )
					{
						writer.WriteEncodedInt( 1 + ((j * sbInfos.Count) + i) );
						writer.WriteEncodedInt( doubled );
					}
				}
			}

			writer.WriteEncodedInt( 0 );
		}

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

			int version = reader.ReadInt();

			LoadSBInfo();

			ArrayList sbInfos = this.SBInfos;

			switch ( version )
			{
				case 1:
				{
					int index;

					while ( (index = reader.ReadEncodedInt()) > 0 )
					{
						int doubled = reader.ReadEncodedInt();

						if ( sbInfos != null )
						{
							index -= 1;
							int sbInfoIndex = index % sbInfos.Count;
							int buyInfoIndex = index / sbInfos.Count;
 
							if ( sbInfoIndex >= 0 && sbInfoIndex < sbInfos.Count )
							{
								SBInfo sbInfo = (SBInfo)sbInfos[sbInfoIndex];
								ArrayList buyInfo = sbInfo.BuyInfo;

								if ( buyInfo != null && buyInfoIndex >= 0 && buyInfoIndex < buyInfo.Count )
								{
									GenericBuyInfo gbi = (GenericBuyInfo)buyInfo[buyInfoIndex];

									int amount = 20;

									switch ( doubled )
									{
										case 1: amount =  40; break;
										case 2: amount =  80; break;
										case 3: amount = 160; break;
										case 4: amount = 320; break;
										case 5: amount = 640; break;
										case 6: amount = 999; break;
									}

									gbi.Amount = gbi.MaxAmount = amount;
								}
							}
						}
					}

					break;
				}
			}

			if ( Core.AOS && NameHue == 0x35 )
				NameHue = -1;

			CheckMorph();
		}

		public override void AddCustomContextEntries( Mobile from, ArrayList list )
		{
			if ( from.Alive && IsActiveVendor )
			{
				if ( IsActiveSeller )
					list.Add( new VendorBuyEntry( from, this ) );

				if ( IsActiveBuyer )
					list.Add( new VendorSellEntry( from, this ) );

				if ( SupportsBulkOrders( from ) )
					list.Add( new BulkOrderInfoEntry( from, this ) );
			}

			base.AddCustomContextEntries( from, list );
		}

		public virtual IShopSellInfo[] GetSellInfo()
		{
			return (IShopSellInfo[])m_ArmorSellInfo.ToArray( typeof( IShopSellInfo ) );
		}

		public virtual IBuyItemInfo[] GetBuyInfo()
		{
			return (IBuyItemInfo[])m_ArmorBuyInfo.ToArray( typeof( IBuyItemInfo ) );
		}

		public override bool CanBeDamaged()
		{
			return !IsInvulnerable;
		}
	}
}

namespace Server.ContextMenus
{
	public class VendorBuyEntry : ContextMenuEntry
	{
		private BaseVendor m_Vendor;

		public VendorBuyEntry( Mobile from, BaseVendor vendor ) : base( 6103, 8 )
		{
			m_Vendor = vendor;
			Enabled = vendor.CheckVendorAccess( from );
		}

		public override void OnClick()
		{
			m_Vendor.VendorBuy( this.Owner.From );
		}
	}

	public class VendorSellEntry : ContextMenuEntry
	{
		private BaseVendor m_Vendor;

		public VendorSellEntry( Mobile from, BaseVendor vendor ) : base( 6104, 8 )
		{
			m_Vendor = vendor;
			Enabled = vendor.CheckVendorAccess( from );
		}

		public override void OnClick()
		{
			m_Vendor.VendorSell( this.Owner.From );
		}
	}
}

namespace Server
{
	public interface IShopSellInfo
	{
		//get display name for an item
		string GetNameFor( Item item );

		//get price for an item which the player is selling
		int GetSellPriceFor( Item item );

		//get price for an item which the player is buying
		int GetBuyPriceFor( Item item );

		//can we sell this item to this vendor?
		bool IsSellable( Item item );

		//What do we sell?
		Type[] Types{ get; }

		//does the vendor resell this item?
		bool IsResellable( Item item );
	}

	public interface IBuyItemInfo
	{
		//get a new instance of an object (we just bought it)
		object GetObject();

		int ControlSlots{ get; }

		int PriceScalar{ get; set; }

		//display price of the item
		int Price{ get; }

		//display name of the item
		string Name{ get; }

		//display hue
		int Hue{ get; }

		//display id
		int ItemID{ get; }

		//amount in stock
		int Amount{ get; set; }

		//max amount in stock
		int MaxAmount{ get; }

		//Attempt to restock with item, (return true if restock sucessful)
		bool Restock( Item item, int amount );

		//called when its time for the whole shop to restock
		void OnRestock();
	}
}
 

Freya

Wanderer
Hmmm... tried that... now getting this error on compiling

Code:
- Error: Scripts\Mobiles\Vendors\BaseVendor.cs: CS0246: (line 715, column 9) The type or namespace name 'daat99OWLTR' could not be found (are you missing a using directive or an assembly reference?)
- Error: Scripts\Mobiles\Vendors\BaseVendor.cs: CS0246: (line 742, column 9) The type or namespace name 'Daat99OWLTR' could not be found (are you missing a using directive or an assembly reference?)

Ok, got it to compile, but had to remove the items listed in link... so still having the "not acceptable bod problem" lol Thanks for all the help so far all =) I appreciate it!
 

Rosey1

Wanderer
ok so i don't know now.

here is my drag and drop and i have the daat and fs system and all that. My taming bod works. Try it and see. I'm trying to remember what i did to. :eek:

Since i don't use the tokens, I took it out but you could comment it out. I think it wasn't properly comments out.


Code:
	public override bool OnDragDrop( Mobile from, Item dropped )
		{
			if ( dropped is SmallBOD || dropped is LargeBOD )
			{
				daat99.daat99.ClaimBods( from, dropped );

				return true;
			}
			else if ( dropped is SmallMobileBOD || dropped is LargeMobileBOD )
			{
				if ( !IsValidBulkOrder( dropped ) || !SupportsBulkOrders( from ) )
				{
					SayTo( from, 1045130 ); // That order is for some other shopkeeper.
					return false;
				}
				else if ( (dropped is SmallMobileBOD && !((SmallMobileBOD)dropped).Complete) || (dropped is LargeMobileBOD && !((LargeMobileBOD)dropped).Complete) )
				{
					SayTo( from, 1045131 ); // You have not completed the order yet.
					return false;
				}

				Item reward;
				int gold, fame;

				if ( dropped is SmallMobileBOD )
				{
					((SmallMobileBOD)dropped).GetRewards( out reward, out gold, out fame );

				from.SendSound( 0x3D );

				SayTo( from, 1045132 ); // Thank you so much!  Here is a reward for your effort.

				if ( reward != null )
					from.AddToBackpack( reward );

				if ( gold > 1000 )
					from.AddToBackpack( new BankCheck( gold ) );
				else if ( gold > 0 )
					from.AddToBackpack( new Gold( gold ) );
				
				//start daat99 tokens for bods 1/1
				[color=red]//[/color]if (Daat99OWLTR.Ops[14].Setting && gold > 100)
				[color=red]//[/color]GiveTokens.RewardTokens(from, (int)(gold/100));
				//end daat99 tokens for bods 1/1

				Titles.AwardFame( from, fame, true );

				dropped.Delete();

					return true;
				}
				else if ( dropped is LargeMobileBOD )
				{
					((LargeMobileBOD)dropped).GetRewards( out reward, out gold, out fame );

				from.SendSound( 0x3D );

				SayTo( from, 1045132 ); // Thank you so much!  Here is a reward for your effort.

				if ( reward != null )
					from.AddToBackpack( reward );

				if ( gold > 1000 )
					from.AddToBackpack( new BankCheck( gold ) );
				else if ( gold > 0 )
					from.AddToBackpack( new Gold( gold ) );
				
				//start daat99 tokens for bods 1/1
				[color=red]//[/color]if (Daat99OWLTR.Ops[14].Setting && gold > 100)
				[color=red]//[/color]	GiveTokens.RewardTokens(from, (int)(gold/100));
				//end daat99 tokens for bods 1/1

				Titles.AwardFame( from, fame, true );

				dropped.Delete();

					return true;
				}

				return true;
			}

			return base.OnDragDrop( from, dropped );
		}
 

Celestria

Wanderer
* bangs her head on keyboard.... * Okay there is smoke pouring out of my ears! lol
Does anyone have this and daats working and is willing to share their modified scripts with me? I'll keep trying to figure out my problems but I am near fried.
Here is what is going on. My animal breeder has nothign to sell Mobile Bod's aren't working, can't get bod's from Animal trainer, and small mobile bod crashes the shard... so far those are the bugs I have gotten. =(
okay now I am going to go read the rest of the 15 pages on this topic to see if anyone has already answered my question =)
Thanks Y'all.
 

Freya

Wanderer
The animal breeder doesn't sell anything, he's used to go to when you have two pets to breed... The crashing on making small bod problem, make sure that the "Taming" folder that comes w/the system is placed inside of your data/bulk orders folder. This should fix the crash... now the bod's working themselves, being able to turn them in to animal trainer and such, I'm having that problem still... haven't been able to get it worked properly yet, it gives the BOD but will not accept them once full, I tried the fixes posted above but it gave error messages, but try what I said to fix the crash problem... =)
 

Freya

Wanderer
Yw =) I'm still working on the other problem w/the BOD's being accepted when filled, if I come up w/anything on that, I'll let you know =)
 
Top