I've found a perfect MoTD script but I cannot get it to launch without typing MOTD. Is there a folder location I can place a script that will launch the MOTD script on login?
 
I had posted this before to fix this :
Right below the released MOTD I had posted this:
I changed the true and false in these 2 lines, then the gump opens on login
private static bool kAlwaysShowMotdOnLogin = true;// should be const, used static to get avoid compiler warning
private static bool kTextInsteadOfGumpOnLogin = false; // should be const, used static to get avoid compiler warning
** it also states the motd tags an account so if not updated it shouldn't open again, but I didn't test this- but if you reload then it will
-------------------------------------------------------
the text one goes into the data folder
------------------------------------------------------------------------
 
I have both set to True but I still only get the MOTD message if I type MOTD. Tested on on an admin account and a regular player account.
 
C#:
#region AuthorHeader
//
//    Motd.cs version 2.0, by Xanthos
//
//    This is a RunUO assembly to display a message of the day (motd) gump
//    at login.  It supports archiving and display of previous motd content.
//    You may use this code as you please as long as you leave this AuthorHeader
//    in place.
//
#endregion AuthorHeader
#region Header
//
//    Using this is pretty simple.  Place this file in your custom directory.
//    It will create a Motd subdirectory in your data directory and an Archive
//    directory beneath that.  Place a file named motd.txt in the Motd sub-
//    directory, enter the game as an admin and type [motd.  Select the reload
//    button and all players will see the new motd on login. Once the motd is
//    presented to a player, their account is tagged so they will not see it
//    again on login unless the Reload button is used as described above.
//    Players may, at any time, see the motd by typing motd. The Reload
//    option allows an admin to make small changes to the motd and then get
//    them brought into the motd cache without a restart of the server.
//
//    The [motd admin command also allows archiving of the current motd.txt
//    into the Archive directory and replacing the existing motd file with one
//    named new.txt.  This action will also tag all accounts so that the motd
//    will be displayed at login.  The archives are given names in sequence
//    starting at 1.txt.  The current motd, when archived is always given the
//    name 1.txt after any older files are propagated to higher numbered names.
//    By default, a maximum of nine archives will be shown in the gump.  The
//    number of archives maintained in the Archive directory is limited only
//    by the file system.  Archiving may take longer as the number of files
//    increases however.  If an motd.txt file is not present when the Reload
//    or Archive functions are used, all accounts are tagged so that the motd
//    will not be displayed.
//
//    There are a number of static variables that can be used to customize
//    aspects of this program.  In most cases no modifications are needed.
//
//    This work was done by Xanthos, based on code written by Viago and others,
//    see the credits page for more details.
//    - Xanthos.
//
//    editor tabs = 4
//
#endregion Header
using System;
using System.IO;
using System.Text;
using System.Threading;
using Server;
using Server.Gumps;
using Server.Network;
using Server.Mobiles;
using Server.Accounting;
using Server.Commands;

namespace Xanthos.Utilities
{
    public class NewsGump : Gump
    {
        // Modify these constants to suit your needs
        private const string kNewFile        = "new";
        private const string kMotdFile        = "motd";
        private const string kFileSuffix    = ".txt";
        private const string kPathMotd        = "Data/Motd/";
        private const string kPathArchive    = kPathMotd + "Archive/";
        private const string kGreeting        = "Greetings And Welcome To Warwickshire";
        private const string kDefaultBody    = "There is no current news.";
        private const string kDefaultTitle    = "Current News";
        private const string kNewMotdMessage= "The message of the day has been updated. To see it, type motd.";
        private static int   kMaximumArchives            = 9;    // should be const, used static to get avoid compiler warning
        private    static bool     kAlwaysShowMotdOnLogin        = true ;// should be const, used static to get avoid compiler warning
        private    static bool  kTextInsteadOfGumpOnLogin    = false;    // should be const, used static to get avoid compiler warning
       
        internal const int    kDataColor = 50;
        internal const int    kLabelColor = 88;
        internal const string kLabelHtmlColor = "66CCFF";

        //----- Edting below this line is not recommended -----

        #region Static Methods

        private static volatile string [] s_ArchiveFilenameCache;
        private static volatile string s_MotdCache;
        private static volatile Mutex s_Mutex = new Mutex();

        public static void Initialize()
        {
            try
            {
                // Make sure we have a message store
                if ( !Directory.Exists( kPathArchive ) )
                    Directory.CreateDirectory( kPathArchive );

                LoadMotd();
            }
            catch
            {
                World.Broadcast( kLabelColor, true, "Motd: no motd file found");
            }

            try { GetArchiveList(); }
            catch { World.Broadcast( kLabelColor, true, "Motd: no archive files found"); }

            EventSink.Login += new LoginEventHandler( MOTD_Login );
            EventSink.Speech += new SpeechEventHandler( EventSink_Speech );
            CommandHandlers.Register( "MOTD", AccessLevel.Administrator, new CommandEventHandler( MOTD_OnCommand ) );
        }

        private static bool LoadMotd()    // Not thread safe, call only from a locked block
        {
            string Filename = kPathMotd + kMotdFile + kFileSuffix;
            string str = "";

            try
            {
                StreamReader reader = new StreamReader( Filename );
                str = reader.ReadToEnd();
                reader.Close();
            }
            finally
            {
                s_MotdCache = ( str == "" ? kDefaultBody : str );
            }

            return !( s_MotdCache == kDefaultBody );
        }

        private static void ArchiveMotd( PlayerMobile mobile ) // Not thread safe, call only from a locked block
        {
            string [] list = Directory.GetFiles( kPathArchive, "*" + kFileSuffix );
            int totalFiles = list.Length;
            string source;

            // Rename all files to make room for the new #1
            for ( int i = totalFiles, j = i + 1; i > 0; i--, j-- )
            {
                if ( File.Exists( source = kPathArchive + i + kFileSuffix ) )
                    File.Move( source, kPathArchive + j + kFileSuffix );
            }

            // Copy the motd file to the #1 slot in the archive, and replace old motd with the new motd file
            if ( File.Exists( source = kPathMotd + kMotdFile + kFileSuffix ) )
                File.Move( source, kPathArchive + "1" + kFileSuffix );

            if ( File.Exists( source = kPathMotd + kNewFile + kFileSuffix ) )
                File.Move( kPathMotd + kNewFile + kFileSuffix, kPathMotd + kMotdFile + kFileSuffix );
        }

