View Full Version: Heures d'ouverture

RunUO.FR Support > System > Heures d'ouverture


Title: Heures d'ouverture


Vortal - September 18, 2004 06:48 AM (GMT)
Description : Petit script simpliste permettant de gérer les heures d'ouverture des vendeurs NPC en fonction de l'heure in-game. Lorsqu'il fait nuit, le vendeur refusera toute vente de même que tout achat et refusera d'entrainer les joueurs étant donné que "la boutique est fermée".

Installation : Remplacez le code de votre \Scripts\Mobiles\Vendors\BaseVendor.cs par celui ci-bas (sans oublier de faire une copie backup de votre ancienne version en cas de problème).

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;

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; } } // response 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;
 }

 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()
  {
   int hours, minutes;
   Server.Items.Clock.GetTime( m_Vendor.Map, m_Vendor.X, m_Vendor.Y, out hours, out minutes );
   if ( hours < 5 || hours > 22 )
    m_Vendor.Say( "Sorry, we're closed for today. Please come back tomorrow" );
   else
   {
    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 override void OnSpeech( SpeechEventArgs incomingMessage )
 {
  int hours, minutes;
  Server.Items.Clock.GetTime( this.Map, this.X, this.Y, out hours, out minutes );

  base.OnSpeech( incomingMessage );
  Mobile from = incomingMessage.Mobile;

  if ( from.InRange( this, 2 ))
  {
   if ( hours < 5 || hours > 22 )
   {
    this.Say( "Sorry, we're closed for today. Please come back tomorrow" );
   }
   else
   {
    if (incomingMessage.Speech.ToLower().IndexOf( "bonjour" ) >= 0 || incomingMessage.Speech.ToLower().IndexOf( "salut" ) >= 0 || incomingMessage.Speech.ToLower().IndexOf( "bonsoir" ) >= 0)
     this.Say( "Welcome! Come and see my wares" );
    else if (incomingMessage.Speech.ToLower().IndexOf( "aurevoir" ) >= 0 || incomingMessage.Speech.ToLower().IndexOf( "au revoir" ) >= 0)
     this.Say( "Thank you, goodbye" );
   }
  }
 }

 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;
 }

 protected override void OnLocationChange( Point3D oldLocation )
 {
  base.OnLocationChange( oldLocation );

  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();

  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;
   }

   switch ( Utility.Random( 9 ) )
   {
    case 0: AddItem( new Afro( hairHue ) ); break;
    case 1: AddItem( new KrisnaHair( hairHue ) ); break;
    case 2: AddItem( new PageboyHair( hairHue ) ); break;
    case 3: AddItem( new PonyTail( hairHue ) ); break;
    case 4: AddItem( new ReceedingHair( hairHue ) ); break;
    case 5: AddItem( new TwoPigTails( hairHue ) ); break;
    case 6: AddItem( new ShortHair( hairHue ) ); break;
    case 7: AddItem( new LongHair( hairHue ) ); break;
    case 8: AddItem( new BunsHair( hairHue ) ); break;
   }
  }
  else
  {
   switch ( Utility.Random( 2 ) )
   {
    case 0: AddItem( new LongPants( GetRandomHue() ) ); break;
    case 1: AddItem( new ShortPants( GetRandomHue() ) ); break;
   }

   switch ( Utility.Random( 8 ) )
   {
    case 0: AddItem( new Afro( hairHue ) ); break;
    case 1: AddItem( new KrisnaHair( hairHue ) ); break;
    case 2: AddItem( new PageboyHair( hairHue ) ); break;
    case 3: AddItem( new PonyTail( hairHue ) ); break;
    case 4: AddItem( new ReceedingHair( hairHue ) ); break;
    case 5: AddItem( new TwoPigTails( hairHue ) ); break;
    case 6: AddItem( new ShortHair( hairHue ) ); break;
    case 7: AddItem( new LongHair( hairHue ) ); 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 )
 {
  int hours, minutes;
  Server.Items.Clock.GetTime( this.Map, this.X, this.Y, out hours, out minutes );
  if ( hours < 5 || hours > 22 )
  {
   this.Say( "Sorry, we're closed for today. Please come back tomorrow" );
   return;
  }

  if ( !IsActiveSeller )
   return;

  if ( !from.CheckAlive() )
   return;

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

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

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

  for (int idx=0;idx<buyInfo.Length;idx++)
  {
   IBuyItemInfo buyItem = (IBuyItemInfo)buyInfo[idx];
   if ( buyItem.Amount > 0 )
   {
    if ( list.Count < 250 )
    {
     list.Add( new BuyItemState( buyItem.Name, cont.Serial, 0x7FFFFFFF - idx, buyItem.Price, buyItem.Amount, buyItem.ItemID, buyItem.Hue ) );
     count++;
    }
   }
  }

  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++;
   }
  }

  //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

   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 )
 {
  int hours, minutes;
  Server.Items.Clock.GetTime( this.Map, this.X, this.Y, out hours, out minutes );
  if ( hours < 5 || hours > 22 )
  {
   this.Say( "Sorry, we're closed for today. Please come back tomorrow" );
   return;
  }

  if ( !IsActiveBuyer )
   return;

  if ( !from.CheckAlive() )
   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 )
 {
  int hours, minutes;
  Server.Items.Clock.GetTime( this.Map, this.X, this.Y, out hours, out minutes );
  if ( hours < 5 || hours > 22 ) // NIGHT
  {
   this.Say( "Sorry, we're closed for today. Please come back tomorrow" );
   return false;
  }

  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 );
 }

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

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

  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 = 0x7FFFFFFF - buy.Serial;
   int amount = buy.Amount;
   if ( ser >= 0 && ser <= buyInfo.Length )
   {
    IBuyItemInfo bii = buyInfo[ser];
    if ( amount > bii.Amount )
     amount = bii.Amount;
    if ( amount <= 0 )
     continue;

    int slots = bii.ControlSlots * amount;

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

    totalCost += bii.Price * amount;
    validBuy.Add( buy );
   }
   else
   {
    Item item = World.FindItem( buy.Serial );

    if ( item == null || item.RootParent != this )
     continue;

    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;
      }
     }
    }
   }
  }//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 = 0x7FFFFFFF - buy.Serial;
   int amount = buy.Amount;

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

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

    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 );
      }
     }
    }
   }
   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 OnSellItems( Mobile seller, ArrayList list )
 {
  if ( !IsActiveBuyer )
   return false;

  if ( !seller.CheckAlive() )
   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;
 }

 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;
 }

 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; }

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


