PageRenderTime 74ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/CoreNew/Server/Item.cs

https://bitbucket.org/Kel/crepuscule
C# | 4722 lines | 3371 code | 877 blank | 474 comment | 1071 complexity | 5f3a22d9652127f89b72489d5188f6b5 MD5 | raw file
  1. /***************************************************************************
  2. * Item.cs
  3. * -------------------
  4. * begin : May 1, 2002
  5. * copyright : (C) The RunUO Software Team
  6. * email : info@runuo.com
  7. *
  8. * $Id: Item.cs 649 2010-12-26 05:18:57Z asayre $
  9. *
  10. ***************************************************************************/
  11. /***************************************************************************
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation; either version 2 of the License, or
  16. * (at your option) any later version.
  17. *
  18. ***************************************************************************/
  19. using System;
  20. using System.IO;
  21. using System.Collections;
  22. using System.Collections.Generic;
  23. using Server.Network;
  24. using Server.Items;
  25. using Server.ContextMenus;
  26. namespace Server
  27. {
  28. /// <summary>
  29. /// Enumeration of item layer values.
  30. /// </summary>
  31. public enum Layer : byte
  32. {
  33. /// <summary>
  34. /// Invalid layer.
  35. /// </summary>
  36. Invalid = 0x00,
  37. /// <summary>
  38. /// First valid layer. Equivalent to <c>Layer.OneHanded</c>.
  39. /// </summary>
  40. FirstValid = 0x01,
  41. /// <summary>
  42. /// One handed weapon.
  43. /// </summary>
  44. OneHanded = 0x01,
  45. /// <summary>
  46. /// Two handed weapon or shield.
  47. /// </summary>
  48. TwoHanded = 0x02,
  49. /// <summary>
  50. /// Shoes.
  51. /// </summary>
  52. Shoes = 0x03,
  53. /// <summary>
  54. /// Pants.
  55. /// </summary>
  56. Pants = 0x04,
  57. /// <summary>
  58. /// Shirts.
  59. /// </summary>
  60. Shirt = 0x05,
  61. /// <summary>
  62. /// Helmets, hats, and masks.
  63. /// </summary>
  64. Helm = 0x06,
  65. /// <summary>
  66. /// Gloves.
  67. /// </summary>
  68. Gloves = 0x07,
  69. /// <summary>
  70. /// Rings.
  71. /// </summary>
  72. Ring = 0x08,
  73. /// <summary>
  74. /// Talismans.
  75. /// </summary>
  76. Talisman = 0x09,
  77. /// <summary>
  78. /// Gorgets and necklaces.
  79. /// </summary>
  80. Neck = 0x0A,
  81. /// <summary>
  82. /// Hair.
  83. /// </summary>
  84. Hair = 0x0B,
  85. /// <summary>
  86. /// Half aprons.
  87. /// </summary>
  88. Waist = 0x0C,
  89. /// <summary>
  90. /// Torso, inner layer.
  91. /// </summary>
  92. InnerTorso = 0x0D,
  93. /// <summary>
  94. /// Bracelets.
  95. /// </summary>
  96. Bracelet = 0x0E,
  97. /// <summary>
  98. /// Unused.
  99. /// </summary>
  100. Unused_xF = 0x0F,
  101. /// <summary>
  102. /// Beards and mustaches.
  103. /// </summary>
  104. FacialHair = 0x10,
  105. /// <summary>
  106. /// Torso, outer layer.
  107. /// </summary>
  108. MiddleTorso = 0x11,
  109. /// <summary>
  110. /// Earings.
  111. /// </summary>
  112. Earrings = 0x12,
  113. /// <summary>
  114. /// Arms and sleeves.
  115. /// </summary>
  116. Arms = 0x13,
  117. /// <summary>
  118. /// Cloaks.
  119. /// </summary>
  120. Cloak = 0x14,
  121. /// <summary>
  122. /// Backpacks.
  123. /// </summary>
  124. Backpack = 0x15,
  125. /// <summary>
  126. /// Torso, outer layer.
  127. /// </summary>
  128. OuterTorso = 0x16,
  129. /// <summary>
  130. /// Leggings, outer layer.
  131. /// </summary>
  132. OuterLegs = 0x17,
  133. /// <summary>
  134. /// Leggings, inner layer.
  135. /// </summary>
  136. InnerLegs = 0x18,
  137. /// <summary>
  138. /// Last valid non-internal layer. Equivalent to <c>Layer.InnerLegs</c>.
  139. /// </summary>
  140. LastUserValid= 0x18,
  141. /// <summary>
  142. /// Mount item layer.
  143. /// </summary>
  144. Mount = 0x19,
  145. /// <summary>
  146. /// Vendor 'buy pack' layer.
  147. /// </summary>
  148. ShopBuy = 0x1A,
  149. /// <summary>
  150. /// Vendor 'resale pack' layer.
  151. /// </summary>
  152. ShopResale = 0x1B,
  153. /// <summary>
  154. /// Vendor 'sell pack' layer.
  155. /// </summary>
  156. ShopSell = 0x1C,
  157. /// <summary>
  158. /// Bank box layer.
  159. /// </summary>
  160. Bank = 0x1D,
  161. /// <summary>
  162. /// Last valid layer. Equivalent to <c>Layer.Bank</c>.
  163. /// </summary>
  164. LastValid = 0x1D
  165. }
  166. /// <summary>
  167. /// Internal flags used to signal how the item should be updated and resent to nearby clients.
  168. /// </summary>
  169. [Flags]
  170. public enum ItemDelta
  171. {
  172. /// <summary>
  173. /// Nothing.
  174. /// </summary>
  175. None = 0x00000000,
  176. /// <summary>
  177. /// Resend the item.
  178. /// </summary>
  179. Update = 0x00000001,
  180. /// <summary>
  181. /// Resend the item only if it is equiped.
  182. /// </summary>
  183. EquipOnly = 0x00000002,
  184. /// <summary>
  185. /// Resend the item's properties.
  186. /// </summary>
  187. Properties = 0x00000004
  188. }
  189. /// <summary>
  190. /// Enumeration containing possible ways to handle item ownership on death.
  191. /// </summary>
  192. public enum DeathMoveResult
  193. {
  194. /// <summary>
  195. /// The item should be placed onto the corpse.
  196. /// </summary>
  197. MoveToCorpse,
  198. /// <summary>
  199. /// The item should remain equiped.
  200. /// </summary>
  201. RemainEquiped,
  202. /// <summary>
  203. /// The item should be placed into the owners backpack.
  204. /// </summary>
  205. MoveToBackpack
  206. }
  207. /// <summary>
  208. /// Enumeration containing all possible light types. These are only applicable to light source items, like lanterns, candles, braziers, etc.
  209. /// </summary>
  210. public enum LightType
  211. {
  212. /// <summary>
  213. /// Window shape, arched, ray shining east.
  214. /// </summary>
  215. ArchedWindowEast,
  216. /// <summary>
  217. /// Medium circular shape.
  218. /// </summary>
  219. Circle225,
  220. /// <summary>
  221. /// Small circular shape.
  222. /// </summary>
  223. Circle150,
  224. /// <summary>
  225. /// Door shape, shining south.
  226. /// </summary>
  227. DoorSouth,
  228. /// <summary>
  229. /// Door shape, shining east.
  230. /// </summary>
  231. DoorEast,
  232. /// <summary>
  233. /// Large semicircular shape (180 degrees), north wall.
  234. /// </summary>
  235. NorthBig,
  236. /// <summary>
  237. /// Large pie shape (90 degrees), north-east corner.
  238. /// </summary>
  239. NorthEastBig,
  240. /// <summary>
  241. /// Large semicircular shape (180 degrees), east wall.
  242. /// </summary>
  243. EastBig,
  244. /// <summary>
  245. /// Large semicircular shape (180 degrees), west wall.
  246. /// </summary>
  247. WestBig,
  248. /// <summary>
  249. /// Large pie shape (90 degrees), south-west corner.
  250. /// </summary>
  251. SouthWestBig,
  252. /// <summary>
  253. /// Large semicircular shape (180 degrees), south wall.
  254. /// </summary>
  255. SouthBig,
  256. /// <summary>
  257. /// Medium semicircular shape (180 degrees), north wall.
  258. /// </summary>
  259. NorthSmall,
  260. /// <summary>
  261. /// Medium pie shape (90 degrees), north-east corner.
  262. /// </summary>
  263. NorthEastSmall,
  264. /// <summary>
  265. /// Medium semicircular shape (180 degrees), east wall.
  266. /// </summary>
  267. EastSmall,
  268. /// <summary>
  269. /// Medium semicircular shape (180 degrees), west wall.
  270. /// </summary>
  271. WestSmall,
  272. /// <summary>
  273. /// Medium semicircular shape (180 degrees), south wall.
  274. /// </summary>
  275. SouthSmall,
  276. /// <summary>
  277. /// Shaped like a wall decoration, north wall.
  278. /// </summary>
  279. DecorationNorth,
  280. /// <summary>
  281. /// Shaped like a wall decoration, north-east corner.
  282. /// </summary>
  283. DecorationNorthEast,
  284. /// <summary>
  285. /// Small semicircular shape (180 degrees), east wall.
  286. /// </summary>
  287. EastTiny,
  288. /// <summary>
  289. /// Shaped like a wall decoration, west wall.
  290. /// </summary>
  291. DecorationWest,
  292. /// <summary>
  293. /// Shaped like a wall decoration, south-west corner.
  294. /// </summary>
  295. DecorationSouthWest,
  296. /// <summary>
  297. /// Small semicircular shape (180 degrees), south wall.
  298. /// </summary>
  299. SouthTiny,
  300. /// <summary>
  301. /// Window shape, rectangular, no ray, shining south.
  302. /// </summary>
  303. RectWindowSouthNoRay,
  304. /// <summary>
  305. /// Window shape, rectangular, no ray, shining east.
  306. /// </summary>
  307. RectWindowEastNoRay,
  308. /// <summary>
  309. /// Window shape, rectangular, ray shining south.
  310. /// </summary>
  311. RectWindowSouth,
  312. /// <summary>
  313. /// Window shape, rectangular, ray shining east.
  314. /// </summary>
  315. RectWindowEast,
  316. /// <summary>
  317. /// Window shape, arched, no ray, shining south.
  318. /// </summary>
  319. ArchedWindowSouthNoRay,
  320. /// <summary>
  321. /// Window shape, arched, no ray, shining east.
  322. /// </summary>
  323. ArchedWindowEastNoRay,
  324. /// <summary>
  325. /// Window shape, arched, ray shining south.
  326. /// </summary>
  327. ArchedWindowSouth,
  328. /// <summary>
  329. /// Large circular shape.
  330. /// </summary>
  331. Circle300,
  332. /// <summary>
  333. /// Large pie shape (90 degrees), north-west corner.
  334. /// </summary>
  335. NorthWestBig,
  336. /// <summary>
  337. /// Negative light. Medium pie shape (90 degrees), south-east corner.
  338. /// </summary>
  339. DarkSouthEast,
  340. /// <summary>
  341. /// Negative light. Medium semicircular shape (180 degrees), south wall.
  342. /// </summary>
  343. DarkSouth,
  344. /// <summary>
  345. /// Negative light. Medium pie shape (90 degrees), north-west corner.
  346. /// </summary>
  347. DarkNorthWest,
  348. /// <summary>
  349. /// Negative light. Medium pie shape (90 degrees), south-east corner. Equivalent to <c>LightType.SouthEast</c>.
  350. /// </summary>
  351. DarkSouthEast2,
  352. /// <summary>
  353. /// Negative light. Medium circular shape (180 degrees), east wall.
  354. /// </summary>
  355. DarkEast,
  356. /// <summary>
  357. /// Negative light. Large circular shape.
  358. /// </summary>
  359. DarkCircle300,
  360. /// <summary>
  361. /// Opened door shape, shining south.
  362. /// </summary>
  363. DoorOpenSouth,
  364. /// <summary>
  365. /// Opened door shape, shining east.
  366. /// </summary>
  367. DoorOpenEast,
  368. /// <summary>
  369. /// Window shape, square, ray shining east.
  370. /// </summary>
  371. SquareWindowEast,
  372. /// <summary>
  373. /// Window shape, square, no ray, shining east.
  374. /// </summary>
  375. SquareWindowEastNoRay,
  376. /// <summary>
  377. /// Window shape, square, ray shining south.
  378. /// </summary>
  379. SquareWindowSouth,
  380. /// <summary>
  381. /// Window shape, square, no ray, shining south.
  382. /// </summary>
  383. SquareWindowSouthNoRay,
  384. /// <summary>
  385. /// Empty.
  386. /// </summary>
  387. Empty,
  388. /// <summary>
  389. /// Window shape, skinny, no ray, shining south.
  390. /// </summary>
  391. SkinnyWindowSouthNoRay,
  392. /// <summary>
  393. /// Window shape, skinny, ray shining east.
  394. /// </summary>
  395. SkinnyWindowEast,
  396. /// <summary>
  397. /// Window shape, skinny, no ray, shining east.
  398. /// </summary>
  399. SkinnyWindowEastNoRay,
  400. /// <summary>
  401. /// Shaped like a hole, shining south.
  402. /// </summary>
  403. HoleSouth,
  404. /// <summary>
  405. /// Shaped like a hole, shining south.
  406. /// </summary>
  407. HoleEast,
  408. /// <summary>
  409. /// Large circular shape with a moongate graphic embeded.
  410. /// </summary>
  411. Moongate,
  412. /// <summary>
  413. /// Unknown usage. Many rows of slightly angled lines.
  414. /// </summary>
  415. Strips,
  416. /// <summary>
  417. /// Shaped like a small hole, shining south.
  418. /// </summary>
  419. SmallHoleSouth,
  420. /// <summary>
  421. /// Shaped like a small hole, shining east.
  422. /// </summary>
  423. SmallHoleEast,
  424. /// <summary>
  425. /// Large semicircular shape (180 degrees), north wall. Identical graphic as <c>LightType.NorthBig</c>, but slightly different positioning.
  426. /// </summary>
  427. NorthBig2,
  428. /// <summary>
  429. /// Large semicircular shape (180 degrees), west wall. Identical graphic as <c>LightType.WestBig</c>, but slightly different positioning.
  430. /// </summary>
  431. WestBig2,
  432. /// <summary>
  433. /// Large pie shape (90 degrees), north-west corner. Equivalent to <c>LightType.NorthWestBig</c>.
  434. /// </summary>
  435. NorthWestBig2
  436. }
  437. /// <summary>
  438. /// Enumeration of an item's loot and steal state.
  439. /// </summary>
  440. public enum LootType : byte
  441. {
  442. /// <summary>
  443. /// Stealable. Lootable.
  444. /// </summary>
  445. Regular = 0,
  446. /// <summary>
  447. /// Unstealable. Unlootable, unless owned by a murderer.
  448. /// </summary>
  449. Newbied = 1,
  450. /// <summary>
  451. /// Unstealable. Unlootable, always.
  452. /// </summary>
  453. Blessed = 2,
  454. /// <summary>
  455. /// Stealable. Lootable, always.
  456. /// </summary>
  457. Cursed = 3
  458. }
  459. public class BounceInfo
  460. {
  461. public Map m_Map;
  462. public Point3D m_Location, m_WorldLoc;
  463. public object m_Parent;
  464. public BounceInfo( Item item )
  465. {
  466. m_Map = item.Map;
  467. m_Location = item.Location;
  468. m_WorldLoc = item.GetWorldLocation();
  469. m_Parent = item.Parent;
  470. }
  471. private BounceInfo( Map map, Point3D loc, Point3D worldLoc, object parent )
  472. {
  473. m_Map = map;
  474. m_Location = loc;
  475. m_WorldLoc = worldLoc;
  476. m_Parent = parent;
  477. }
  478. public static BounceInfo Deserialize( GenericReader reader )
  479. {
  480. if ( reader.ReadBool() )
  481. {
  482. Map map = reader.ReadMap();
  483. Point3D loc = reader.ReadPoint3D();
  484. Point3D worldLoc = reader.ReadPoint3D();
  485. object parent;
  486. Serial serial = reader.ReadInt();
  487. if ( serial.IsItem )
  488. parent = World.FindItem( serial );
  489. else if ( serial.IsMobile )
  490. parent = World.FindMobile( serial );
  491. else
  492. parent = null;
  493. return new BounceInfo( map, loc, worldLoc, parent );
  494. }
  495. else
  496. {
  497. return null;
  498. }
  499. }
  500. public static void Serialize( BounceInfo info, GenericWriter writer )
  501. {
  502. if ( info == null )
  503. {
  504. writer.Write( false );
  505. }
  506. else
  507. {
  508. writer.Write( true );
  509. writer.Write( info.m_Map );
  510. writer.Write( info.m_Location );
  511. writer.Write( info.m_WorldLoc );
  512. if ( info.m_Parent is Mobile )
  513. writer.Write( (Mobile) info.m_Parent );
  514. else if ( info.m_Parent is Item )
  515. writer.Write( (Item) info.m_Parent );
  516. else
  517. writer.Write( (Serial) 0 );
  518. }
  519. }
  520. }
  521. public enum TotalType
  522. {
  523. Gold,
  524. Items,
  525. Weight,
  526. }
  527. [Flags]
  528. public enum ExpandFlag
  529. {
  530. None = 0x00,
  531. Name = 0x01,
  532. Items = 0x02,
  533. Bounce = 0x04,
  534. Holder = 0x08,
  535. Blessed = 0x10,
  536. TempFlag = 0x20,
  537. SaveFlag = 0x40,
  538. Weight = 0x80
  539. }
  540. public class Item : IEntity, IHued, IComparable<Item>, ISerializable, ISpawnable
  541. {
  542. public static readonly List<Item> EmptyItems = new List<Item>();
  543. public int CompareTo( IEntity other )
  544. {
  545. if ( other == null )
  546. return -1;
  547. return m_Serial.CompareTo( other.Serial );
  548. }
  549. public int CompareTo( Item other )
  550. {
  551. return this.CompareTo( (IEntity) other );
  552. }
  553. public int CompareTo( object other )
  554. {
  555. if ( other == null || other is IEntity )
  556. return this.CompareTo( (IEntity) other );
  557. throw new ArgumentException();
  558. }
  559. #region Standard fields
  560. private Serial m_Serial;
  561. private Point3D m_Location;
  562. private int m_ItemID;
  563. private int m_Hue;
  564. private int m_Amount;
  565. private Layer m_Layer;
  566. private object m_Parent; // Mobile, Item, or null=World
  567. private Map m_Map;
  568. private LootType m_LootType;
  569. private DateTime m_LastMovedTime;
  570. private Direction m_Direction;
  571. #endregion
  572. #region Crepuscule stuff
  573. private bool m_ShouldAssignProperties = true;
  574. private bool m_PropertiesAssigned = false;
  575. public virtual void OnAssignProperties()
  576. {
  577. }
  578. [CommandProperty(AccessLevel.GameMaster)]
  579. public bool ShouldAssignProperties
  580. {
  581. get { return m_ShouldAssignProperties; }
  582. set { m_ShouldAssignProperties = value; }
  583. }
  584. public bool PropertiesAssigned
  585. {
  586. get { return m_PropertiesAssigned; }
  587. }
  588. private bool NeedAssignProperties()
  589. {
  590. return m_ShouldAssignProperties && !m_PropertiesAssigned;
  591. }
  592. #endregion
  593. private ItemDelta m_DeltaFlags;
  594. private ImplFlag m_Flags;
  595. #region Packet caches
  596. private Packet m_WorldPacket;
  597. private Packet m_WorldPacketSA;
  598. private Packet m_WorldPacketHS;
  599. private Packet m_RemovePacket;
  600. private Packet m_OPLPacket;
  601. private ObjectPropertyList m_PropertyList;
  602. #endregion
  603. public int TempFlags
  604. {
  605. get
  606. {
  607. CompactInfo info = LookupCompactInfo();
  608. if ( info != null )
  609. return info.m_TempFlags;
  610. return 0;
  611. }
  612. set
  613. {
  614. CompactInfo info = AcquireCompactInfo();
  615. info.m_TempFlags = value;
  616. if ( info.m_TempFlags == 0 )
  617. VerifyCompactInfo();
  618. }
  619. }
  620. public int SavedFlags
  621. {
  622. get
  623. {
  624. CompactInfo info = LookupCompactInfo();
  625. if ( info != null )
  626. return info.m_SavedFlags;
  627. return 0;
  628. }
  629. set
  630. {
  631. CompactInfo info = AcquireCompactInfo();
  632. info.m_SavedFlags = value;
  633. if ( info.m_SavedFlags == 0 )
  634. VerifyCompactInfo();
  635. }
  636. }
  637. /// <summary>
  638. /// The <see cref="Mobile" /> who is currently <see cref="Mobile.Holding">holding</see> this item.
  639. /// </summary>
  640. public Mobile HeldBy
  641. {
  642. get
  643. {
  644. CompactInfo info = LookupCompactInfo();
  645. if ( info != null )
  646. return info.m_HeldBy;
  647. return null;
  648. }
  649. set
  650. {
  651. CompactInfo info = AcquireCompactInfo();
  652. info.m_HeldBy = value;
  653. if ( info.m_HeldBy == null )
  654. VerifyCompactInfo();
  655. }
  656. }
  657. [Flags]
  658. private enum ImplFlag : byte
  659. {
  660. None = 0x00,
  661. Visible = 0x01,
  662. Movable = 0x02,
  663. Deleted = 0x04,
  664. Stackable = 0x08,
  665. InQueue = 0x10,
  666. Insured = 0x20,
  667. PayedInsurance = 0x40,
  668. QuestItem = 0x80
  669. }
  670. private class CompactInfo
  671. {
  672. public string m_Name;
  673. public List<Item> m_Items;
  674. public BounceInfo m_Bounce;
  675. public Mobile m_HeldBy;
  676. public Mobile m_BlessedFor;
  677. public int m_TempFlags;
  678. public int m_SavedFlags;
  679. public double m_Weight = -1;
  680. }
  681. private CompactInfo m_CompactInfo;
  682. public ExpandFlag GetExpandFlags()
  683. {
  684. CompactInfo info = LookupCompactInfo();
  685. ExpandFlag flags = 0;
  686. if ( info != null )
  687. {
  688. if ( info.m_BlessedFor != null )
  689. flags |= ExpandFlag.Blessed;
  690. if ( info.m_Bounce != null )
  691. flags |= ExpandFlag.Bounce;
  692. if ( info.m_HeldBy != null )
  693. flags |= ExpandFlag.Holder;
  694. if ( info.m_Items != null )
  695. flags |= ExpandFlag.Items;
  696. if ( info.m_Name != null )
  697. flags |= ExpandFlag.Name;
  698. if ( info.m_SavedFlags != 0 )
  699. flags |= ExpandFlag.SaveFlag;
  700. if ( info.m_TempFlags != 0 )
  701. flags |= ExpandFlag.TempFlag;
  702. if ( info.m_Weight != -1 )
  703. flags |= ExpandFlag.Weight;
  704. }
  705. return flags;
  706. }
  707. private CompactInfo LookupCompactInfo()
  708. {
  709. return m_CompactInfo;
  710. }
  711. private CompactInfo AcquireCompactInfo()
  712. {
  713. if ( m_CompactInfo == null )
  714. m_CompactInfo = new CompactInfo();
  715. return m_CompactInfo;
  716. }
  717. private void ReleaseCompactInfo()
  718. {
  719. m_CompactInfo = null;
  720. }
  721. private void VerifyCompactInfo()
  722. {
  723. CompactInfo info = m_CompactInfo;
  724. if ( info == null )
  725. return;
  726. bool isValid = ( info.m_Name != null )
  727. || ( info.m_Items != null )
  728. || ( info.m_Bounce != null )
  729. || ( info.m_HeldBy != null )
  730. || ( info.m_BlessedFor != null )
  731. || ( info.m_TempFlags != 0 )
  732. || ( info.m_SavedFlags != 0 )
  733. || ( info.m_Weight != -1 );
  734. if ( !isValid )
  735. ReleaseCompactInfo();
  736. }
  737. public List<Item> LookupItems()
  738. {
  739. if ( this is Container )
  740. return ( this as Container ).m_Items;
  741. CompactInfo info = LookupCompactInfo();
  742. if ( info != null )
  743. return info.m_Items;
  744. return null;
  745. }
  746. public List<Item> AcquireItems()
  747. {
  748. if ( this is Container )
  749. {
  750. Container cont = this as Container;
  751. if ( cont.m_Items == null ) {
  752. cont.m_Items = new List<Item>();
  753. }
  754. return cont.m_Items;
  755. }
  756. CompactInfo info = AcquireCompactInfo();
  757. info.m_Items = new List<Item>();
  758. return info.m_Items;
  759. }
  760. private void SetFlag( ImplFlag flag, bool value )
  761. {
  762. if ( value )
  763. m_Flags |= flag;
  764. else
  765. m_Flags &= ~flag;
  766. }
  767. private bool GetFlag( ImplFlag flag )
  768. {
  769. return ( (m_Flags & flag) != 0 );
  770. }
  771. public BounceInfo GetBounce()
  772. {
  773. CompactInfo info = LookupCompactInfo();
  774. if ( info != null )
  775. return info.m_Bounce;
  776. return null;
  777. }
  778. public void RecordBounce()
  779. {
  780. CompactInfo info = AcquireCompactInfo();
  781. info.m_Bounce = new BounceInfo( this );
  782. }
  783. public void ClearBounce()
  784. {
  785. CompactInfo info = LookupCompactInfo();
  786. if ( info != null )
  787. {
  788. BounceInfo bounce = info.m_Bounce;
  789. if ( bounce != null )
  790. {
  791. info.m_Bounce = null;
  792. if ( bounce.m_Parent is Item )
  793. {
  794. Item parent = (Item) bounce.m_Parent;
  795. if ( !parent.Deleted )
  796. parent.OnItemBounceCleared( this );
  797. }
  798. else if ( bounce.m_Parent is Mobile )
  799. {
  800. Mobile parent = (Mobile) bounce.m_Parent;
  801. if ( !parent.Deleted )
  802. parent.OnItemBounceCleared( this );
  803. }
  804. VerifyCompactInfo();
  805. }
  806. }
  807. }
  808. /// <summary>
  809. /// Overridable. Virtual event invoked when a client, <paramref name="from" />, invokes a 'help request' for the Item. Seemingly no longer functional in newer clients.
  810. /// </summary>
  811. public virtual void OnHelpRequest( Mobile from )
  812. {
  813. }
  814. /// <summary>
  815. /// Overridable. Method checked to see if the item can be traded.
  816. /// </summary>
  817. /// <returns>True if the trade is allowed, false if not.</returns>
  818. public virtual bool AllowSecureTrade( Mobile from, Mobile to, Mobile newOwner, bool accepted )
  819. {
  820. return true;
  821. }
  822. /// <summary>
  823. /// Overridable. Virtual event invoked when a trade has completed, either successfully or not.
  824. /// </summary>
  825. public virtual void OnSecureTrade( Mobile from, Mobile to, Mobile newOwner, bool accepted )
  826. {
  827. }
  828. /// <summary>
  829. /// Overridable. Method checked to see if the elemental resistances of this Item conflict with another Item on the <see cref="Mobile" />.
  830. /// </summary>
  831. /// <returns>
  832. /// <list type="table">
  833. /// <item>
  834. /// <term>True</term>
  835. /// <description>There is a confliction. The elemental resistance bonuses of this Item should not be applied to the <see cref="Mobile" /></description>
  836. /// </item>
  837. /// <item>
  838. /// <term>False</term>
  839. /// <description>There is no confliction. The bonuses should be applied.</description>
  840. /// </item>
  841. /// </list>
  842. /// </returns>
  843. public virtual bool CheckPropertyConfliction( Mobile m )
  844. {
  845. return false;
  846. }
  847. /// <summary>
  848. /// Overridable. Sends the <see cref="PropertyList">object property list</see> to <paramref name="from" />.
  849. /// </summary>
  850. public virtual void SendPropertiesTo( Mobile from )
  851. {
  852. from.Send( PropertyList );
  853. }
  854. /// <summary>
  855. /// Overridable. Adds the name of this item to the given <see cref="ObjectPropertyList" />. This method should be overriden if the item requires a complex naming format.
  856. /// </summary>
  857. public virtual void AddNameProperty( ObjectPropertyList list )
  858. {
  859. string name = this.Name;
  860. if ( name == null )
  861. {
  862. if ( m_Amount <= 1 )
  863. list.Add( LabelNumber );
  864. else
  865. list.Add( 1050039, "{0}\t#{1}", m_Amount, LabelNumber ); // ~1_NUMBER~ ~2_ITEMNAME~
  866. }
  867. else
  868. {
  869. if ( m_Amount <= 1 )
  870. list.Add( name );
  871. else
  872. list.Add( 1050039, "{0}\t{1}", m_Amount, Name ); // ~1_NUMBER~ ~2_ITEMNAME~
  873. }
  874. }
  875. /// <summary>
  876. /// Overridable. Adds the loot type of this item to the given <see cref="ObjectPropertyList" />. By default, this will be either 'blessed', 'cursed', or 'insured'.
  877. /// </summary>
  878. public virtual void AddLootTypeProperty( ObjectPropertyList list )
  879. {
  880. if ( m_LootType == LootType.Blessed )
  881. list.Add( 1038021 ); // blessed
  882. else if ( m_LootType == LootType.Cursed )
  883. list.Add( 1049643 ); // cursed
  884. else if ( Insured )
  885. list.Add( 1061682 ); // <b>insured</b>
  886. }
  887. /// <summary>
  888. /// Overridable. Adds any elemental resistances of this item to the given <see cref="ObjectPropertyList" />.
  889. /// </summary>
  890. public virtual void AddResistanceProperties( ObjectPropertyList list )
  891. {
  892. int v = PhysicalResistance;
  893. if ( v != 0 )
  894. list.Add( 1060448, v.ToString() ); // physical resist ~1_val~%
  895. v = FireResistance;
  896. if ( v != 0 )
  897. list.Add( 1060447, v.ToString() ); // fire resist ~1_val~%
  898. v = ColdResistance;
  899. if ( v != 0 )
  900. list.Add( 1060445, v.ToString() ); // cold resist ~1_val~%
  901. v = PoisonResistance;
  902. if ( v != 0 )
  903. list.Add( 1060449, v.ToString() ); // poison resist ~1_val~%
  904. v = EnergyResistance;
  905. if ( v != 0 )
  906. list.Add( 1060446, v.ToString() ); // energy resist ~1_val~%
  907. }
  908. /// <summary>
  909. /// Overridable. Determines whether the item will show <see cref="AddWeightProperty" />.
  910. /// </summary>
  911. public virtual bool DisplayWeight
  912. {
  913. get
  914. {
  915. if ( !Core.ML )
  916. return false;
  917. if ( !Movable && !( IsLockedDown || IsSecure ) && ItemData.Weight == 255 )
  918. return false;
  919. return false;
  920. }
  921. }
  922. /// <summary>
  923. /// Overridable. Displays cliloc 1072788-1072789.
  924. /// </summary>
  925. public virtual void AddWeightProperty( ObjectPropertyList list )
  926. {
  927. int weight = this.PileWeight + this.TotalWeight;
  928. if ( weight == 1 ) {
  929. list.Add( 1072788, weight.ToString() ); //Weight: ~1_WEIGHT~ stone
  930. } else {
  931. list.Add( 1072789, weight.ToString() ); //Weight: ~1_WEIGHT~ stones
  932. }
  933. }
  934. /// <summary>
  935. /// Overridable. Adds header properties. By default, this invokes <see cref="AddNameProperty" />, <see cref="AddBlessedForProperty" /> (if applicable), and <see cref="AddLootTypeProperty" /> (if <see cref="DisplayLootType" />).
  936. /// </summary>
  937. public virtual void AddNameProperties( ObjectPropertyList list )
  938. {
  939. AddNameProperty( list );
  940. if ( IsSecure )
  941. AddSecureProperty( list );
  942. else if ( IsLockedDown )
  943. AddLockedDownProperty( list );
  944. Mobile blessedFor = this.BlessedFor;
  945. if ( blessedFor != null && !blessedFor.Deleted )
  946. AddBlessedForProperty( list, blessedFor );
  947. if ( DisplayLootType )
  948. AddLootTypeProperty( list );
  949. if ( DisplayWeight )
  950. AddWeightProperty( list );
  951. if( QuestItem )
  952. AddQuestItemProperty( list );
  953. AppendChildNameProperties( list );
  954. }
  955. /// <summary>
  956. /// Overridable. Adds the "Quest Item" property to the given <see cref="ObjectPropertyList" />.
  957. /// </summary>
  958. public virtual void AddQuestItemProperty( ObjectPropertyList list )
  959. {
  960. list.Add( 1072351 ); // Quest Item
  961. }
  962. /// <summary>
  963. /// Overridable. Adds the "Locked Down & Secure" property to the given <see cref="ObjectPropertyList" />.
  964. /// </summary>
  965. public virtual void AddSecureProperty( ObjectPropertyList list )
  966. {
  967. list.Add( 501644 ); // locked down & secure
  968. }
  969. /// <summary>
  970. /// Overridable. Adds the "Locked Down" property to the given <see cref="ObjectPropertyList" />.
  971. /// </summary>
  972. public virtual void AddLockedDownProperty( ObjectPropertyList list )
  973. {
  974. list.Add( 501643 ); // locked down
  975. }
  976. /// <summary>
  977. /// Overridable. Adds the "Blessed for ~1_NAME~" property to the given <see cref="ObjectPropertyList" />.
  978. /// </summary>
  979. public virtual void AddBlessedForProperty( ObjectPropertyList list, Mobile m )
  980. {
  981. list.Add( 1062203, "{0}", m.Name ); // Blessed for ~1_NAME~
  982. }
  983. /// <summary>
  984. /// Overridable. Fills an <see cref="ObjectPropertyList" /> with everything applicable. By default, this invokes <see cref="AddNameProperties" />, then <see cref="Item.GetChildProperties">Item.GetChildProperties</see> or <see cref="Mobile.GetChildProperties">Mobile.GetChildProperties</see>. This method should be overriden to add any custom properties.
  985. /// </summary>
  986. public virtual void GetProperties( ObjectPropertyList list )
  987. {
  988. AddNameProperties( list );
  989. }
  990. /// <summary>
  991. /// Overridable. Event invoked when a child (<paramref name="item" />) is building it's <see cref="ObjectPropertyList" />. Recursively calls <see cref="Item.GetChildProperties">Item.GetChildProperties</see> or <see cref="Mobile.GetChildProperties">Mobile.GetChildProperties</see>.
  992. /// </summary>
  993. public virtual void GetChildProperties( ObjectPropertyList list, Item item )
  994. {
  995. if ( m_Parent is Item )
  996. ((Item)m_Parent).GetChildProperties( list, item );
  997. else if ( m_Parent is Mobile )
  998. ((Mobile)m_Parent).GetChildProperties( list, item );
  999. }
  1000. /// <summary>
  1001. /// Overridable. Event invoked when a child (<paramref name="item" />) is building it's Name <see cref="ObjectPropertyList" />. Recursively calls <see cref="Item.GetChildProperties">Item.GetChildNameProperties</see> or <see cref="Mobile.GetChildProperties">Mobile.GetChildNameProperties</see>.
  1002. /// </summary>
  1003. public virtual void GetChildNameProperties( ObjectPropertyList list, Item item )
  1004. {
  1005. if ( m_Parent is Item )
  1006. ((Item)m_Parent).GetChildNameProperties( list, item );
  1007. else if ( m_Parent is Mobile )
  1008. ((Mobile)m_Parent).GetChildNameProperties( list, item );
  1009. }
  1010. public virtual bool IsChildVisibleTo( Mobile m, Item child )
  1011. {
  1012. return true;
  1013. }
  1014. public void Bounce( Mobile from )
  1015. {
  1016. if ( m_Parent is Item )
  1017. ((Item)m_Parent).RemoveItem( this );
  1018. else if ( m_Parent is Mobile )
  1019. ((Mobile)m_Parent).RemoveItem( this );
  1020. m_Parent = null;
  1021. BounceInfo bounce = this.GetBounce();
  1022. if ( bounce != null )
  1023. {
  1024. object parent = bounce.m_Parent;
  1025. if ( parent is Item && !((Item)parent).Deleted )
  1026. {
  1027. Item p = (Item)parent;
  1028. object root = p.RootParent;
  1029. if ( p.IsAccessibleTo( from ) && ( !(root is Mobile) || ((Mobile)root).CheckNonlocalDrop( from, this, p ) ) )
  1030. {
  1031. Location = bounce.m_Location;
  1032. p.AddItem( this );
  1033. }
  1034. else
  1035. {
  1036. MoveToWorld( from.Location, from.Map );
  1037. }
  1038. }
  1039. else if ( parent is Mobile && !((Mobile)parent).Deleted )
  1040. {
  1041. if ( !((Mobile)parent).EquipItem( this ) )
  1042. MoveToWorld( bounce.m_WorldLoc, bounce.m_Map );
  1043. }
  1044. else
  1045. {
  1046. MoveToWorld( bounce.m_WorldLoc, bounce.m_Map );
  1047. }
  1048. ClearBounce();
  1049. }
  1050. else
  1051. {
  1052. MoveToWorld( from.Location, from.Map );
  1053. }
  1054. }
  1055. /// <summary>
  1056. /// Overridable. Method checked to see if this item may be equiped while casting a spell. By default, this returns false. It is overriden on spellbook and spell channeling weapons or shields.
  1057. /// </summary>
  1058. /// <returns>True if it may, false if not.</returns>
  1059. /// <example>
  1060. /// <code>
  1061. /// public override bool AllowEquipedCast( Mobile from )
  1062. /// {
  1063. /// if ( from.Int &gt;= 100 )
  1064. /// return true;
  1065. ///
  1066. /// return base.AllowEquipedCast( from );
  1067. /// }</code>
  1068. ///
  1069. /// When placed in an Item script, the item may be cast when equiped if the <paramref name="from" /> has 100 or more intelligence. Otherwise, it will drop to their backpack.
  1070. /// </example>
  1071. public virtual bool AllowEquipedCast( Mobile from )
  1072. {
  1073. return false;
  1074. }
  1075. public virtual bool CheckConflictingLayer( Mobile m, Item item, Layer layer )
  1076. {
  1077. return ( m_Layer == layer );
  1078. }
  1079. public virtual bool CanEquip( Mobile m )
  1080. {
  1081. return ( m_Layer != Layer.Invalid && m.FindItemOnLayer( m_Layer ) == null );
  1082. }
  1083. public virtual void GetChildContextMenuEntries( Mobile from, List<ContextMenuEntry> list, Item item )
  1084. {
  1085. if ( m_Parent is Item )
  1086. ((Item)m_Parent).GetChildContextMenuEntries( from, list, item );
  1087. else if ( m_Parent is Mobile )
  1088. ((Mobile)m_Parent).GetChildContextMenuEntries( from, list, item );
  1089. }
  1090. public virtual void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
  1091. {
  1092. if ( m_Parent is Item )
  1093. ((Item)m_Parent).GetChildContextMenuEntries( from, list, this );
  1094. else if ( m_Parent is Mobile )
  1095. ((Mobile)m_Parent).GetChildContextMenuEntries( from, list, this );
  1096. }
  1097. public virtual bool VerifyMove( Mobile from )
  1098. {
  1099. return Movable;
  1100. }
  1101. public virtual DeathMoveResult OnParentDeath( Mobile parent )
  1102. {
  1103. if ( !Movable )
  1104. return DeathMoveResult.RemainEquiped;
  1105. else if ( parent.KeepsItemsOnDeath )
  1106. return DeathMoveResult.MoveToBackpack;
  1107. else if ( CheckBlessed( parent ) )
  1108. return DeathMoveResult.MoveToBackpack;
  1109. else if ( CheckNewbied() && parent.Kills < 5 )
  1110. return DeathMoveResult.MoveToBackpack;
  1111. else if( parent.Player && Nontransferable )
  1112. return DeathMoveResult.MoveToBackpack;
  1113. else
  1114. return DeathMoveResult.MoveToCorpse;
  1115. }
  1116. public virtual DeathMoveResult OnInventoryDeath( Mobile parent )
  1117. {
  1118. if ( !Movable )
  1119. return DeathMoveResult.MoveToBackpack;
  1120. else if ( parent.KeepsItemsOnDeath )
  1121. return DeathMoveResult.MoveToBackpack;
  1122. else if ( CheckBlessed( parent ) )
  1123. return DeathMoveResult.MoveToBackpack;
  1124. else if ( CheckNewbied() && parent.Kills < 5 )
  1125. return DeathMoveResult.MoveToBackpack;
  1126. else if( parent.Player && Nontransferable )
  1127. return DeathMoveResult.MoveToBackpack;
  1128. else
  1129. return DeathMoveResult.MoveToCorpse;
  1130. }
  1131. /// <summary>
  1132. /// Moves the Item to <paramref name="location" />. The Item does not change maps.
  1133. /// </summary>
  1134. public virtual void MoveToWorld( Point3D location )
  1135. {
  1136. MoveToWorld( location, m_Map );
  1137. }
  1138. public void LabelTo( Mobile to, int number )
  1139. {
  1140. to.Send( new MessageLocalized( m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", "" ) );
  1141. }
  1142. public void LabelTo( Mobile to, int number, string args )
  1143. {
  1144. to.Send( new MessageLocalized( m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", args ) );
  1145. }
  1146. public void LabelTo( Mobile to, string text )
  1147. {
  1148. to.Send( new UnicodeMessage( m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, "ENU", "", text ) );
  1149. }
  1150. public void LabelTo( Mobile to, string format, params object[] args )
  1151. {
  1152. LabelTo( to, String.Format( format, args ) );
  1153. }
  1154. public void LabelToAffix( Mobile to, int number, AffixType type, string affix )
  1155. {
  1156. to.Send( new MessageLocalizedAffix( m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", type, affix, "" ) );
  1157. }
  1158. public void LabelToAffix( Mobile to, int number, AffixType type, string affix, string args )
  1159. {
  1160. to.Send( new MessageLocalizedAffix( m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", type, affix, args ) );
  1161. }
  1162. public virtual void LabelLootTypeTo( Mobile to )
  1163. {
  1164. if ( m_LootType == LootType.Blessed )
  1165. LabelTo( to, 1041362 ); // (blessed)
  1166. else if ( m_LootType == LootType.Cursed )
  1167. LabelTo( to, "(cursed)" );
  1168. }
  1169. public bool AtWorldPoint( int x, int y )
  1170. {
  1171. return ( m_Parent == null && m_Location.m_X == x && m_Location.m_Y == y );
  1172. }
  1173. public bool AtPoint( int x, int y )
  1174. {
  1175. return ( m_Location.m_X == x && m_Location.m_Y == y );
  1176. }
  1177. /// <summary>
  1178. /// Moves the Item to a given <paramref name="location" /> and <paramref name="map" />.
  1179. /// </summary>
  1180. public void MoveToWorld( Point3D location, Map map )
  1181. {
  1182. if ( Deleted )
  1183. return;
  1184. Point3D oldLocation = GetWorldLocation();
  1185. Point3D oldRealLocation = m_Location;
  1186. SetLastMoved();
  1187. if ( Parent is Mobile )
  1188. ((Mobile)Parent).RemoveItem( this );
  1189. else if ( Parent is Item )
  1190. ((Item)Parent).RemoveItem( this );
  1191. if ( m_Map != map )
  1192. {
  1193. Map old = m_Map;
  1194. if ( m_Map != null )
  1195. {
  1196. m_Map.OnLeave( this );
  1197. if ( oldLocation.m_X != 0 )
  1198. {
  1199. Packet remPacket = null;
  1200. IPooledEnumerable eable = m_Map.GetClientsInRange( oldLocation, GetMaxUpdateRange() );
  1201. foreach ( NetState state in eable )
  1202. {
  1203. Mobile m = state.Mobile;
  1204. if ( m.InRange( oldLocation, GetUpdateRange( m ) ) )
  1205. {
  1206. if ( remPacket == null )
  1207. remPacket = this.RemovePacket;
  1208. state.Send( remPacket );
  1209. }
  1210. }
  1211. eable.Free();
  1212. }
  1213. }
  1214. m_Location = location;
  1215. this.OnLocationChange( oldRealLocation );
  1216. ReleaseWorldPackets();
  1217. List<Item> items = LookupItems();
  1218. if ( items != null )
  1219. {
  1220. for ( int i = 0; i < items.Count; ++i )
  1221. items[i].Map = map;
  1222. }
  1223. m_Map = map;
  1224. if ( m_Map != null )
  1225. m_Map.OnEnter( this );
  1226. OnMapChange();
  1227. if ( m_Map != null )
  1228. {
  1229. IPooledEnumerable eable = m_Map.GetClientsInRange( m_Location, GetMaxUpdateRange() );
  1230. foreach ( NetState state in eable )
  1231. {
  1232. Mobile m = state.Mobile;
  1233. if ( m.CanSee( this ) && m.InRange( m_Location, GetUpdateRange( m ) ) )
  1234. SendInfoTo( state );
  1235. }
  1236. eable.Free();
  1237. }
  1238. RemDelta( ItemDelta.Update );
  1239. if ( old == null || old == Map.Internal )
  1240. InvalidateProperties();
  1241. }
  1242. else if ( m_Map != null )
  1243. {
  1244. IPooledEnumerable eable;
  1245. if ( oldLocation.m_X != 0 )
  1246. {
  1247. Packet removeThis = null;
  1248. eable = m_Map.GetClientsInRange( oldLocation, GetMaxUpdateRange() );
  1249. foreach ( NetState state in eable )
  1250. {
  1251. Mobile m = state.Mobile;
  1252. if ( !m.InRange( location, GetUpdateRange( m ) ) )
  1253. {
  1254. if ( removeThis == null )
  1255. removeThis = this.RemovePacket;
  1256. state.Send( removeThis );
  1257. }
  1258. }
  1259. eable.Free();
  1260. }
  1261. Point3D oldInternalLocation = m_Location;
  1262. m_Location = location;
  1263. this.OnLocationChange( oldRealLocation );
  1264. ReleaseWorldPackets();
  1265. eable = m_Map.GetClientsInRange( m_Location, GetMaxUpdateRange() );
  1266. foreach ( NetState state in eable )
  1267. {
  1268. Mobile m = state.Mobile;
  1269. if ( m.CanSee( this ) && m.InRange( m_Location, GetUpdateRange( m ) ) )
  1270. SendInfoTo( state );
  1271. }
  1272. eable.Free();
  1273. m_Map.OnMove( oldInternalLocation, this );
  1274. RemDelta( ItemDelta.Update );
  1275. }
  1276. else
  1277. {
  1278. Map = map;
  1279. Location = location;
  1280. }
  1281. }
  1282. /// <summary>
  1283. /// Has the item been deleted?
  1284. /// </summary>
  1285. public bool Deleted{ get{ return GetFlag( ImplFlag.Deleted ); } }
  1286. [CommandProperty( AccessLevel.GameMaster )]
  1287. public LootType LootType
  1288. {
  1289. get
  1290. {
  1291. return m_LootType;
  1292. }
  1293. set
  1294. {
  1295. if ( m_LootType != value )
  1296. {
  1297. m_LootType = value;
  1298. if ( DisplayLootType )
  1299. InvalidateProperties();
  1300. }
  1301. }
  1302. }
  1303. private static TimeSpan m_DDT = TimeSpan.FromHours( 1.0 );
  1304. public static TimeSpan DefaultDecayTime{ get{ return m_DDT; } set{ m_DDT = value; } }
  1305. [CommandProperty( AccessLevel.GameMaster )]
  1306. public virtual TimeSpan DecayTime
  1307. {
  1308. get
  1309. {
  1310. return m_DDT;
  1311. }
  1312. }
  1313. [CommandProperty( AccessLevel.GameMaster )]
  1314. public virtual bool Decays
  1315. {
  1316. get
  1317. {
  1318. return (Movable && Visible);
  1319. }
  1320. }
  1321. public virtual bool OnDecay()
  1322. {
  1323. return ( Decays && Parent == null && Map != Map.Internal && Region.Find( Location, Map ).OnDecay( this ) );
  1324. }
  1325. public void SetLastMoved()
  1326. {
  1327. m_LastMovedTime = DateTime.Now;
  1328. }
  1329. public DateTime LastMoved
  1330. {
  1331. get
  1332. {
  1333. return m_LastMovedTime;
  1334. }
  1335. set
  1336. {
  1337. m_LastMovedTime = value;
  1338. }
  1339. }
  1340. public bool StackWith( Mobile from, Item dropped )
  1341. {
  1342. return StackWith( from, dropped, true );
  1343. }
  1344. public virtual bool StackWith( Mobile from, Item dropped, bool playSound )
  1345. {
  1346. if ( dropped.Stackable && Stackable && dropped.GetType() == GetType() && dropped.ItemID == ItemID && dropped.Hue == Hue && dropped.Name == Name && (dropped.Amount + Amount) <= 60000 )
  1347. {
  1348. if ( m_LootType != dropped.m_LootType )
  1349. m_LootType = LootType.Regular;
  1350. Amount += dropped.Amount;
  1351. dropped.Delete();
  1352. if ( playSound && from != null )
  1353. {
  1354. int soundID = GetDropSound();
  1355. if ( soundID == -1 )
  1356. soundID = 0x42;
  1357. from.SendSound( soundID, GetWorldLocation() );
  1358. }
  1359. return true;
  1360. }
  1361. return false;
  1362. }
  1363. public virtual bool OnDragDrop( Mobile from, Item dropped )
  1364. {
  1365. if ( Parent is Container )
  1366. return ((Container)Parent).OnStackAttempt( from, this, dropped );
  1367. return StackWith( from, dropped );
  1368. }
  1369. public Rectangle2D GetGraphicBounds()
  1370. {
  1371. int itemID = m_ItemID;
  1372. bool doubled = m_Amount > 1;
  1373. if ( itemID >= 0xEEA && itemID <= 0xEF2 ) // Are we coins?
  1374. {
  1375. int coinBase = (itemID - 0xEEA) / 3;
  1376. coinBase *= 3;
  1377. coinBase += 0xEEA;
  1378. doubled = false;
  1379. if ( m_Amount <= 1 )
  1380. {
  1381. // A single coin
  1382. itemID = coinBase;
  1383. }
  1384. else if ( m_Amount <= 5 )
  1385. {
  1386. // A stack of coins
  1387. itemID = coinBase + 1;
  1388. }
  1389. else // m_Amount > 5
  1390. {
  1391. // A pile of coins
  1392. itemID = coinBase + 2;
  1393. }
  1394. }
  1395. Rectangle2D bounds = ItemBounds.Table[itemID & 0x3FFF];
  1396. if ( doubled )
  1397. {
  1398. bounds.Set( bounds.X, bounds.Y, bounds.Width + 5, bounds.Height + 5 );
  1399. }
  1400. return bounds;
  1401. }
  1402. [CommandProperty( AccessLevel.GameMaster )]
  1403. public bool Stackable
  1404. {
  1405. get{ return GetFlag( ImplFlag.Stackable ); }
  1406. set{ SetFlag( ImplFlag.Stackable, value ); }
  1407. }
  1408. public Packet RemovePacket
  1409. {
  1410. get
  1411. {
  1412. if ( m_RemovePacket == null )
  1413. {
  1414. m_RemovePacket = new RemoveItem( this );
  1415. m_RemovePacket.SetStatic();
  1416. }
  1417. return m_RemovePacket;
  1418. }
  1419. }
  1420. public Packet OPLPacket
  1421. {
  1422. get
  1423. {
  1424. if ( m_OPLPacket == null )
  1425. {
  1426. m_OPLPacket = new OPLInfo( PropertyList );
  1427. m_OPLPacket.SetStatic();
  1428. }
  1429. return m_OPLPacket;
  1430. }
  1431. }
  1432. public ObjectPropertyList PropertyList
  1433. {
  1434. get
  1435. {
  1436. if ( m_PropertyList == null )
  1437. {
  1438. m_PropertyList = new ObjectPropertyList( this );
  1439. GetProperties( m_PropertyList );
  1440. AppendChildProperties( m_PropertyList );
  1441. m_PropertyList.Terminate();
  1442. m_PropertyList.SetStatic();
  1443. }
  1444. return m_PropertyList;
  1445. }
  1446. }
  1447. public virtual void AppendChildProperties( ObjectPropertyList list )
  1448. {
  1449. if ( m_Parent is Item )
  1450. ((Item)m_Parent).GetChildProperties( list, this );
  1451. else if ( m_Parent is Mobile )
  1452. ((Mobile)m_Parent).GetChildProperties( list, this );
  1453. }
  1454. public virtual void AppendChildNameProperties( ObjectPropertyList list )
  1455. {
  1456. if ( m_Parent is Item )
  1457. ((Item)m_Parent).GetChildNameProperties( list, this );
  1458. else if ( m_Parent is Mobile )
  1459. ((Mobile)m_Parent).GetChildNameProperties( list, this );
  1460. }
  1461. public void ClearProperties()
  1462. {
  1463. Packet.Release( ref m_PropertyList );
  1464. Packet.Release( ref m_OPLPacket );
  1465. }
  1466. public void InvalidateProperties()
  1467. {
  1468. if ( !ObjectPropertyList.Enabled )
  1469. return;
  1470. if ( m_Map != null && m_Map != Map.Internal && !World.Loading )
  1471. {
  1472. ObjectPropertyList oldList = m_PropertyList;
  1473. m_PropertyList = null;
  1474. ObjectPropertyList newList = PropertyList;
  1475. if ( oldList == null || oldList.Hash != newList.Hash )
  1476. {
  1477. Packet.Release( ref m_OPLPacket );
  1478. Delta( ItemDelta.Properties );
  1479. }
  1480. }
  1481. else
  1482. {
  1483. ClearProperties();
  1484. }
  1485. }
  1486. public Packet WorldPacket
  1487. {
  1488. get
  1489. {
  1490. // This needs to be invalidated when any of the following changes:
  1491. // - ItemID
  1492. // - Amount
  1493. // - Location
  1494. // - Hue
  1495. // - Packet Flags
  1496. // - Direction
  1497. if ( m_WorldPacket == null )
  1498. {
  1499. m_WorldPacket = new WorldItem( this );
  1500. m_WorldPacket.SetStatic();
  1501. }
  1502. return m_WorldPacket;
  1503. }
  1504. }
  1505. public Packet WorldPacketSA
  1506. {
  1507. get
  1508. {
  1509. // This needs to be invalidated when any of the following changes:
  1510. // - ItemID
  1511. // - Amount
  1512. // - Location
  1513. // - Hue
  1514. // - Packet Flags
  1515. // - Direction
  1516. if ( m_WorldPacketSA == null )
  1517. {
  1518. m_WorldPacketSA = new WorldItemSA( this );
  1519. m_WorldPacketSA.SetStatic();
  1520. }
  1521. return m_WorldPacketSA;
  1522. }
  1523. }
  1524. public Packet WorldPacketHS
  1525. {
  1526. get
  1527. {
  1528. // This needs to be invalidated when any of the following changes:
  1529. // - ItemID
  1530. // - Amount
  1531. // - Location
  1532. // - Hue
  1533. // - Packet Flags
  1534. // - Direction
  1535. if ( m_WorldPacketHS == null )
  1536. {
  1537. m_WorldPacketHS = new WorldItemHS( this );
  1538. m_WorldPacketHS.SetStatic();
  1539. }
  1540. return m_WorldPacketHS;
  1541. }
  1542. }
  1543. public void ReleaseWorldPackets()
  1544. {
  1545. Packet.Release( ref m_WorldPacket );
  1546. Packet.Release( ref m_WorldPacketSA );
  1547. Packet.Release( ref m_WorldPacketHS );
  1548. }
  1549. [CommandProperty( AccessLevel.GameMaster )]
  1550. public bool Visible
  1551. {
  1552. get{ return GetFlag( ImplFlag.Visible ); }
  1553. set
  1554. {
  1555. if ( GetFlag( ImplFlag.Visible ) != value )
  1556. {
  1557. SetFlag( ImplFlag.Visible, value );
  1558. ReleaseWorldPackets();
  1559. if ( m_Map != null )
  1560. {
  1561. Packet removeThis = null;
  1562. Point3D worldLoc = GetWorldLocation();
  1563. IPooledEnumerable eable = m_Map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
  1564. foreach ( NetState state in eable )
  1565. {
  1566. Mobile m = state.Mobile;
  1567. if ( !m.CanSee( this ) && m.InRange( worldLoc, GetUpdateRange( m ) ) )
  1568. {
  1569. if ( removeThis == null )
  1570. removeThis = this.RemovePacket;
  1571. state.Send( removeThis );
  1572. }
  1573. }
  1574. eable.Free();
  1575. }
  1576. Delta( ItemDelta.Update );
  1577. }
  1578. }
  1579. }
  1580. [CommandProperty( AccessLevel.GameMaster )]
  1581. public bool Movable
  1582. {
  1583. get{ return GetFlag( ImplFlag.Movable ); }
  1584. set
  1585. {
  1586. if ( GetFlag( ImplFlag.Movable ) != value )
  1587. {
  1588. SetFlag( ImplFlag.Movable, value );
  1589. ReleaseWorldPackets();
  1590. Delta( ItemDelta.Update );
  1591. }
  1592. }
  1593. }
  1594. public virtual bool ForceShowProperties{ get{ return false; } }
  1595. public virtual int GetPacketFlags()
  1596. {
  1597. int flags = 0;
  1598. if ( !Visible )
  1599. flags |= 0x80;
  1600. if ( Movable || ForceShowProperties )
  1601. flags |= 0x20;
  1602. return flags;
  1603. }
  1604. public virtual bool OnMoveOff( Mobile m )
  1605. {
  1606. return true;
  1607. }
  1608. public virtual bool OnMoveOver( Mobile m )
  1609. {
  1610. return true;
  1611. }
  1612. public virtual bool HandlesOnMovement{ get{ return false; } }
  1613. public virtual void OnMovement( Mobile m, Point3D oldLocation )
  1614. {
  1615. }
  1616. public void Internalize()
  1617. {
  1618. MoveToWorld( Point3D.Zero, Map.Internal );
  1619. }
  1620. public virtual void OnMapChange()
  1621. {
  1622. }
  1623. public virtual void OnRemoved( object parent )
  1624. {
  1625. }
  1626. public virtual void OnAdded( object parent )
  1627. {
  1628. }
  1629. [CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
  1630. public Map Map
  1631. {
  1632. get
  1633. {
  1634. return m_Map;
  1635. }
  1636. set
  1637. {
  1638. if ( m_Map != value )
  1639. {
  1640. Map old = m_Map;
  1641. if ( m_Map != null && m_Parent == null )
  1642. {
  1643. m_Map.OnLeave( this );
  1644. SendRemovePacket();
  1645. }
  1646. List<Item> items = LookupItems();
  1647. if ( items != null )
  1648. {
  1649. for ( int i = 0; i < items.Count; ++i )
  1650. items[i].Map = value;
  1651. }
  1652. m_Map = value;
  1653. if ( m_Map != null && m_Parent == null )
  1654. m_Map.OnEnter( this );
  1655. Delta( ItemDelta.Update );
  1656. this.OnMapChange();
  1657. if ( old == null || old == Map.Internal )
  1658. InvalidateProperties();
  1659. }
  1660. }
  1661. }
  1662. [Flags]
  1663. private enum SaveFlag
  1664. {
  1665. None = 0x00000000,
  1666. Direction = 0x00000001,
  1667. Bounce = 0x00000002,
  1668. LootType = 0x00000004,
  1669. LocationFull = 0x00000008,
  1670. ItemID = 0x00000010,
  1671. Hue = 0x00000020,
  1672. Amount = 0x00000040,
  1673. Layer = 0x00000080,
  1674. Name = 0x00000100,
  1675. Parent = 0x00000200,
  1676. Items = 0x00000400,
  1677. WeightNot1or0 = 0x00000800,
  1678. Map = 0x00001000,
  1679. Visible = 0x00002000,
  1680. Movable = 0x00004000,
  1681. Stackable = 0x00008000,
  1682. WeightIs0 = 0x00010000,
  1683. LocationSByteZ = 0x00020000,
  1684. LocationShortXY = 0x00040000,
  1685. LocationByteXY = 0x00080000,
  1686. ImplFlags = 0x00100000,
  1687. InsuredFor = 0x00200000,
  1688. BlessedFor = 0x00400000,
  1689. HeldBy = 0x00800000,
  1690. IntWeight = 0x01000000,
  1691. SavedFlags = 0x02000000,
  1692. NullWeight = 0x04000000
  1693. }
  1694. private static void SetSaveFlag( ref SaveFlag flags, SaveFlag toSet, bool setIf )
  1695. {
  1696. if ( setIf )
  1697. flags |= toSet;
  1698. }
  1699. private static bool GetSaveFlag( SaveFlag flags, SaveFlag toGet )
  1700. {
  1701. return ( (flags & toGet) != 0 );
  1702. }
  1703. int ISerializable.TypeReference {
  1704. get { return m_TypeRef; }
  1705. }
  1706. int ISerializable.SerialIdentity {
  1707. get { return m_Serial; }
  1708. }
  1709. public virtual void Serialize( GenericWriter writer )
  1710. {
  1711. writer.Write( 9 ); // version
  1712. writer.Write(m_ShouldAssignProperties);
  1713. writer.Write(m_PropertiesAssigned);
  1714. SaveFlag flags = SaveFlag.None;
  1715. int x = m_Location.m_X, y = m_Location.m_Y, z = m_Location.m_Z;
  1716. if ( x != 0 || y != 0 || z != 0 )
  1717. {
  1718. if ( x >= short.MinValue && x <= short.MaxValue && y >= short.MinValue && y <= short.MaxValue && z >= sbyte.MinValue && z <= sbyte.MaxValue )
  1719. {
  1720. if ( x != 0 || y != 0 )
  1721. {
  1722. if ( x >= byte.MinValue && x <= byte.MaxValue && y >= byte.MinValue && y <= byte.MaxValue )
  1723. flags |= SaveFlag.LocationByteXY;
  1724. else
  1725. flags |= SaveFlag.LocationShortXY;
  1726. }
  1727. if ( z != 0 )
  1728. flags |= SaveFlag.LocationSByteZ;
  1729. }
  1730. else
  1731. {
  1732. flags |= SaveFlag.LocationFull;
  1733. }
  1734. }
  1735. CompactInfo info = LookupCompactInfo();
  1736. List<Item> items = LookupItems();
  1737. if ( m_Direction != Direction.North )
  1738. flags |= SaveFlag.Direction;
  1739. if ( info != null && info.m_Bounce != null )
  1740. flags |= SaveFlag.Bounce;
  1741. if ( m_LootType != LootType.Regular )
  1742. flags |= SaveFlag.LootType;
  1743. if ( m_ItemID != 0 )
  1744. flags |= SaveFlag.ItemID;
  1745. if ( m_Hue != 0 )
  1746. flags |= SaveFlag.Hue;
  1747. if ( m_Amount != 1 )
  1748. flags |= SaveFlag.Amount;
  1749. if ( m_Layer != Layer.Invalid )
  1750. flags |= SaveFlag.Layer;
  1751. if ( info != null && info.m_Name != null )
  1752. flags |= SaveFlag.Name;
  1753. if ( m_Parent != null )
  1754. flags |= SaveFlag.Parent;
  1755. if ( items != null && items.Count > 0 )
  1756. flags |= SaveFlag.Items;
  1757. if ( m_Map != Map.Internal )
  1758. flags |= SaveFlag.Map;
  1759. //if ( m_InsuredFor != null && !m_InsuredFor.Deleted )
  1760. //flags |= SaveFlag.InsuredFor;
  1761. if ( info != null && info.m_BlessedFor != null && !info.m_BlessedFor.Deleted )
  1762. flags |= SaveFlag.BlessedFor;
  1763. if ( info != null && info.m_HeldBy != null && !info.m_HeldBy.Deleted )
  1764. flags |= SaveFlag.HeldBy;
  1765. if ( info != null && info.m_SavedFlags != 0 )
  1766. flags |= SaveFlag.SavedFlags;
  1767. if ( info == null || info.m_Weight == -1 )
  1768. {
  1769. flags |= SaveFlag.NullWeight;
  1770. }
  1771. else
  1772. {
  1773. if ( info.m_Weight == 0.0 )
  1774. {
  1775. flags |= SaveFlag.WeightIs0;
  1776. }
  1777. else if ( info.m_Weight != 1.0 )
  1778. {
  1779. if ( info.m_Weight == (int) info.m_Weight )
  1780. flags |= SaveFlag.IntWeight;
  1781. else
  1782. flags |= SaveFlag.WeightNot1or0;
  1783. }
  1784. }
  1785. ImplFlag implFlags = ( m_Flags & ( ImplFlag.Visible | ImplFlag.Movable | ImplFlag.Stackable | ImplFlag.Insured | ImplFlag.PayedInsurance | ImplFlag.QuestItem ) );
  1786. if ( implFlags != ( ImplFlag.Visible | ImplFlag.Movable ) )
  1787. flags |= SaveFlag.ImplFlags;
  1788. writer.Write( (int) flags );
  1789. /* begin last moved time optimization */
  1790. long ticks = m_LastMovedTime.Ticks;
  1791. long now = DateTime.Now.Ticks;
  1792. TimeSpan d;
  1793. try { d = new TimeSpan( ticks - now ); }
  1794. catch { if ( ticks < now ) d = TimeSpan.MaxValue; else d = TimeSpan.MaxValue; }
  1795. double minutes = -d.TotalMinutes;
  1796. if ( minutes < int.MinValue )
  1797. minutes = int.MinValue;
  1798. else if ( minutes > int.MaxValue )
  1799. minutes = int.MaxValue;
  1800. writer.WriteEncodedInt( (int) minutes );
  1801. /* end */
  1802. if ( GetSaveFlag( flags, SaveFlag.Direction ) )
  1803. writer.Write( (byte) m_Direction );
  1804. if ( GetSaveFlag( flags, SaveFlag.Bounce ) )
  1805. BounceInfo.Serialize( info.m_Bounce, writer );
  1806. if ( GetSaveFlag( flags, SaveFlag.LootType ) )
  1807. writer.Write( (byte) m_LootType );
  1808. if ( GetSaveFlag( flags, SaveFlag.LocationFull ) )
  1809. {
  1810. writer.WriteEncodedInt( x );
  1811. writer.WriteEncodedInt( y );
  1812. writer.WriteEncodedInt( z );
  1813. }
  1814. else
  1815. {
  1816. if ( GetSaveFlag( flags, SaveFlag.LocationByteXY ) )
  1817. {
  1818. writer.Write( (byte) x );
  1819. writer.Write( (byte) y );
  1820. }
  1821. else if ( GetSaveFlag( flags, SaveFlag.LocationShortXY ) )
  1822. {
  1823. writer.Write( (short) x );
  1824. writer.Write( (short) y );
  1825. }
  1826. if ( GetSaveFlag( flags, SaveFlag.LocationSByteZ ) )
  1827. writer.Write( (sbyte) z );
  1828. }
  1829. if ( GetSaveFlag( flags, SaveFlag.ItemID ) )
  1830. writer.WriteEncodedInt( (int) m_ItemID );
  1831. if ( GetSaveFlag( flags, SaveFlag.Hue ) )
  1832. writer.WriteEncodedInt( (int) m_Hue );
  1833. if ( GetSaveFlag( flags, SaveFlag.Amount ) )
  1834. writer.WriteEncodedInt( (int) m_Amount );
  1835. if ( GetSaveFlag( flags, SaveFlag.Layer ) )
  1836. writer.Write( (byte) m_Layer );
  1837. if ( GetSaveFlag( flags, SaveFlag.Name ) )
  1838. writer.Write( (string) info.m_Name );
  1839. if ( GetSaveFlag( flags, SaveFlag.Parent ) )
  1840. {
  1841. if ( m_Parent is Mobile && !( (Mobile) m_Parent ).Deleted )
  1842. writer.Write( ( (Mobile) m_Parent ).Serial );
  1843. else if ( m_Parent is Item && !( (Item) m_Parent ).Deleted )
  1844. writer.Write( ( (Item) m_Parent ).Serial );
  1845. else
  1846. writer.Write( (int) Serial.MinusOne );
  1847. }
  1848. if ( GetSaveFlag( flags, SaveFlag.Items ) )
  1849. writer.Write( items, false );
  1850. if ( GetSaveFlag( flags, SaveFlag.IntWeight ) )
  1851. writer.WriteEncodedInt( (int) info.m_Weight );
  1852. else if ( GetSaveFlag( flags, SaveFlag.WeightNot1or0 ) )
  1853. writer.Write( (double) info.m_Weight );
  1854. if ( GetSaveFlag( flags, SaveFlag.Map ) )
  1855. writer.Write( (Map) m_Map );
  1856. if ( GetSaveFlag( flags, SaveFlag.ImplFlags ) )
  1857. writer.WriteEncodedInt( (int) implFlags );
  1858. if ( GetSaveFlag( flags, SaveFlag.InsuredFor ) )
  1859. writer.Write( (Mobile) null );
  1860. if ( GetSaveFlag( flags, SaveFlag.BlessedFor ) )
  1861. writer.Write( info.m_BlessedFor );
  1862. if ( GetSaveFlag( flags, SaveFlag.HeldBy ) )
  1863. writer.Write( info.m_HeldBy );
  1864. if ( GetSaveFlag( flags, SaveFlag.SavedFlags ) )
  1865. writer.WriteEncodedInt( info.m_SavedFlags );
  1866. }
  1867. public IPooledEnumerable GetObjectsInRange( int range )
  1868. {
  1869. Map map = m_Map;
  1870. if ( map == null )
  1871. return Server.Map.NullEnumerable.Instance;
  1872. if ( m_Parent == null )
  1873. return map.GetObjectsInRange( m_Location, range );
  1874. return map.GetObjectsInRange( GetWorldLocation(), range );
  1875. }
  1876. public IPooledEnumerable GetItemsInRange( int range )
  1877. {
  1878. Map map = m_Map;
  1879. if ( map == null )
  1880. return Server.Map.NullEnumerable.Instance;
  1881. if ( m_Parent == null )
  1882. return map.GetItemsInRange( m_Location, range );
  1883. return map.GetItemsInRange( GetWorldLocation(), range );
  1884. }
  1885. public IPooledEnumerable GetMobilesInRange( int range )
  1886. {
  1887. Map map = m_Map;
  1888. if ( map == null )
  1889. return Server.Map.NullEnumerable.Instance;
  1890. if ( m_Parent == null )
  1891. return map.GetMobilesInRange( m_Location, range );
  1892. return map.GetMobilesInRange( GetWorldLocation(), range );
  1893. }
  1894. public IPooledEnumerable GetClientsInRange( int range )
  1895. {
  1896. Map map = m_Map;
  1897. if ( map == null )
  1898. return Server.Map.NullEnumerable.Instance;
  1899. if ( m_Parent == null )
  1900. return map.GetClientsInRange( m_Location, range );
  1901. return map.GetClientsInRange( GetWorldLocation(), range );
  1902. }
  1903. private static int m_LockedDownFlag;
  1904. private static int m_SecureFlag;
  1905. public static int LockedDownFlag
  1906. {
  1907. get{ return m_LockedDownFlag; }
  1908. set{ m_LockedDownFlag = value; }
  1909. }
  1910. public static int SecureFlag
  1911. {
  1912. get{ return m_SecureFlag; }
  1913. set{ m_SecureFlag = value; }
  1914. }
  1915. public bool IsLockedDown
  1916. {
  1917. get{ return GetTempFlag( m_LockedDownFlag ); }
  1918. set{ SetTempFlag( m_LockedDownFlag, value ); InvalidateProperties(); }
  1919. }
  1920. public bool IsSecure
  1921. {
  1922. get{ return GetTempFlag( m_SecureFlag ); }
  1923. set{ SetTempFlag( m_SecureFlag, value ); InvalidateProperties(); }
  1924. }
  1925. public bool GetTempFlag( int flag )
  1926. {
  1927. CompactInfo info = LookupCompactInfo();
  1928. if ( info == null )
  1929. return false;
  1930. return ( (info.m_TempFlags & flag) != 0 );
  1931. }
  1932. public void SetTempFlag( int flag, bool value )
  1933. {
  1934. CompactInfo info = AcquireCompactInfo();
  1935. if ( value )
  1936. info.m_TempFlags |= flag;
  1937. else
  1938. info.m_TempFlags &= ~flag;
  1939. if ( info.m_TempFlags == 0 )
  1940. VerifyCompactInfo();
  1941. }
  1942. public bool GetSavedFlag( int flag )
  1943. {
  1944. CompactInfo info = LookupCompactInfo();
  1945. if ( info == null )
  1946. return false;
  1947. return ( ( info.m_SavedFlags & flag ) != 0 );
  1948. }
  1949. public void SetSavedFlag( int flag, bool value )
  1950. {
  1951. CompactInfo info = AcquireCompactInfo();
  1952. if ( value )
  1953. info.m_SavedFlags |= flag;
  1954. else
  1955. info.m_SavedFlags &= ~flag;
  1956. if ( info.m_SavedFlags == 0 )
  1957. VerifyCompactInfo();
  1958. }
  1959. public virtual void Deserialize( GenericReader reader )
  1960. {
  1961. int version = reader.ReadInt();
  1962. SetLastMoved();
  1963. switch ( version )
  1964. {
  1965. case 9:
  1966. case 8:
  1967. {
  1968. m_ShouldAssignProperties = reader.ReadBool();
  1969. m_PropertiesAssigned = reader.ReadBool();
  1970. goto case 7;
  1971. }
  1972. case 7:
  1973. case 6:
  1974. {
  1975. SaveFlag flags = (SaveFlag)reader.ReadInt();
  1976. if ( version < 7 )
  1977. {
  1978. LastMoved = reader.ReadDeltaTime();
  1979. }
  1980. else
  1981. {
  1982. int minutes = reader.ReadEncodedInt();
  1983. try{ LastMoved = DateTime.Now - TimeSpan.FromMinutes( minutes ); }
  1984. catch{ LastMoved = DateTime.Now; }
  1985. }
  1986. if ( GetSaveFlag( flags, SaveFlag.Direction ) )
  1987. m_Direction = (Direction)reader.ReadByte();
  1988. if ( GetSaveFlag( flags, SaveFlag.Bounce ) )
  1989. AcquireCompactInfo().m_Bounce = BounceInfo.Deserialize( reader );
  1990. if ( GetSaveFlag( flags, SaveFlag.LootType ) )
  1991. m_LootType = (LootType)reader.ReadByte();
  1992. int x = 0, y = 0, z = 0;
  1993. if ( GetSaveFlag( flags, SaveFlag.LocationFull ) )
  1994. {
  1995. x = reader.ReadEncodedInt();
  1996. y = reader.ReadEncodedInt();
  1997. z = reader.ReadEncodedInt();
  1998. }
  1999. else
  2000. {
  2001. if ( GetSaveFlag( flags, SaveFlag.LocationByteXY ) )
  2002. {
  2003. x = reader.ReadByte();
  2004. y = reader.ReadByte();
  2005. }
  2006. else if ( GetSaveFlag( flags, SaveFlag.LocationShortXY ) )
  2007. {
  2008. x = reader.ReadShort();
  2009. y = reader.ReadShort();
  2010. }
  2011. if ( GetSaveFlag( flags, SaveFlag.LocationSByteZ ) )
  2012. z = reader.ReadSByte();
  2013. }
  2014. m_Location = new Point3D( x, y, z );
  2015. if ( GetSaveFlag( flags, SaveFlag.ItemID ) )
  2016. m_ItemID = reader.ReadEncodedInt();
  2017. if ( GetSaveFlag( flags, SaveFlag.Hue ) )
  2018. m_Hue = reader.ReadEncodedInt();
  2019. if ( GetSaveFlag( flags, SaveFlag.Amount ) )
  2020. m_Amount = reader.ReadEncodedInt();
  2021. else
  2022. m_Amount = 1;
  2023. if ( GetSaveFlag( flags, SaveFlag.Layer ) )
  2024. m_Layer = (Layer)reader.ReadByte();
  2025. if ( GetSaveFlag( flags, SaveFlag.Name ) )
  2026. {
  2027. string name = reader.ReadString();
  2028. if ( name != this.DefaultName )
  2029. AcquireCompactInfo().m_Name = name;
  2030. }
  2031. if ( GetSaveFlag( flags, SaveFlag.Parent ) )
  2032. {
  2033. Serial parent = reader.ReadInt();
  2034. if ( parent.IsMobile )
  2035. m_Parent = World.FindMobile( parent );
  2036. else if ( parent.IsItem )
  2037. m_Parent = World.FindItem( parent );
  2038. else
  2039. m_Parent = null;
  2040. if ( m_Parent == null && (parent.IsMobile || parent.IsItem) )
  2041. Delete();
  2042. }
  2043. if ( GetSaveFlag( flags, SaveFlag.Items ) )
  2044. {
  2045. List<Item> items = reader.ReadStrongItemList();
  2046. if ( this is Container )
  2047. ( this as Container ).m_Items = items;
  2048. else
  2049. AcquireCompactInfo().m_Items = items;
  2050. }
  2051. if ( version < 8 || !GetSaveFlag( flags, SaveFlag.NullWeight ) )
  2052. {
  2053. double weight;
  2054. if ( GetSaveFlag( flags, SaveFlag.IntWeight ) )
  2055. weight = reader.ReadEncodedInt();
  2056. else if ( GetSaveFlag( flags, SaveFlag.WeightNot1or0 ) )
  2057. weight = reader.ReadDouble();
  2058. else if ( GetSaveFlag( flags, SaveFlag.WeightIs0 ) )
  2059. weight = 0.0;
  2060. else
  2061. weight = 1.0;
  2062. if ( weight != DefaultWeight )
  2063. AcquireCompactInfo().m_Weight = weight;
  2064. }
  2065. if ( GetSaveFlag( flags, SaveFlag.Map ) )
  2066. m_Map = reader.ReadMap();
  2067. else
  2068. m_Map = Map.Internal;
  2069. if ( GetSaveFlag( flags, SaveFlag.Visible ) )
  2070. SetFlag( ImplFlag.Visible, reader.ReadBool() );
  2071. else
  2072. SetFlag( ImplFlag.Visible, true );
  2073. if ( GetSaveFlag( flags, SaveFlag.Movable ) )
  2074. SetFlag( ImplFlag.Movable, reader.ReadBool() );
  2075. else
  2076. SetFlag( ImplFlag.Movable, true );
  2077. if ( GetSaveFlag( flags, SaveFlag.Stackable ) )
  2078. SetFlag( ImplFlag.Stackable, reader.ReadBool() );
  2079. if ( GetSaveFlag( flags, SaveFlag.ImplFlags ) )
  2080. m_Flags = (ImplFlag)reader.ReadEncodedInt();
  2081. if ( GetSaveFlag( flags, SaveFlag.InsuredFor ) )
  2082. /*m_InsuredFor = */reader.ReadMobile();
  2083. if ( GetSaveFlag( flags, SaveFlag.BlessedFor ) )
  2084. AcquireCompactInfo().m_BlessedFor = reader.ReadMobile();
  2085. if ( GetSaveFlag( flags, SaveFlag.HeldBy ) )
  2086. AcquireCompactInfo().m_HeldBy = reader.ReadMobile();
  2087. if ( GetSaveFlag( flags, SaveFlag.SavedFlags ) )
  2088. AcquireCompactInfo().m_SavedFlags = reader.ReadEncodedInt();
  2089. if ( m_Map != null && m_Parent == null )
  2090. m_Map.OnEnter( this );
  2091. break;
  2092. }
  2093. case 5:
  2094. {
  2095. SaveFlag flags = (SaveFlag)reader.ReadInt();
  2096. LastMoved = reader.ReadDeltaTime();
  2097. if ( GetSaveFlag( flags, SaveFlag.Direction ) )
  2098. m_Direction = (Direction)reader.ReadByte();
  2099. if ( GetSaveFlag( flags, SaveFlag.Bounce ) )
  2100. AcquireCompactInfo().m_Bounce = BounceInfo.Deserialize( reader );
  2101. if ( GetSaveFlag( flags, SaveFlag.LootType ) )
  2102. m_LootType = (LootType)reader.ReadByte();
  2103. if ( GetSaveFlag( flags, SaveFlag.LocationFull ) )
  2104. m_Location = reader.ReadPoint3D();
  2105. if ( GetSaveFlag( flags, SaveFlag.ItemID ) )
  2106. m_ItemID = reader.ReadInt();
  2107. if ( GetSaveFlag( flags, SaveFlag.Hue ) )
  2108. m_Hue = reader.ReadInt();
  2109. if ( GetSaveFlag( flags, SaveFlag.Amount ) )
  2110. m_Amount = reader.ReadInt();
  2111. else
  2112. m_Amount = 1;
  2113. if ( GetSaveFlag( flags, SaveFlag.Layer ) )
  2114. m_Layer = (Layer)reader.ReadByte();
  2115. if ( GetSaveFlag( flags, SaveFlag.Name ) )
  2116. {
  2117. string name = reader.ReadString();
  2118. if ( name != this.DefaultName )
  2119. AcquireCompactInfo().m_Name = name;
  2120. }
  2121. if ( GetSaveFlag( flags, SaveFlag.Parent ) )
  2122. {
  2123. Serial parent = reader.ReadInt();
  2124. if ( parent.IsMobile )
  2125. m_Parent = World.FindMobile( parent );
  2126. else if ( parent.IsItem )
  2127. m_Parent = World.FindItem( parent );
  2128. else
  2129. m_Parent = null;
  2130. if ( m_Parent == null && (parent.IsMobile || parent.IsItem) )
  2131. Delete();
  2132. }
  2133. if ( GetSaveFlag( flags, SaveFlag.Items ) )
  2134. {
  2135. List<Item> items = reader.ReadStrongItemList();
  2136. if ( this is Container )
  2137. ( this as Container ).m_Items = items;
  2138. else
  2139. AcquireCompactInfo().m_Items = items;
  2140. }
  2141. double weight;
  2142. if ( GetSaveFlag( flags, SaveFlag.IntWeight ) )
  2143. weight = reader.ReadEncodedInt();
  2144. else if ( GetSaveFlag( flags, SaveFlag.WeightNot1or0 ) )
  2145. weight = reader.ReadDouble();
  2146. else if ( GetSaveFlag( flags, SaveFlag.WeightIs0 ) )
  2147. weight = 0.0;
  2148. else
  2149. weight = 1.0;
  2150. if ( weight != DefaultWeight )
  2151. AcquireCompactInfo().m_Weight = weight;
  2152. if ( GetSaveFlag( flags, SaveFlag.Map ) )
  2153. m_Map = reader.ReadMap();
  2154. else
  2155. m_Map = Map.Internal;
  2156. if ( GetSaveFlag( flags, SaveFlag.Visible ) )
  2157. SetFlag( ImplFlag.Visible, reader.ReadBool() );
  2158. else
  2159. SetFlag( ImplFlag.Visible, true );
  2160. if ( GetSaveFlag( flags, SaveFlag.Movable ) )
  2161. SetFlag( ImplFlag.Movable, reader.ReadBool() );
  2162. else
  2163. SetFlag( ImplFlag.Movable, true );
  2164. if ( GetSaveFlag( flags, SaveFlag.Stackable ) )
  2165. SetFlag( ImplFlag.Stackable, reader.ReadBool() );
  2166. if ( m_Map != null && m_Parent == null )
  2167. m_Map.OnEnter( this );
  2168. break;
  2169. }
  2170. case 4: // Just removed variables
  2171. case 3:
  2172. {
  2173. m_Direction = (Direction)reader.ReadInt();
  2174. goto case 2;
  2175. }
  2176. case 2:
  2177. {
  2178. AcquireCompactInfo().m_Bounce = BounceInfo.Deserialize( reader );
  2179. LastMoved = reader.ReadDeltaTime();
  2180. goto case 1;
  2181. }
  2182. case 1:
  2183. {
  2184. m_LootType = (LootType) reader.ReadByte();//m_Newbied = reader.ReadBool();
  2185. goto case 0;
  2186. }
  2187. case 0:
  2188. {
  2189. m_Location = reader.ReadPoint3D();
  2190. m_ItemID = reader.ReadInt();
  2191. m_Hue = reader.ReadInt();
  2192. m_Amount = reader.ReadInt();
  2193. m_Layer = (Layer) reader.ReadByte();
  2194. string name = reader.ReadString();
  2195. if ( name != this.DefaultName )
  2196. AcquireCompactInfo().m_Name = name;
  2197. Serial parent = reader.ReadInt();
  2198. if ( parent.IsMobile )
  2199. m_Parent = World.FindMobile( parent );
  2200. else if ( parent.IsItem )
  2201. m_Parent = World.FindItem( parent );
  2202. else
  2203. m_Parent = null;
  2204. if ( m_Parent == null && (parent.IsMobile || parent.IsItem) )
  2205. Delete();
  2206. int count = reader.ReadInt();
  2207. if ( count > 0 )
  2208. {
  2209. List<Item> items = new List<Item>( count );
  2210. for ( int i = 0; i < count; ++i )
  2211. {
  2212. Item item = reader.ReadItem();
  2213. if ( item != null )
  2214. items.Add( item );
  2215. }
  2216. if ( this is Container )
  2217. ( this as Container ).m_Items = items;
  2218. else
  2219. AcquireCompactInfo().m_Items = items;
  2220. }
  2221. double weight = reader.ReadDouble();
  2222. if ( weight != DefaultWeight )
  2223. AcquireCompactInfo().m_Weight = weight;
  2224. if ( version <= 3 )
  2225. {
  2226. reader.ReadInt();
  2227. reader.ReadInt();
  2228. reader.ReadInt();
  2229. }
  2230. m_Map = reader.ReadMap();
  2231. SetFlag( ImplFlag.Visible, reader.ReadBool() );
  2232. SetFlag( ImplFlag.Movable, reader.ReadBool() );
  2233. if ( version <= 3 )
  2234. /*m_Deleted =*/ reader.ReadBool();
  2235. Stackable = reader.ReadBool();
  2236. if ( m_Map != null && m_Parent == null )
  2237. m_Map.OnEnter( this );
  2238. break;
  2239. }
  2240. }
  2241. if ( this.HeldBy != null )
  2242. Timer.DelayCall( TimeSpan.Zero, new TimerCallback( FixHolding_Sandbox ) );
  2243. //if ( version < 9 )
  2244. VerifyCompactInfo();
  2245. }
  2246. private void FixHolding_Sandbox()
  2247. {
  2248. Mobile heldBy = this.HeldBy;
  2249. if ( heldBy != null )
  2250. {
  2251. if ( this.GetBounce() != null )
  2252. {
  2253. Bounce( heldBy );
  2254. }
  2255. else
  2256. {
  2257. heldBy.Holding = null;
  2258. heldBy.AddToBackpack( this );
  2259. ClearBounce();
  2260. }
  2261. }
  2262. }
  2263. public virtual int GetMaxUpdateRange()
  2264. {
  2265. return 18;
  2266. }
  2267. public virtual int GetUpdateRange( Mobile m )
  2268. {
  2269. return 18;
  2270. }
  2271. public void SendInfoTo( NetState state ) {
  2272. SendInfoTo( state, ObjectPropertyList.Enabled );
  2273. }
  2274. public virtual void SendInfoTo( NetState state, bool sendOplPacket ) {
  2275. state.Send( GetWorldPacketFor( state ) );
  2276. if ( sendOplPacket ) {
  2277. state.Send( OPLPacket );
  2278. }
  2279. }
  2280. protected virtual Packet GetWorldPacketFor( NetState state ) {
  2281. if ( state.HighSeas )
  2282. return this.WorldPacketHS;
  2283. else if ( state.StygianAbyss )
  2284. return this.WorldPacketSA;
  2285. else
  2286. return this.WorldPacket;
  2287. }
  2288. public virtual bool IsVirtualItem{ get{ return false; } }
  2289. public virtual int GetTotal( TotalType type )
  2290. {
  2291. return 0;
  2292. }
  2293. public virtual void UpdateTotal( Item sender, TotalType type, int delta )
  2294. {
  2295. if ( !IsVirtualItem )
  2296. {
  2297. if ( m_Parent is Item )
  2298. ( m_Parent as Item ).UpdateTotal( sender, type, delta );
  2299. else if ( m_Parent is Mobile )
  2300. ( m_Parent as Mobile ).UpdateTotal( sender, type, delta );
  2301. else if ( this.HeldBy != null )
  2302. ( this.HeldBy as Mobile ).UpdateTotal( sender, type, delta );
  2303. }
  2304. }
  2305. public virtual void UpdateTotals()
  2306. {
  2307. }
  2308. public virtual int LabelNumber
  2309. {
  2310. get
  2311. {
  2312. if ( m_ItemID < 0x4000 )
  2313. return 1020000 + m_ItemID;
  2314. else
  2315. return 1078872 + m_ItemID;
  2316. }
  2317. }
  2318. [CommandProperty( AccessLevel.GameMaster )]
  2319. public int TotalGold
  2320. {
  2321. get { return GetTotal( TotalType.Gold ); }
  2322. }
  2323. [CommandProperty( AccessLevel.GameMaster )]
  2324. public int TotalItems
  2325. {
  2326. get { return GetTotal( TotalType.Items ); }
  2327. }
  2328. [CommandProperty( AccessLevel.GameMaster )]
  2329. public int TotalWeight
  2330. {
  2331. get { return GetTotal( TotalType.Weight ); }
  2332. }
  2333. public virtual double DefaultWeight
  2334. {
  2335. get
  2336. {
  2337. if ( m_ItemID < 0 || m_ItemID > TileData.MaxItemValue || this is BaseMulti )
  2338. return 0;
  2339. int weight = TileData.ItemTable[m_ItemID].Weight;
  2340. if ( weight == 255 || weight == 0 )
  2341. weight = 1;
  2342. return weight;
  2343. }
  2344. }
  2345. [CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
  2346. public double Weight
  2347. {
  2348. get
  2349. {
  2350. CompactInfo info = LookupCompactInfo();
  2351. if ( info != null && info.m_Weight != -1 )
  2352. return info.m_Weight;
  2353. return this.DefaultWeight;
  2354. }
  2355. set
  2356. {
  2357. if ( this.Weight != value )
  2358. {
  2359. CompactInfo info = AcquireCompactInfo();
  2360. int oldPileWeight = this.PileWeight;
  2361. info.m_Weight = value;
  2362. if ( info.m_Weight == -1 )
  2363. VerifyCompactInfo();
  2364. int newPileWeight = this.PileWeight;
  2365. UpdateTotal( this, TotalType.Weight, newPileWeight - oldPileWeight );
  2366. InvalidateProperties();
  2367. }
  2368. }
  2369. }
  2370. [CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
  2371. public int PileWeight
  2372. {
  2373. get
  2374. {
  2375. return (int)Math.Ceiling( this.Weight * this.Amount );
  2376. }
  2377. }
  2378. public virtual int HuedItemID
  2379. {
  2380. get
  2381. {
  2382. return m_ItemID;
  2383. }
  2384. }
  2385. [Hue, CommandProperty( AccessLevel.GameMaster )]
  2386. public virtual int Hue
  2387. {
  2388. get
  2389. {
  2390. return (QuestItem ? QuestItemHue : m_Hue);
  2391. }
  2392. set
  2393. {
  2394. if ( m_Hue != value )
  2395. {
  2396. m_Hue = value;
  2397. ReleaseWorldPackets();
  2398. Delta( ItemDelta.Update );
  2399. }
  2400. }
  2401. }
  2402. public virtual int QuestItemHue
  2403. {
  2404. get { return 0x04EA; } //HMMMM... For EA?
  2405. }
  2406. public virtual bool Nontransferable
  2407. {
  2408. get { return QuestItem; }
  2409. }
  2410. public virtual void HandleInvalidTransfer( Mobile from )
  2411. {
  2412. if( QuestItem )
  2413. from.SendLocalizedMessage( 1074769 ); // An item must be in your backpack (and not in a container within) to be toggled as a quest item.
  2414. }
  2415. [CommandProperty( AccessLevel.GameMaster )]
  2416. public virtual Layer Layer
  2417. {
  2418. get
  2419. {
  2420. return m_Layer;
  2421. }
  2422. set
  2423. {
  2424. if ( m_Layer != value )
  2425. {
  2426. m_Layer = value;
  2427. Delta( ItemDelta.EquipOnly );
  2428. }
  2429. }
  2430. }
  2431. public List<Item> Items
  2432. {
  2433. get
  2434. {
  2435. List<Item> items = LookupItems();
  2436. if( items == null )
  2437. items = EmptyItems;
  2438. return items;
  2439. }
  2440. }
  2441. public object RootParent
  2442. {
  2443. get
  2444. {
  2445. object p = m_Parent;
  2446. while ( p is Item )
  2447. {
  2448. Item item = (Item)p;
  2449. if ( item.m_Parent == null )
  2450. {
  2451. break;
  2452. }
  2453. else
  2454. {
  2455. p = item.m_Parent;
  2456. }
  2457. }
  2458. return p;
  2459. }
  2460. }
  2461. public bool ParentsContain<T>() where T : Item
  2462. {
  2463. object p = m_Parent;
  2464. while( p is Item )
  2465. {
  2466. if( p is T )
  2467. return true;
  2468. Item item = (Item)p;
  2469. if( item.m_Parent == null )
  2470. {
  2471. break;
  2472. }
  2473. else
  2474. {
  2475. p = item.m_Parent;
  2476. }
  2477. }
  2478. return false;
  2479. }
  2480. public virtual void AddItem( Item item )
  2481. {
  2482. if ( item == null || item.Deleted || item.m_Parent == this )
  2483. {
  2484. return;
  2485. }
  2486. else if ( item == this )
  2487. {
  2488. Console.WriteLine( "Warning: Adding item to itself: [0x{0:X} {1}].AddItem( [0x{2:X} {3}] )", this.Serial.Value, this.GetType().Name, item.Serial.Value, item.GetType().Name );
  2489. Console.WriteLine( new System.Diagnostics.StackTrace() );
  2490. return;
  2491. }
  2492. else if ( IsChildOf( item ) )
  2493. {
  2494. Console.WriteLine( "Warning: Adding parent item to child: [0x{0:X} {1}].AddItem( [0x{2:X} {3}] )", this.Serial.Value, this.GetType().Name, item.Serial.Value, item.GetType().Name );
  2495. Console.WriteLine( new System.Diagnostics.StackTrace() );
  2496. return;
  2497. }
  2498. else if ( item.m_Parent is Mobile )
  2499. {
  2500. ((Mobile)item.m_Parent).RemoveItem( item );
  2501. }
  2502. else if ( item.m_Parent is Item )
  2503. {
  2504. ((Item)item.m_Parent).RemoveItem( item );
  2505. }
  2506. else
  2507. {
  2508. item.SendRemovePacket();
  2509. }
  2510. item.Parent = this;
  2511. item.Map = m_Map;
  2512. List<Item> items = AcquireItems();
  2513. items.Add( item );
  2514. if ( !item.IsVirtualItem )
  2515. {
  2516. UpdateTotal( item, TotalType.Gold, item.TotalGold );
  2517. UpdateTotal( item, TotalType.Items, item.TotalItems + 1 );
  2518. UpdateTotal( item, TotalType.Weight, item.TotalWeight + item.PileWeight );
  2519. }
  2520. item.Delta( ItemDelta.Update );
  2521. item.OnAdded( this );
  2522. OnItemAdded( item );
  2523. }
  2524. private static List<Item> m_DeltaQueue = new List<Item>();
  2525. public void Delta( ItemDelta flags )
  2526. {
  2527. if ( m_Map == null || m_Map == Map.Internal )
  2528. return;
  2529. m_DeltaFlags |= flags;
  2530. if ( !GetFlag( ImplFlag.InQueue ) )
  2531. {
  2532. SetFlag( ImplFlag.InQueue, true );
  2533. m_DeltaQueue.Add( this );
  2534. }
  2535. Core.Set();
  2536. }
  2537. public void RemDelta( ItemDelta flags )
  2538. {
  2539. m_DeltaFlags &= ~flags;
  2540. if ( GetFlag( ImplFlag.InQueue ) && m_DeltaFlags == ItemDelta.None )
  2541. {
  2542. SetFlag( ImplFlag.InQueue, false );
  2543. m_DeltaQueue.Remove( this );
  2544. }
  2545. }
  2546. public void ProcessDelta()
  2547. {
  2548. ItemDelta flags = m_DeltaFlags;
  2549. SetFlag( ImplFlag.InQueue, false );
  2550. m_DeltaFlags = ItemDelta.None;
  2551. Map map = m_Map;
  2552. if ( map != null && !Deleted )
  2553. {
  2554. bool sendOPLUpdate = ObjectPropertyList.Enabled && (flags & ItemDelta.Properties) != 0;
  2555. Container contParent = m_Parent as Container;
  2556. if ( contParent != null && !contParent.IsPublicContainer )
  2557. {
  2558. if ( (flags & ItemDelta.Update) != 0 )
  2559. {
  2560. Point3D worldLoc = GetWorldLocation();
  2561. Mobile rootParent = contParent.RootParent as Mobile;
  2562. Mobile tradeRecip = null;
  2563. if ( rootParent != null )
  2564. {
  2565. NetState ns = rootParent.NetState;
  2566. if ( ns != null )
  2567. {
  2568. if ( rootParent.CanSee( this ) && rootParent.InRange( worldLoc, GetUpdateRange( rootParent ) ) )
  2569. {
  2570. if ( ns.ContainerGridLines )
  2571. ns.Send( new ContainerContentUpdate6017( this ) );
  2572. else
  2573. ns.Send( new ContainerContentUpdate( this ) );
  2574. if ( ObjectPropertyList.Enabled )
  2575. ns.Send( OPLPacket );
  2576. }
  2577. }
  2578. }
  2579. SecureTradeContainer stc = this.GetSecureTradeCont();
  2580. if ( stc != null )
  2581. {
  2582. SecureTrade st = stc.Trade;
  2583. if ( st != null )
  2584. {
  2585. Mobile test = st.From.Mobile;
  2586. if ( test != null && test != rootParent )
  2587. tradeRecip = test;
  2588. test = st.To.Mobile;
  2589. if ( test != null && test != rootParent )
  2590. tradeRecip = test;
  2591. if ( tradeRecip != null )
  2592. {
  2593. NetState ns = tradeRecip.NetState;
  2594. if ( ns != null )
  2595. {
  2596. if ( tradeRecip.CanSee( this ) && tradeRecip.InRange( worldLoc, GetUpdateRange( tradeRecip ) ) )
  2597. {
  2598. if ( ns.ContainerGridLines )
  2599. ns.Send( new ContainerContentUpdate6017( this ) );
  2600. else
  2601. ns.Send( new ContainerContentUpdate( this ) );
  2602. if ( ObjectPropertyList.Enabled )
  2603. ns.Send( OPLPacket );
  2604. }
  2605. }
  2606. }
  2607. }
  2608. }
  2609. List<Mobile> openers = contParent.Openers;
  2610. if ( openers != null )
  2611. {
  2612. for ( int i = 0; i < openers.Count; ++i )
  2613. {
  2614. Mobile mob = openers[i];
  2615. int range = GetUpdateRange( mob );
  2616. if ( mob.Map != map || !mob.InRange( worldLoc, range ) )
  2617. {
  2618. openers.RemoveAt( i-- );
  2619. }
  2620. else
  2621. {
  2622. if ( mob == rootParent || mob == tradeRecip )
  2623. continue;
  2624. NetState ns = mob.NetState;
  2625. if ( ns != null )
  2626. {
  2627. if ( mob.CanSee( this ) )
  2628. {
  2629. if ( ns.ContainerGridLines )
  2630. ns.Send( new ContainerContentUpdate6017( this ) );
  2631. else
  2632. ns.Send( new ContainerContentUpdate( this ) );
  2633. if ( ObjectPropertyList.Enabled )
  2634. ns.Send( OPLPacket );
  2635. }
  2636. }
  2637. }
  2638. }
  2639. if ( openers.Count == 0 )
  2640. contParent.Openers = null;
  2641. }
  2642. return;
  2643. }
  2644. }
  2645. if ( (flags & ItemDelta.Update) != 0 )
  2646. {
  2647. Packet p = null;
  2648. Point3D worldLoc = GetWorldLocation();
  2649. IPooledEnumerable eable = map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
  2650. foreach ( NetState state in eable ) {
  2651. Mobile m = state.Mobile;
  2652. if ( m.CanSee( this ) && m.InRange( worldLoc, GetUpdateRange( m ) ) ) {
  2653. if ( m_Parent == null ) {
  2654. SendInfoTo( state, ObjectPropertyList.Enabled );
  2655. } else {
  2656. if ( p == null ) {
  2657. if ( m_Parent is Item ) {
  2658. if ( state.ContainerGridLines )
  2659. state.Send( new ContainerContentUpdate6017( this ) );
  2660. else
  2661. state.Send( new ContainerContentUpdate( this ) );
  2662. } else if ( m_Parent is Mobile ) {
  2663. p = new EquipUpdate( this );
  2664. p.Acquire();
  2665. state.Send( p );
  2666. }
  2667. } else {
  2668. state.Send( p );
  2669. }
  2670. if ( ObjectPropertyList.Enabled ) {
  2671. state.Send( OPLPacket );
  2672. }
  2673. }
  2674. }
  2675. }
  2676. if ( p != null )
  2677. Packet.Release( p );
  2678. eable.Free();
  2679. sendOPLUpdate = false;
  2680. }
  2681. else if ( (flags & ItemDelta.EquipOnly ) != 0 )
  2682. {
  2683. if ( m_Parent is Mobile )
  2684. {
  2685. Packet p = null;
  2686. Point3D worldLoc = GetWorldLocation();
  2687. IPooledEnumerable eable = map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
  2688. foreach ( NetState state in eable )
  2689. {
  2690. Mobile m = state.Mobile;
  2691. if ( m.CanSee( this ) && m.InRange( worldLoc, GetUpdateRange( m ) ) )
  2692. {
  2693. //if ( sendOPLUpdate )
  2694. // state.Send( RemovePacket );
  2695. if ( p == null )
  2696. p = Packet.Acquire( new EquipUpdate( this ) );
  2697. state.Send( p );
  2698. if ( ObjectPropertyList.Enabled )
  2699. state.Send( OPLPacket );
  2700. }
  2701. }
  2702. Packet.Release( p );
  2703. eable.Free();
  2704. sendOPLUpdate = false;
  2705. }
  2706. }
  2707. if ( sendOPLUpdate )
  2708. {
  2709. Point3D worldLoc = GetWorldLocation();
  2710. IPooledEnumerable eable = map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
  2711. foreach ( NetState state in eable )
  2712. {
  2713. Mobile m = state.Mobile;
  2714. if ( m.CanSee( this ) && m.InRange( worldLoc, GetUpdateRange( m ) ) )
  2715. state.Send( OPLPacket );
  2716. }
  2717. eable.Free();
  2718. }
  2719. }
  2720. }
  2721. public static void ProcessDeltaQueue()
  2722. {
  2723. int count = m_DeltaQueue.Count;
  2724. for ( int i = 0; i < m_DeltaQueue.Count; ++i )
  2725. {
  2726. m_DeltaQueue[i].ProcessDelta();
  2727. if ( i >= count )
  2728. break;
  2729. }
  2730. if ( m_DeltaQueue.Count > 0 )
  2731. m_DeltaQueue.Clear();
  2732. }
  2733. public virtual void OnDelete()
  2734. {
  2735. if ( m_Spawner != null )
  2736. {
  2737. m_Spawner.Remove( this );
  2738. m_Spawner = null;
  2739. }
  2740. }
  2741. public virtual void OnParentDeleted( object parent )
  2742. {
  2743. this.Delete();
  2744. }
  2745. public virtual void FreeCache()
  2746. {
  2747. ReleaseWorldPackets();
  2748. Packet.Release( ref m_RemovePacket );
  2749. Packet.Release( ref m_OPLPacket );
  2750. Packet.Release( ref m_PropertyList );
  2751. }
  2752. public virtual void Delete()
  2753. {
  2754. if ( Deleted )
  2755. return;
  2756. else if ( !World.OnDelete( this ) )
  2757. return;
  2758. OnDelete();
  2759. List<Item> items = LookupItems();
  2760. if ( items != null )
  2761. {
  2762. for ( int i = items.Count - 1; i >= 0; --i )
  2763. {
  2764. if ( i < items.Count )
  2765. items[i].OnParentDeleted( this );
  2766. }
  2767. }
  2768. SendRemovePacket();
  2769. SetFlag( ImplFlag.Deleted, true );
  2770. if ( Parent is Mobile )
  2771. ((Mobile)Parent).RemoveItem( this );
  2772. else if ( Parent is Item )
  2773. ((Item)Parent).RemoveItem( this );
  2774. ClearBounce();
  2775. if ( m_Map != null )
  2776. {
  2777. if ( m_Parent == null )
  2778. m_Map.OnLeave( this );
  2779. m_Map = null;
  2780. }
  2781. World.RemoveItem( this );
  2782. OnAfterDelete();
  2783. FreeCache();
  2784. }
  2785. public void PublicOverheadMessage( MessageType type, int hue, bool ascii, string text )
  2786. {
  2787. if ( m_Map != null )
  2788. {
  2789. Packet p = null;
  2790. Point3D worldLoc = GetWorldLocation();
  2791. IPooledEnumerable eable = m_Map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
  2792. foreach ( NetState state in eable )
  2793. {
  2794. Mobile m = state.Mobile;
  2795. if ( m.CanSee( this ) && m.InRange( worldLoc, GetUpdateRange( m ) ) )
  2796. {
  2797. if ( p == null )
  2798. {
  2799. if ( ascii )
  2800. p = new AsciiMessage( m_Serial, m_ItemID, type, hue, 3, this.Name, text );
  2801. else
  2802. p = new UnicodeMessage( m_Serial, m_ItemID, type, hue, 3, "ENU", this.Name, text );
  2803. p.Acquire();
  2804. }
  2805. state.Send( p );
  2806. }
  2807. }
  2808. Packet.Release( p );
  2809. eable.Free();
  2810. }
  2811. }
  2812. public void PublicOverheadMessage( MessageType type, int hue, int number )
  2813. {
  2814. PublicOverheadMessage( type, hue, number, "" );
  2815. }
  2816. public void PublicOverheadMessage( MessageType type, int hue, int number, string args )
  2817. {
  2818. if ( m_Map != null )
  2819. {
  2820. Packet p = null;
  2821. Point3D worldLoc = GetWorldLocation();
  2822. IPooledEnumerable eable = m_Map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
  2823. foreach ( NetState state in eable )
  2824. {
  2825. Mobile m = state.Mobile;
  2826. if ( m.CanSee( this ) && m.InRange( worldLoc, GetUpdateRange( m ) ) )
  2827. {
  2828. if ( p == null )
  2829. p = Packet.Acquire( new MessageLocalized( m_Serial, m_ItemID, type, hue, 3, number, this.Name, args ) );
  2830. state.Send( p );
  2831. }
  2832. }
  2833. Packet.Release( p );
  2834. eable.Free();
  2835. }
  2836. }
  2837. public virtual void OnAfterDelete()
  2838. {
  2839. }
  2840. public virtual void RemoveItem( Item item )
  2841. {
  2842. List<Item> items = LookupItems();
  2843. if ( items != null && items.Contains( item ) )
  2844. {
  2845. item.SendRemovePacket();
  2846. items.Remove( item );
  2847. if ( !item.IsVirtualItem )
  2848. {
  2849. UpdateTotal( item, TotalType.Gold, -item.TotalGold );
  2850. UpdateTotal( item, TotalType.Items, -( item.TotalItems + 1 ) );
  2851. UpdateTotal( item, TotalType.Weight, -( item.TotalWeight + item.PileWeight ) );
  2852. }
  2853. item.Parent = null;
  2854. item.OnRemoved( this );
  2855. OnItemRemoved( item );
  2856. }
  2857. }
  2858. public virtual void OnAfterDuped( Item newItem )
  2859. {
  2860. }
  2861. public virtual bool OnDragLift( Mobile from )
  2862. {
  2863. return true;
  2864. }
  2865. public virtual bool OnEquip( Mobile from )
  2866. {
  2867. return true;
  2868. }
  2869. //TODO: Move to CompactInfo.
  2870. private ISpawner m_Spawner;
  2871. public ISpawner Spawner{ get{ return m_Spawner; } set{ m_Spawner = value; } }
  2872. public virtual void OnBeforeSpawn( Point3D location, Map m )
  2873. {
  2874. }
  2875. public virtual void OnAfterSpawn()
  2876. {
  2877. }
  2878. public virtual int PhysicalResistance{ get{ return 0; } }
  2879. public virtual int FireResistance{ get{ return 0; } }
  2880. public virtual int ColdResistance{ get{ return 0; } }
  2881. public virtual int PoisonResistance{ get{ return 0; } }
  2882. public virtual int EnergyResistance{ get{ return 0; } }
  2883. [CommandProperty( AccessLevel.Counselor )]
  2884. public Serial Serial
  2885. {
  2886. get
  2887. {
  2888. return m_Serial;
  2889. }
  2890. }
  2891. [CommandProperty( AccessLevel.GameMaster )]
  2892. public IEntity ParentEntity
  2893. {
  2894. get
  2895. {
  2896. IEntity p = Parent as IEntity;
  2897. return p;
  2898. }
  2899. }
  2900. [CommandProperty( AccessLevel.GameMaster )]
  2901. public IEntity RootParentEntity
  2902. {
  2903. get
  2904. {
  2905. IEntity p = RootParent as IEntity;
  2906. return p;
  2907. }
  2908. }
  2909. #region Location Location Location!
  2910. public virtual void OnLocationChange( Point3D oldLocation )
  2911. {
  2912. }
  2913. [CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
  2914. public virtual Point3D Location
  2915. {
  2916. get
  2917. {
  2918. return m_Location;
  2919. }
  2920. set
  2921. {
  2922. Point3D oldLocation = m_Location;
  2923. if ( oldLocation != value )
  2924. {
  2925. if ( m_Map != null )
  2926. {
  2927. if ( m_Parent == null )
  2928. {
  2929. IPooledEnumerable eable;
  2930. if ( m_Location.m_X != 0 )
  2931. {
  2932. Packet removeThis = null;
  2933. eable = m_Map.GetClientsInRange( oldLocation, GetMaxUpdateRange() );
  2934. foreach ( NetState state in eable )
  2935. {
  2936. Mobile m = state.Mobile;
  2937. if ( !m.InRange( value, GetUpdateRange( m ) ) )
  2938. {
  2939. if ( removeThis == null )
  2940. removeThis = this.RemovePacket;
  2941. state.Send( removeThis );
  2942. }
  2943. }
  2944. eable.Free();
  2945. }
  2946. m_Location = value;
  2947. ReleaseWorldPackets();
  2948. SetLastMoved();
  2949. eable = m_Map.GetClientsInRange( m_Location, GetMaxUpdateRange() );
  2950. foreach ( NetState state in eable )
  2951. {
  2952. Mobile m = state.Mobile;
  2953. if ( m.CanSee( this ) && m.InRange( m_Location, GetUpdateRange( m ) ) )
  2954. SendInfoTo( state );
  2955. }
  2956. eable.Free();
  2957. RemDelta( ItemDelta.Update );
  2958. }
  2959. else if ( m_Parent is Item )
  2960. {
  2961. m_Location = value;
  2962. ReleaseWorldPackets();
  2963. Delta( ItemDelta.Update );
  2964. }
  2965. else
  2966. {
  2967. m_Location = value;
  2968. ReleaseWorldPackets();
  2969. }
  2970. if ( m_Parent == null )
  2971. m_Map.OnMove( oldLocation, this );
  2972. }
  2973. else
  2974. {
  2975. m_Location = value;
  2976. ReleaseWorldPackets();
  2977. }
  2978. this.OnLocationChange( oldLocation );
  2979. }
  2980. }
  2981. }
  2982. [CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
  2983. public int X
  2984. {
  2985. get{ return m_Location.m_X; }
  2986. set{ Location = new Point3D( value, m_Location.m_Y, m_Location.m_Z ); }
  2987. }
  2988. [CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
  2989. public int Y
  2990. {
  2991. get{ return m_Location.m_Y; }
  2992. set{ Location = new Point3D( m_Location.m_X, value, m_Location.m_Z ); }
  2993. }
  2994. [CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
  2995. public int Z
  2996. {
  2997. get{ return m_Location.m_Z; }
  2998. set{ Location = new Point3D( m_Location.m_X, m_Location.m_Y, value ); }
  2999. }
  3000. #endregion
  3001. [CommandProperty( AccessLevel.GameMaster )]
  3002. public virtual int ItemID
  3003. {
  3004. get
  3005. {
  3006. return m_ItemID;
  3007. }
  3008. set
  3009. {
  3010. if ( m_ItemID != value )
  3011. {
  3012. int oldPileWeight = this.PileWeight;
  3013. m_ItemID = value;
  3014. ReleaseWorldPackets();
  3015. int newPileWeight = this.PileWeight;
  3016. UpdateTotal( this, TotalType.Weight, newPileWeight - oldPileWeight );
  3017. InvalidateProperties();
  3018. Delta( ItemDelta.Update );
  3019. }
  3020. }
  3021. }
  3022. public virtual string DefaultName
  3023. {
  3024. get { return null; }
  3025. }
  3026. [CommandProperty( AccessLevel.GameMaster )]
  3027. public string Name
  3028. {
  3029. get
  3030. {
  3031. CompactInfo info = LookupCompactInfo();
  3032. if ( info != null && info.m_Name != null )
  3033. return info.m_Name;
  3034. return this.DefaultName;
  3035. }
  3036. set
  3037. {
  3038. if ( value == null || value != DefaultName )
  3039. {
  3040. CompactInfo info = AcquireCompactInfo();
  3041. info.m_Name = value;
  3042. if ( info.m_Name == null )
  3043. VerifyCompactInfo();
  3044. InvalidateProperties();
  3045. }
  3046. }
  3047. }
  3048. public virtual object Parent
  3049. {
  3050. get
  3051. {
  3052. return m_Parent;
  3053. }
  3054. set
  3055. {
  3056. if ( m_Parent == value )
  3057. return;
  3058. object oldParent = m_Parent;
  3059. m_Parent = value;
  3060. if ( m_Map != null )
  3061. {
  3062. if ( oldParent != null && m_Parent == null )
  3063. m_Map.OnEnter( this );
  3064. else if ( m_Parent != null )
  3065. m_Map.OnLeave( this );
  3066. }
  3067. }
  3068. }
  3069. [CommandProperty( AccessLevel.GameMaster )]
  3070. public LightType Light
  3071. {
  3072. get
  3073. {
  3074. return (LightType)m_Direction;
  3075. }
  3076. set
  3077. {
  3078. if ( (LightType)m_Direction != value )
  3079. {
  3080. m_Direction = (Direction)value;
  3081. ReleaseWorldPackets();
  3082. Delta( ItemDelta.Update );
  3083. }
  3084. }
  3085. }
  3086. [CommandProperty( AccessLevel.GameMaster )]
  3087. public Direction Direction
  3088. {
  3089. get
  3090. {
  3091. return m_Direction;
  3092. }
  3093. set
  3094. {
  3095. if ( m_Direction != value )
  3096. {
  3097. m_Direction = value;
  3098. ReleaseWorldPackets();
  3099. Delta( ItemDelta.Update );
  3100. }
  3101. }
  3102. }
  3103. [CommandProperty( AccessLevel.GameMaster )]
  3104. public int Amount
  3105. {
  3106. get
  3107. {
  3108. return m_Amount;
  3109. }
  3110. set
  3111. {
  3112. int oldValue = m_Amount;
  3113. if ( oldValue != value )
  3114. {
  3115. int oldPileWeight = this.PileWeight;
  3116. m_Amount = value;
  3117. ReleaseWorldPackets();
  3118. int newPileWeight = this.PileWeight;
  3119. UpdateTotal( this, TotalType.Weight, newPileWeight - oldPileWeight );
  3120. OnAmountChange( oldValue );
  3121. Delta( ItemDelta.Update );
  3122. if ( oldValue > 1 || value > 1 )
  3123. InvalidateProperties();
  3124. if ( !Stackable && m_Amount > 1 )
  3125. Console.WriteLine( "Warning: 0x{0:X}: Amount changed for non-stackable item '{2}'. ({1})", m_Serial.Value, m_Amount, GetType().Name );
  3126. }
  3127. }
  3128. }
  3129. protected virtual void OnAmountChange( int oldValue )
  3130. {
  3131. }
  3132. public virtual bool HandlesOnSpeech{ get{ return false; } }
  3133. public virtual void OnSpeech( SpeechEventArgs e )
  3134. {
  3135. }
  3136. public virtual bool OnDroppedToMobile( Mobile from, Mobile target )
  3137. {
  3138. if( Nontransferable && from.Player && from.AccessLevel <= AccessLevel.GameMaster )
  3139. {
  3140. HandleInvalidTransfer( from );
  3141. return false;
  3142. }
  3143. return true;
  3144. }
  3145. public virtual bool DropToMobile( Mobile from, Mobile target, Point3D p )
  3146. {
  3147. if ( Deleted || from.Deleted || target.Deleted || from.Map != target.Map || from.Map == null || target.Map == null )
  3148. return false;
  3149. else if ( from.AccessLevel < AccessLevel.GameMaster && !from.InRange( target.Location, 2 ) )
  3150. return false;
  3151. else if ( !from.CanSee( target ) || !from.InLOS( target ) )
  3152. return false;
  3153. else if ( !from.OnDroppedItemToMobile( this, target ) )
  3154. return false;
  3155. else if ( !OnDroppedToMobile( from, target ) )
  3156. return false;
  3157. else if (!target.OnDragDrop(from, this))
  3158. return false;
  3159. else
  3160. {
  3161. // Template system hook
  3162. if (NeedAssignProperties())
  3163. {
  3164. m_PropertiesAssigned = true;
  3165. OnAssignProperties();
  3166. }
  3167. return true;
  3168. }
  3169. }
  3170. public virtual bool OnDroppedInto( Mobile from, Container target, Point3D p )
  3171. {
  3172. if( !from.OnDroppedItemInto( this, target, p ) )
  3173. {
  3174. return false;
  3175. }
  3176. else if( Nontransferable && from.Player && target != from.Backpack && from.AccessLevel <= AccessLevel.GameMaster )
  3177. {
  3178. HandleInvalidTransfer( from );
  3179. return false;
  3180. }
  3181. return target.OnDragDropInto( from, this, p );
  3182. }
  3183. public virtual bool OnDroppedOnto( Mobile from, Item target )
  3184. {
  3185. if ( Deleted || from.Deleted || target.Deleted || from.Map != target.Map || from.Map == null || target.Map == null )
  3186. return false;
  3187. else if ( from.AccessLevel < AccessLevel.GameMaster && !from.InRange( target.GetWorldLocation(), 2 ) )
  3188. return false;
  3189. else if ( !from.CanSee( target ) || !from.InLOS( target ) )
  3190. return false;
  3191. else if ( !target.IsAccessibleTo( from ) )
  3192. return false;
  3193. else if ( !from.OnDroppedItemOnto( this, target ) )
  3194. return false;
  3195. else if( Nontransferable && from.Player && from.AccessLevel <= AccessLevel.GameMaster )
  3196. {
  3197. HandleInvalidTransfer( from );
  3198. return false;
  3199. }
  3200. else
  3201. return target.OnDragDrop( from, this );
  3202. }
  3203. public virtual bool DropToItem( Mobile from, Item target, Point3D p )
  3204. {
  3205. if ( Deleted || from.Deleted || target.Deleted || from.Map != target.Map || from.Map == null || target.Map == null )
  3206. return false;
  3207. object root = target.RootParent;
  3208. if ( from.AccessLevel < AccessLevel.GameMaster && !from.InRange( target.GetWorldLocation(), 2 ) )
  3209. return false;
  3210. else if ( !from.CanSee( target ) || !from.InLOS( target ) )
  3211. return false;
  3212. else if ( !target.IsAccessibleTo( from ) )
  3213. return false;
  3214. else if ( root is Mobile && !((Mobile)root).CheckNonlocalDrop( from, this, target ) )
  3215. return false;
  3216. else if ( !from.OnDroppedItemToItem( this, target, p ) )
  3217. return false;
  3218. else if (target is Container && p.m_X != -1 && p.m_Y != -1)
  3219. {
  3220. // Template system hook
  3221. if (NeedAssignProperties())
  3222. {
  3223. m_PropertiesAssigned = true;
  3224. OnAssignProperties();
  3225. }
  3226. return OnDroppedInto(from, (Container)target, p);
  3227. }
  3228. else
  3229. {
  3230. // Template system hook
  3231. if (NeedAssignProperties())
  3232. {
  3233. m_PropertiesAssigned = true;
  3234. OnAssignProperties();
  3235. }
  3236. return OnDroppedOnto(from, target);
  3237. }
  3238. }
  3239. public virtual bool OnDroppedToWorld( Mobile from, Point3D p )
  3240. {
  3241. if( Nontransferable && from.Player && from.AccessLevel <= AccessLevel.GameMaster )
  3242. {
  3243. HandleInvalidTransfer( from );
  3244. return false;
  3245. }
  3246. return true;
  3247. }
  3248. public virtual int GetLiftSound( Mobile from )
  3249. {
  3250. return 0x57;
  3251. }
  3252. private static int m_OpenSlots;
  3253. public virtual bool DropToWorld( Mobile from, Point3D p )
  3254. {
  3255. if ( Deleted || from.Deleted || from.Map == null )
  3256. return false;
  3257. else if ( !from.InRange( p, 2 ) )
  3258. return false;
  3259. Map map = from.Map;
  3260. if ( map == null )
  3261. return false;
  3262. int x = p.m_X, y = p.m_Y;
  3263. int z = int.MinValue;
  3264. int maxZ = from.Z + 16;
  3265. Tile landTile = map.Tiles.GetLandTile( x, y );
  3266. TileFlag landFlags = TileData.LandTable[landTile.ID & TileData.MaxLandValue].Flags;
  3267. int landZ = 0, landAvg = 0, landTop = 0;
  3268. map.GetAverageZ( x, y, ref landZ, ref landAvg, ref landTop );
  3269. if ( !landTile.Ignored && (landFlags & TileFlag.Impassable) == 0 )
  3270. {
  3271. if ( landAvg <= maxZ )
  3272. z = landAvg;
  3273. }
  3274. var tiles = map.Tiles.GetStaticTiles( x, y, true );
  3275. for ( int i = 0; i < tiles.Length; ++i )
  3276. {
  3277. var tile = tiles[i];
  3278. var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
  3279. if ( !id.Surface )
  3280. continue;
  3281. int top = tile.Z + id.CalcHeight;
  3282. if ( top > maxZ || top < z )
  3283. continue;
  3284. z = top;
  3285. }
  3286. List<Item> items = new List<Item>();
  3287. IPooledEnumerable eable = map.GetItemsInRange( p, 0 );
  3288. foreach ( Item item in eable )
  3289. {
  3290. if ( item is BaseMulti || item.ItemID > TileData.MaxItemValue )
  3291. continue;
  3292. items.Add( item );
  3293. ItemData id = item.ItemData;
  3294. if ( !id.Surface )
  3295. continue;
  3296. int top = item.Z + id.CalcHeight;
  3297. if ( top > maxZ || top < z )
  3298. continue;
  3299. z = top;
  3300. }
  3301. eable.Free();
  3302. if ( z == int.MinValue )
  3303. return false;
  3304. if ( z > maxZ )
  3305. return false;
  3306. m_OpenSlots = (1<<20)-1;
  3307. int surfaceZ = z;
  3308. for ( int i = 0; i < tiles.Length; ++i )
  3309. {
  3310. var tile = tiles[i];
  3311. var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
  3312. int checkZ = tile.Z;
  3313. int checkTop = checkZ + id.CalcHeight;
  3314. if ( checkTop == checkZ && !id.Surface )
  3315. ++checkTop;
  3316. int zStart = checkZ - z;
  3317. int zEnd = checkTop - z;
  3318. if ( zStart >= 20 || zEnd < 0 )
  3319. continue;
  3320. if ( zStart < 0 )
  3321. zStart = 0;
  3322. if ( zEnd > 19 )
  3323. zEnd = 19;
  3324. int bitCount = zEnd-zStart;
  3325. m_OpenSlots &= ~(((1<<bitCount)-1)<<zStart);
  3326. }
  3327. for ( int i = 0; i < items.Count; ++i )
  3328. {
  3329. Item item = items[i];
  3330. ItemData id = item.ItemData;
  3331. int checkZ = item.Z;
  3332. int checkTop = checkZ + id.CalcHeight;
  3333. if ( checkTop == checkZ && !id.Surface )
  3334. ++checkTop;
  3335. int zStart = checkZ - z;
  3336. int zEnd = checkTop - z;
  3337. if ( zStart >= 20 || zEnd < 0 )
  3338. continue;
  3339. if ( zStart < 0 )
  3340. zStart = 0;
  3341. if ( zEnd > 19 )
  3342. zEnd = 19;
  3343. int bitCount = zEnd-zStart;
  3344. m_OpenSlots &= ~(((1<<bitCount)-1)<<zStart);
  3345. }
  3346. int height = ItemData.Height;
  3347. if ( height == 0 )
  3348. ++height;
  3349. if ( height > 30 )
  3350. height = 30;
  3351. int match = (1<<height)-1;
  3352. bool okay = false;
  3353. for ( int i = 0; i < 20; ++i )
  3354. {
  3355. if ( (i+height) > 20 )
  3356. match >>= 1;
  3357. okay = ((m_OpenSlots>>i)&match) == match;
  3358. if ( okay )
  3359. {
  3360. z += i;
  3361. break;
  3362. }
  3363. }
  3364. if ( !okay )
  3365. return false;
  3366. height = ItemData.Height;
  3367. if ( height == 0 )
  3368. ++height;
  3369. if ( landAvg > z && (z + height) > landZ )
  3370. return false;
  3371. else if ( (landFlags & TileFlag.Impassable) != 0 && landAvg > surfaceZ && (z + height) > landZ )
  3372. return false;
  3373. for ( int i = 0; i < tiles.Length; ++i )
  3374. {
  3375. var tile = tiles[i];
  3376. var id = TileData.ItemTable[tile.ID & TileData.MaxItemValue];
  3377. int checkZ = tile.Z;
  3378. int checkTop = checkZ + id.CalcHeight;
  3379. if ( checkTop > z && (z + height) > checkZ )
  3380. return false;
  3381. else if ( (id.Surface || id.Impassable) && checkTop > surfaceZ && (z + height) > checkZ )
  3382. return false;
  3383. }
  3384. for ( int i = 0; i < items.Count; ++i )
  3385. {
  3386. Item item = items[i];
  3387. ItemData id = item.ItemData;
  3388. //int checkZ = item.Z;
  3389. //int checkTop = checkZ + id.CalcHeight;
  3390. if ( (item.Z + id.CalcHeight) > z && (z + height) > item.Z )
  3391. return false;
  3392. }
  3393. p = new Point3D( x, y, z );
  3394. if ( !from.InLOS( new Point3D( x, y, z + 1 ) ) )
  3395. return false;
  3396. else if ( !from.OnDroppedItemToWorld( this, p ) )
  3397. return false;
  3398. else if ( !OnDroppedToWorld( from, p ) )
  3399. return false;
  3400. int soundID = GetDropSound();
  3401. // Template system hook
  3402. if (NeedAssignProperties())
  3403. {
  3404. m_PropertiesAssigned = true;
  3405. OnAssignProperties();
  3406. }
  3407. MoveToWorld( p, from.Map );
  3408. from.SendSound( soundID == -1 ? 0x42 : soundID, GetWorldLocation() );
  3409. return true;
  3410. }
  3411. public void SendRemovePacket()
  3412. {
  3413. if ( !Deleted && m_Map != null )
  3414. {
  3415. Packet p = null;
  3416. Point3D worldLoc = GetWorldLocation();
  3417. IPooledEnumerable eable = m_Map.GetClientsInRange( worldLoc, GetMaxUpdateRange() );
  3418. foreach ( NetState state in eable )
  3419. {
  3420. Mobile m = state.Mobile;
  3421. if ( m.InRange( worldLoc, GetUpdateRange( m ) ) )
  3422. {
  3423. if ( p == null )
  3424. p = this.RemovePacket;
  3425. state.Send( p );
  3426. }
  3427. }
  3428. eable.Free();
  3429. }
  3430. }
  3431. public virtual int GetDropSound()
  3432. {
  3433. return -1;
  3434. }
  3435. public Point3D GetWorldLocation()
  3436. {
  3437. object root = RootParent;
  3438. if ( root == null )
  3439. return m_Location;
  3440. else
  3441. return ((IEntity)root).Location;
  3442. //return root == null ? m_Location : new Point3D( (IPoint3D) root );
  3443. }
  3444. public virtual bool BlocksFit{ get{ return false; } }
  3445. public Point3D GetSurfaceTop()
  3446. {
  3447. object root = RootParent;
  3448. if ( root == null )
  3449. return new Point3D( m_Location.m_X, m_Location.m_Y, m_Location.m_Z + (ItemData.Surface ? ItemData.CalcHeight : 0) );
  3450. else
  3451. return ((IEntity)root).Location;
  3452. }
  3453. public Point3D GetWorldTop()
  3454. {
  3455. object root = RootParent;
  3456. if ( root == null )
  3457. return new Point3D( m_Location.m_X, m_Location.m_Y, m_Location.m_Z + ItemData.CalcHeight );
  3458. else
  3459. return ((IEntity)root).Location;
  3460. }
  3461. public void SendLocalizedMessageTo( Mobile to, int number )
  3462. {
  3463. if ( Deleted || !to.CanSee( this ) )
  3464. return;
  3465. to.Send( new MessageLocalized( Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", "" ) );
  3466. }
  3467. public void SendLocalizedMessageTo( Mobile to, int number, string args )
  3468. {
  3469. if ( Deleted || !to.CanSee( this ) )
  3470. return;
  3471. to.Send( new MessageLocalized( Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", args ) );
  3472. }
  3473. public void SendLocalizedMessageTo( Mobile to, int number, AffixType affixType, string affix, string args )
  3474. {
  3475. if ( Deleted || !to.CanSee( this ) )
  3476. return;
  3477. to.Send( new MessageLocalizedAffix( Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", affixType, affix, args ) );
  3478. }
  3479. #region OnDoubleClick[...]
  3480. public virtual void OnDoubleClick( Mobile from )
  3481. {
  3482. }
  3483. public virtual void OnDoubleClickOutOfRange( Mobile from )
  3484. {
  3485. }
  3486. public virtual void OnDoubleClickCantSee( Mobile from )
  3487. {
  3488. }
  3489. public virtual void OnDoubleClickDead( Mobile from )
  3490. {
  3491. from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019048 ); // I am dead and cannot do that.
  3492. }
  3493. public virtual void OnDoubleClickNotAccessible( Mobile from )
  3494. {
  3495. from.SendLocalizedMessage( 500447 ); // That is not accessible.
  3496. }
  3497. public virtual void OnDoubleClickSecureTrade( Mobile from )
  3498. {
  3499. from.SendLocalizedMessage( 500447 ); // That is not accessible.
  3500. }
  3501. #endregion
  3502. public virtual void OnSnoop( Mobile from )
  3503. {
  3504. }
  3505. public bool InSecureTrade
  3506. {
  3507. get
  3508. {
  3509. return ( GetSecureTradeCont() != null );
  3510. }
  3511. }
  3512. public SecureTradeContainer GetSecureTradeCont()
  3513. {
  3514. object p = this;
  3515. while ( p is Item )
  3516. {
  3517. if ( p is SecureTradeContainer )
  3518. return (SecureTradeContainer)p;
  3519. p = ((Item)p).m_Parent;
  3520. }
  3521. return null;
  3522. }
  3523. public virtual void OnItemAdded( Item item )
  3524. {
  3525. if ( m_Parent is Item )
  3526. ((Item)m_Parent).OnSubItemAdded( item );
  3527. else if ( m_Parent is Mobile )
  3528. ((Mobile)m_Parent).OnSubItemAdded( item );
  3529. }
  3530. public virtual void OnItemRemoved( Item item )
  3531. {
  3532. if ( m_Parent is Item )
  3533. ((Item)m_Parent).OnSubItemRemoved( item );
  3534. else if ( m_Parent is Mobile )
  3535. ((Mobile)m_Parent).OnSubItemRemoved( item );
  3536. }
  3537. public virtual void OnSubItemAdded( Item item )
  3538. {
  3539. if ( m_Parent is Item )
  3540. ((Item)m_Parent).OnSubItemAdded( item );
  3541. else if ( m_Parent is Mobile )
  3542. ((Mobile)m_Parent).OnSubItemAdded( item );
  3543. }
  3544. public virtual void OnSubItemRemoved( Item item )
  3545. {
  3546. if ( m_Parent is Item )
  3547. ((Item)m_Parent).OnSubItemRemoved( item );
  3548. else if ( m_Parent is Mobile )
  3549. ((Mobile)m_Parent).OnSubItemRemoved( item );
  3550. }
  3551. public virtual void OnItemBounceCleared( Item item )
  3552. {
  3553. if ( m_Parent is Item )
  3554. ((Item)m_Parent).OnSubItemBounceCleared( item );
  3555. else if ( m_Parent is Mobile )
  3556. ((Mobile)m_Parent).OnSubItemBounceCleared( item );
  3557. }
  3558. public virtual void OnSubItemBounceCleared( Item item )
  3559. {
  3560. if ( m_Parent is Item )
  3561. ((Item)m_Parent).OnSubItemBounceCleared( item );
  3562. else if ( m_Parent is Mobile )
  3563. ((Mobile)m_Parent).OnSubItemBounceCleared( item );
  3564. }
  3565. public virtual bool CheckTarget( Mobile from, Server.Targeting.Target targ, object targeted )
  3566. {
  3567. if ( m_Parent is Item )
  3568. return ((Item)m_Parent).CheckTarget( from, targ, targeted );
  3569. else if ( m_Parent is Mobile )
  3570. return ((Mobile)m_Parent).CheckTarget( from, targ, targeted );
  3571. return true;
  3572. }
  3573. public virtual bool IsAccessibleTo( Mobile check )
  3574. {
  3575. if ( m_Parent is Item )
  3576. return ((Item)m_Parent).IsAccessibleTo( check );
  3577. Region reg = Region.Find( GetWorldLocation(), m_Map );
  3578. return reg.CheckAccessibility( this, check );
  3579. /*SecureTradeContainer cont = GetSecureTradeCont();
  3580. if ( cont != null && !cont.IsChildOf( check ) )
  3581. return false;
  3582. return true;*/
  3583. }
  3584. public bool IsChildOf( object o )
  3585. {
  3586. return IsChildOf( o, false );
  3587. }
  3588. public bool IsChildOf( object o, bool allowNull )
  3589. {
  3590. object p = m_Parent;
  3591. if ( (p == null || o == null) && !allowNull )
  3592. return false;
  3593. if ( p == o )
  3594. return true;
  3595. while ( p is Item )
  3596. {
  3597. Item item = (Item)p;
  3598. if ( item.m_Parent == null )
  3599. {
  3600. break;
  3601. }
  3602. else
  3603. {
  3604. p = item.m_Parent;
  3605. if ( p == o )
  3606. return true;
  3607. }
  3608. }
  3609. return false;
  3610. }
  3611. public ItemData ItemData
  3612. {
  3613. get
  3614. {
  3615. return TileData.ItemTable[m_ItemID & TileData.MaxItemValue];
  3616. }
  3617. }
  3618. public virtual void OnItemUsed( Mobile from, Item item )
  3619. {
  3620. if ( m_Parent is Item )
  3621. ((Item)m_Parent).OnItemUsed( from, item );
  3622. else if ( m_Parent is Mobile )
  3623. ((Mobile)m_Parent).OnItemUsed( from, item );
  3624. }
  3625. public bool CheckItemUse( Mobile from )
  3626. {
  3627. return CheckItemUse( from, this );
  3628. }
  3629. public virtual bool CheckItemUse( Mobile from, Item item )
  3630. {
  3631. if ( m_Parent is Item )
  3632. return ((Item)m_Parent).CheckItemUse( from, item );
  3633. else if ( m_Parent is Mobile )
  3634. return ((Mobile)m_Parent).CheckItemUse( from, item );
  3635. else
  3636. return true;
  3637. }
  3638. public virtual void OnItemLifted( Mobile from, Item item )
  3639. {
  3640. if ( m_Parent is Item )
  3641. ((Item)m_Parent).OnItemLifted( from, item );
  3642. else if ( m_Parent is Mobile )
  3643. ((Mobile)m_Parent).OnItemLifted( from, item );
  3644. }
  3645. public bool CheckLift( Mobile from )
  3646. {
  3647. LRReason reject = LRReason.Inspecific;
  3648. return CheckLift( from, this, ref reject );
  3649. }
  3650. public virtual bool CheckLift( Mobile from, Item item, ref LRReason reject )
  3651. {
  3652. if ( m_Parent is Item )
  3653. return ((Item)m_Parent).CheckLift( from, item, ref reject );
  3654. else if ( m_Parent is Mobile )
  3655. return ((Mobile)m_Parent).CheckLift( from, item, ref reject );
  3656. else
  3657. return true;
  3658. }
  3659. public virtual bool CanTarget{ get{ return true; } }
  3660. public virtual bool DisplayLootType{ get{ return true; } }
  3661. public virtual void OnSingleClickContained( Mobile from, Item item )
  3662. {
  3663. if ( m_Parent is Item )
  3664. ((Item)m_Parent).OnSingleClickContained( from, item );
  3665. }
  3666. public virtual void OnAosSingleClick( Mobile from )
  3667. {
  3668. ObjectPropertyList opl = this.PropertyList;
  3669. if ( opl.Header > 0 )
  3670. from.Send( new MessageLocalized( m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, opl.Header, this.Name, opl.HeaderArgs ) );
  3671. }
  3672. public virtual void OnSingleClick( Mobile from )
  3673. {
  3674. if ( Deleted || !from.CanSee( this ) )
  3675. return;
  3676. if ( DisplayLootType )
  3677. LabelLootTypeTo( from );
  3678. NetState ns = from.NetState;
  3679. if ( ns != null )
  3680. {
  3681. if ( this.Name == null )
  3682. {
  3683. if ( m_Amount <= 1 )
  3684. ns.Send( new MessageLocalized( m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, LabelNumber, "", "" ) );
  3685. else
  3686. ns.Send( new MessageLocalizedAffix( m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, LabelNumber, "", AffixType.Append, String.Format( " : {0}", m_Amount ), "" ) );
  3687. }
  3688. else
  3689. {
  3690. ns.Send( new UnicodeMessage( m_Serial, m_ItemID, MessageType.Label, 0x3B2, 3, "ENU", "", this.Name + ( m_Amount > 1 ? " : " + m_Amount : "" ) ) );
  3691. }
  3692. }
  3693. }
  3694. private static bool m_ScissorCopyLootType;
  3695. public static bool ScissorCopyLootType
  3696. {
  3697. get{ return m_ScissorCopyLootType; }
  3698. set{ m_ScissorCopyLootType = value; }
  3699. }
  3700. public virtual void ScissorHelper( Mobile from, Item newItem, int amountPerOldItem )
  3701. {
  3702. ScissorHelper( from, newItem, amountPerOldItem, true );
  3703. }
  3704. public virtual void ScissorHelper( Mobile from, Item newItem, int amountPerOldItem, bool carryHue )
  3705. {
  3706. int amount = Amount;
  3707. if ( amount > (60000 / amountPerOldItem) ) // let's not go over 60000
  3708. amount = (60000 / amountPerOldItem);
  3709. Amount -= amount;
  3710. int ourHue = Hue;
  3711. Map thisMap = this.Map;
  3712. object thisParent = this.m_Parent;
  3713. Point3D worldLoc = this.GetWorldLocation();
  3714. LootType type = this.LootType;
  3715. if ( Amount == 0 )
  3716. Delete();
  3717. newItem.Amount = amount * amountPerOldItem;
  3718. if ( carryHue )
  3719. newItem.Hue = ourHue;
  3720. if ( m_ScissorCopyLootType )
  3721. newItem.LootType = type;
  3722. if ( !(thisParent is Container) || !((Container)thisParent).TryDropItem( from, newItem, false ) )
  3723. newItem.MoveToWorld( worldLoc, thisMap );
  3724. }
  3725. public virtual void Consume()
  3726. {
  3727. Consume( 1 );
  3728. }
  3729. public virtual void Consume( int amount )
  3730. {
  3731. this.Amount -= amount;
  3732. if ( this.Amount <= 0 )
  3733. this.Delete();
  3734. }
  3735. [CommandProperty( AccessLevel.GameMaster )]
  3736. public bool QuestItem
  3737. {
  3738. get { return GetFlag( ImplFlag.QuestItem ); }
  3739. set
  3740. {
  3741. SetFlag( ImplFlag.QuestItem, value );
  3742. InvalidateProperties();
  3743. ReleaseWorldPackets();
  3744. Delta( ItemDelta.Update );
  3745. }
  3746. }
  3747. public bool Insured
  3748. {
  3749. get{ return GetFlag( ImplFlag.Insured ); }
  3750. set{ SetFlag( ImplFlag.Insured, value ); InvalidateProperties(); }
  3751. }
  3752. public bool PayedInsurance
  3753. {
  3754. get{ return GetFlag( ImplFlag.PayedInsurance ); }
  3755. set{ SetFlag( ImplFlag.PayedInsurance, value ); }
  3756. }
  3757. public Mobile BlessedFor
  3758. {
  3759. get
  3760. {
  3761. CompactInfo info = LookupCompactInfo();
  3762. if ( info != null )
  3763. return info.m_BlessedFor;
  3764. return null;
  3765. }
  3766. set
  3767. {
  3768. CompactInfo info = AcquireCompactInfo();
  3769. info.m_BlessedFor = value;
  3770. if ( info.m_BlessedFor == null )
  3771. VerifyCompactInfo();
  3772. InvalidateProperties();
  3773. }
  3774. }
  3775. public virtual bool CheckBlessed( object obj )
  3776. {
  3777. return CheckBlessed( obj as Mobile );
  3778. }
  3779. public virtual bool CheckBlessed( Mobile m )
  3780. {
  3781. if ( m_LootType == LootType.Blessed || (Mobile.InsuranceEnabled && Insured) )
  3782. return true;
  3783. return ( m != null && m == this.BlessedFor );
  3784. }
  3785. public virtual bool CheckNewbied()
  3786. {
  3787. return ( m_LootType == LootType.Newbied );
  3788. }
  3789. public virtual bool IsStandardLoot()
  3790. {
  3791. if ( Mobile.InsuranceEnabled && Insured )
  3792. return false;
  3793. if ( this.BlessedFor != null )
  3794. return false;
  3795. return ( m_LootType == LootType.Regular );
  3796. }
  3797. public override string ToString()
  3798. {
  3799. return String.Format( "0x{0:X} \"{1}\"", m_Serial.Value, GetType().Name );
  3800. }
  3801. internal int m_TypeRef;
  3802. public Item()
  3803. {
  3804. m_Serial = Serial.NewItem;
  3805. //m_Items = new ArrayList( 1 );
  3806. Visible = true;
  3807. Movable = true;
  3808. Amount = 1;
  3809. m_Map = Map.Internal;
  3810. SetLastMoved();
  3811. World.AddItem( this );
  3812. Type ourType = this.GetType();
  3813. m_TypeRef = World.m_ItemTypes.IndexOf( ourType );
  3814. if ( m_TypeRef == -1 )
  3815. {
  3816. World.m_ItemTypes.Add( ourType );
  3817. m_TypeRef = World.m_ItemTypes.Count - 1;
  3818. }
  3819. }
  3820. [Constructable]
  3821. public Item( int itemID ) : this()
  3822. {
  3823. m_ItemID = itemID;
  3824. }
  3825. public Item( Serial serial )
  3826. {
  3827. m_Serial = serial;
  3828. Type ourType = this.GetType();
  3829. m_TypeRef = World.m_ItemTypes.IndexOf( ourType );
  3830. if ( m_TypeRef == -1 )
  3831. {
  3832. World.m_ItemTypes.Add( ourType );
  3833. m_TypeRef = World.m_ItemTypes.Count - 1;
  3834. }
  3835. }
  3836. public virtual void OnSectorActivate()
  3837. {
  3838. }
  3839. public virtual void OnSectorDeactivate()
  3840. {
  3841. }
  3842. }
  3843. }