        private static void GetArchiveList()    // Not thread safe, call only from a locked block
        {
            s_ArchiveFilenameCache = null;

            // This method may be set to not get all of the files so don't use when archiving.
            // One of these will be unreachable - I chose to live with it rather than use defines.
            // Also Directory.GetFiles has really poor regular expression support
            // so this is about the best you can do without more work.
           
            if ( kMaximumArchives < 10 )
                s_ArchiveFilenameCache = Directory.GetFiles( kPathArchive, "?" + kFileSuffix );
            else
                s_ArchiveFilenameCache = Directory.GetFiles( kPathArchive, "*" + kFileSuffix );
        }
       
        //
        // All thread unsafe methods are bottlenecked in the next three methods.
        //

        private static void PreformArchive( PlayerMobile mobile )
        {
            bool showMotd;

            s_Mutex.WaitOne();
            try
            {
                ArchiveMotd( mobile );
                showMotd = LoadMotd();
                GetArchiveList( );
            }
            catch (Exception exc)
            {
                s_Mutex.ReleaseMutex();
                throw exc;
            }
            s_Mutex.ReleaseMutex();
            SetAllTags( mobile, showMotd );    // no need to block for this
        }
   
        private static void PerformReload( PlayerMobile mobile )
        {
            bool showMotd;

            s_Mutex.WaitOne();
            try
            {
                showMotd = LoadMotd();
                GetArchiveList( );
            }
            catch (Exception exc)
            {
                s_Mutex.ReleaseMutex();
                throw exc;
            }
            s_Mutex.ReleaseMutex();
            SetAllTags( mobile, showMotd );    // no need to block for this
        }

        internal static void SafelySendGumpTo( Mobile mobile, bool admin )
        {
            NewsGump gump;

            s_Mutex.WaitOne();
            try
            {
                int length = s_ArchiveFilenameCache.Length >= kMaximumArchives
                    ? kMaximumArchives : s_ArchiveFilenameCache.Length;

                // Get the caches copied onto the stack of the gump thread.
                gump = new NewsGump( mobile, s_MotdCache, s_ArchiveFilenameCache, length, admin );
            }
            finally
            {
                s_Mutex.ReleaseMutex();
            }
           
            gump.DrawGump( mobile, admin );
            mobile.SendGump( gump );
            ((Account)(((PlayerMobile)mobile).Account)).SetTag( "motd", "false" );
        }

        private static void SetAllTags( Mobile from, bool toTrue )
        {
            if ( kAlwaysShowMotdOnLogin )    // No need to tag if we are always showing
                return;

            string boolValue = toTrue.ToString();
            Account account;

            foreach ( Mobile mobile in World.Mobiles.Values )
            {
                if ( null == mobile || !( mobile is PlayerMobile ) )
                    continue;

                if( null == ( account = (Account)from.Account ) )
                    continue;

                account.SetTag( "motd", boolValue );
            }
            from.SendMessage( kLabelColor, "All players" + ( true == toTrue ? " will " : " will not ") + "see the MOTD Message at next login." );
        }

        #region In-game commands and events

        [Usage( "MOTD" )]
        [Description( "Show MOTD admin menu." )]
        private static void MOTD_OnCommand( CommandEventArgs args )
        {
            Mobile mobile = args.Mobile;
            mobile.CloseGump( typeof(NewsGump) );
            SafelySendGumpTo( mobile, true );
        }

        private static void EventSink_Speech( SpeechEventArgs args )
        {
            Mobile mobile = args.Mobile;
            if ( args.Speech.ToLower().IndexOf( "motd" ) >= 0 )
            {
                SafelySendGumpTo( mobile, false );
            }
        }

        private static void MOTD_Login( LoginEventArgs args )
        {
            Mobile mobile = args.Mobile;
            Account account = (Account)mobile.Account;

            Convert.ToBoolean( account.GetTag( "motd" ) );
                //if ( kAlwaysShowMotdOnLogin || Convert.ToBoolean( account.GetTag( "motd" ) ) )
            {
                // One of these will be unreachable - I chose to live with it rather than use defines.
                // if ( kTextInsteadOfGumpOnLogin )
                    mobile.SendMessage( kLabelColor, kNewMotdMessage );
                //else
                    //SafelySendGumpTo( mobile, false );
            }
        }

        #endregion In-game commands and events
        #endregion Static Methods
        #region News Gump Methods

        private PlayerMobile m_Player;
        private string m_UserCount;
        private string m_ItemCount;
        private string m_MobileCount;
        private string m_Body;
        private string [] m_ArchiveList;
        private int    m_TotalPages;
        private int    m_ArchiveCount;
        private int    m_ArchivesLoaded;

        private string LoadNextArchive()
        {
            string Filename;
            string text = "";

            if ( m_ArchiveList != null && m_ArchivesLoaded < m_ArchiveCount
                && (( Filename = m_ArchiveList[ m_ArchivesLoaded ].ToString() ) != null )
                && File.Exists( Filename ) )
            {
                StreamReader reader = new StreamReader( Filename );

                text = reader.ReadToEnd();
                reader.Close();

                m_ArchivesLoaded++;
            }
            return text == "" ? kDefaultBody : text;
        }

        private NewsGump( Mobile mobile, string body, string [] archiveList, int archiveCount, bool admin ) : base( 100, 100 )
        {
            mobile.CloseGump( typeof(NewsGump) );
            m_Body            = body;
            m_Player        = (PlayerMobile)mobile;
            m_UserCount        = NetState.Instances.Count.ToString();
            m_ItemCount        = World.Items.Count.ToString();
            m_MobileCount    = World.Mobiles.Count.ToString();
            m_ArchiveList    = archiveList;
            m_ArchiveCount    = ( null == archiveList ? 0 : archiveCount );
            m_ArchivesLoaded = 0;
            m_TotalPages    = 0;
        }

