using Server.Network; using Server.Multis; using Server.Gumps; using Server.Targeting; namespace Server.Items { public enum DecorateCommand { None, Turn, Up, Down } public class InteriorDecorator : Item { private DecorateCommand m_Command; [CommandProperty( AccessLevel.GameMaster )] public DecorateCommand Command{ get => m_Command; set{ m_Command = value; InvalidateProperties(); } } [Constructible] public InteriorDecorator() : base( 0xFC1 ) { Weight = 1.0; LootType = LootType.Blessed; } public override int LabelNumber => 1041280; // an interior decorator public InteriorDecorator( Serial serial ) : base( serial ) { } public override void GetProperties( ObjectPropertyList list ) { base.GetProperties( list ); if ( m_Command != DecorateCommand.None ) list.Add( 1018322 + (int)m_Command ); // Turn/Up/Down } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 0 ); // version } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); } public override void OnDoubleClick( Mobile from ) { if ( !CheckUse( this, from ) ) return; if ( from.FindGump( typeof( InternalGump ) ) == null ) from.SendGump( new InternalGump( this ) ); if ( m_Command != DecorateCommand.None ) from.Target = new InternalTarget( this ); } public static bool InHouse( Mobile from ) { BaseHouse house = BaseHouse.FindHouseAt( from ); return ( house != null && house.IsCoOwner( from ) ); } public static bool CheckUse( InteriorDecorator tool, Mobile from ) { /*if ( tool.Deleted || !tool.IsChildOf( from.Backpack ) ) from.SendLocalizedMessage( 1042001 ); // That must be in your pack for you to use it. else*/ if ( !InHouse( from ) ) from.SendLocalizedMessage( 502092 ); // You must be in your house to do this. else return true; return false; } private class InternalGump : Gump { private InteriorDecorator m_Decorator; public InternalGump( InteriorDecorator decorator ) : base( 150, 50 ) { m_Decorator = decorator; AddBackground( 0, 0, 200, 200, 2600 ); AddButton( 50, 45, ( decorator.Command == DecorateCommand.Turn ? 2154 : 2152 ), 2154, 1, GumpButtonType.Reply, 0 ); AddHtmlLocalized( 90, 50, 70, 40, 1018323, false, false ); // Turn AddButton( 50, 95, ( decorator.Command == DecorateCommand.Up ? 2154 : 2152 ), 2154, 2, GumpButtonType.Reply, 0 ); AddHtmlLocalized( 90, 100, 70, 40, 1018324, false, false ); // Up AddButton( 50, 145, ( decorator.Command == DecorateCommand.Down ? 2154 : 2152 ), 2154, 3, GumpButtonType.Reply, 0 ); AddHtmlLocalized( 90, 150, 70, 40, 1018325, false, false ); // Down } public override void OnResponse( NetState sender, RelayInfo info ) { DecorateCommand command = DecorateCommand.None; switch ( info.ButtonID ) { case 1: command = DecorateCommand.Turn; break; case 2: command = DecorateCommand.Up; break; case 3: command = DecorateCommand.Down; break; } if ( command != DecorateCommand.None ) { m_Decorator.Command = command; sender.Mobile.SendGump( new InternalGump( m_Decorator ) ); sender.Mobile.Target = new InternalTarget( m_Decorator ); } else Target.Cancel( sender.Mobile ); } } private class InternalTarget : Target { private InteriorDecorator m_Decorator; public InternalTarget( InteriorDecorator decorator ) : base( -1, false, TargetFlags.None ) { CheckLOS = false; m_Decorator = decorator; } protected override void OnTargetNotAccessible( Mobile from, object targeted ) { OnTarget( from, targeted ); } protected override void OnTarget( Mobile from, object targeted ) { if ( targeted is Item item && CheckUse( m_Decorator, from ) ) { BaseHouse house = BaseHouse.FindHouseAt( from ); bool isDecorableComponent = false; object addon = null; int count = 0; if (item is AddonComponent component) { count = component.Addon.Components.Count; addon = component.Addon; } else if (item is AddonContainerComponent containerComponent) { count = containerComponent.Addon.Components.Count; addon = containerComponent.Addon; } else if (item is BaseAddonContainer container) { count = container.Components.Count; addon = container; } if (addon != null) { if ( count == 1 && Core.SE ) isDecorableComponent = true; if ( m_Decorator.Command == DecorateCommand.Turn ) { FlippableAddonAttribute[] attributes = (FlippableAddonAttribute[]) addon.GetType().GetCustomAttributes( typeof( FlippableAddonAttribute ), false ); if ( attributes.Length > 0 ) isDecorableComponent = true; } } if ( house == null || !house.IsCoOwner( from ) ) { from.SendLocalizedMessage( 502092 ); // You must be in your house to do this. } else if ( item.Parent != null || !house.IsInside( item ) ) { from.SendLocalizedMessage( 1042270 ); // That is not in your house. } else if ( !house.IsLockedDown( item ) && !house.IsSecure( item ) && !isDecorableComponent ) { if ( item is AddonComponent && m_Decorator.Command == DecorateCommand.Up ) from.SendLocalizedMessage( 1042274 ); // You cannot raise it up any higher. else if ( item is AddonComponent && m_Decorator.Command == DecorateCommand.Down ) from.SendLocalizedMessage( 1042275 ); // You cannot lower it down any further. else from.SendLocalizedMessage( 1042271 ); // That is not locked down. } else if ( item is VendorRentalContract ) { from.SendLocalizedMessage( 1062491 ); // You cannot use the house decorator on that object. } else if ( item.TotalWeight + item.PileWeight > 100 ) { from.SendLocalizedMessage( 1042272 ); // That is too heavy. } else { switch ( m_Decorator.Command ) { case DecorateCommand.Up: Up( item, from ); break; case DecorateCommand.Down: Down( item, from ); break; case DecorateCommand.Turn: Turn( item, from ); break; } } } from.Target = new InternalTarget( m_Decorator ); } protected override void OnTargetCancel( Mobile from, TargetCancelType cancelType ) { if ( cancelType == TargetCancelType.Canceled ) from.CloseGump( typeof( InternalGump ) ); } private static void Turn( Item item, Mobile from ) { object addon = null; if (item is AddonComponent component) addon = component.Addon; else if (item is AddonContainerComponent containerComponent) addon = containerComponent.Addon; else if (item is BaseAddonContainer container) addon = container; if (addon != null) { FlippableAddonAttribute[] aAttributes = (FlippableAddonAttribute[]) addon.GetType().GetCustomAttributes( typeof( FlippableAddonAttribute ), false ); if ( aAttributes.Length > 0 ) { aAttributes[ 0 ].Flip( from, (Item) addon ); return; } } FlippableAttribute[] attributes = (FlippableAttribute[]) item.GetType().GetCustomAttributes( typeof( FlippableAttribute ), false ); if ( attributes.Length > 0 ) attributes[ 0 ].Flip( item ); else from.SendLocalizedMessage( 1042273 ); // You cannot turn that. } private static void Up( Item item, Mobile from ) { int floorZ = GetFloorZ( item ); if ( floorZ > int.MinValue && item.Z < (floorZ + 15) ) // Confirmed : no height checks here item.Location = new Point3D( item.Location, item.Z + 1 ); else from.SendLocalizedMessage( 1042274 ); // You cannot raise it up any higher. } private static void Down( Item item, Mobile from ) { int floorZ = GetFloorZ( item ); if ( floorZ > int.MinValue && item.Z > GetFloorZ( item ) ) item.Location = new Point3D( item.Location, item.Z - 1 ); else from.SendLocalizedMessage( 1042275 ); // You cannot lower it down any further. } private static int GetFloorZ( Item item ) { Map map = item.Map; if ( map == null ) return int.MinValue; StaticTile[] tiles = map.Tiles.GetStaticTiles( item.X, item.Y, true ); int z = int.MinValue; for ( int i = 0; i < tiles.Length; ++i ) { StaticTile tile = tiles[i]; ItemData id = TileData.ItemTable[tile.ID & TileData.MaxItemValue]; int top = tile.Z; // Confirmed : no height checks here if ( id.Surface && !id.Impassable && top > z && top <= item.Z ) z = top; } return z; } } } }