Making Vendor live own life...
So first, I have the BaseVendor.cs script:
Where or how add these lines:
m_NextSpeakTime = DateTime.Now + ( TimeSpan.FromSeconds( 10 ) );
Say( m_Phrases[Utility.Random( m_Phrases.Length )] );
to make vendors talk randomily? It is very nice feature, if you played Gothic, you know what am i talking about...
So first, I have the BaseVendor.cs script:
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; }
[COLOR="DarkRed"]
private DateTime m_NextSpeakTime; // To prevent spam
private static string[] m_Phrases = new string[] // Things to say while greeting
{
"Ludzie zawsze gadaja...",
"Nie powinnismy o tym mowic.",
"Krol Rhobar jest chyba najlepszym wladca ktorego mielismy.",
"Nie, nie..",
"No tak... to prawda.",
"Moze pogodzimy ich ze soba...",
};[/COLOR]
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 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();
CantWalk = true;
BodyValue = 400;
Name = NameList.RandomName( "male" );
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()
{
int hairHue = GetHairHue();
AddItem( Server.Items.Hair.GetRandomHair( Female, hairHue ) );
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 )
{
if ( !IsValidBulkOrder( dropped ) || !SupportsBulkOrders( from ) )
{
SayTo( from, 1045130 ); // That order is for some other shopkeeper.
return false;
}
else if ( (dropped is SmallBOD && !((SmallBOD)dropped).Complete) || (dropped is LargeBOD && !((LargeBOD)dropped).Complete) )
{
SayTo( from, 1045131 ); // You have not completed the order yet.
return false;
}
Item reward;
int gold, fame;
if ( dropped is SmallBOD )
((SmallBOD)dropped).GetRewards( out reward, out gold, out fame );
else
((LargeBOD)dropped).GetRewards( out reward, out gold, out fame );
from.SendSound( 0x3D );
SayTo( from, 1045132 ); // Thank you so much! Here is a reward for your effort.
if ( reward != null )
from.AddToBackpack( reward );
if ( gold > 1000 )
from.AddToBackpack( new BankCheck( gold ) );
else if ( gold > 0 )
from.AddToBackpack( new Gold( gold ) );
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 ) );
}
}
//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();
}
}
Where or how add these lines:
m_NextSpeakTime = DateTime.Now + ( TimeSpan.FromSeconds( 10 ) );
Say( m_Phrases[Utility.Random( m_Phrases.Length )] );
to make vendors talk randomily? It is very nice feature, if you played Gothic, you know what am i talking about...