        private void DrawGump( Mobile mobile, bool admin )
        {
            if ( admin )
            {
                int colOne = 10;
                int colTwo = colOne + 35;
                int rowOne = 10;
                int rowHeight = 25;
                int row = rowOne;

                AddPage( 1 );
                AddBackground( 0, 0, 205, 180, 5054 );
                AddButton( colOne, rowOne, 0xFB7, 0xFB9, 100, GumpButtonType.Reply, 0 );                // Archive
                AddLabel( colTwo, rowOne, kLabelColor, "Archive motd File" );
                AddButton( colOne, (row += rowHeight), 0xFB7, 0xFB9, 101, GumpButtonType.Reply, 0 );    // Reload
                AddLabel( colTwo, row, kLabelColor, "Reload motd File" );
                AddButton( colOne, (row += rowHeight + 10), 0xFB7, 0xFB9, 0, GumpButtonType.Reply, 0 ); // Cancel
                AddLabel( colTwo, row, kLabelColor, "Cancel" );
                AddLabel( colOne, (row += rowHeight + 10), kDataColor, "Warning, admins have both" );
                AddLabel( colOne, (row += rowHeight - 10), kDataColor, "the [motd and motd commands." );
                AddLabel( colOne, (row += rowHeight - 10), kDataColor, "Press Cancel unless you know" );
                AddLabel( colOne, (row += rowHeight - 10), kDataColor, "what these options do." );
            }
            else
            {
                AddNewPage( m_Body );

                while ( m_ArchivesLoaded < m_ArchiveCount )
                {
                    AddNewPage( LoadNextArchive() );
                }
            }
        }

        private void AddNewPage( string bodyText )
        {
            AddPage( ++m_TotalPages );

            AddBackground( 50, 0, 514, 280, 9270 );
            AddBackground( 50, 80, 514, 400, 9270 );

            AddLabel( 170, 15, kDataColor, kGreeting );
            AddLabel( 80, 33, kDataColor, m_Player.Name );
            AddLabel( 205, 33, kLabelColor, "Online Users" );
            AddLabel( 205, 47, kDataColor, m_UserCount );
            AddLabel( 315, 33, kLabelColor, "Total Items" );
            AddLabel( 315, 47, kDataColor, m_ItemCount );
            AddLabel( 425, 33, kLabelColor, "Total Mobiles" );
            AddLabel( 425, 47, kDataColor, m_MobileCount);

            AddHtml( 65, 95, 485, 25, CenterAndColor( 1 == m_TotalPages ? kDefaultTitle : "Previous News" ), false, false );
            AddHtml( 65, 120, 485, 330, bodyText, true, true );
            AddHtml( 65, 450, 485, 25, CenterAndColor( "Page " + ( m_TotalPages ) + " of " + ( m_ArchiveCount + 1 ) ), false, false );
           
            AddButton( 525, 15, 25, 26, 102, GumpButtonType.Reply, 0 );        // Close button
            AddButton( 60, 55, 5522, 5523, 103, GumpButtonType.Reply, 0 );    // Account button
            AddButton( 65, 12, 22153, 22154, 104, GumpButtonType.Reply, 0 );// About button
            AddButton( 500, 95, 5537, 5538, 0, GumpButtonType.Page, m_TotalPages - 1 );    // Navigation left button
            AddButton( 525, 95, 5540, 5541, 0, GumpButtonType.Page, m_TotalPages + 1 );    // Navigation right button
        }

        private static string CenterAndColor( string text )
        {
            return String.Format( "<BASEFONT COLOR=#"+ kLabelHtmlColor + "><CENTER>{0}</CENTER></BASEFONT>", text );
        }

        public override void OnResponse( NetState sender, RelayInfo info )
        {
            Mobile from = sender.Mobile;

            switch ( info.ButtonID )
            {
                case 100:    // Archive
                    try
                    {
                        PreformArchive( (PlayerMobile)from );
                        SafelySendGumpTo( from, false );
                        World.Broadcast( kLabelColor, true, kNewMotdMessage );
                    }
                    catch (Exception exc) { from.SendMessage( kLabelColor, "Archive: exception encountered - " + exc.Message); }
                    break;
                case 101:    // Reload
                    try
                    {
                        PerformReload( (PlayerMobile)from );
                        SafelySendGumpTo( from, false );
                        World.Broadcast( kLabelColor, true, kNewMotdMessage );
                    }
                    catch (Exception exc) { from.SendMessage( kLabelColor, "Archive: exception encountered - " + exc.Message); }
                    break;
                case 102:    // Close Account Gump
                    from.CloseGump( typeof(AccountGump) );
                    break;
                case 103:    // Account Gump
                    from.SendGump( new AccountGump( from, sender, false ) );
                    break;
                case 104:    // Credits
                    from.SendGump( new AccountGump( from, sender, true ) );
                    break;
                case 105:    // Motd from credits only page - $$$ not tested, may not work
                    from.CloseGump( typeof(AccountGump) );
                    SafelySendGumpTo( from, false );
                    break;
            }
        }

        #endregion News Gump Methods
        #region AccountGump

