using System; using ModernUO.Serialization; using Server.Factions; using Server.Gumps; using Server.Misc; using Server.Mobiles; using Server.Network; using Server.Regions; namespace Server.Items; [DispellableField] [SerializationGenerator(0, false)] public partial class Moongate : Item { [SerializableField(0)] [SerializedCommandProperty(AccessLevel.GameMaster)] private Point3D _target; [SerializableField(1)] [SerializedCommandProperty(AccessLevel.GameMaster)] private Map _targetMap; [SerializableField(2)] [SerializedCommandProperty(AccessLevel.GameMaster)] private bool _dispellable; [Constructible] public Moongate(bool dispellable = true) : this(Point3D.Zero, null, dispellable) { } [Constructible] public Moongate(Point3D target, Map targetMap = null, bool dispellable = true) : base(0xF6C) { Movable = false; Light = LightType.Circle300; Target = target; TargetMap = targetMap; Dispellable = dispellable; } public virtual bool ShowFeluccaWarning => false; public override void OnDoubleClick(Mobile from) { if (!from.Player) { return; } if (from.InRange(GetWorldLocation(), 1)) { CheckGate(from, 1); } else { from.SendLocalizedMessage(500446); // That is too far away. } } public override bool OnMoveOver(Mobile m) { if (m.Player) { CheckGate(m, 0); } return true; } public virtual void CheckGate(Mobile m, int range) { if (m.Hidden && m.AccessLevel == AccessLevel.Player && Core.ML) { m.RevealingAction(); } new DelayTimer(m, this, range).Start(); } public virtual void OnGateUsed(Mobile m) { } public virtual void UseGate(Mobile m) { var flags = m.NetState?.Flags ?? ClientFlags.None; if (Sigil.ExistsOn(m)) { m.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil. } else if (TargetMap == Map.Felucca && m is PlayerMobile mobile && mobile.Young) { mobile.SendLocalizedMessage(1049543); // You decide against traveling to Felucca while you are still young. } else if (m.Murderer && TargetMap != Map.Felucca || TargetMap == Map.Tokuno && (flags & ClientFlags.Tokuno) == 0 || TargetMap == Map.Malas && (flags & ClientFlags.Malas) == 0 || TargetMap == Map.Ilshenar && (flags & ClientFlags.Ilshenar) == 0 || TargetMap == Map.TerMur && (flags & ClientFlags.TerMur) == 0) { m.SendLocalizedMessage(1019004); // You are not allowed to travel there. } else if (m.Spell != null) { m.SendLocalizedMessage(1049616); // You are too busy to do that at the moment. } else if (TargetMap != null && TargetMap != Map.Internal) { BaseCreature.TeleportPets(m, Target, TargetMap); m.MoveToWorld(Target, TargetMap); if (m.AccessLevel == AccessLevel.Player || !m.Hidden) { m.PlaySound(0x1FE); } OnGateUsed(m); } else { m.SendMessage("This moongate does not seem to go anywhere."); } } public virtual bool ValidateUse(Mobile from, bool message) { if (from.Deleted || Deleted) { return false; } if (from.Map != Map || !from.InRange(this, 1)) { if (message) { from.SendLocalizedMessage(500446); // That is too far away. } return false; } return true; } public virtual void BeginConfirmation(Mobile from) { if (IsInTown(from.Location, from.Map) && !IsInTown(Target, TargetMap) || from.Map != Map.Felucca && TargetMap == Map.Felucca && ShowFeluccaWarning) { if (from.AccessLevel == AccessLevel.Player || !from.Hidden) { from.SendSound(0x20E, from); } from.SendGump(new MoongateConfirmGump(from, this)); } else { EndConfirmation(from); } } public virtual void EndConfirmation(Mobile from) { if (!ValidateUse(from, true)) { return; } UseGate(from); } public virtual void DelayCallback(Mobile from, int range) { if (!ValidateUse(from, false) || !from.InRange(this, range)) { return; } if (TargetMap != null) { BeginConfirmation(from); } else { from.SendMessage("This moongate does not seem to go anywhere."); } } public static bool IsInTown(Point3D p, Map map) => map != null && Region.Find(p, map).GetRegion()?.IsDisabled() == false; private class DelayTimer : Timer { private Mobile _from; private Moongate _gate; private int _range; public DelayTimer(Mobile from, Moongate gate, int range) : base(TimeSpan.FromSeconds(1.0)) { _from = from; _gate = gate; _range = range; } protected override void OnTick() { _gate.DelayCallback(_from, _range); } } } [SerializationGenerator(1, false)] public partial class ConfirmationMoongate : Moongate { [SerializableField(0)] [SerializedCommandProperty(AccessLevel.GameMaster)] private TextDefinition _message; [SerializableField(1)] [SerializedCommandProperty(AccessLevel.GameMaster)] private int _gumpWidth; [SerializableField(2)] [SerializedCommandProperty(AccessLevel.GameMaster)] private int _gumpHeight; [SerializableField(3)] [SerializedCommandProperty(AccessLevel.GameMaster)] private int _titleColor; [SerializableField(4)] [SerializedCommandProperty(AccessLevel.GameMaster)] private int _messageColor; [SerializableField(5)] [SerializedCommandProperty(AccessLevel.GameMaster)] private int _titleNumber; [Constructible] public ConfirmationMoongate() : this(Point3D.Zero) { } [Constructible] public ConfirmationMoongate(Point3D target, Map targetMap = null) : base(target, targetMap) { } public virtual void Warning_Callback(Mobile from, bool okay) { if (okay) { EndConfirmation(from); } } public override void BeginConfirmation(Mobile from) { if (GumpWidth > 0 && GumpHeight > 0 && TitleNumber > 0 && Message?.IsEmpty == false) { from.SendGump( new WarningGump( TitleNumber, TitleColor, Message, MessageColor, GumpWidth, GumpHeight, okay => Warning_Callback(from, okay) ), true ); } else { base.BeginConfirmation(from); } } private void Deserialize(IGenericReader reader, int version) { base.Deserialize(reader); GumpWidth = reader.ReadEncodedInt(); GumpHeight = reader.ReadEncodedInt(); TitleColor = reader.ReadEncodedInt(); MessageColor = reader.ReadEncodedInt(); TitleNumber = reader.ReadEncodedInt(); var number = reader.ReadEncodedInt(); var message = reader.ReadString(); Message = number > 0 ? number : message; } } public class MoongateConfirmGump : Gump { private Mobile _from; private Moongate _gate; public override bool Singleton => true; public MoongateConfirmGump(Mobile from, Moongate gate) : base(Core.AOS ? 110 : 20, Core.AOS ? 100 : 30) { _from = from; _gate = gate; if (Core.AOS) { Closable = false; AddPage(0); AddBackground(0, 0, 420, 280, 5054); AddImageTiled(10, 10, 400, 20, 2624); AddAlphaRegion(10, 10, 400, 20); AddHtmlLocalized(10, 10, 400, 20, 1062051, 30720); // Gate Warning AddImageTiled(10, 40, 400, 200, 2624); AddAlphaRegion(10, 40, 400, 200); if (from.Map != Map.Felucca && gate.TargetMap == Map.Felucca && gate.ShowFeluccaWarning) { AddHtmlLocalized( 10, 40, 400, 200, 1062050, // This Gate goes to Felucca... Continue to enter the gate, Cancel to stay here 32512, false, true ); } else { AddHtmlLocalized( 10, 40, 400, 200, 1062049, // Dost thou wish to step into the moongate? Continue to enter the gate, Cancel to stay here 32512, false, true ); } AddImageTiled(10, 250, 400, 20, 2624); AddAlphaRegion(10, 250, 400, 20); AddButton(10, 250, 4005, 4007, 1); AddHtmlLocalized(40, 250, 170, 20, 1011036, 32767); // OKAY AddButton(210, 250, 4005, 4007, 0); AddHtmlLocalized(240, 250, 170, 20, 1011012, 32767); // CANCEL } else { AddPage(0); AddBackground(0, 0, 420, 400, 5054); AddBackground(10, 10, 400, 380, 3000); AddHtmlLocalized( 20, 40, 380, 60, 1062049 // Dost thou wish to step into the moongate? Continue to enter the gate, Cancel to stay here ); AddHtmlLocalized(55, 110, 290, 20, 1011012); // CANCEL AddButton(20, 110, 4005, 4007, 0); AddHtmlLocalized(55, 140, 290, 40, 1011011); // CONTINUE AddButton(20, 140, 4005, 4007, 1); } } public override void OnResponse(NetState state, in RelayInfo info) { if (info.ButtonID == 1) { _gate.EndConfirmation(_from); } } }