#region References using System; using System.Collections.Generic; using Server.Commands; using Server.Engines.Craft; using Server.Ethics; using Server.Multis; using Server.Network; using Server.Spells; using Server.Targeting; using Server.Mobiles; using Server.Spells.Mysticism; using Server.Factions; #endregion namespace Server.Items { public enum SpellbookType { Invalid = -1, Regular, Necromancer, Paladin, Ninja, Samurai, Arcanist, Mystic, SkillMasteries } public enum BookQuality { Regular, Exceptional, } public class Spellbook : Item, ICraftable, ISlayer, IEngravable, IVvVItem, IOwnerRestricted, IWearableDurability, IFactionItem { private static readonly Dictionary> m_Table = new Dictionary>(); private static readonly int[] m_LegendPropertyCounts = new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 properties : 21/52 : 40% 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 property : 15/52 : 29% 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 2 properties : 10/52 : 19% 3, 3, 3, 3, 3, 3 // 3 properties : 6/52 : 12% }; private static readonly int[] m_ElderPropertyCounts = new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 properties : 15/34 : 44% 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1 property : 10/34 : 29% 2, 2, 2, 2, 2, 2, // 2 properties : 6/34 : 18% 3, 3, 3 // 3 properties : 3/34 : 9% }; private static readonly int[] m_GrandPropertyCounts = new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 properties : 10/20 : 50% 1, 1, 1, 1, 1, 1, // 1 property : 6/20 : 30% 2, 2, 2, // 2 properties : 3/20 : 15% 3 // 3 properties : 1/20 : 5% }; private static readonly int[] m_MasterPropertyCounts = new[] { 0, 0, 0, 0, 0, 0, // 0 properties : 6/10 : 60% 1, 1, 1, // 1 property : 3/10 : 30% 2 // 2 properties : 1/10 : 10% }; private static readonly int[] m_AdeptPropertyCounts = new[] { 0, 0, 0, // 0 properties : 3/4 : 75% 1 // 1 property : 1/4 : 25% }; #region Factions private FactionItem m_FactionState; public FactionItem FactionItemState { get { return m_FactionState; } set { m_FactionState = value; LootType = (m_FactionState == null ? LootType.Regular : LootType.Blessed); } } #endregion private string m_EngravedText; private BookQuality m_Quality; private AosAttributes m_AosAttributes; private AosSkillBonuses m_AosSkillBonuses; private NegativeAttributes m_NegativeAttributes; private ulong m_Content; private int m_Count; private Mobile m_Crafter; private SlayerName m_Slayer; private SlayerName m_Slayer2; //Currently though there are no dual slayer spellbooks, OSI has a habit of putting dual slayer stuff in later [Constructable] public Spellbook() : this((ulong)0) { } [Constructable] public Spellbook(ulong content) : this(content, 0xEFA) { } public Spellbook(ulong content, int itemID) : base(itemID) { m_AosAttributes = new AosAttributes(this); m_AosSkillBonuses = new AosSkillBonuses(this); m_NegativeAttributes = new NegativeAttributes(this); Weight = 3.0; Layer = Layer.OneHanded; LootType = LootType.Blessed; Content = content; } public Spellbook(Serial serial) : base(serial) { } [CommandProperty(AccessLevel.GameMaster)] public string EngravedText { get { return m_EngravedText; } set { m_EngravedText = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public BookQuality Quality { get { return m_Quality; } set { m_Quality = value; InvalidateProperties(); } } public override bool DisplayWeight { get { return false; } } [CommandProperty(AccessLevel.GameMaster)] public AosAttributes Attributes { get { return m_AosAttributes; } set { } } [CommandProperty(AccessLevel.GameMaster)] public AosSkillBonuses SkillBonuses { get { return m_AosSkillBonuses; } set { } } [CommandProperty(AccessLevel.GameMaster)] public NegativeAttributes NegativeAttributes { get { return m_NegativeAttributes; } set { } } public virtual SpellbookType SpellbookType { get { return SpellbookType.Regular; } } public virtual int BookOffset { get { return 0; } } public virtual int BookCount { get { return 64; } } [CommandProperty(AccessLevel.GameMaster)] public ulong Content { get { return m_Content; } set { if (m_Content != value) { m_Content = value; m_Count = 0; while (value > 0) { m_Count += (int)(value & 0x1); value >>= 1; } InvalidateProperties(); } } } [CommandProperty(AccessLevel.GameMaster)] public int SpellCount { get { return m_Count; } } [CommandProperty(AccessLevel.GameMaster)] public Mobile Crafter { get { return m_Crafter; } set { m_Crafter = value; InvalidateProperties(); } } public override bool DisplayLootType { get { return Core.AOS; } } [CommandProperty(AccessLevel.GameMaster)] public SlayerName Slayer { get { return m_Slayer; } set { m_Slayer = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public SlayerName Slayer2 { get { return m_Slayer2; } set { m_Slayer2 = value; InvalidateProperties(); } } #region IVvVItem / IOwnerRestricted private bool _VvVItem; private Mobile _Owner; private string _OwnerName; [CommandProperty(AccessLevel.GameMaster)] public bool IsVvVItem { get { return _VvVItem; } set { _VvVItem = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public Mobile Owner { get { return _Owner; } set { _Owner = value; if (_Owner != null) _OwnerName = _Owner.Name; InvalidateProperties(); } } public virtual string OwnerName { get { return _OwnerName; } set { _OwnerName = value; InvalidateProperties(); } } #endregion #region IWearableDurability private int m_MaxHitPoints; private int m_HitPoints; [CommandProperty(AccessLevel.GameMaster)] public int HitPoints { get { return m_HitPoints; } set { if (m_HitPoints == value) { return; } if (value > m_MaxHitPoints) { value = m_MaxHitPoints; } m_HitPoints = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public int MaxHitPoints { get { return m_MaxHitPoints; } set { m_MaxHitPoints = value; InvalidateProperties(); } } public virtual bool CanFortify { get { return false; } } public virtual int InitMinHits { get { return 0; } } public virtual int InitMaxHits { get { return 0; } } public virtual void ScaleDurability() { } public virtual void UnscaleDurability() { } public virtual int OnHit(BaseWeapon weap, int damage) { if (m_MaxHitPoints == 0) return damage; int chance = m_NegativeAttributes.Antique > 0 ? 50 : 25; if (chance > Utility.Random(100)) // 25% chance to lower durability { if (m_HitPoints >= 1) { HitPoints--; } else if (m_MaxHitPoints > 0) { MaxHitPoints--; if (Parent is Mobile) ((Mobile)Parent).LocalOverheadMessage(MessageType.Regular, 0x3B2, 1061121); // Your equipment is severely damaged. if (m_MaxHitPoints == 0) { Delete(); } } } return damage; } #endregion public static void Initialize() { EventSink.OpenSpellbookRequest += EventSink_OpenSpellbookRequest; EventSink.CastSpellRequest += EventSink_CastSpellRequest; EventSink.TargetedSpell += Targeted_Spell; CommandSystem.Register("AllSpells", AccessLevel.GameMaster, AllSpells_OnCommand); } #region Enhanced Client private static void Targeted_Spell(TargetedSpellEventArgs e) { try { Mobile from = e.Mobile; if (!DesignContext.Check(from)) { return; // They are customizing } Spellbook book = null; int spellID = e.SpellID; if (book == null || !book.HasSpell(spellID)) { book = Find(from, spellID); } if (book != null && book.HasSpell(spellID)) { SpecialMove move = SpellRegistry.GetSpecialMove(spellID); if (move != null) { SpecialMove.SetCurrentMove(from, move); } else { Mobile to = World.FindMobile(e.Target.Serial); Item toI = World.FindItem(e.Target.Serial); Spell spell = SpellRegistry.NewSpell(spellID, from, null); if (to != null) { spell.InstantTarget = to; } else if (toI != null) { spell.InstantTarget = toI as IDamageableItem; } if (spell != null) { spell.Cast(); } else if (!Server.Spells.SkillMasteries.MasteryInfo.IsPassiveMastery(spellID)) { from.SendLocalizedMessage(502345); // This spell has been temporarily disabled. } } } else { from.SendLocalizedMessage(500015); // You do not have that spell! } } catch { } } #endregion public static SpellbookType GetTypeForSpell(int spellID) { if (spellID >= 0 && spellID < 64) { return SpellbookType.Regular; } else if (spellID >= 100 && spellID < 117) { return SpellbookType.Necromancer; } else if (spellID >= 200 && spellID < 210) { return SpellbookType.Paladin; } else if (spellID >= 400 && spellID < 406) { return SpellbookType.Samurai; } else if (spellID >= 500 && spellID < 508) { return SpellbookType.Ninja; } else if (spellID >= 600 && spellID < 617) { return SpellbookType.Arcanist; } else if (spellID >= 677 && spellID < 693) { return SpellbookType.Mystic; } else if (spellID >= 700 && spellID < 746) { return SpellbookType.SkillMasteries; } return SpellbookType.Invalid; } public static Spellbook FindRegular(Mobile from) { return Find(from, -1, SpellbookType.Regular); } public static Spellbook FindNecromancer(Mobile from) { return Find(from, -1, SpellbookType.Necromancer); } public static Spellbook FindPaladin(Mobile from) { return Find(from, -1, SpellbookType.Paladin); } public static Spellbook FindSamurai(Mobile from) { return Find(from, -1, SpellbookType.Samurai); } public static Spellbook FindNinja(Mobile from) { return Find(from, -1, SpellbookType.Ninja); } public static Spellbook FindArcanist(Mobile from) { return Find(from, -1, SpellbookType.Arcanist); } public static Spellbook FindMystic(Mobile from) { return Find(from, -1, SpellbookType.Mystic); } public static Spellbook Find(Mobile from, int spellID) { return Find(from, spellID, GetTypeForSpell(spellID)); } public static Spellbook Find(Mobile from, int spellID, SpellbookType type) { if (from == null) { return null; } if (from.Deleted) { m_Table.Remove(from); return null; } List list = null; m_Table.TryGetValue(from, out list); bool searchAgain = false; if (list == null) { m_Table[from] = list = FindAllSpellbooks(from); } else { searchAgain = true; } Spellbook book = FindSpellbookInList(list, from, spellID, type); if (book == null && searchAgain) { m_Table[from] = list = FindAllSpellbooks(from); book = FindSpellbookInList(list, from, spellID, type); } return book; } public static Spellbook FindSpellbookInList(List list, Mobile from, int spellID, SpellbookType type) { Container pack = from.Backpack; for (int i = list.Count - 1; i >= 0; --i) { if (i >= list.Count) { continue; } Spellbook book = list[i]; if (!book.Deleted && (book.Parent == from || (pack != null && book.Parent == pack)) && ValidateSpellbook(book, spellID, type)) { return book; } list.RemoveAt(i); } return null; } public static List FindAllSpellbooks(Mobile from) { var list = new List(); Item item = from.FindItemOnLayer(Layer.OneHanded); if (item is Spellbook) { list.Add((Spellbook)item); } Container pack = from.Backpack; if (pack == null) { return list; } for (int i = 0; i < pack.Items.Count; ++i) { item = pack.Items[i]; if (item is Spellbook) { list.Add((Spellbook)item); } } return list; } public static Spellbook FindEquippedSpellbook(Mobile from) { return (from.FindItemOnLayer(Layer.OneHanded) as Spellbook); } public static bool ValidateSpellbook(Spellbook book, int spellID, SpellbookType type) { return (book.SpellbookType == type && (spellID == -1 || book.HasSpell(spellID))); } public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted) { if (!Ethic.CheckTrade(from, to, newOwner, this)) { return false; } return base.AllowSecureTrade(from, to, newOwner, accepted); } public override bool CanEquip(Mobile from) { if (!Ethic.CheckEquip(from, this)) { return false; } else if (!from.CanBeginAction(typeof(BaseWeapon))) { return false; } else if (_Owner != null && _Owner != from) { from.SendLocalizedMessage(501023); // You must be the owner to use this item. return false; } else if (IsVvVItem && !Engines.VvV.ViceVsVirtueSystem.IsVvV(from)) { from.SendLocalizedMessage(1155496); // This item can only be used by VvV participants! return false; } return base.CanEquip(from); } public override bool AllowEquipedCast(Mobile from) { return true; } public override bool OnDragDrop(Mobile from, Item dropped) { if (dropped is SpellScroll && !(dropped is SpellStone)) { SpellScroll scroll = (SpellScroll)dropped; SpellbookType type = GetTypeForSpell(scroll.SpellID); if (type != SpellbookType) { return false; } else if (HasSpell(scroll.SpellID)) { from.SendLocalizedMessage(500179); // That spell is already present in that spellbook. return false; } else { int val = scroll.SpellID - BookOffset; if (val >= 0 && val < BookCount) { from.Send(new PlaySound(0x249, GetWorldLocation())); m_Content |= (ulong)1 << val; ++m_Count; if (dropped.Amount > 1) { dropped.Amount--; return base.OnDragDrop(from, dropped); } else { InvalidateProperties(); scroll.Delete(); return true; } } return false; } } return false; } public override void OnAfterDuped(Item newItem) { Spellbook book = newItem as Spellbook; if (book == null) { return; } book.m_AosAttributes = new AosAttributes(newItem, m_AosAttributes); book.m_AosSkillBonuses = new AosSkillBonuses(newItem, m_AosSkillBonuses); book.m_NegativeAttributes = new NegativeAttributes(newItem, m_NegativeAttributes); base.OnAfterDuped(newItem); } public override void OnAdded(object parent) { if (Core.AOS && parent is Mobile) { Mobile from = (Mobile)parent; m_AosSkillBonuses.AddTo(from); int strBonus = m_AosAttributes.BonusStr; int dexBonus = m_AosAttributes.BonusDex; int intBonus = m_AosAttributes.BonusInt; if (strBonus != 0 || dexBonus != 0 || intBonus != 0) { string modName = Serial.ToString(); if (strBonus != 0) { from.AddStatMod(new StatMod(StatType.Str, modName + "Str", strBonus, TimeSpan.Zero)); } if (dexBonus != 0) { from.AddStatMod(new StatMod(StatType.Dex, modName + "Dex", dexBonus, TimeSpan.Zero)); } if (intBonus != 0) { from.AddStatMod(new StatMod(StatType.Int, modName + "Int", intBonus, TimeSpan.Zero)); } } if (HasSocket()) { Caddellite.UpdateBuff(from); } from.CheckStatTimers(); } } public override void OnRemoved(object parent) { if (Core.AOS && parent is Mobile) { Mobile from = (Mobile)parent; m_AosSkillBonuses.Remove(); if (HasSocket()) { Caddellite.UpdateBuff(from); } string modName = Serial.ToString(); from.RemoveStatMod(modName + "Str"); from.RemoveStatMod(modName + "Dex"); from.RemoveStatMod(modName + "Int"); from.CheckStatTimers(); } } public bool HasSpell(int spellID) { spellID -= BookOffset; return (spellID >= 0 && spellID < BookCount && (m_Content & ((ulong)1 << spellID)) != 0); } public void DisplayTo(Mobile to) { // The client must know about the spellbook or it will crash! NetState ns = to.NetState; if (ns == null) { return; } if (Parent == null) { to.Send(WorldPacket); } else if (Parent is Item) { // What will happen if the client doesn't know about our parent? if (ns.ContainerGridLines) { to.Send(new ContainerContentUpdate6017(this)); } else { to.Send(new ContainerContentUpdate(this)); } } else if (Parent is Mobile) { // What will happen if the client doesn't know about our parent? to.Send(new EquipUpdate(this)); } if (ns.HighSeas) { to.Send(new DisplaySpellbookHS(this)); } else { to.Send(new DisplaySpellbook(this)); } if (ObjectPropertyList.Enabled) { if (ns.NewSpellbook) { to.Send(new NewSpellbookContent(this, ItemID, BookOffset + 1, m_Content)); } else { if (ns.ContainerGridLines) { to.Send(new SpellbookContent6017(m_Count, BookOffset + 1, m_Content, this)); } else { to.Send(new SpellbookContent(m_Count, BookOffset + 1, m_Content, this)); } } } else { if (ns.ContainerGridLines) { to.Send(new SpellbookContent6017(m_Count, BookOffset + 1, m_Content, this)); } else { to.Send(new SpellbookContent(m_Count, BookOffset + 1, m_Content, this)); } } } public override void AddNameProperties(ObjectPropertyList list) { base.AddNameProperties(list); if (m_Quality == BookQuality.Exceptional) { list.Add(1063341); // exceptional } if (m_EngravedText != null) { list.Add(1072305, Utility.FixHtml(m_EngravedText)); // Engraved: ~1_INSCRIPTION~ } if (m_Crafter != null) { list.Add(1050043, m_Crafter.TitleName); // crafted by ~1_NAME~ } #region Factions FactionEquipment.AddFactionProperties(this, list); #endregion if (IsVvVItem) { list.Add(1154937); // VvV Item } if (OwnerName != null) { list.Add(1153213, OwnerName); } if (m_NegativeAttributes != null) { m_NegativeAttributes.GetProperties(list, this); } m_AosSkillBonuses.GetProperties(list); if (m_Slayer != SlayerName.None) { SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer); if (entry != null) { list.Add(entry.Title); } } if (m_Slayer2 != SlayerName.None) { SlayerEntry entry = SlayerGroup.GetEntryByName(m_Slayer2); if (entry != null) { list.Add(entry.Title); } } if (HasSocket()) { list.Add(1158662); // Caddellite Infused } int prop; if ((prop = m_AosAttributes.SpellChanneling) != 0) { list.Add(1060482); // spell channeling } if ((prop = m_AosAttributes.NightSight) != 0) { list.Add(1060441); // night sight } if ((prop = m_AosAttributes.BonusStr) != 0) { list.Add(1060485, prop.ToString()); // strength bonus ~1_val~ } if ((prop = m_AosAttributes.BonusDex) != 0) { list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~ } if ((prop = m_AosAttributes.BonusInt) != 0) { list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~ } if ((prop = m_AosAttributes.BonusHits) != 0) { list.Add(1060431, prop.ToString()); // hit point increase ~1_val~ } if ((prop = m_AosAttributes.BonusStam) != 0) { list.Add(1060484, prop.ToString()); // stamina increase ~1_val~ } if ((prop = m_AosAttributes.BonusMana) != 0) { list.Add(1060439, prop.ToString()); // mana increase ~1_val~ } if ((prop = m_AosAttributes.RegenHits) != 0) { list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~ } if ((prop = m_AosAttributes.RegenStam) != 0) { list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~ } if ((prop = m_AosAttributes.RegenMana) != 0) { list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~ } if ((prop = m_AosAttributes.Luck) != 0) { list.Add(1060436, prop.ToString()); // luck ~1_val~ } if ((prop = m_AosAttributes.EnhancePotions) != 0) { list.Add(1060411, prop.ToString()); // enhance potions ~1_val~% } if ((prop = m_AosAttributes.ReflectPhysical) != 0) { list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~% } if ((prop = m_AosAttributes.AttackChance) != 0) { list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~% } if ((prop = m_AosAttributes.WeaponSpeed) != 0) { list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~% } if ((prop = m_AosAttributes.WeaponDamage) != 0) { list.Add(1060401, prop.ToString()); // damage increase ~1_val~% } if ((prop = m_AosAttributes.DefendChance) != 0) { list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~% } if ((prop = m_AosAttributes.CastRecovery) != 0) { list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~ } if ((prop = m_AosAttributes.CastSpeed) != 0) { list.Add(1060413, prop.ToString()); // faster casting ~1_val~ } if ((prop = m_AosAttributes.SpellDamage) != 0) { list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~% } if ((prop = m_AosAttributes.LowerManaCost) != 0) { list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~% } if ((prop = m_AosAttributes.LowerRegCost) != 0) { list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~% } if (Core.ML && (prop = m_AosAttributes.IncreasedKarmaLoss) != 0) { list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~% } AddProperty(list); list.Add(1042886, m_Count.ToString()); // ~1_NUMBERS_OF_SPELLS~ Spells if (this.m_MaxHitPoints > 0) list.Add(1060639, "{0}\t{1}", this.m_HitPoints, this.m_MaxHitPoints); // durability ~1_val~ / ~2_val~ } public virtual void AddProperty(ObjectPropertyList list) { } public override void OnSingleClick(Mobile from) { base.OnSingleClick(from); if (m_Crafter != null) { LabelTo(from, 1050043, m_Crafter.TitleName); // crafted by ~1_NAME~ } LabelTo(from, 1042886, m_Count.ToString()); } public override void OnDoubleClick(Mobile from) { Container pack = from.Backpack; if (Parent == from || (pack != null && Parent == pack)) { DisplayTo(from); } else { from.SendLocalizedMessage(500207); // The spellbook must be in your backpack (and not in a container within) to open. } } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write(6); // version m_NegativeAttributes.Serialize(writer); writer.Write(m_HitPoints); writer.Write(m_MaxHitPoints); writer.Write(_VvVItem); writer.Write(_Owner); writer.Write(_OwnerName); writer.Write((byte)m_Quality); writer.Write(m_EngravedText); writer.Write(m_Crafter); writer.Write((int)m_Slayer); writer.Write((int)m_Slayer2); m_AosAttributes.Serialize(writer); m_AosSkillBonuses.Serialize(writer); writer.Write(m_Content); writer.Write(m_Count); } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); switch (version) { case 6: { m_NegativeAttributes = new NegativeAttributes(this, reader); m_MaxHitPoints = reader.ReadInt(); m_HitPoints = reader.ReadInt(); _VvVItem = reader.ReadBool(); _Owner = reader.ReadMobile(); _OwnerName = reader.ReadString(); goto case 5; } case 5: { m_Quality = (BookQuality)reader.ReadByte(); goto case 4; } case 4: { m_EngravedText = reader.ReadString(); goto case 3; } case 3: { m_Crafter = reader.ReadMobile(); goto case 2; } case 2: { m_Slayer = (SlayerName)reader.ReadInt(); m_Slayer2 = (SlayerName)reader.ReadInt(); goto case 1; } case 1: { m_AosAttributes = new AosAttributes(this, reader); m_AosSkillBonuses = new AosSkillBonuses(this, reader); goto case 0; } case 0: { m_Content = reader.ReadULong(); m_Count = reader.ReadInt(); break; } } if (m_AosAttributes == null) { m_AosAttributes = new AosAttributes(this); } if (m_AosSkillBonuses == null) { m_AosSkillBonuses = new AosSkillBonuses(this); } if (m_NegativeAttributes == null) { m_NegativeAttributes = new NegativeAttributes(this); } if (Core.AOS && Parent is Mobile) { m_AosSkillBonuses.AddTo((Mobile)Parent); } int strBonus = m_AosAttributes.BonusStr; int dexBonus = m_AosAttributes.BonusDex; int intBonus = m_AosAttributes.BonusInt; if (Parent is Mobile && (strBonus != 0 || dexBonus != 0 || intBonus != 0)) { Mobile m = (Mobile)Parent; string modName = Serial.ToString(); if (strBonus != 0) { m.AddStatMod(new StatMod(StatType.Str, modName + "Str", strBonus, TimeSpan.Zero)); } if (dexBonus != 0) { m.AddStatMod(new StatMod(StatType.Dex, modName + "Dex", dexBonus, TimeSpan.Zero)); } if (intBonus != 0) { m.AddStatMod(new StatMod(StatType.Int, modName + "Int", intBonus, TimeSpan.Zero)); } } if (Parent is Mobile) { ((Mobile)Parent).CheckStatTimers(); } } public virtual int OnCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, ITool tool, CraftItem craftItem, int resHue) { int magery = from.Skills.Magery.BaseFixedPoint; if (magery >= 800) { int[] propertyCounts; int minIntensity; int maxIntensity; if (magery >= 1000) { if (magery >= 1200) { propertyCounts = m_LegendPropertyCounts; } else if (magery >= 1100) { propertyCounts = m_ElderPropertyCounts; } else { propertyCounts = m_GrandPropertyCounts; } minIntensity = 55; maxIntensity = 75; } else if (magery >= 900) { propertyCounts = m_MasterPropertyCounts; minIntensity = 25; maxIntensity = 45; } else { propertyCounts = m_AdeptPropertyCounts; minIntensity = 0; maxIntensity = 15; } int propertyCount = propertyCounts[Utility.Random(propertyCounts.Length)]; GuaranteedSpellbookImprovementTalisman talisman = from.FindItemOnLayer(Layer.Talisman) as GuaranteedSpellbookImprovementTalisman; if (talisman != null && talisman.Charges > 0) { propertyCount++; talisman.Charges--; from.SendLocalizedMessage(1157210); // Your talisman magically improves your spellbook. if (talisman.Charges <= 0) { from.SendLocalizedMessage(1157211); // Your talisman has been destroyed. talisman.Delete(); } } BaseRunicTool.ApplyAttributesTo(this, true, 0, propertyCount, minIntensity, maxIntensity); } if (makersMark) { Crafter = from; } m_Quality = (BookQuality)(quality - 1); return quality; } [Usage("AllSpells")] [Description("Completely fills a targeted spellbook with scrolls.")] private static void AllSpells_OnCommand(CommandEventArgs e) { e.Mobile.BeginTarget(-1, false, TargetFlags.None, AllSpells_OnTarget); e.Mobile.SendMessage("Target the spellbook to fill."); } private static void AllSpells_OnTarget(Mobile from, object obj) { if (obj is Spellbook) { Spellbook book = (Spellbook)obj; if (book.BookCount == 64) { book.Content = ulong.MaxValue; } else { book.Content = (1ul << book.BookCount) - 1; } from.SendMessage("The spellbook has been filled."); CommandLogging.WriteLine( from, "{0} {1} filling spellbook {2}", from.AccessLevel, CommandLogging.Format(from), CommandLogging.Format(book)); } else { from.BeginTarget(-1, false, TargetFlags.None, AllSpells_OnTarget); from.SendMessage("That is not a spellbook. Try again."); } } private static void EventSink_OpenSpellbookRequest(OpenSpellbookRequestEventArgs e) { Mobile from = e.Mobile; if (!DesignContext.Check(from)) { return; // They are customizing } SpellbookType type; switch (e.Type) { default: case 1: type = SpellbookType.Regular; break; case 2: type = SpellbookType.Necromancer; break; case 3: type = SpellbookType.Paladin; break; case 4: type = SpellbookType.Ninja; break; case 5: type = SpellbookType.Samurai; break; case 6: type = SpellbookType.Arcanist; break; case 7: type = SpellbookType.Mystic; break; } Spellbook book = Find(from, -1, type); if (book != null) { book.DisplayTo(from); } } private static void EventSink_CastSpellRequest(CastSpellRequestEventArgs e) { Mobile from = e.Mobile; if (!DesignContext.Check(from)) { return; // They are customizing } Spellbook book = e.Spellbook as Spellbook; int spellID = e.SpellID; if (book == null || !book.HasSpell(spellID)) { book = Find(from, spellID); } if (book != null && book.HasSpell(spellID)) { SpecialMove move = SpellRegistry.GetSpecialMove(spellID); if (move != null) { SpecialMove.SetCurrentMove(from, move); } else { Spell spell = SpellRegistry.NewSpell(spellID, from, null); if (spell != null) { spell.Cast(); } else if ( !Server.Spells.SkillMasteries.MasteryInfo.IsPassiveMastery( spellID ) ) { from.SendLocalizedMessage( 502345 ); // This spell has been temporarily disabled. } } } else { from.SendLocalizedMessage(500015); // You do not have that spell! } } } }