        internal class AccountGump : Gump
        {
            public AccountGump( Mobile from, NetState state, bool showOnlyCredits ) : base( 30, 20 )
            {
                if ( null == state )
                    return;

                PlayerMobile mobile = (PlayerMobile)from;

                AddPage( 1 );

                if ( !showOnlyCredits )
                {
                    AddBackground( 50, 0, 479, 309, 9270 );
                    AddImage( 0, 0, 10400 );
                    AddImage( 0, 225, 10402 );
                    AddImage( 495, 0, 10410 );
                    AddImage( 495, 225, 10412 );
                    AddImage( 60, 15, 5536 );
                    AddImage( 275, 15, 1025 );
                    AddLabel( 205, 43, NewsGump.kLabelColor, "Account Name" );
                    AddLabel( 205, 57, 0x480, mobile.Account.ToString() );
                    AddLabel( 205, 80, NewsGump.kLabelColor, "Account Password" );
                    AddLabel( 205, 98, NewsGump.kDataColor, "-(Protected)-" );
                    AddLabel( 355, 43, NewsGump.kLabelColor, "Online Character" );
                    AddLabel( 355, 57, NewsGump.kDataColor, mobile.Name );
                    AddLabel( 355, 80, NewsGump.kLabelColor, "Character Age" );
                    AddLabel( 355, 100, NewsGump.kDataColor, mobile.GameTime.Days.ToString() + " Days" );
                    AddLabel( 355, 115, NewsGump.kDataColor, mobile.GameTime.Hours.ToString() + " Hours" );
                    AddLabel( 355, 130, NewsGump.kDataColor, mobile.GameTime.Minutes.ToString() + " Minutes" );
                    AddLabel( 355, 144, NewsGump.kDataColor, mobile.GameTime.Seconds.ToString() + " Seconds" );
                    AddLabel( 205, 120, NewsGump.kLabelColor, "Account Access Level" );
                    AddLabel( 205, 135, NewsGump.kDataColor, from.AccessLevel.ToString() );
                    AddButton( 470, 15, 25, 26, 0, GumpButtonType.Reply, 0 );        // Close
                    AddLabel( 355, 165, NewsGump.kLabelColor, "IP Address" );
                    AddLabel( 355, 180, NewsGump.kDataColor, state.ToString());
                    AddLabel( 205, 165, NewsGump.kLabelColor, "Client Version" );
                    AddLabel(205, 180, NewsGump.kDataColor,
                        state.SupportsExpansion(Expansion.HS)?"High Seas":
                        state.SupportsExpansion(Expansion.ML)? "Mondain's Legacy":
                        state.SupportsExpansion(Expansion.SE) ? "Samurai Empire" :
                        state.SupportsExpansion(Expansion.AOS) ? "Age of Shadows" :
                        state.SupportsExpansion(Expansion.LBR) ? "Blackthorn's Revenge" :
                        state.SupportsExpansion(Expansion.UOTD) ? "Third Dawn" :
                        state.SupportsExpansion(Expansion.UOR) ? "Renaissance" : "The Second Age");
                    AddLabel( 205, 200, NewsGump.kLabelColor, "Client Patch" );
                    AddLabel( 205, 215, NewsGump.kDataColor, null == state.Version ? "(null)" : state.Version.ToString() );
                    AddButton( 445, 15, 22153, 22154, 0, GumpButtonType.Page, 2 );    // About

                    AddPage( 2 );
                }

                // Credits page
                AddBackground( 50, 0, 479, 309, 9270 );
                AddImage( 0, 0, 10400 );
                AddImage( 0, 225, 10402 );
                AddImage( 495, 0, 10410 );
                AddImage( 495, 225, 10412 );
                AddImage( 60, 15, 5536 );
                AddLabel( 205, 45, NewsGump.kLabelColor, "Code By" );
                AddLabel( 205, 60, NewsGump.kDataColor, "Xanthos" );
                AddLabel( 205, 80, NewsGump.kLabelColor, "Inspiration By" );
                AddLabel( 205, 95, NewsGump.kDataColor, "Princess Monika" );
                AddLabel( 205, 110, NewsGump.kLabelColor, "Gumps By" );
                AddLabel( 205, 125, NewsGump.kDataColor, "Viago" );
                AddLabel( 355, 45, NewsGump.kLabelColor, "Credit To" );
                AddLabel( 355, 60, NewsGump.kDataColor, "Xuse" );
                AddLabel( 355, 75, NewsGump.kDataColor, "The RunUO Comunity" );
                AddLabel( 355, 90, NewsGump.kDataColor, "Lady Rouge" );
                AddLabel( 355, 105, NewsGump.kDataColor, "RoninGT" );
                AddButton( 470, 15, 25, 26, 0, GumpButtonType.Reply, 0 );        // Close
            }
            #endregion AccountGump
        }
    }
}
 
Last edited by a moderator:
I added [ CODE ] tags for you. Please make use of them. the symbol on the toolbar looks like this: </>
 
Starting around 278, you have the login part that shows the gump commented out. If you uncomment those you should be good to go.
 
C#:
#region AuthorHeader
//
//    Motd.cs version 2.0, by Xanthos
//
//    This is a RunUO assembly to display a message of the day (motd) gump
//    at login.  It supports archiving and display of previous motd content.
//    You may use this code as you please as long as you leave this AuthorHeader
//    in place.
//
#endregion AuthorHeader
#region Header
//
//    Using this is pretty simple.  Place this file in your custom directory.
//    It will create a Motd subdirectory in your data directory and an Archive
//    directory beneath that.  Place a file named motd.txt in the Motd sub-
//    directory, enter the game as an admin and type [motd.  Select the reload
//    button and all players will see the new motd on login. Once the motd is
//    presented to a player, their account is tagged so they will not see it
//    again on login unless the Reload button is used as described above.
//    Players may, at any time, see the motd by typing motd. The Reload
//    option allows an admin to make small changes to the motd and then get
//    them brought into the motd cache without a restart of the server.
//
//    The [motd admin command also allows archiving of the current motd.txt
//    into the Archive directory and replacing the existing motd file with one
//    named new.txt.  This action will also tag all accounts so that the motd
//    will be displayed at login.  The archives are given names in sequence
//    starting at 1.txt.  The current motd, when archived is always given the
//    name 1.txt after any older files are propagated to higher numbered names.
//    By default, a maximum of nine archives will be shown in the gump.  The
//    number of archives maintained in the Archive directory is limited only
//    by the file system.  Archiving may take longer as the number of files
//    increases however.  If an motd.txt file is not present when the Reload
//    or Archive functions are used, all accounts are tagged so that the motd
//    will not be displayed.
//
//    There are a number of static variables that can be used to customize
//    aspects of this program.  In most cases no modifications are needed.
//
//    This work was done by Xanthos, based on code written by Viago and others,
//    see the credits page for more details.
//    - Xanthos.
//
//    editor tabs = 4
//
#endregion Header
using System;
using System.IO;
using System.Text;
using System.Threading;
using Server;
using Server.Gumps;
using Server.Network;
using Server.Mobiles;
using Server.Accounting;
using Server.Commands;

