using System; using System.Collections.Generic; using Server.Engines.ConPVP; using Server.Engines.Craft; namespace Server.Items { public enum PotionEffect { Nightsight, CureLesser, Cure, CureGreater, Agility, AgilityGreater, Strength, StrengthGreater, PoisonLesser, Poison, PoisonGreater, PoisonDeadly, Refresh, RefreshTotal, HealLesser, Heal, HealGreater, ExplosionLesser, Explosion, ExplosionGreater, Conflagration, ConflagrationGreater, MaskOfDeath, // Mask of Death is not available in OSI but does exist in cliloc files MaskOfDeathGreater, // included in enumeration for compatibility if later enabled by OSI ConfusionBlast, ConfusionBlastGreater, Invisibility, Parasitic, Darkglow } public abstract class BasePotion : Item, ICraftable, ICommodity { private PotionEffect m_PotionEffect; public BasePotion(int itemID, PotionEffect effect) : base(itemID) { m_PotionEffect = effect; Stackable = Core.ML; Weight = 1.0; } public BasePotion(Serial serial) : base(serial) { } public PotionEffect PotionEffect { get => m_PotionEffect; set { m_PotionEffect = value; InvalidateProperties(); } } public override int LabelNumber => 1041314 + (int)m_PotionEffect; public virtual bool RequireFreeHand => true; int ICommodity.DescriptionNumber => LabelNumber; bool ICommodity.IsDeedable => Core.ML; #region ICraftable Members public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CraftItem craftItem, int resHue) { if (craftSystem is DefAlchemy) { Container pack = from.Backpack; if (pack != null) { if ((int)PotionEffect >= (int)PotionEffect.Invisibility) return 1; List kegs = pack.FindItemsByType(); for (int i = 0; i < kegs.Count; ++i) { PotionKeg keg = kegs[i]; // Should never happen // if (keg == null) // continue; if (keg.Held <= 0 || keg.Held >= 100) continue; if (keg.Type != PotionEffect) continue; ++keg.Held; Consume(); from.AddToBackpack(new Bottle()); return -1; // signal placed in keg } } } return 1; } #endregion public static bool HasFreeHand(Mobile m) { Item handOne = m.FindItemOnLayer(Layer.OneHanded); Item handTwo = m.FindItemOnLayer(Layer.TwoHanded); if (handTwo is BaseWeapon) handOne = handTwo; if (handTwo is BaseRanged ranged && ranged.Balanced) return true; return handOne == null || handTwo == null; } public override void OnDoubleClick(Mobile from) { if (!Movable) return; if (from.InRange(GetWorldLocation(), 1)) { if (!RequireFreeHand || HasFreeHand(from)) { if (this is BaseExplosionPotion && Amount > 1) { BasePotion pot = (BasePotion)Activator.CreateInstance(GetType()); Amount--; if (from.Backpack?.Deleted != false) from.Backpack.DropItem(pot); else pot.MoveToWorld(from.Location, from.Map); pot.Drink(from); } else { Drink(from); } } else { from.SendLocalizedMessage(502172); // You must have a free hand to drink a potion. } } else { from.SendLocalizedMessage(502138); // That is too far away for you to use } } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write(1); // version writer.Write((int)m_PotionEffect); } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); switch (version) { case 1: case 0: { m_PotionEffect = (PotionEffect)reader.ReadInt(); break; } } if (version == 0) Stackable = Core.ML; } public abstract void Drink(Mobile from); public static void PlayDrinkEffect(Mobile m) { m.RevealingAction(); m.PlaySound(0x2D6); #region Dueling if (!DuelContext.IsFreeConsume(m)) m.AddToBackpack(new Bottle()); #endregion if (m.Body.IsHuman && !m.Mounted) m.Animate(34, 5, 1, true, false, 0); } public static int EnhancePotions(Mobile m) { int EP = AosAttributes.GetValue(m, AosAttribute.EnhancePotions); int skillBonus = m.Skills.Alchemy.Fixed / 330 * 10; if (Core.ML && EP > 50 && m.AccessLevel <= AccessLevel.Player) EP = 50; return EP + skillBonus; } public static TimeSpan Scale(Mobile m, TimeSpan v) { if (!Core.AOS) return v; double scalar = 1.0 + 0.01 * EnhancePotions(m); return TimeSpan.FromSeconds(v.TotalSeconds * scalar); } public static double Scale(Mobile m, double v) { if (!Core.AOS) return v; double scalar = 1.0 + 0.01 * EnhancePotions(m); return v * scalar; } public static int Scale(Mobile m, int v) { if (!Core.AOS) return v; return AOS.Scale(v, 100 + EnhancePotions(m)); } public override bool StackWith(Mobile from, Item dropped, bool playSound) { return dropped is BasePotion potion && potion.m_PotionEffect == m_PotionEffect && base.StackWith(from, potion, playSound); } } }