Suggestion et ajouts possibles : Ici, tous les vendeurs, quels qu'ils soient, seront gérés par ce script. On aurait pu désirer certaines exceptions, comme pour les BarKeeper, par exemple.

Mise en garde : Les heures d'ouverture de ce script sont de 5h00am à 22h00pm. Si vous pensez que ces heures ne conviennent pas pour votre serveur, faire attention à faire les changements partout à l'intérieur du script.

Note finale : Utilisez le comme bon vous semble, modifiez le, détruisez le, ça ne me dérange pas. Par contre, j'aprécierais des commentaires sur ce que vous pensez de ce script ainsi que des différentes suggestions qui pourraient vous venir à l'esprit pour l'améliorer. Si vous découvrez des bugs, merci de me le faire savoir afin que je corrige au plus vite.

Merci à zedar et Injall pour leur contribution sur les NPC parlant.

Injall - September 18, 2004 09:20 AM (GMT)
QUOTE
Les heures d'ouverture de ce script sont de 5h00am à 22h00pm.


:D IRL ou les heures dans le jeu ?

Vortal - September 18, 2004 09:22 AM (GMT)
Dans le jeu, bien sûr :P

Kaervek - September 18, 2004 02:59 PM (GMT)
QUOTE
Suggestion et ajouts possibles : Ici, tous les vendeurs, quels qu'ils soient, seront gérés par ce script. On aurait pu désirer certaines exceptions, comme pour les BarKeeper, par exemple.



Afin d'éviter d'avoir tous les PNJ comme cela, je conseillerai d'utiliser le script suivant (je n'ai rien oublié de ce que tu voulais faire dedans hein?) au lieu de modifier directement le BaseVendor. De plus, en cas de changement de version, ceci facilite la tâche de ne pas devoir bidouiller sur des scripts de base.
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;

namespace Server.Mobiles
{
public abstract class VendeurJour : BaseVendor
{
public VendeurJour( string title ) : base( title )
 {
 }
public override bool OnDragDrop( Mobile from, Item dropped )
 {
   int hours, minutes;
   Server.Items.Clock.GetTime( this.Map, this.X, this.Y, out hours, out minutes );
   if ( hours < 5 || hours > 22 ) // NIGHT
   {
    this.Say( "Désolé mais nous sommes fermé actuellement.  Merci de revenir demain matin." );
    return false;
   }
 return base.OnDragDrop( from, dropped );
}



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



Donc, ensuite, si vous voulez qu'un de vos vendeurs ferme bien la nuit, vous faites:
CODE
public class VotreVendeur : VendeurJour


Voici un exemple concret:
CODE
using System;
using System.Collections;
using Server;

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

 public override NpcGuild NpcGuild{ get{ return NpcGuild.MagesGuild; } }

 [Constructable]
 public HytanAlchimiste() : base( "L'Alchimiste" )
 {
 Name = "Ethan";
 NameHue = 1158;
 Title = "L'Alchimiste";
 }

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

 public override VendorShoeType ShoeType
 {
  get{ return Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; }
 }

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

  AddItem( new Server.Items.Robe( Utility.RandomNeutralHue() ) );
 }


public override void OnSpeech( SpeechEventArgs m )
{
if ( m.Mobile.InRange( this, 3 ) ) //if a player is within 2 tiles of the NPC
{

if ( m.Speech.ToLower().IndexOf( "bonjour" ) >= 0 ) //Checks to see if the player says Hey or Hello
{
Say( String.Format( "Bonjour. Quelles plantes désirez vous acheter ?" ) );
}

}
}

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




Note: Non testé car Slade doit tjrs m'envoyer un fichier pour la compilation...
Mais il n'y avait plus aucun problème de compilation due au script ci-dessus. Donc il compile. Reste à voir s'il est bien efficace in game... Chose que je n'ai pas encore pu tester malheureusement...

Vortal - September 18, 2004 05:24 PM (GMT)
N'empêche que ton idée est pas mauvaise du tout. C'est là qu'on voit l'expérience d'un scripteur ! hahahaha

Kaervek - September 18, 2004 07:21 PM (GMT)
Oh tu sais, elle n'est pas si grande que ça mon expérience :P
Le véritable professionnel c'est Slade.

De plus, je n'ai fait que simplifier légèrement ton script. Toute l'idée te revient! B) Et, selon moi, c'est hyper important les idées!




Hosted for free by InvisionFree