namespace Xanthos.Utilities
{
    public class NewsGump : Gump
    {
        // Modify these constants to suit your needs
        private const string kNewFile        = "new";
        private const string kMotdFile        = "motd";
        private const string kFileSuffix    = ".txt";
        private const string kPathMotd        = "Data/Motd/";
        private const string kPathArchive    = kPathMotd + "Archive/";
        private const string kGreeting        = "Greetings And Welcome To Warwickshire";
        private const string kDefaultBody    = "There is no current news.";
        private const string kDefaultTitle    = "Current News";
        private const string kNewMotdMessage= "The message of the day has been updated. To see it, type motd.";
        private static int   kMaximumArchives            = 9;    // should be const, used static to get avoid compiler warning
        private    static bool     kAlwaysShowMotdOnLogin        = true ;// should be const, used static to get avoid compiler warning
        private    static bool  kTextInsteadOfGumpOnLogin    = false;    // should be const, used static to get avoid compiler warning
        
        internal const int    kDataColor = 50;
        internal const int    kLabelColor = 88;
        internal const string kLabelHtmlColor = "66CCFF";

        //----- Edting below this line is not recommended -----

        #region Static Methods

        private static volatile string [] s_ArchiveFilenameCache;
        private static volatile string s_MotdCache;
        private static volatile Mutex s_Mutex = new Mutex();

        public static void Initialize()
        {
            try
            {
                // Make sure we have a message store
                if ( !Directory.Exists( kPathArchive ) )
                    Directory.CreateDirectory( kPathArchive );

                LoadMotd();
            }
            catch
            {
                World.Broadcast( kLabelColor, true, "Motd: no motd file found");
            }

            try { GetArchiveList(); }
            catch { World.Broadcast( kLabelColor, true, "Motd: no archive files found"); }

            EventSink.Login += new LoginEventHandler( MOTD_Login );
            EventSink.Speech += new SpeechEventHandler( EventSink_Speech );
            CommandHandlers.Register( "MOTD", AccessLevel.Administrator, new CommandEventHandler( MOTD_OnCommand ) );
        }

        private static bool LoadMotd()    // Not thread safe, call only from a locked block
        {
            string Filename = kPathMotd + kMotdFile + kFileSuffix;
            string str = "";

            try
            {
                StreamReader reader = new StreamReader( Filename );
                str = reader.ReadToEnd();
                reader.Close();
            }
            finally
            {
                s_MotdCache = ( str == "" ? kDefaultBody : str );
            }

            return !( s_MotdCache == kDefaultBody );
        }

        private static void ArchiveMotd( PlayerMobile mobile ) // Not thread safe, call only from a locked block
        {
            string [] list = Directory.GetFiles( kPathArchive, "*" + kFileSuffix );
            int totalFiles = list.Length;
            string source;

            // Rename all files to make room for the new #1
            for ( int i = totalFiles, j = i + 1; i > 0; i--, j-- )
            {
                if ( File.Exists( source = kPathArchive + i + kFileSuffix ) )
                    File.Move( source, kPathArchive + j + kFileSuffix );
            }

            // Copy the motd file to the #1 slot in the archive, and replace old motd with the new motd file
            if ( File.Exists( source = kPathMotd + kMotdFile + kFileSuffix ) )
                File.Move( source, kPathArchive + "1" + kFileSuffix );

            if ( File.Exists( source = kPathMotd + kNewFile + kFileSuffix ) )
                File.Move( kPathMotd + kNewFile + kFileSuffix, kPathMotd + kMotdFile + kFileSuffix );
        }

        private static void GetArchiveList()    // Not thread safe, call only from a locked block
        {
            s_ArchiveFilenameCache = null;

            // This method may be set to not get all of the files so don't use when archiving.
            // One of these will be unreachable - I chose to live with it rather than use defines.
            // Also Directory.GetFiles has really poor regular expression support
            // so this is about the best you can do without more work.
            
            if ( kMaximumArchives < 10 )
                s_ArchiveFilenameCache = Directory.GetFiles( kPathArchive, "?" + kFileSuffix );
            else
                s_ArchiveFilenameCache = Directory.GetFiles( kPathArchive, "*" + kFileSuffix );
        }
        
        //
        // All thread unsafe methods are bottlenecked in the next three methods.
        //

        private static void PreformArchive( PlayerMobile mobile )
        {
            bool showMotd;

            s_Mutex.WaitOne();
            try
            {
                ArchiveMotd( mobile );
                showMotd = LoadMotd();
                GetArchiveList( );
            }
            catch (Exception exc)
            {
                s_Mutex.ReleaseMutex();
                throw exc;
            }
            s_Mutex.ReleaseMutex();
            SetAllTags( mobile, showMotd );    // no need to block for this
        }
    
        private static void PerformReload( PlayerMobile mobile )
        {
            bool showMotd;

            s_Mutex.WaitOne();
            try
            {
                showMotd = LoadMotd();
                GetArchiveList( );
            }
            catch (Exception exc)
            {
                s_Mutex.ReleaseMutex();
                throw exc;
            }
            s_Mutex.ReleaseMutex();
            SetAllTags( mobile, showMotd );    // no need to block for this
        }

        internal static void SafelySendGumpTo( Mobile mobile, bool admin )
        {
            NewsGump gump;

            s_Mutex.WaitOne();
            try
            {
                int length = s_ArchiveFilenameCache.Length >= kMaximumArchives
                    ? kMaximumArchives : s_ArchiveFilenameCache.Length;

                // Get the caches copied onto the stack of the gump thread.
                gump = new NewsGump( mobile, s_MotdCache, s_ArchiveFilenameCache, length, admin );
            }
            finally
            {
                s_Mutex.ReleaseMutex();
            }
            
            gump.DrawGump( mobile, admin );
            mobile.SendGump( gump );
            ((Account)(((PlayerMobile)mobile).Account)).SetTag( "motd", "false" );
        }

