PageRenderTime 59ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/CoreNew/Server/Item.cs

https://bitbucket.org/Kel/crepuscule
C# | 4722 lines | 3371 code | 877 blank | 474 comment | 1071 complexity | 5f3a22d9652127f89b72489d5188f6b5 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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

Large files files are truncated, but you can click here to view the full file