/Scripts/Mobiles/PlayerMobile.cs

https://bitbucket.org/servuo/servuo · C# · 6246 lines · 5156 code · 1060 blank · 30 comment · 1277 complexity · 9dac92646eb6963edc8dc6bb52ee9bbb MD5 · raw file

Large files are truncated click here to view the full file

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Server.Accounting;
  5. using Server.ContextMenus;
  6. using Server.Engines.CannedEvil;
  7. using Server.Engines.Craft;
  8. using Server.Engines.Help;
  9. using Server.Engines.PartySystem;
  10. using Server.Engines.Quests;
  11. using Server.Engines.XmlSpawner2;
  12. using Server.Factions;
  13. using Server.Gumps;
  14. using Server.Items;
  15. using Server.Misc;
  16. using Server.Multis;
  17. using Server.Network;
  18. using Server.Regions;
  19. using Server.Spells;
  20. using Server.Spells.Bushido;
  21. using Server.Spells.Fifth;
  22. using Server.Spells.Necromancy;
  23. using Server.Spells.Ninjitsu;
  24. using Server.Spells.Seventh;
  25. using Server.Spells.Spellweaving;
  26. using Server.Targeting;
  27. namespace Server.Mobiles
  28. {
  29. #region Enums
  30. [Flags]
  31. public enum PlayerFlag // First 16 bits are reserved for default-distro use, start custom flags at 0x00010000
  32. {
  33. None = 0x00000000,
  34. Glassblowing = 0x00000001,
  35. Masonry = 0x00000002,
  36. SandMining = 0x00000004,
  37. StoneMining = 0x00000008,
  38. ToggleMiningStone = 0x00000010,
  39. KarmaLocked = 0x00000020,
  40. AutoRenewInsurance = 0x00000040,
  41. UseOwnFilter = 0x00000080,
  42. PublicMyRunUO = 0x00000100,
  43. PagingSquelched = 0x00000200,
  44. Young = 0x00000400,
  45. AcceptGuildInvites = 0x00000800,
  46. DisplayChampionTitle = 0x00001000,
  47. HasStatReward = 0x00002000,
  48. Bedlam = 0x00010000,
  49. LibraryFriend = 0x00020000,
  50. Spellweaving = 0x00040000,
  51. GemMining = 0x00080000,
  52. ToggleMiningGem = 0x00100000,
  53. BasketWeaving = 0x00200000,
  54. AbyssEntry = 0x00400000,
  55. ToggleClippings = 0x00800000,
  56. ToggleCutClippings = 0x01000000,
  57. ToggleCutReeds = 0x02000000,
  58. MechanicalLife = 0x04000000
  59. }
  60. public enum NpcGuild
  61. {
  62. None,
  63. MagesGuild,
  64. WarriorsGuild,
  65. ThievesGuild,
  66. RangersGuild,
  67. HealersGuild,
  68. MinersGuild,
  69. MerchantsGuild,
  70. TinkersGuild,
  71. TailorsGuild,
  72. FishermensGuild,
  73. BardsGuild,
  74. BlacksmithsGuild
  75. }
  76. public enum SolenFriendship
  77. {
  78. None,
  79. Red,
  80. Black
  81. }
  82. #endregion
  83. public partial class PlayerMobile : Mobile, IHonorTarget
  84. {
  85. #region Mount Blocking
  86. public void SetMountBlock(BlockMountType type, TimeSpan duration, bool dismount)
  87. {
  88. if (dismount)
  89. {
  90. BaseMount.Dismount(this, this, type, duration, false);
  91. }
  92. else
  93. {
  94. BaseMount.SetMountPrevention(this, type, duration);
  95. }
  96. }
  97. #endregion
  98. #region Stygian Abyss
  99. public override void ToggleFlying()
  100. {
  101. if (this.Race != Race.Gargoyle)
  102. return;
  103. else if (this.Flying)
  104. {
  105. this.Freeze(TimeSpan.FromSeconds(1));
  106. this.Animate(61, 10, 1, true, false, 0);
  107. this.Flying = false;
  108. BuffInfo.RemoveBuff(this, BuffIcon.Fly);
  109. this.SendMessage("You have landed.");
  110. BaseMount.Dismount(this);
  111. return;
  112. }
  113. BlockMountType type = BaseMount.GetMountPrevention(this);
  114. if (!this.Alive)
  115. this.SendLocalizedMessage(1113082); // You may not fly while dead.
  116. else if (this.IsBodyMod && !(this.BodyMod == 666 || this.BodyMod == 667))
  117. this.SendLocalizedMessage(1112453); // You can't fly in your current form!
  118. else if (type != BlockMountType.None)
  119. {
  120. switch (type)
  121. {
  122. case BlockMountType.Dazed:
  123. this.SendLocalizedMessage(1112457);
  124. break; // You are still too dazed to fly.
  125. case BlockMountType.BolaRecovery:
  126. this.SendLocalizedMessage(1112455);
  127. break; // You cannot fly while recovering from a bola throw.
  128. case BlockMountType.DismountRecovery:
  129. this.SendLocalizedMessage(1112456);
  130. break; // You cannot fly while recovering from a dismount maneuver.
  131. }
  132. return;
  133. }
  134. else if (this.Hits < 25) // TODO confirm
  135. this.SendLocalizedMessage(1112454); // You must heal before flying.
  136. else
  137. {
  138. if (!this.Flying)
  139. {
  140. // No message?
  141. if (this.Spell is FlySpell)
  142. {
  143. FlySpell spell = (FlySpell)this.Spell;
  144. spell.Stop();
  145. }
  146. new FlySpell(this).Cast();
  147. }
  148. else
  149. {
  150. this.Flying = false;
  151. BuffInfo.RemoveBuff(this, BuffIcon.Fly);
  152. }
  153. }
  154. }
  155. #endregion
  156. private class CountAndTimeStamp
  157. {
  158. private int m_Count;
  159. private DateTime m_Stamp;
  160. public CountAndTimeStamp()
  161. {
  162. }
  163. public DateTime TimeStamp
  164. {
  165. get
  166. {
  167. return this.m_Stamp;
  168. }
  169. }
  170. public int Count
  171. {
  172. get
  173. {
  174. return this.m_Count;
  175. }
  176. set
  177. {
  178. this.m_Count = value;
  179. this.m_Stamp = DateTime.Now;
  180. }
  181. }
  182. }
  183. private DesignContext m_DesignContext;
  184. private NpcGuild m_NpcGuild;
  185. private DateTime m_NpcGuildJoinTime;
  186. private DateTime m_NextBODTurnInTime;
  187. private TimeSpan m_NpcGuildGameTime;
  188. private PlayerFlag m_Flags;
  189. private int m_StepsTaken;
  190. private int m_Profession;
  191. private bool m_IsStealthing; // IsStealthing should be moved to Server.Mobiles
  192. private bool m_IgnoreMobiles; // IgnoreMobiles should be moved to Server.Mobiles
  193. private int m_NonAutoreinsuredItems; // number of items that could not be automaitically reinsured because gold in bank was not enough
  194. private bool m_NinjaWepCooldown;
  195. /*
  196. * a value of zero means, that the mobile is not executing the spell. Otherwise,
  197. * the value should match the BaseMana required
  198. */
  199. private int m_ExecutesLightningStrike; // move to Server.Mobiles??
  200. private DateTime m_LastOnline;
  201. private Server.Guilds.RankDefinition m_GuildRank;
  202. private int m_GuildMessageHue, m_AllianceMessageHue;
  203. private List<Mobile> m_AutoStabled;
  204. private List<Mobile> m_AllFollowers;
  205. private List<Mobile> m_RecentlyReported;
  206. #region Guantlet Points
  207. private double m_GauntletPoints;
  208. [CommandProperty(AccessLevel.Administrator)]
  209. public double GauntletPoints
  210. {
  211. get
  212. {
  213. return this.m_GauntletPoints;
  214. }
  215. set
  216. {
  217. this.m_GauntletPoints = value;
  218. }
  219. }
  220. #endregion
  221. #region Getters & Setters
  222. public List<Mobile> RecentlyReported
  223. {
  224. get
  225. {
  226. return this.m_RecentlyReported;
  227. }
  228. set
  229. {
  230. this.m_RecentlyReported = value;
  231. }
  232. }
  233. public List<Mobile> AutoStabled
  234. {
  235. get
  236. {
  237. return this.m_AutoStabled;
  238. }
  239. }
  240. public bool NinjaWepCooldown
  241. {
  242. get
  243. {
  244. return this.m_NinjaWepCooldown;
  245. }
  246. set
  247. {
  248. this.m_NinjaWepCooldown = value;
  249. }
  250. }
  251. public List<Mobile> AllFollowers
  252. {
  253. get
  254. {
  255. if (this.m_AllFollowers == null)
  256. this.m_AllFollowers = new List<Mobile>();
  257. return this.m_AllFollowers;
  258. }
  259. }
  260. public Server.Guilds.RankDefinition GuildRank
  261. {
  262. get
  263. {
  264. if (this.AccessLevel >= AccessLevel.GameMaster)
  265. return Server.Guilds.RankDefinition.Leader;
  266. else
  267. return this.m_GuildRank;
  268. }
  269. set
  270. {
  271. this.m_GuildRank = value;
  272. }
  273. }
  274. [CommandProperty(AccessLevel.GameMaster)]
  275. public int GuildMessageHue
  276. {
  277. get
  278. {
  279. return this.m_GuildMessageHue;
  280. }
  281. set
  282. {
  283. this.m_GuildMessageHue = value;
  284. }
  285. }
  286. [CommandProperty(AccessLevel.GameMaster)]
  287. public int AllianceMessageHue
  288. {
  289. get
  290. {
  291. return this.m_AllianceMessageHue;
  292. }
  293. set
  294. {
  295. this.m_AllianceMessageHue = value;
  296. }
  297. }
  298. [CommandProperty(AccessLevel.GameMaster)]
  299. public int Profession
  300. {
  301. get
  302. {
  303. return this.m_Profession;
  304. }
  305. set
  306. {
  307. this.m_Profession = value;
  308. }
  309. }
  310. public int StepsTaken
  311. {
  312. get
  313. {
  314. return this.m_StepsTaken;
  315. }
  316. set
  317. {
  318. this.m_StepsTaken = value;
  319. }
  320. }
  321. [CommandProperty(AccessLevel.GameMaster)]
  322. public bool IsStealthing // IsStealthing should be moved to Server.Mobiles
  323. {
  324. get
  325. {
  326. return this.m_IsStealthing;
  327. }
  328. set
  329. {
  330. this.m_IsStealthing = value;
  331. }
  332. }
  333. [CommandProperty(AccessLevel.GameMaster)]
  334. public bool IgnoreMobiles // IgnoreMobiles should be moved to Server.Mobiles
  335. {
  336. get
  337. {
  338. return this.m_IgnoreMobiles;
  339. }
  340. set
  341. {
  342. if (this.m_IgnoreMobiles != value)
  343. {
  344. this.m_IgnoreMobiles = value;
  345. this.Delta(MobileDelta.Flags);
  346. }
  347. }
  348. }
  349. [CommandProperty(AccessLevel.GameMaster)]
  350. public NpcGuild NpcGuild
  351. {
  352. get
  353. {
  354. return this.m_NpcGuild;
  355. }
  356. set
  357. {
  358. this.m_NpcGuild = value;
  359. }
  360. }
  361. [CommandProperty(AccessLevel.GameMaster)]
  362. public DateTime NpcGuildJoinTime
  363. {
  364. get
  365. {
  366. return this.m_NpcGuildJoinTime;
  367. }
  368. set
  369. {
  370. this.m_NpcGuildJoinTime = value;
  371. }
  372. }
  373. [CommandProperty(AccessLevel.GameMaster)]
  374. public DateTime NextBODTurnInTime
  375. {
  376. get
  377. {
  378. return this.m_NextBODTurnInTime;
  379. }
  380. set
  381. {
  382. this.m_NextBODTurnInTime = value;
  383. }
  384. }
  385. [CommandProperty(AccessLevel.GameMaster)]
  386. public DateTime LastOnline
  387. {
  388. get
  389. {
  390. return this.m_LastOnline;
  391. }
  392. set
  393. {
  394. this.m_LastOnline = value;
  395. }
  396. }
  397. [CommandProperty(AccessLevel.GameMaster)]
  398. public DateTime LastMoved
  399. {
  400. get
  401. {
  402. return this.LastMoveTime;
  403. }
  404. }
  405. [CommandProperty(AccessLevel.GameMaster)]
  406. public TimeSpan NpcGuildGameTime
  407. {
  408. get
  409. {
  410. return this.m_NpcGuildGameTime;
  411. }
  412. set
  413. {
  414. this.m_NpcGuildGameTime = value;
  415. }
  416. }
  417. private int m_ToTItemsTurnedIn;
  418. [CommandProperty(AccessLevel.GameMaster)]
  419. public int ToTItemsTurnedIn
  420. {
  421. get
  422. {
  423. return this.m_ToTItemsTurnedIn;
  424. }
  425. set
  426. {
  427. this.m_ToTItemsTurnedIn = value;
  428. }
  429. }
  430. private int m_ToTTotalMonsterFame;
  431. [CommandProperty(AccessLevel.GameMaster)]
  432. public int ToTTotalMonsterFame
  433. {
  434. get
  435. {
  436. return this.m_ToTTotalMonsterFame;
  437. }
  438. set
  439. {
  440. this.m_ToTTotalMonsterFame = value;
  441. }
  442. }
  443. public int ExecutesLightningStrike
  444. {
  445. get
  446. {
  447. return this.m_ExecutesLightningStrike;
  448. }
  449. set
  450. {
  451. this.m_ExecutesLightningStrike = value;
  452. }
  453. }
  454. private int m_VASTotalMonsterFame;
  455. [CommandProperty(AccessLevel.GameMaster)]
  456. public int VASTotalMonsterFame
  457. {
  458. get
  459. {
  460. return this.m_VASTotalMonsterFame;
  461. }
  462. set
  463. {
  464. this.m_VASTotalMonsterFame = value;
  465. }
  466. }
  467. [CommandProperty(AccessLevel.GameMaster)]
  468. public int ToothAche
  469. {
  470. get
  471. {
  472. return CandyCane.GetToothAche(this);
  473. }
  474. set
  475. {
  476. CandyCane.SetToothAche(this, value);
  477. }
  478. }
  479. [CommandProperty(AccessLevel.GameMaster)]
  480. public bool MechanicalLife
  481. {
  482. get
  483. {
  484. return this.GetFlag(PlayerFlag.MechanicalLife);
  485. }
  486. set
  487. {
  488. this.SetFlag(PlayerFlag.MechanicalLife, value);
  489. }
  490. }
  491. #endregion
  492. #region PlayerFlags
  493. public PlayerFlag Flags
  494. {
  495. get
  496. {
  497. return this.m_Flags;
  498. }
  499. set
  500. {
  501. this.m_Flags = value;
  502. }
  503. }
  504. [CommandProperty(AccessLevel.GameMaster)]
  505. public bool PagingSquelched
  506. {
  507. get
  508. {
  509. return this.GetFlag(PlayerFlag.PagingSquelched);
  510. }
  511. set
  512. {
  513. this.SetFlag(PlayerFlag.PagingSquelched, value);
  514. }
  515. }
  516. [CommandProperty(AccessLevel.GameMaster)]
  517. public bool Glassblowing
  518. {
  519. get
  520. {
  521. return this.GetFlag(PlayerFlag.Glassblowing);
  522. }
  523. set
  524. {
  525. this.SetFlag(PlayerFlag.Glassblowing, value);
  526. }
  527. }
  528. [CommandProperty(AccessLevel.GameMaster)]
  529. public bool Masonry
  530. {
  531. get
  532. {
  533. return this.GetFlag(PlayerFlag.Masonry);
  534. }
  535. set
  536. {
  537. this.SetFlag(PlayerFlag.Masonry, value);
  538. }
  539. }
  540. [CommandProperty(AccessLevel.GameMaster)]
  541. public bool SandMining
  542. {
  543. get
  544. {
  545. return this.GetFlag(PlayerFlag.SandMining);
  546. }
  547. set
  548. {
  549. this.SetFlag(PlayerFlag.SandMining, value);
  550. }
  551. }
  552. [CommandProperty(AccessLevel.GameMaster)]
  553. public bool StoneMining
  554. {
  555. get
  556. {
  557. return this.GetFlag(PlayerFlag.StoneMining);
  558. }
  559. set
  560. {
  561. this.SetFlag(PlayerFlag.StoneMining, value);
  562. }
  563. }
  564. [CommandProperty(AccessLevel.GameMaster)]
  565. public bool GemMining
  566. {
  567. get
  568. {
  569. return this.GetFlag(PlayerFlag.GemMining);
  570. }
  571. set
  572. {
  573. this.SetFlag(PlayerFlag.GemMining, value);
  574. }
  575. }
  576. [CommandProperty(AccessLevel.GameMaster)]
  577. public bool BasketWeaving
  578. {
  579. get
  580. {
  581. return this.GetFlag(PlayerFlag.BasketWeaving);
  582. }
  583. set
  584. {
  585. this.SetFlag(PlayerFlag.BasketWeaving, value);
  586. }
  587. }
  588. [CommandProperty(AccessLevel.GameMaster)]
  589. public bool ToggleMiningStone
  590. {
  591. get
  592. {
  593. return this.GetFlag(PlayerFlag.ToggleMiningStone);
  594. }
  595. set
  596. {
  597. this.SetFlag(PlayerFlag.ToggleMiningStone, value);
  598. }
  599. }
  600. [CommandProperty(AccessLevel.GameMaster)]
  601. public bool AbyssEntry
  602. {
  603. get
  604. {
  605. return this.GetFlag(PlayerFlag.AbyssEntry);
  606. }
  607. set
  608. {
  609. this.SetFlag(PlayerFlag.AbyssEntry, value);
  610. }
  611. }
  612. [CommandProperty(AccessLevel.GameMaster)]
  613. public bool ToggleMiningGem
  614. {
  615. get
  616. {
  617. return this.GetFlag(PlayerFlag.ToggleMiningGem);
  618. }
  619. set
  620. {
  621. this.SetFlag(PlayerFlag.ToggleMiningGem, value);
  622. }
  623. }
  624. [CommandProperty(AccessLevel.GameMaster)]
  625. public bool KarmaLocked
  626. {
  627. get
  628. {
  629. return this.GetFlag(PlayerFlag.KarmaLocked);
  630. }
  631. set
  632. {
  633. this.SetFlag(PlayerFlag.KarmaLocked, value);
  634. }
  635. }
  636. [CommandProperty(AccessLevel.GameMaster)]
  637. public bool AutoRenewInsurance
  638. {
  639. get
  640. {
  641. return this.GetFlag(PlayerFlag.AutoRenewInsurance);
  642. }
  643. set
  644. {
  645. this.SetFlag(PlayerFlag.AutoRenewInsurance, value);
  646. }
  647. }
  648. [CommandProperty(AccessLevel.GameMaster)]
  649. public bool UseOwnFilter
  650. {
  651. get
  652. {
  653. return this.GetFlag(PlayerFlag.UseOwnFilter);
  654. }
  655. set
  656. {
  657. this.SetFlag(PlayerFlag.UseOwnFilter, value);
  658. }
  659. }
  660. [CommandProperty(AccessLevel.GameMaster)]
  661. public bool PublicMyRunUO
  662. {
  663. get
  664. {
  665. return this.GetFlag(PlayerFlag.PublicMyRunUO);
  666. }
  667. set
  668. {
  669. this.SetFlag(PlayerFlag.PublicMyRunUO, value);
  670. this.InvalidateMyRunUO();
  671. }
  672. }
  673. [CommandProperty(AccessLevel.GameMaster)]
  674. public bool AcceptGuildInvites
  675. {
  676. get
  677. {
  678. return this.GetFlag(PlayerFlag.AcceptGuildInvites);
  679. }
  680. set
  681. {
  682. this.SetFlag(PlayerFlag.AcceptGuildInvites, value);
  683. }
  684. }
  685. [CommandProperty(AccessLevel.GameMaster)]
  686. public bool HasStatReward
  687. {
  688. get
  689. {
  690. return this.GetFlag(PlayerFlag.HasStatReward);
  691. }
  692. set
  693. {
  694. this.SetFlag(PlayerFlag.HasStatReward, value);
  695. }
  696. }
  697. #region QueensLoyaltySystem
  698. private long m_LevelExp; // Experience Needed for next Experience Level
  699. [CommandProperty(AccessLevel.Owner)]
  700. public long LevelExp
  701. {
  702. get
  703. {
  704. return this.m_LevelExp;
  705. }
  706. set
  707. {
  708. this.m_LevelExp = value;
  709. this.InvalidateProperties();
  710. }
  711. }
  712. private long m_Exp; // Experience at the current Experience Level
  713. [CommandProperty(AccessLevel.GameMaster)]
  714. public long Exp
  715. {
  716. get
  717. {
  718. return this.m_Exp;
  719. }
  720. set
  721. {
  722. this.m_Exp = value;
  723. this.InvalidateProperties();
  724. }
  725. }
  726. private int m_Level; // Experience Level
  727. [CommandProperty(AccessLevel.GameMaster)]
  728. public int Level
  729. {
  730. get
  731. {
  732. return this.m_Level;
  733. }
  734. set
  735. {
  736. this.m_Level = value;
  737. this.InvalidateProperties();
  738. }
  739. }
  740. public string m_ExpTitle; // Title based on both levels
  741. [CommandProperty(AccessLevel.Owner)]
  742. public string ExpTitle
  743. {
  744. get
  745. {
  746. return this.m_ExpTitle;
  747. }
  748. set
  749. {
  750. this.m_ExpTitle = value;
  751. this.InvalidateProperties();
  752. }
  753. }
  754. #endregion
  755. #region Plant system
  756. [CommandProperty(AccessLevel.GameMaster)]
  757. public bool ToggleClippings
  758. {
  759. get
  760. {
  761. return this.GetFlag(PlayerFlag.ToggleClippings);
  762. }
  763. set
  764. {
  765. this.SetFlag(PlayerFlag.ToggleClippings, value);
  766. }
  767. }
  768. [CommandProperty(AccessLevel.GameMaster)]
  769. public bool ToggleCutReeds
  770. {
  771. get
  772. {
  773. return this.GetFlag(PlayerFlag.ToggleCutReeds);
  774. }
  775. set
  776. {
  777. this.SetFlag(PlayerFlag.ToggleCutReeds, value);
  778. }
  779. }
  780. [CommandProperty(AccessLevel.GameMaster)]
  781. public bool ToggleCutClippings
  782. {
  783. get
  784. {
  785. return this.GetFlag(PlayerFlag.ToggleCutClippings);
  786. }
  787. set
  788. {
  789. this.SetFlag(PlayerFlag.ToggleCutClippings, value);
  790. }
  791. }
  792. private DateTime m_SSNextSeed;
  793. [CommandProperty(AccessLevel.GameMaster)]
  794. public DateTime SSNextSeed
  795. {
  796. get
  797. {
  798. return this.m_SSNextSeed;
  799. }
  800. set
  801. {
  802. this.m_SSNextSeed = value;
  803. }
  804. }
  805. private DateTime m_SSSeedExpire;
  806. [CommandProperty(AccessLevel.GameMaster)]
  807. public DateTime SSSeedExpire
  808. {
  809. get
  810. {
  811. return this.m_SSSeedExpire;
  812. }
  813. set
  814. {
  815. this.m_SSSeedExpire = value;
  816. }
  817. }
  818. private Point3D m_SSSeedLocation;
  819. public Point3D SSSeedLocation
  820. {
  821. get
  822. {
  823. return this.m_SSSeedLocation;
  824. }
  825. set
  826. {
  827. this.m_SSSeedLocation = value;
  828. }
  829. }
  830. private Map m_SSSeedMap;
  831. public Map SSSeedMap
  832. {
  833. get
  834. {
  835. return this.m_SSSeedMap;
  836. }
  837. set
  838. {
  839. this.m_SSSeedMap = value;
  840. }
  841. }
  842. #endregion
  843. #endregion
  844. #region Auto Arrow Recovery
  845. private Dictionary<Type, int> m_RecoverableAmmo = new Dictionary<Type, int>();
  846. public Dictionary<Type, int> RecoverableAmmo
  847. {
  848. get
  849. {
  850. return this.m_RecoverableAmmo;
  851. }
  852. }
  853. public void RecoverAmmo()
  854. {
  855. if (Core.SE && this.Alive)
  856. {
  857. foreach (KeyValuePair<Type, int> kvp in this.m_RecoverableAmmo)
  858. {
  859. if (kvp.Value > 0)
  860. {
  861. Item ammo = null;
  862. try
  863. {
  864. ammo = Activator.CreateInstance(kvp.Key) as Item;
  865. }
  866. catch
  867. {
  868. }
  869. if (ammo != null)
  870. {
  871. string name = ammo.Name;
  872. ammo.Amount = kvp.Value;
  873. if (name == null)
  874. {
  875. if (ammo is Arrow)
  876. name = "arrow";
  877. else if (ammo is Bolt)
  878. name = "bolt";
  879. }
  880. if (name != null && ammo.Amount > 1)
  881. name = String.Format("{0}s", name);
  882. if (name == null)
  883. name = String.Format("#{0}", ammo.LabelNumber);
  884. this.PlaceInBackpack(ammo);
  885. this.SendLocalizedMessage(1073504, String.Format("{0}\t{1}", ammo.Amount, name)); // You recover ~1_NUM~ ~2_AMMO~.
  886. }
  887. }
  888. }
  889. this.m_RecoverableAmmo.Clear();
  890. }
  891. }
  892. #endregion
  893. private DateTime m_AnkhNextUse;
  894. [CommandProperty(AccessLevel.GameMaster)]
  895. public DateTime AnkhNextUse
  896. {
  897. get
  898. {
  899. return this.m_AnkhNextUse;
  900. }
  901. set
  902. {
  903. this.m_AnkhNextUse = value;
  904. }
  905. }
  906. #region Mondain's Legacy
  907. [CommandProperty(AccessLevel.GameMaster)]
  908. public bool Bedlam
  909. {
  910. get
  911. {
  912. return this.GetFlag(PlayerFlag.Bedlam);
  913. }
  914. set
  915. {
  916. this.SetFlag(PlayerFlag.Bedlam, value);
  917. }
  918. }
  919. [CommandProperty(AccessLevel.GameMaster)]
  920. public bool LibraryFriend
  921. {
  922. get
  923. {
  924. return this.GetFlag(PlayerFlag.LibraryFriend);
  925. }
  926. set
  927. {
  928. this.SetFlag(PlayerFlag.LibraryFriend, value);
  929. }
  930. }
  931. [CommandProperty(AccessLevel.GameMaster)]
  932. public bool Spellweaving
  933. {
  934. get
  935. {
  936. return this.GetFlag(PlayerFlag.Spellweaving);
  937. }
  938. set
  939. {
  940. this.SetFlag(PlayerFlag.Spellweaving, value);
  941. }
  942. }
  943. #endregion
  944. [CommandProperty(AccessLevel.GameMaster)]
  945. public TimeSpan DisguiseTimeLeft
  946. {
  947. get
  948. {
  949. return DisguiseTimers.TimeRemaining(this);
  950. }
  951. }
  952. private DateTime m_PeacedUntil;
  953. [CommandProperty(AccessLevel.GameMaster)]
  954. public DateTime PeacedUntil
  955. {
  956. get
  957. {
  958. return this.m_PeacedUntil;
  959. }
  960. set
  961. {
  962. this.m_PeacedUntil = value;
  963. }
  964. }
  965. #region Scroll of Alacrity
  966. private DateTime m_AcceleratedStart;
  967. [CommandProperty(AccessLevel.GameMaster)]
  968. public DateTime AcceleratedStart
  969. {
  970. get
  971. {
  972. return this.m_AcceleratedStart;
  973. }
  974. set
  975. {
  976. this.m_AcceleratedStart = value;
  977. }
  978. }
  979. private SkillName m_AcceleratedSkill;
  980. [CommandProperty(AccessLevel.GameMaster)]
  981. public SkillName AcceleratedSkill
  982. {
  983. get
  984. {
  985. return this.m_AcceleratedSkill;
  986. }
  987. set
  988. {
  989. this.m_AcceleratedSkill = value;
  990. }
  991. }
  992. #endregion
  993. public static Direction GetDirection4(Point3D from, Point3D to)
  994. {
  995. int dx = from.X - to.X;
  996. int dy = from.Y - to.Y;
  997. int rx = dx - dy;
  998. int ry = dx + dy;
  999. Direction ret;
  1000. if (rx >= 0 && ry >= 0)
  1001. ret = Direction.West;
  1002. else if (rx >= 0 && ry < 0)
  1003. ret = Direction.South;
  1004. else if (rx < 0 && ry < 0)
  1005. ret = Direction.East;
  1006. else
  1007. ret = Direction.North;
  1008. return ret;
  1009. }
  1010. public override bool OnDroppedItemToWorld(Item item, Point3D location)
  1011. {
  1012. if (!base.OnDroppedItemToWorld(item, location))
  1013. return false;
  1014. if (Core.AOS)
  1015. {
  1016. IPooledEnumerable mobiles = this.Map.GetMobilesInRange(location, 0);
  1017. foreach (Mobile m in mobiles)
  1018. {
  1019. if (m.Z >= location.Z && m.Z < location.Z + 16)
  1020. {
  1021. mobiles.Free();
  1022. return false;
  1023. }
  1024. }
  1025. mobiles.Free();
  1026. }
  1027. BounceInfo bi = item.GetBounce();
  1028. if (bi != null)
  1029. {
  1030. Type type = item.GetType();
  1031. if (type.IsDefined(typeof(FurnitureAttribute), true) || type.IsDefined(typeof(DynamicFlipingAttribute), true))
  1032. {
  1033. object[] objs = type.GetCustomAttributes(typeof(FlipableAttribute), true);
  1034. if (objs != null && objs.Length > 0)
  1035. {
  1036. FlipableAttribute fp = objs[0] as FlipableAttribute;
  1037. if (fp != null)
  1038. {
  1039. int[] itemIDs = fp.ItemIDs;
  1040. Point3D oldWorldLoc = bi.m_WorldLoc;
  1041. Point3D newWorldLoc = location;
  1042. if (oldWorldLoc.X != newWorldLoc.X || oldWorldLoc.Y != newWorldLoc.Y)
  1043. {
  1044. Direction dir = GetDirection4(oldWorldLoc, newWorldLoc);
  1045. if (itemIDs.Length == 2)
  1046. {
  1047. switch ( dir )
  1048. {
  1049. case Direction.North:
  1050. case Direction.South:
  1051. item.ItemID = itemIDs[0];
  1052. break;
  1053. case Direction.East:
  1054. case Direction.West:
  1055. item.ItemID = itemIDs[1];
  1056. break;
  1057. }
  1058. }
  1059. else if (itemIDs.Length == 4)
  1060. {
  1061. switch ( dir )
  1062. {
  1063. case Direction.South:
  1064. item.ItemID = itemIDs[0];
  1065. break;
  1066. case Direction.East:
  1067. item.ItemID = itemIDs[1];
  1068. break;
  1069. case Direction.North:
  1070. item.ItemID = itemIDs[2];
  1071. break;
  1072. case Direction.West:
  1073. item.ItemID = itemIDs[3];
  1074. break;
  1075. }
  1076. }
  1077. }
  1078. }
  1079. }
  1080. }
  1081. }
  1082. return true;
  1083. }
  1084. public override int GetPacketFlags()
  1085. {
  1086. int flags = base.GetPacketFlags();
  1087. if (this.m_IgnoreMobiles)
  1088. flags |= 0x10;
  1089. return flags;
  1090. }
  1091. public override int GetOldPacketFlags()
  1092. {
  1093. int flags = base.GetOldPacketFlags();
  1094. if (this.m_IgnoreMobiles)
  1095. flags |= 0x10;
  1096. return flags;
  1097. }
  1098. public bool GetFlag(PlayerFlag flag)
  1099. {
  1100. return ((this.m_Flags & flag) != 0);
  1101. }
  1102. public void SetFlag(PlayerFlag flag, bool value)
  1103. {
  1104. if (value)
  1105. this.m_Flags |= flag;
  1106. else
  1107. this.m_Flags &= ~flag;
  1108. }
  1109. public DesignContext DesignContext
  1110. {
  1111. get
  1112. {
  1113. return this.m_DesignContext;
  1114. }
  1115. set
  1116. {
  1117. this.m_DesignContext = value;
  1118. }
  1119. }
  1120. public static void Initialize()
  1121. {
  1122. if (FastwalkPrevention)
  1123. PacketHandlers.RegisterThrottler(0x02, new ThrottlePacketCallback(MovementThrottle_Callback));
  1124. EventSink.Login += new LoginEventHandler(OnLogin);
  1125. EventSink.Logout += new LogoutEventHandler(OnLogout);
  1126. EventSink.Connected += new ConnectedEventHandler(EventSink_Connected);
  1127. EventSink.Disconnected += new DisconnectedEventHandler(EventSink_Disconnected);
  1128. if (Core.SE)
  1129. {
  1130. Timer.DelayCall(TimeSpan.Zero, new TimerCallback(CheckPets));
  1131. }
  1132. }
  1133. private static void CheckPets()
  1134. {
  1135. foreach (Mobile m in World.Mobiles.Values)
  1136. {
  1137. if (m is PlayerMobile)
  1138. {
  1139. PlayerMobile pm = (PlayerMobile)m;
  1140. if (((!pm.Mounted || (pm.Mount != null && pm.Mount is EtherealMount)) && (pm.AllFollowers.Count > pm.AutoStabled.Count)) ||
  1141. (pm.Mounted && (pm.AllFollowers.Count > (pm.AutoStabled.Count + 1))))
  1142. {
  1143. pm.AutoStablePets(); /* autostable checks summons, et al: no need here */
  1144. }
  1145. }
  1146. }
  1147. }
  1148. public override void OnSkillInvalidated(Skill skill)
  1149. {
  1150. if (Core.AOS && skill.SkillName == SkillName.MagicResist)
  1151. this.UpdateResistances();
  1152. }
  1153. public override int GetMaxResistance(ResistanceType type)
  1154. {
  1155. if (this.IsStaff())
  1156. return int.MaxValue;
  1157. int max = base.GetMaxResistance(type);
  1158. if (type != ResistanceType.Physical && 60 < max && Spells.Fourth.CurseSpell.UnderEffect(this))
  1159. max = 60;
  1160. if (Core.ML && this.Race == Race.Elf && type == ResistanceType.Energy)
  1161. max += 5; //Intended to go after the 60 max from curse
  1162. return max;
  1163. }
  1164. protected override void OnRaceChange(Race oldRace)
  1165. {
  1166. this.ValidateEquipment();
  1167. this.UpdateResistances();
  1168. }
  1169. public override int MaxWeight
  1170. {
  1171. get
  1172. {
  1173. return (((Core.ML && this.Race == Race.Human) ? 100 : 40) + (int)(3.5 * this.Str));
  1174. }
  1175. }
  1176. private int m_LastGlobalLight = -1, m_LastPersonalLight = -1;
  1177. public override void OnNetStateChanged()
  1178. {
  1179. this.m_LastGlobalLight = -1;
  1180. this.m_LastPersonalLight = -1;
  1181. }
  1182. public override void ComputeBaseLightLevels(out int global, out int personal)
  1183. {
  1184. global = LightCycle.ComputeLevelFor(this);
  1185. bool racialNightSight = (Core.ML && this.Race == Race.Elf);
  1186. if (this.LightLevel < 21 && (AosAttributes.GetValue(this, AosAttribute.NightSight) > 0 || racialNightSight))
  1187. personal = 21;
  1188. else
  1189. personal = this.LightLevel;
  1190. }
  1191. public override void CheckLightLevels(bool forceResend)
  1192. {
  1193. NetState ns = this.NetState;
  1194. if (ns == null)
  1195. return;
  1196. int global, personal;
  1197. this.ComputeLightLevels(out global, out personal);
  1198. if (!forceResend)
  1199. forceResend = (global != this.m_LastGlobalLight || personal != this.m_LastPersonalLight);
  1200. if (!forceResend)
  1201. return;
  1202. this.m_LastGlobalLight = global;
  1203. this.m_LastPersonalLight = personal;
  1204. ns.Send(GlobalLightLevel.Instantiate(global));
  1205. ns.Send(new PersonalLightLevel(this, personal));
  1206. }
  1207. public override int GetMinResistance(ResistanceType type)
  1208. {
  1209. int magicResist = (int)(this.Skills[SkillName.MagicResist].Value * 10);
  1210. int min = int.MinValue;
  1211. if (magicResist >= 1000)
  1212. min = 40 + ((magicResist - 1000) / 50);
  1213. else if (magicResist >= 400)
  1214. min = (magicResist - 400) / 15;
  1215. if (min > MaxPlayerResistance)
  1216. min = MaxPlayerResistance;
  1217. int baseMin = base.GetMinResistance(type);
  1218. if (min < baseMin)
  1219. min = baseMin;
  1220. return min;
  1221. }
  1222. public override void OnManaChange(int oldValue)
  1223. {
  1224. base.OnManaChange(oldValue);
  1225. if (this.m_ExecutesLightningStrike > 0)
  1226. {
  1227. if (this.Mana < this.m_ExecutesLightningStrike)
  1228. {
  1229. LightningStrike.ClearCurrentMove(this);
  1230. }
  1231. }
  1232. }
  1233. private static void OnLogin(LoginEventArgs e)
  1234. {
  1235. Mobile from = e.Mobile;
  1236. CheckAtrophies(from);
  1237. if (AccountHandler.LockdownLevel > AccessLevel.VIP)
  1238. {
  1239. string notice;
  1240. Accounting.Account acct = from.Account as Accounting.Account;
  1241. if (acct == null || !acct.HasAccess(from.NetState))
  1242. {
  1243. if (from.IsPlayer())
  1244. notice = "The server is currently under lockdown. No players are allowed to log in at this time.";
  1245. else
  1246. notice = "The server is currently under lockdown. You do not have sufficient access level to connect.";
  1247. Timer.DelayCall(TimeSpan.FromSeconds(1.0), new TimerStateCallback(Disconnect), from);
  1248. }
  1249. else if (from.AccessLevel >= AccessLevel.Administrator)
  1250. {
  1251. notice = "The server is currently under lockdown. As you are an administrator, you may change this from the [Admin gump.";
  1252. }
  1253. else
  1254. {
  1255. notice = "The server is currently under lockdown. You have sufficient access level to connect.";
  1256. }
  1257. from.SendGump(new NoticeGump(1060637, 30720, notice, 0xFFC000, 300, 140, null, null));
  1258. return;
  1259. }
  1260. if (from is PlayerMobile)
  1261. ((PlayerMobile)from).ClaimAutoStabledPets();
  1262. }
  1263. private bool m_NoDeltaRecursion;
  1264. public void ValidateEquipment()
  1265. {
  1266. if (this.m_NoDeltaRecursion || this.Map == null || this.Map == Map.Internal)
  1267. return;
  1268. if (this.Items == null)
  1269. return;
  1270. this.m_NoDeltaRecursion = true;
  1271. Timer.DelayCall(TimeSpan.Zero, new TimerCallback(ValidateEquipment_Sandbox));
  1272. }
  1273. private void ValidateEquipment_Sandbox()
  1274. {
  1275. try
  1276. {
  1277. if (this.Map == null || this.Map == Map.Internal)
  1278. return;
  1279. List<Item> items = this.Items;
  1280. if (items == null)
  1281. return;
  1282. bool moved = false;
  1283. int str = this.Str;
  1284. int dex = this.Dex;
  1285. int intel = this.Int;
  1286. #region Factions
  1287. int factionItemCount = 0;
  1288. #endregion
  1289. Mobile from = this;
  1290. #region Ethics
  1291. Ethics.Ethic ethic = Ethics.Ethic.Find(from);
  1292. #endregion
  1293. for (int i = items.Count - 1; i >= 0; --i)
  1294. {
  1295. if (i >= items.Count)
  1296. continue;
  1297. Item item = items[i];
  1298. #region Ethics
  1299. if ((item.SavedFlags & 0x100) != 0)
  1300. {
  1301. if (item.Hue != Ethics.Ethic.Hero.Definition.PrimaryHue)
  1302. {
  1303. item.SavedFlags &= ~0x100;
  1304. }
  1305. else if (ethic != Ethics.Ethic.Hero)
  1306. {
  1307. from.AddToBackpack(item);
  1308. moved = true;
  1309. continue;
  1310. }
  1311. }
  1312. else if ((item.SavedFlags & 0x200) != 0)
  1313. {
  1314. if (item.Hue != Ethics.Ethic.Evil.Definition.PrimaryHue)
  1315. {
  1316. item.SavedFlags &= ~0x200;
  1317. }
  1318. else if (ethic != Ethics.Ethic.Evil)
  1319. {
  1320. from.AddToBackpack(item);
  1321. moved = true;
  1322. continue;
  1323. }
  1324. }
  1325. #endregion
  1326. if (item is BaseWeapon)
  1327. {
  1328. BaseWeapon weapon = (BaseWeapon)item;
  1329. bool drop = false;
  1330. if (dex < weapon.DexRequirement)
  1331. drop = true;
  1332. else if (str < AOS.Scale(weapon.StrRequirement, 100 - weapon.GetLowerStatReq()))
  1333. drop = true;
  1334. else if (intel < weapon.IntRequirement)
  1335. drop = true;
  1336. else if (weapon.RequiredRace != null && weapon.RequiredRace != this.Race)
  1337. drop = true;
  1338. if (drop)
  1339. {
  1340. string name = weapon.Name;
  1341. if (name == null)
  1342. name = String.Format("#{0}", weapon.LabelNumber);
  1343. from.SendLocalizedMessage(1062001, name); // You can no longer wield your ~1_WEAPON~
  1344. from.AddToBackpack(weapon);
  1345. moved = true;
  1346. }
  1347. }
  1348. else if (item is BaseArmor)
  1349. {
  1350. BaseArmor armor = (BaseArmor)item;
  1351. bool drop = false;
  1352. if (!armor.AllowMaleWearer && !from.Female && from.AccessLevel < AccessLevel.GameMaster)
  1353. {
  1354. drop = true;
  1355. }
  1356. else if (!armor.AllowFemaleWearer && from.Female && from.AccessLevel < AccessLevel.GameMaster)
  1357. {
  1358. drop = true;
  1359. }
  1360. else if (armor.RequiredRace != null && armor.RequiredRace != this.Race)
  1361. {
  1362. drop = true;
  1363. }
  1364. else
  1365. {
  1366. int strBonus = armor.ComputeStatBonus(StatType.Str), strReq = armor.ComputeStatReq(StatType.Str);
  1367. int dexBonus = armor.ComputeStatBonus(StatType.Dex), dexReq = armor.ComputeStatReq(StatType.Dex);
  1368. int intBonus = armor.ComputeStatBonus(StatType.Int), intReq = armor.ComputeStatReq(StatType.Int);
  1369. if (dex < dexReq || (dex + dexBonus) < 1)
  1370. drop = true;
  1371. else if (str < strReq || (str + strBonus) < 1)
  1372. drop = true;
  1373. else if (intel < intReq || (intel + intBonus) < 1)
  1374. drop = true;
  1375. }
  1376. if (drop)
  1377. {
  1378. string name = armor.Name;
  1379. if (name == null)
  1380. name = String.Format("#{0}", armor.LabelNumber);
  1381. if (armor is BaseShield)
  1382. from.SendLocalizedMessage(1062003, name); // You can no longer equip your ~1_SHIELD~
  1383. else
  1384. from.SendLocalizedMessage(1062002, name); // You can no longer wear your ~1_ARMOR~
  1385. from.AddToBackpack(armor);
  1386. moved = true;
  1387. }
  1388. }
  1389. else if (item is BaseClothing)
  1390. {
  1391. BaseClothing clothing = (BaseClothing)item;
  1392. bool drop = false;
  1393. if (!clothing.AllowMaleWearer && !from.Female && from.AccessLevel < AccessLevel.GameMaster)
  1394. {
  1395. drop = true;
  1396. }
  1397. else if (!clothing.AllowFemaleWearer && from.Female && from.AccessLevel < AccessLevel.GameMaster)
  1398. {
  1399. drop = true;
  1400. }
  1401. else if (clothing.RequiredRace != null && clothing.RequiredRace != this.Race)
  1402. {
  1403. drop = true;
  1404. }
  1405. else
  1406. {
  1407. int strBonus = clothing.ComputeStatBonus(StatType.Str);
  1408. int strReq = clothing.ComputeStatReq(StatType.Str);
  1409. if (str < strReq || (str + strBonus) < 1)
  1410. drop = true;
  1411. }
  1412. if (drop)
  1413. {
  1414. string name = clothing.Name;
  1415. if (name == null)
  1416. name = String.Format("#{0}", clothing.LabelNumber);
  1417. from.SendLocalizedMessage(1062002, name); // You can no longer wear your ~1_ARMOR~
  1418. from.AddToBackpack(clothing);
  1419. moved = true;
  1420. }
  1421. }
  1422. FactionItem factionItem = FactionItem.Find(item);
  1423. if (factionItem != null)
  1424. {
  1425. bool drop = false;
  1426. Faction ourFaction = Faction.Find(this);
  1427. if (ourFaction == null || ourFaction != factionItem.Faction)
  1428. drop = true;
  1429. else if (++factionItemCount > FactionItem.GetMaxWearables(this))
  1430. drop = true;
  1431. if (drop)
  1432. {
  1433. from.AddToBackpack(item);
  1434. moved = true;
  1435. }
  1436. }
  1437. }
  1438. if (moved)
  1439. from.SendLocalizedMessage(500647); // Some equipment has been moved to your backpack.
  1440. }
  1441. catch (Exception e)
  1442. {
  1443. Console.WriteLine(e);
  1444. }
  1445. finally
  1446. {
  1447. this.m_NoDeltaRecursion = false;
  1448. }
  1449. }
  1450. public override void Delta(MobileDelta flag)
  1451. {
  1452. base.Delta(flag);
  1453. if ((flag & MobileDelta.Stat) != 0)
  1454. this.ValidateEquipment();
  1455. if ((flag & (MobileDelta.Name | MobileDelta.Hue)) != 0)
  1456. this.InvalidateMyRunUO();
  1457. }
  1458. private static void Disconnect(object state)
  1459. {
  1460. NetState ns = ((Mobile)state).NetState;
  1461. if (ns != null)
  1462. ns.Dispose();
  1463. }
  1464. private static void OnLogout(LogoutEventArgs e)
  1465. {
  1466. if (e.Mobile is PlayerMobile)
  1467. ((PlayerMobile)e.Mobile).AutoStablePets();
  1468. #region Scroll of Alacrity
  1469. if (((PlayerMobile)e.Mobile).AcceleratedStart > DateTime.Now)
  1470. {
  1471. ((PlayerMobile)e.Mobile).AcceleratedStart = DateTime.Now;
  1472. Server.Items.ScrollofAlacrity.AlacrityEnd((PlayerMobile)e.Mobile);
  1473. }
  1474. #endregion
  1475. }
  1476. private static void EventSink_Connected(ConnectedEventArgs e)
  1477. {
  1478. PlayerMobile pm = e.Mobile as PlayerMobile;
  1479. if (pm != null)
  1480. {
  1481. pm.m_SessionStart = DateTime.Now;
  1482. if (pm.m_Quest != null)
  1483. pm.m_Quest.StartTimer();
  1484. #region Mondain's Legacy
  1485. QuestHelper.StartTimer(pm);
  1486. #endregion
  1487. pm.BedrollLogout = false;
  1488. pm.LastOnline = DateTime.Now;
  1489. }
  1490. DisguiseTimers.StartTimer(e.Mobile);
  1491. Timer.DelayCall(TimeSpan.Zero, new TimerStateCallback(ClearSpecialMovesCallback), e.Mobile);
  1492. }
  1493. private static void ClearSpecialMovesCallback(object state)
  1494. {
  1495. Mobile from = (Mobile)state;
  1496. SpecialMove.ClearAllMoves(from);
  1497. }
  1498. private static void EventSink_Disconnected(DisconnectedEventArgs e)
  1499. {
  1500. Mobile from = e.Mobile;
  1501. DesignContext context = DesignContext.Find(from);
  1502. if (context != null)
  1503. {
  1504. /* Client disconnected
  1505. * - Remove design context
  1506. * - Eject all from house
  1507. * - Restore relocated entities
  1508. */
  1509. // Remove design context
  1510. DesignContext.Remove(from);
  1511. // Eject all from house
  1512. from.RevealingAction();
  1513. foreach (Item item in context.Foundation.GetItems())
  1514. item.Location = context.Foundation.BanLocation;
  1515. foreach (Mobile mobile in context.Foundation.GetMobiles())
  1516. mobile.Location = context.Foundation.BanLocation;
  1517. // Restore relocated entities
  1518. context.Foundation.RestoreRelocatedEntities();
  1519. }
  1520. PlayerMobile pm = e.Mobile as PlayerMobile;
  1521. if (pm != null)
  1522. {
  1523. pm.m_GameTime += (DateTime.Now - pm.m_SessionStart);
  1524. if (pm.m_Quest != null)
  1525. pm.m_Quest.StopTimer();
  1526. #region Mondain's Legacy
  1527. QuestHelper.StopTimer(pm);
  1528. #endregion
  1529. pm.m_SpeechLog = null;
  1530. pm.LastOnline = DateTime.Now;
  1531. }
  1532. DisguiseTimers.StopTimer(from);
  1533. }
  1534. public override void RevealingAction()
  1535. {
  1536. if (this.m_DesignContext != null)
  1537. return;
  1538. Spells.Sixth.InvisibilitySpell.RemoveTimer(this);
  1539. base.RevealingAction();
  1540. this.m_IsStealthing = false; // IsStealthing should be moved to Server.Mobiles
  1541. }
  1542. [CommandProperty(AccessLevel.GameMaster)]
  1543. public override bool Hidden
  1544. {
  1545. get
  1546. {
  1547. return base.Hidden;
  1548. }
  1549. set
  1550. {
  1551. base.Hidden = value;
  1552. this.RemoveBuff(BuffIcon.Invisibility); //Always remove, default to the hiding icon EXCEPT in the invis spell where it's explicitly set
  1553. if (!this.Hidden)
  1554. {
  1555. this.RemoveBuff(BuffIcon.HidingAndOrStealth);
  1556. }
  1557. else // if( !InvisibilitySpell.HasTimer( this ) )
  1558. {
  1559. BuffInfo.AddBuff(this, new BuffInfo(BuffIcon.HidingAndOrStealth, 1075655)); //Hidden/Stealthing & You Are Hidden
  1560. }
  1561. }
  1562. }
  1563. public override void OnSubItemAdded(Item item)
  1564. {
  1565. if (this.AccessLevel < AccessLevel.GameMaster && item.IsChildOf(this.Backpack))
  1566. {
  1567. int maxWeight = WeightOverloading.GetMaxWeight(this);
  1568. int curWeight = Mobile.BodyWeight + this.TotalWeight;
  1569. if (curWeight > maxWeight)
  1570. this.SendLocalizedMessage(1019035, true, String.Format(" : {0} / {1}", curWeight, maxWeight));
  1571. }
  1572. }
  1573. public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness)
  1574. {
  1575. if (this.m_DesignContext != null || (target is PlayerMobile && ((PlayerMobile)target).m_DesignContext != null))
  1576. return false;
  1577. #region Mondain's Legacy
  1578. if (this.Peaced)
  1579. {
  1580. //!+ TODO: message
  1581. return false;
  1582. }
  1583. #endregion
  1584. if ((target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier)
  1585. {
  1586. if (message)
  1587. {
  1588. if (target.Title == null)
  1589. this.SendMessage("{0} the vendor cannot be harmed.", target.Name);
  1590. else
  1591. this.SendMessage("{0} {1} cannot be harmed.", target.Name, target.Title);
  1592. }
  1593. return false;
  1594. }
  1595. return base.CanBeHarmful(target, message, ignoreOurBlessedness);
  1596. }
  1597. public override bool CanBeBeneficial(Mobile target, bool message, bool allowDead)
  1598. {
  1599. if (this.m_DesignContext != null || (target is PlayerMobile && ((PlayerMobile)target).m_DesignContext != null))
  1600. return false;
  1601. return base.CanBeBeneficial(target, message, allowDead);
  1602. }
  1603. public override bool CheckContextMenuDisplay(IEntity target)
  1604. {
  1605. return (this.m_DesignContext == null);
  1606. }
  1607. public override void OnItemAdded(Item item)
  1608. {
  1609. base.OnItemAdded(item);
  1610. if (item is BaseArmor || item is BaseWeapon)
  1611. {
  1612. this.Hits = this.Hits;
  1613. this.Stam = this.Stam;
  1614. this.Mana = this.Mana;
  1615. }
  1616. if (this.NetState != null)
  1617. this.CheckLightLevels(false);
  1618. this.InvalidateMyRunUO();
  1619. }
  1620. public override void OnItemRemoved(Item item)
  1621. {
  1622. base.OnItemRemoved(item);
  1623. if (item is BaseArmor || item is BaseWeapon)
  1624. {
  1625. this.Hits = this.Hits;
  1626. this.Stam = this.Stam;
  1627. this.Mana = this.Mana;
  1628. }
  1629. if (this.NetState != null)
  1630. this.CheckLightLevels(false);
  1631. this.InvalidateMyRunUO();
  1632. }
  1633. public override double ArmorRating
  1634. {
  1635. get
  1636. {
  1637. //BaseArmor ar;
  1638. double rating = 0.0;
  1639. this.AddArmorRating(ref rating, this.NeckArmor);
  1640. this.AddArmorRating(ref rating, this.HandArmor);
  1641. this.AddArmorRating(ref rating, this.HeadArmor);
  1642. this.AddArmorRating(ref rating, this.ArmsArmor);
  1643. this.AddArmorRating(ref rating, this.LegsArmor);
  1644. this.AddArmorRating(ref rating, this.ChestArmor);
  1645. this.AddArmorRating(ref rating, this.ShieldArmor);
  1646. return this.VirtualArmor + this.VirtualArmorMod + rating;
  1647. }
  1648. }
  1649. private void AddArmorRating(ref double rating, Item armor)
  1650. {
  1651. BaseArmor ar = armor as BaseArmor;
  1652. if (ar != null && (!Core.AOS || ar.ArmorAttributes.MageArmor == 0))
  1653. rating += ar.ArmorRatingScaled;
  1654. }
  1655. #region [Stats]Max
  1656. [CommandProperty(AccessLevel.GameMaster)]
  1657. public override int HitsMax
  1658. {
  1659. get
  1660. {
  1661. int strBase;
  1662. int strOffs = this.GetStatOffset(StatType.Str);
  1663. if (Core.AOS)
  1664. {
  1665. strBase = this.Str; //this.Str already includes GetStatOffset/str
  1666. strOffs = AosAttributes.GetValue(this, AosAttribute.BonusHits);
  1667. if (Core.ML && strOffs > 25 && this.IsPlayer())
  1668. strOffs = 25;
  1669. if (AnimalForm.UnderTransformation(this, typeof(BakeKitsune)) || AnimalForm.UnderTransformation(this, typeof(GreyWolf)))
  1670. strOffs += 20;
  1671. }
  1672. else
  1673. {
  1674. strBase = this.RawStr;
  1675. }
  1676. return (strBase / 2) + 50 + strOffs;
  1677. }
  1678. }
  1679. [CommandProperty(AccessLevel.GameMaster)]
  1680. public override int StamMax
  1681. {
  1682. get
  1683. {
  1684. return base.StamMax + AosAttributes.GetValue(this, AosAttribute.BonusStam);
  1685. }
  1686. }
  1687. [CommandProperty(AccessLevel.GameMaster)]
  1688. public override int ManaMax
  1689. {
  1690. get
  1691. {
  1692. return base.ManaMax + AosAttributes.GetValue(this, AosAttribute.BonusMana) + ((Core.ML && this.Race == Race.Elf) ? 20 : 0);
  1693. }
  1694. }
  1695. #endregion
  1696. #region Stat Getters/Setters
  1697. [CommandProperty(AccessLevel.GameMaster)]
  1698. public override int Str
  1699. {
  1700. get
  1701. {
  1702. if (Core.ML && this.IsPlayer())
  1703. return Math.Min(base.Str, 150);
  1704. return base.Str;
  1705. }
  1706. set
  1707. {
  1708. base.Str = value;
  1709. }
  1710. }
  1711. [CommandProperty(AccessLevel.GameMaster)]
  1712. public override int Int
  1713. {
  1714. get
  1715. {
  1716. if (Core.ML && this.IsPlayer())
  1717. return Math.Min(base.Int, 150);
  1718. return base.Int;
  1719. }
  1720. set
  1721. {
  1722. base.Int = value;
  1723. }
  1724. }
  1725. [CommandProperty(AccessLevel.GameMaster)]
  1726. public override int Dex
  1727. {
  1728. get
  1729. {
  1730. if (Core.ML && this.IsPlayer())
  1731. return Math.Min(base.Dex, 150);
  1732. return base.Dex;
  1733. }
  1734. set
  1735. {
  1736. base.Dex = value;
  1737. }
  1738. }
  1739. #endregion
  1740. public override bool Move(Direction d)
  1741. {
  1742. NetState ns = this.NetState;
  1743. if (ns != null)
  1744. {
  1745. if (this.HasGump(typeof(ResurrectGump)))
  1746. {
  1747. if (this.Alive)
  1748. {
  1749. this.CloseGump(typeof(ResurrectGump));
  1750. }
  1751. else
  1752. {
  1753. this.SendLocalizedMessage(500111); // You are frozen and cannot move.
  1754. return false;
  1755. }
  1756. }
  1757. }
  1758. TimeSpan speed = this.ComputeMovementSpeed(d);
  1759. bool res;
  1760. if (!this.Alive)
  1761. Server.Movement.MovementImpl.IgnoreMovableImpassables = true;
  1762. res = base.Move(d);
  1763. Server.Movement.MovementImpl.IgnoreMovableImpassables = false;
  1764. if (!res)
  1765. return false;
  1766. this.m_NextMovementTime += speed;
  1767. return true;
  1768. }
  1769. public override bool CheckMovement(Direction d, out int newZ)
  1770. {
  1771. DesignContext context = this.m_DesignContext;
  1772. if (context == null)
  1773. return base.CheckMovement(d, out newZ);
  1774. HouseFoundation foundation = context.Foundation;
  1775. newZ = foundation.Z + HouseFoundation.GetLevelZ(context.Level, context.Foundation);
  1776. int newX = this.X, newY = this.Y;
  1777. Movement.Movement.Offset(d, ref newX, ref newY);
  1778. int startX = foundation.X + foundation.Components.Min.X + 1;
  1779. int startY = foundation.Y + foundation.Components.Min.Y + 1;
  1780. int endX = startX + foundation.Components.Width - 1;
  1781. int endY = startY + foundation.Components.Height - 2;
  1782. return (newX >= startX && newY >= startY && newX < endX && newY < endY && this.Map == foundation.Map);
  1783. }
  1784. public override bool AllowItemUse(Item item)
  1785. {
  1786. #region Dueling
  1787. if (this.m_DuelContext != null && !this.m_DuelContext.AllowItemUse(this, item))
  1788. return false;
  1789. #endregion
  1790. return DesignContext.Check(this);
  1791. }
  1792. public SkillName[] AnimalFormRestrictedSkills
  1793. {
  1794. get
  1795. {
  1796. return this.m_AnimalFormRestrictedSkills;
  1797. }
  1798. }
  1799. private SkillName[] m_AnimalFormRestrictedSkills = new SkillName[]
  1800. {
  1801. SkillName.ArmsLore, SkillName.Begging, SkillName.Discordance, SkillName.Forensics,
  1802. SkillName.Inscribe, SkillName.ItemID, SkillName.Meditation, SkillName.Peacemaking,
  1803. SkillName.Provocation, SkillName.RemoveTrap, SkillName.SpiritSpeak, SkillName.Stealing,
  1804. SkillName.TasteID
  1805. };
  1806. public override bool AllowSkillUse(SkillName skill)
  1807. {
  1808. if (AnimalForm.UnderTransformation(this))
  1809. {
  1810. for (int i = 0; i < this.m_AnimalFormRestrictedSkills.Length; i++)
  1811. {
  1812. if (this.m_AnimalFormRestrictedSkills[i] == skill)
  1813. {
  1814. #region Mondain's Legacy
  1815. AnimalFormContext context = AnimalForm.GetContext(this);
  1816. if (skill == SkillName.Stealing && context.StealingMod.Value > 0)
  1817. continue;
  1818. #endregion
  1819. this.SendLocalizedMessage(1070771); // You cannot use that skill in this form.
  1820. return false;
  1821. }
  1822. }
  1823. }
  1824. #region Dueling
  1825. if (this.m_DuelContext != null && !this.m_DuelContext.AllowSkillUse(this, skill))
  1826. return false;
  1827. #endregion
  1828. return DesignContext.Check(this);
  1829. }
  1830. private bool m_LastProtectedMessage;
  1831. private int m_NextProtectionCheck = 10;
  1832. public virtual void RecheckTownProtection()
  1833. {
  1834. this.m_NextProtectionCheck = 10;
  1835. Regions.GuardedRegion reg = (Regions.GuardedRegion)this.Region.GetRegion(typeof(Regions.GuardedRegion));
  1836. bool isProtected = (reg != null && !reg.IsDisabled());
  1837. if (isProtected != this.m_LastProtectedMessage)
  1838. {
  1839. if (isProtected)
  1840. this.SendLocalizedMessage(500112); // You are now under the protection of the town guards.
  1841. else
  1842. this.SendLocalizedMessage(500113); // You have left the protection of the town guards.
  1843. this.m_LastProtectedMessage = isProtected;
  1844. }
  1845. }
  1846. public override void MoveToWorld(Point3D loc, Map map)
  1847. {
  1848. base.MoveToWorld(loc, map);
  1849. this.RecheckTownProtection();
  1850. }
  1851. public override void SetLocation(Point3D loc, bool isTeleport)
  1852. {
  1853. if (!isTeleport && this.IsPlayer())
  1854. {
  1855. // moving, not teleporting
  1856. int zDrop = (this.Location.Z - loc.Z);
  1857. if (zDrop > 20) // we fell more than one story
  1858. this.Hits -= ((zDrop / 20) * 10) - 5; // deal some damage; does not kill, disrupt, etc
  1859. }
  1860. base.SetLocation(loc, isTeleport);
  1861. if (isTeleport || --this.m_NextProtectionCheck == 0)
  1862. this.RecheckTownProtection();
  1863. }
  1864. public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
  1865. {
  1866. base.GetContextMenuEntries(from, list);
  1867. if (from == this)
  1868. {
  1869. if (this.m_Quest != null)
  1870. this.m_Quest.GetContextMenuEntries(list);
  1871. if (this.Alive && InsuranceEnabled)
  1872. {
  1873. list.Add(new CallbackEntry(6201, new ContextCallback(ToggleItemInsurance)));
  1874. if (this.AutoRenewInsurance)
  1875. list.Add(new CallbackEntry(6202, new ContextCallback(CancelRenewInventoryInsurance)));
  1876. else
  1877. list.Add(new CallbackEntry(6200, new ContextCallback(AutoRenewInventoryInsurance)));
  1878. }
  1879. BaseHouse house = BaseHouse.FindHouseAt(this);
  1880. if (house != null)
  1881. {
  1882. if (this.Alive && house.InternalizedVendors.Count > 0 && house.IsOwner(this))
  1883. list.Add(new CallbackEntry(6204, new ContextCallback(GetVendor)));
  1884. if (house.IsAosRules && !this.Region.IsPartOf(typeof(Engines.ConPVP.SafeZone))) // Dueling
  1885. list.Add(new CallbackEntry(6207, new ContextCallback(LeaveHouse)));
  1886. }
  1887. if (this.m_JusticeProtectors.Count > 0)
  1888. list.Add(new CallbackEntry(6157, new ContextCallback(CancelProtection)));
  1889. if (this.Alive)
  1890. list.Add(new CallbackEntry(6210, new ContextCallback(ToggleChampionTitleDisplay)));
  1891. #region Mondain's Legacy
  1892. if (this.Alive)
  1893. {
  1894. QuestHelper.GetContextMenuEntries(list);
  1895. if (this.m_CollectionTitles.Count > 0)
  1896. list.Add(new CallbackEntry(6229, new ContextCallback(ShowChangeTitle)));
  1897. }
  1898. #endregion
  1899. }
  1900. if (from != this)
  1901. {
  1902. if (this.Alive && Core.Expansion >= Expansion.AOS)
  1903. {
  1904. Party theirParty = from.Party as Party;
  1905. Party ourParty = this.Party as Party;
  1906. if (theirParty == null && ourParty == null)
  1907. {
  1908. list.Add(new AddToPartyEntry(from, this));
  1909. }
  1910. else if (theirParty != null && theirParty.Leader == from)
  1911. {
  1912. if (ourParty == null)
  1913. {
  1914. list.Add(new AddToPartyEntry(from, this));
  1915. }
  1916. else if (ourParty == theirParty)
  1917. {
  1918. list.Add(new RemoveFromPartyEntry(from, this));
  1919. }
  1920. }
  1921. }
  1922. BaseHouse curhouse = BaseHouse.FindHouseAt(this);
  1923. if (curhouse != null)
  1924. {
  1925. if (this.Alive && Core.Expansion >= Expansion.AOS && curhouse.IsAosRules && curhouse.IsFriend(from))
  1926. list.Add(new EjectPlayerEntry(from, this));
  1927. }
  1928. }
  1929. }
  1930. private void CancelProtection()
  1931. {
  1932. for (int i = 0; i < this.m_JusticeProtectors.Count; ++i)
  1933. {
  1934. Mobile prot = this.m_JusticeProtectors[i];
  1935. string args = String.Format("{0}\t{1}", this.Name, prot.Name);
  1936. prot.SendLocalizedMessage(1049371, args); // The protective relationship between ~1_PLAYER1~ and ~2_PLAYER2~ has been ended.
  1937. this.SendLocalizedMessage(1049371, args); // The protective relationship between ~1_PLAYER1~ and ~2_PLAYER2~ has been ended.
  1938. }
  1939. this.m_JusticeProtectors.Clear();
  1940. }
  1941. #region Insurance
  1942. private void ToggleItemInsurance()
  1943. {
  1944. if (!this.CheckAlive())
  1945. return;
  1946. this.BeginTarget(-1, false, TargetFlags.None, new TargetCallback(ToggleItemInsurance_Callback));
  1947. this.SendLocalizedMessage(1060868); // Target the item you wish to toggle insurance status on <ESC> to cancel
  1948. }
  1949. private bool CanInsure(Item item)
  1950. {
  1951. #region Mondain's Legacy
  1952. if (item is BaseQuiver && item.LootType == LootType.Regular)
  1953. return true;
  1954. #endregion
  1955. if (((item is Container) && !(item is BaseQuiver)) || item is BagOfSending || item is KeyRing)
  1956. return false;
  1957. if ((item is Spellbook && item.LootType == LootType.Blessed) || item is Runebook || item is PotionKeg || item is Sigil)
  1958. return false;
  1959. if (item.Stackable)
  1960. return false;
  1961. if (item.LootType == LootType.Cursed)
  1962. return false;
  1963. if (item.ItemID == 0x204E) // death shroud
  1964. return false;
  1965. return true;
  1966. }
  1967. private void ToggleItemInsurance_Callback(Mobile from, object obj)
  1968. {
  1969. if (!this.CheckAlive())
  1970. return;
  1971. Item item = obj as Item;
  1972. if (item == null || !item.IsChildOf(this))
  1973. {
  1974. this.BeginTarget(-1, false, TargetFlags.None, new TargetCallback(ToggleItemInsurance_Callback));
  1975. this.SendLocalizedMessage(1060871, "", 0x23); // You can only insure items that you have equipped or that are in your backpack
  1976. }
  1977. else if (item.Insured)
  1978. {
  1979. item.Insured = false;
  1980. this.SendLocalizedMessage(1060874, "", 0x35); // You cancel the insurance on the item
  1981. this.BeginTarget(-1, false, TargetFlags.None, new TargetCallback(ToggleItemInsurance_Callback));
  1982. this.SendLocalizedMessage(1060868, "", 0x23); // Target the item you wish to toggle insurance status on <ESC> to cancel
  1983. }
  1984. else if (!this.CanInsure(item))
  1985. {
  1986. this.BeginTarget(-1, false, TargetFlags.None, new TargetCallback(ToggleItemInsurance_Callback));
  1987. this.SendLocalizedMessage(1060869, "", 0x23); // You cannot insure th…