using System.Collections.Generic; using ModernUO.Serialization; using Server.Ethics.Evil; using Server.Ethics.Hero; using Server.Items; using Server.Mobiles; namespace Server.Ethics; [SerializationGenerator(1)] public abstract partial class Ethic : EthicsEntity { public static Ethic Hero { get; private set; } public static Ethic Evil { get; private set; } public static readonly Ethic[] Ethics = { Hero, Evil }; public static bool RegisterEthic(Ethic ethic) { if (ethic is HeroEthic) { if (Hero == null) { Hero = ethic; return true; } return false; } if (ethic is EvilEthic) { if (Evil == null) { Evil = ethic; return true; } return false; } return false; } public Ethic() => Players = []; public static bool Enabled { get; private set; } public virtual EthicDefinition Definition { get; } public List Players { get; protected set; } public static Ethic Find(Item item) { if ((item.SavedFlags & 0x100) != 0) { if (item.Hue == Hero.Definition.PrimaryHue) { return Hero; } item.SavedFlags &= ~0x100; } if ((item.SavedFlags & 0x200) != 0) { if (item.Hue == Evil.Definition.PrimaryHue) { return Evil; } item.SavedFlags &= ~0x200; } return null; } public static bool CheckTrade(Mobile from, Mobile to, Mobile newOwner, Item item) { var itemEthic = Find(item); if (itemEthic == null || Find(newOwner) == itemEthic) { return true; } if (itemEthic == Hero) { (from == newOwner ? to : from).SendMessage("Only heroes may receive this item."); } else if (itemEthic == Evil) { (from == newOwner ? to : from).SendMessage("Only the evil may receive this item."); } return false; } public static bool CheckEquip(Mobile from, Item item) { var itemEthic = Find(item); if (itemEthic == null || Find(from) == itemEthic) { return true; } if (itemEthic == Hero) { from.SendMessage("Only heroes may wear this item."); } else if (itemEthic == Evil) { from.SendMessage("Only the evil may wear this item."); } return false; } public static bool IsImbued(Item item) => IsImbued(item, false); public static bool IsImbued(Item item, bool recurse) { if (Find(item) != null) { return true; } if (recurse) { foreach (var child in item.Items) { if (IsImbued(child, true)) { return true; } } } return false; } public static void Configure() { Enabled = ServerConfiguration.GetOrUpdateSetting("ethics.enable", false); } public static void Initialize() { if (Enabled) { EventSink.Speech += EventSink_Speech; } } public static void EventSink_Speech(SpeechEventArgs e) { if (e.Blocked || e.Handled) { return; } var pl = Player.Find(e.Mobile); if (pl == null) { for (var i = 0; i < Ethics.Length; ++i) { var ethic = Ethics[i]; if (!ethic.IsEligible(e.Mobile)) { continue; } if (!ethic.Definition.JoinPhrase.String.InsensitiveEquals(e.Speech)) { continue; } var found = false; foreach (var item in e.Mobile.GetItemsInRange(2)) { if (item is AnkhNorth or AnkhWest) { found = true; break; } } if (!found) { continue; } pl = new Player(ethic, e.Mobile); pl.Attach(); e.Mobile.FixedEffect(0x373A, 10, 30); e.Mobile.PlaySound(0x209); e.Handled = true; break; } } else { if (e.Mobile is PlayerMobile mobile && mobile.DuelContext != null) { return; } var ethic = pl.Ethic; for (var i = 0; i < ethic.Definition.Powers.Length; ++i) { var power = ethic.Definition.Powers[i]; if (!power.Definition.Phrase.String.InsensitiveEquals(e.Speech)) { continue; } if (!power.CheckInvoke(pl)) { continue; } power.BeginInvoke(pl); e.Handled = true; break; } } } public static Ethic Find(Mobile mob) => Find(mob, false, false); public static Ethic Find(Mobile mob, bool inherit) => Find(mob, inherit, false); public static Ethic Find(Mobile mob, bool inherit, bool allegiance) { var pl = Player.Find(mob); if (pl != null) { return pl.Ethic; } if (inherit && mob is BaseCreature bc) { if (bc.Controlled) { return Find(bc.ControlMaster, false); } if (bc.Summoned) { return Find(bc.SummonMaster, false); } if (allegiance) { return bc.EthicAllegiance; } } return null; } public abstract bool IsEligible(Mobile mob); private void Deserialize(IGenericReader reader, int version) { var playerCount = reader.ReadEncodedInt(); for (var i = 0; i < playerCount; ++i) { var pl = new Player(this, null); pl.Deserialize(reader); if (pl.Mobile != null) { Timer.StartTimer(pl.CheckAttach); } } } }