        private static void SetAllTags( Mobile from, bool toTrue )
        {
            if ( kAlwaysShowMotdOnLogin )    // No need to tag if we are always showing
                return;

            string boolValue = toTrue.ToString();
            Account account;

            foreach ( Mobile mobile in World.Mobiles.Values )
            {
                if ( null == mobile || !( mobile is PlayerMobile ) )
                    continue;

                if( null == ( account = (Account)from.Account ) )
                    continue;

                account.SetTag( "motd", boolValue );
            }
            from.SendMessage( kLabelColor, "All players" + ( true == toTrue ? " will " : " will not ") + "see the MOTD Message at next login." );
        }

        #region In-game commands and events

        [Usage( "MOTD" )]
        [Description( "Show MOTD admin menu." )]
        private static void MOTD_OnCommand( CommandEventArgs args )
        {
            Mobile mobile = args.Mobile;
            mobile.CloseGump( typeof(NewsGump) );
            SafelySendGumpTo( mobile, true );
        }

        private static void EventSink_Speech( SpeechEventArgs args )
        {
            Mobile mobile = args.Mobile;
            if ( args.Speech.ToLower().IndexOf( "motd" ) >= 0 )
            {
                SafelySendGumpTo( mobile, false );
            }
        }

        private static void MOTD_Login( LoginEventArgs args )
        {
            Mobile mobile = args.Mobile;
            Account account = (Account)mobile.Account;

            Convert.ToBoolean( account.GetTag( "motd" ) );
                if ( kAlwaysShowMotdOnLogin || Convert.ToBoolean( account.GetTag( "motd" ) ) )
            {
                // One of these will be unreachable - I chose to live with it rather than use defines.
                 if ( kTextInsteadOfGumpOnLogin )
                    mobile.SendMessage( kLabelColor, kNewMotdMessage );
                else
                SafelySendGumpTo( mobile, false );
            }
        }

        #endregion In-game commands and events
        #endregion Static Methods
        #region News Gump Methods

        private PlayerMobile m_Player;
        private string m_UserCount;
        private string m_ItemCount;
        private string m_MobileCount;
        private string m_Body;
        private string [] m_ArchiveList;
        private int    m_TotalPages;
        private int    m_ArchiveCount;
        private int    m_ArchivesLoaded;

        private string LoadNextArchive()
        {
            string Filename;
            string text = "";

            if ( m_ArchiveList != null && m_ArchivesLoaded < m_ArchiveCount
                && (( Filename = m_ArchiveList[ m_ArchivesLoaded ].ToString() ) != null )
                && File.Exists( Filename ) )
            {
                StreamReader reader = new StreamReader( Filename );

                text = reader.ReadToEnd();
                reader.Close();

                m_ArchivesLoaded++;
            }
            return text == "" ? kDefaultBody : text;
        }

        private NewsGump( Mobile mobile, string body, string [] archiveList, int archiveCount, bool admin ) : base( 100, 100 )
        {
            mobile.CloseGump( typeof(NewsGump) );
            m_Body            = body;
            m_Player        = (PlayerMobile)mobile;
            m_UserCount        = NetState.Instances.Count.ToString();
            m_ItemCount        = World.Items.Count.ToString();
            m_MobileCount    = World.Mobiles.Count.ToString();
            m_ArchiveList    = archiveList;
            m_ArchiveCount    = ( null == archiveList ? 0 : archiveCount );
            m_ArchivesLoaded = 0;
            m_TotalPages    = 0;
        }

        private void DrawGump( Mobile mobile, bool admin )
        {
            if ( admin )
            {
                int colOne = 10;
                int colTwo = colOne + 35;
                int rowOne = 10;
                int rowHeight = 25;
                int row = rowOne;

                AddPage( 1 );
                AddBackground( 0, 0, 205, 180, 5054 );
                AddButton( colOne, rowOne, 0xFB7, 0xFB9, 100, GumpButtonType.Reply, 0 );                // Archive
                AddLabel( colTwo, rowOne, kLabelColor, "Archive motd File" );
                AddButton( colOne, (row += rowHeight), 0xFB7, 0xFB9, 101, GumpButtonType.Reply, 0 );    // Reload
                AddLabel( colTwo, row, kLabelColor, "Reload motd File" );
                AddButton( colOne, (row += rowHeight + 10), 0xFB7, 0xFB9, 0, GumpButtonType.Reply, 0 ); // Cancel
                AddLabel( colTwo, row, kLabelColor, "Cancel" );
                AddLabel( colOne, (row += rowHeight + 10), kDataColor, "Warning, admins have both" );
                AddLabel( colOne, (row += rowHeight - 10), kDataColor, "the [motd and motd commands." );
                AddLabel( colOne, (row += rowHeight - 10), kDataColor, "Press Cancel unless you know" );
                AddLabel( colOne, (row += rowHeight - 10), kDataColor, "what these options do." );
            }
            else
            {
                AddNewPage( m_Body );

                while ( m_ArchivesLoaded < m_ArchiveCount )
                {
                    AddNewPage( LoadNextArchive() );
                }
            }
        }

        private void AddNewPage( string bodyText )
        {
            AddPage( ++m_TotalPages );

            AddBackground( 50, 0, 514, 280, 9270 );
            AddBackground( 50, 80, 514, 400, 9270 );

            AddLabel( 170, 15, kDataColor, kGreeting );
            AddLabel( 80, 33, kDataColor, m_Player.Name );
            AddLabel( 205, 33, kLabelColor, "Online Users" );
            AddLabel( 205, 47, kDataColor, m_UserCount );
            AddLabel( 315, 33, kLabelColor, "Total Items" );
            AddLabel( 315, 47, kDataColor, m_ItemCount );
            AddLabel( 425, 33, kLabelColor, "Total Mobiles" );
            AddLabel( 425, 47, kDataColor, m_MobileCount);

            AddHtml( 65, 95, 485, 25, CenterAndColor( 1 == m_TotalPages ? kDefaultTitle : "Previous News" ), false, false );
            AddHtml( 65, 120, 485, 330, bodyText, true, true );
            AddHtml( 65, 450, 485, 25, CenterAndColor( "Page " + ( m_TotalPages ) + " of " + ( m_ArchiveCount + 1 ) ), false, false );
            
            AddButton( 525, 15, 25, 26, 102, GumpButtonType.Reply, 0 );        // Close button
            AddButton( 60, 55, 5522, 5523, 103, GumpButtonType.Reply, 0 );    // Account button
            AddButton( 65, 12, 22153, 22154, 104, GumpButtonType.Reply, 0 );// About button
            AddButton( 500, 95, 5537, 5538, 0, GumpButtonType.Page, m_TotalPages - 1 );    // Navigation left button
            AddButton( 525, 95, 5540, 5541, 0, GumpButtonType.Page, m_TotalPages + 1 );    // Navigation right button
        }

        private static string CenterAndColor( string text )
        {
            return String.Format( "<BASEFONT COLOR=#"+ kLabelHtmlColor + "><CENTER>{0}</CENTER></BASEFONT>", text );
        }

        public override void OnResponse( NetState sender, RelayInfo info )
        {
            Mobile from = sender.Mobile;

            switch ( info.ButtonID )
            {
                case 100:    // Archive
                    try
                    {
                        PreformArchive( (PlayerMobile)from );
                        SafelySendGumpTo( from, false );
                        World.Broadcast( kLabelColor, true, kNewMotdMessage );
                    }
                    catch (Exception exc) { from.SendMessage( kLabelColor, "Archive: exception encountered - " + exc.Message); }
                    break;
                case 101:    // Reload
                    try
                    {
                        PerformReload( (PlayerMobile)from );
                        SafelySendGumpTo( from, false );
                        World.Broadcast( kLabelColor, true, kNewMotdMessage );
                    }
                    catch (Exception exc) { from.SendMessage( kLabelColor, "Archive: exception encountered - " + exc.Message); }
                    break;
                case 102:    // Close Account Gump
                    from.CloseGump( typeof(AccountGump) );
                    break;
                case 103:    // Account Gump
                    from.SendGump( new AccountGump( from, sender, false ) );
                    break;
                case 104:    // Credits
                    from.SendGump( new AccountGump( from, sender, true ) );
                    break;
                case 105:    // Motd from credits only page - $$$ not tested, may not work
                    from.CloseGump( typeof(AccountGump) );
                    SafelySendGumpTo( from, false );
                    break;
            }
        }

        #endregion News Gump Methods
        #region AccountGump

        internal class AccountGump : Gump
        {
            public AccountGump( Mobile from, NetState state, bool showOnlyCredits ) : base( 30, 20 )
            {
                if ( null == state )
                    return;

                PlayerMobile mobile = (PlayerMobile)from;

                AddPage( 1 );

                if ( !showOnlyCredits )
                {
                    AddBackground( 50, 0, 479, 309, 9270 );
                    AddImage( 0, 0, 10400 );
                    AddImage( 0, 225, 10402 );
                    AddImage( 495, 0, 10410 );
                    AddImage( 495, 225, 10412 );
                    AddImage( 60, 15, 5536 );
                    AddImage( 275, 15, 1025 );
                    AddLabel( 205, 43, NewsGump.kLabelColor, "Account Name" );
                    AddLabel( 205, 57, 0x480, mobile.Account.ToString() );
                    AddLabel( 205, 80, NewsGump.kLabelColor, "Account Password" );
                    AddLabel( 205, 98, NewsGump.kDataColor, "-(Protected)-" );
                    AddLabel( 355, 43, NewsGump.kLabelColor, "Online Character" );
                    AddLabel( 355, 57, NewsGump.kDataColor, mobile.Name );
                    AddLabel( 355, 80, NewsGump.kLabelColor, "Character Age" );
                    AddLabel( 355, 100, NewsGump.kDataColor, mobile.GameTime.Days.ToString() + " Days" );
                    AddLabel( 355, 115, NewsGump.kDataColor, mobile.GameTime.Hours.ToString() + " Hours" );
                    AddLabel( 355, 130, NewsGump.kDataColor, mobile.GameTime.Minutes.ToString() + " Minutes" );
                    AddLabel( 355, 144, NewsGump.kDataColor, mobile.GameTime.Seconds.ToString() + " Seconds" );
                    AddLabel( 205, 120, NewsGump.kLabelColor, "Account Access Level" );
                    AddLabel( 205, 135, NewsGump.kDataColor, from.AccessLevel.ToString() );
                    AddButton( 470, 15, 25, 26, 0, GumpButtonType.Reply, 0 );        // Close
                    AddLabel( 355, 165, NewsGump.kLabelColor, "IP Address" );
                    AddLabel( 355, 180, NewsGump.kDataColor, state.ToString());
                    AddLabel( 205, 165, NewsGump.kLabelColor, "Client Version" );
                    AddLabel(205, 180, NewsGump.kDataColor,
                        state.SupportsExpansion(Expansion.HS)?"High Seas":
                        state.SupportsExpansion(Expansion.ML)? "Mondain's Legacy":
                        state.SupportsExpansion(Expansion.SE) ? "Samurai Empire" :
                        state.SupportsExpansion(Expansion.AOS) ? "Age of Shadows" :
                        state.SupportsExpansion(Expansion.LBR) ? "Blackthorn's Revenge" :
                        state.SupportsExpansion(Expansion.UOTD) ? "Third Dawn" :
                        state.SupportsExpansion(Expansion.UOR) ? "Renaissance" : "The Second Age");
                    AddLabel( 205, 200, NewsGump.kLabelColor, "Client Patch" );
                    AddLabel( 205, 215, NewsGump.kDataColor, null == state.Version ? "(null)" : state.Version.ToString() );
                    AddButton( 445, 15, 22153, 22154, 0, GumpButtonType.Page, 2 );    // About

                    AddPage( 2 );
                }

                // Credits page
                AddBackground( 50, 0, 479, 309, 9270 );
                AddImage( 0, 0, 10400 );
                AddImage( 0, 225, 10402 );
                AddImage( 495, 0, 10410 );
                AddImage( 495, 225, 10412 );
                AddImage( 60, 15, 5536 );
                AddLabel( 205, 45, NewsGump.kLabelColor, "Code By" );
                AddLabel( 205, 60, NewsGump.kDataColor, "Xanthos" );
                AddLabel( 205, 80, NewsGump.kLabelColor, "Inspiration By" );
                AddLabel( 205, 95, NewsGump.kDataColor, "Princess Monika" );
                AddLabel( 205, 110, NewsGump.kLabelColor, "Gumps By" );
                AddLabel( 205, 125, NewsGump.kDataColor, "Viago" );
                AddLabel( 355, 45, NewsGump.kLabelColor, "Credit To" );
                AddLabel( 355, 60, NewsGump.kDataColor, "Xuse" );
                AddLabel( 355, 75, NewsGump.kDataColor, "The RunUO Comunity" );
                AddLabel( 355, 90, NewsGump.kDataColor, "Lady Rouge" );
                AddLabel( 355, 105, NewsGump.kDataColor, "RoninGT" );
                AddButton( 470, 15, 25, 26, 0, GumpButtonType.Reply, 0 );        // Close
            }
            #endregion AccountGump
        }
    }
}
 
Try this in place of your MOTD_Login method:

C#:
        private static void MOTD_Login( LoginEventArgs args )
        {
            Mobile mobile = args.Mobile;
            Account account = (Account)mobile.Account;
            Console.WriteLine("** motd called by login **");

            Convert.ToBoolean( account.GetTag( "motd" ) );
            if ( kAlwaysShowMotdOnLogin || Convert.ToBoolean( account.GetTag( "motd" ) ) )
            {
                Console.WriteLine("** motd sent to the user **");
                // One of these will be unreachable - I chose to live with it rather than use defines.
                if ( kTextInsteadOfGumpOnLogin )
                {
                    mobile.SendMessage( kLabelColor, kNewMotdMessage );
                    Console.WriteLine("** motd was sent to the user because kTextInsteadOfGumpOnLogin was TRUE **");
                }
                else
                {
                    SafelySendGumpTo( mobile, false );
                    Console.WriteLine("** motd was sent as a gump because kTextInsteadOfGumpOnLogin was FALSE **");
                }
            }
            else
            {
                Console.WriteLine("** motd NOT sent to the user **");
            }
        }

This should give us the info we need. Look at the console while you log in and report back what happens.
 
It's display the MOTD now, here's the console info:

14:11:53 Listening: 127.0.0.1:2593
14:11:53 ----------------------------------------------------------------------
14:11:54 Warning: 1 bad spawns detected, logged: 'badspawn.log'
14:11:56 Cleanup: Detected 1 inaccessible items, including 1 bank boxes, removing..
14:11:56 Cleanup: Detected 6 hair and facial hair items being worn, converting to their virtual counterparts..
14:17:23 Core: Using dual save strategy
14:17:23 World: Saving...
14:17:23 Saving Jailings
14:17:23 Jailings Saved
14:17:23 Closing Save Files.
14:17:24 Closing Save Files.
14:17:24 Save finished in 1.04 seconds.
14:17:24 [Honesty]: Generating...
14:17:24 [Honesty]: Generation completed in 0.00 seconds.
14:18:23 Client: 72.168.129.104: Connected. [1 Online]
14:18:23 Login: 72.168.129.104: Valid credentials for 'crafter'
14:18:23 Client Type: 72.168.129.104: Classic Client
14:18:30 Client: 72.168.129.104: Disconnected. [0 Online] [crafter]
14:18:57 Client: 127.0.0.1: Connected. [1 Online]
14:18:57 Login: 127.0.0.1: Invalid password for 'barclay'
14:18:57 Client: 127.0.0.1: Disconnected. [0 Online]
14:19:08 Client: 127.0.0.1: Connected. [1 Online]
14:19:08 Login: 127.0.0.1: Valid credentials for 'barclay'
14:19:08 Client Type: 127.0.0.1: Enhanced Client
14:19:10 Client: 127.0.0.1: Connected. [2 Online]
14:19:10 Login: 127.0.0.1: Account 'barclay' at character list
14:19:10 barclay: 7 / 7 [SixthCharacterSlot, ExpansionSA, KR, SeventhCharacterSlot]
14:19:10 Client: 127.0.0.1: Disconnected. [1 Online] [barclay]
14:19:12 The Jail timer load process has finished
14:19:12 ** motd called by login **
14:19:12 ** motd sent to the user **
14:19:12 ** motd was sent as a gump because kTextInsteadOfGumpOnLogin was FALSE **
14:19:12 Client: 127.0.0.1: Entered World (0xA790 "Piper")
14:19:47 Client: 127.0.0.1: Disconnected. [0 Online] [barclay]
14:19:53 Client: 127.0.0.1: Connected. [1 Online]
14:19:53 Login: 127.0.0.1: Valid credentials for 'barclay'
14:19:53 Client Type: 127.0.0.1: Enhanced Client
14:19:56 Client: 127.0.0.1: Connected. [2 Online]
14:19:56 Login: 127.0.0.1: Account 'barclay' at character list
14:19:56 barclay: 7 / 7 [SixthCharacterSlot, ExpansionSA, KR, SeventhCharacterSlot]
14:19:56 Client: 127.0.0.1: Disconnected. [1 Online] [barclay]
14:19:57 ** motd called by login **
14:19:57 ** motd sent to the user **
14:19:57 ** motd was sent as a gump because kTextInsteadOfGumpOnLogin was FALSE **
14:19:57 Client: 127.0.0.1: Entered World (0xA790 "Piper")
14:20:08 Client: 127.0.0.1: Disconnected. [0 Online] [barclay]
 
Back