#define FACTIONS using System; using System.IO; using System.Xml; using Server; using Server.Items; using Server.Network; using Server.Mobiles; using System.Collections.Generic; using Server.Targeting; using Server.Gumps; using System.Text; using Server.Commands; using Server.Commands.Generic; namespace Server.Engines.XmlSpawner2 { public class XmlQuestLeaders { private static TimeSpan m_QuestLeaderboardSaveInterval = TimeSpan.FromMinutes(15); // default time interval between quest leaderboard saves private static string m_QuestLeaderboardSaveDirectory = "Leaderboard"; // default directory for saving quest leaderboard xml information private static int m_QuestLeaderboardSaveRanks = 20; // number of ranked players to save to the quest leaderboard. 0 means save all players. private static QuestLeaderboardTimer m_QuestLeaderboardTimer; private static string m_QuestLeaderboardFile; private static List QuestRankList = new List(); private static bool needsupdate = true; public class QuestRankEntry : IComparable { public Mobile Quester; public int Rank; public XmlQuestPoints QuestPointsAttachment; public QuestRankEntry(Mobile m, XmlQuestPoints attachment) { Quester = m; QuestPointsAttachment = attachment; } public int CompareTo( QuestRankEntry p ) { if(p.QuestPointsAttachment == null || QuestPointsAttachment == null) return 0; // break points ties with quests completed (more quests means higher rank) if(p.QuestPointsAttachment.Points - QuestPointsAttachment.Points == 0) { // if kills are the same then compare previous rank if(p.QuestPointsAttachment.QuestsCompleted - QuestPointsAttachment.QuestsCompleted == 0) { return p.QuestPointsAttachment.Rank - QuestPointsAttachment.Rank; } return p.QuestPointsAttachment.QuestsCompleted - QuestPointsAttachment.QuestsCompleted; } return p.QuestPointsAttachment.Points - QuestPointsAttachment.Points; } } private static void RefreshQuestRankList() { if(needsupdate && QuestRankList != null) { QuestRankList.Sort(); int rank = 0; //int prevpoints = 0; for(int i= 0; i(); // flag the rank list for updating on the next attempt to retrieve a rank needsupdate = true; bool found = false; // rank the entries for(int i= 0; i 0) xf.WriteAttributeString( "nentries", nranks.ToString() ); else xf.WriteAttributeString( "nentries", QuestRankList.Count.ToString() ); // go through the sorted list and display the top ranked players for(int i= 0; i 0 && i >= nranks) break; QuestRankEntry r = QuestRankList[i]; XmlQuestPoints a = r.QuestPointsAttachment; if(r.Quester != null && !r.Quester.Deleted && r.Rank > 0 && a != null && !a.Deleted) { string guildname = null; if(r.Quester.Guild != null) guildname = r.Quester.Guild.Abbreviation; #if(FACTIONS) string factionname = null; if(r.Quester is PlayerMobile && ((PlayerMobile)r.Quester).FactionPlayerState != null) factionname = ((PlayerMobile)r.Quester).FactionPlayerState.Faction.ToString(); #endif // check for any ranking change and update rank date if(r.Rank != a.Rank) { a.WhenRanked = DateTime.UtcNow; if(a.Rank > 0) a.DeltaRank = a.Rank - r.Rank; a.Rank = r.Rank; } TimeSpan timeranked = DateTime.UtcNow - a.WhenRanked; // write out the entry information xf.WriteStartElement( "Entry" ); xf.WriteAttributeString( "number", i.ToString() ); xf.WriteStartElement( "Player" ); xf.WriteString( r.Quester.Name ); xf.WriteEndElement(); xf.WriteStartElement( "Guild" ); xf.WriteString( guildname ); xf.WriteEndElement(); #if(FACTIONS) xf.WriteStartElement( "Faction" ); xf.WriteString( factionname ); xf.WriteEndElement(); #endif xf.WriteStartElement( "Points" ); xf.WriteString( a.Points.ToString() ); xf.WriteEndElement(); string quests = "???"; try { quests = a.QuestsCompleted.ToString(); } catch{} xf.WriteStartElement( "Quests" ); xf.WriteString( quests ); xf.WriteEndElement(); xf.WriteStartElement( "Rank" ); xf.WriteString( a.Rank.ToString() ); xf.WriteEndElement(); xf.WriteStartElement( "Change" ); xf.WriteString( a.DeltaRank.ToString() ); xf.WriteEndElement(); xf.WriteStartElement( "Duration" ); xf.WriteString( timeranked.ToString() ); xf.WriteEndElement(); // end the entry xf.WriteEndElement(); } } xf.WriteEndElement(); xf.Close(); } public static void WriteQuestLeaderboardHtml(string filename, int nranks) { string dirname = Path.Combine( m_QuestLeaderboardSaveDirectory, filename ); StreamWriter sw = new StreamWriter( dirname ); if(sw == null) { Console.WriteLine("Error: unable to save HTML quest leaderboard to {0}", dirname); return; } sw.WriteLine(" "); sw.WriteLine( ""); #if(FACTIONS) sw.WriteLine( "
Quest Leaderboard
Player NameGuildFactionPointsQuestsRankChangeTime at current rank"); #else sw.WriteLine( "
Player NameGuildPointsQuestsRankChangeTime at current rank"); #endif // go through the sorted list and display the top ranked players for(int i= 0; i 0 && i >= nranks) break; QuestRankEntry r = QuestRankList[i]; XmlQuestPoints a = r.QuestPointsAttachment; if(r.Quester != null && !r.Quester.Deleted && r.Rank > 0 && a != null && !a.Deleted) { string guildname = null; if(r.Quester.Guild != null) guildname = r.Quester.Guild.Abbreviation; #if(FACTIONS) string factionname = null; if(r.Quester is PlayerMobile && ((PlayerMobile)r.Quester).FactionPlayerState != null) factionname = ((PlayerMobile)r.Quester).FactionPlayerState.Faction.ToString(); #endif // check for any ranking change and update rank date if(r.Rank != a.Rank) { a.WhenRanked = DateTime.UtcNow; if(a.Rank > 0) a.DeltaRank = a.Rank - r.Rank; a.Rank = r.Rank; } TimeSpan timeranked = DateTime.UtcNow - a.WhenRanked; string quests = "???"; try { quests = a.QuestsCompleted.ToString(); } catch{} #if(FACTIONS) // write out the entry information sw.WriteLine( "
{0}{1}{2}{3}{4}{5}{6}{7}", r.Quester.Name, guildname, factionname, a.Points, quests, a.Rank, a.DeltaRank, timeranked ); #else // write out the entry information sw.WriteLine( "
{0}{1}{2}{3}{4}{5}{6}", r.Quester.Name, guildname, a.Points, quests, a.Rank, a.DeltaRank, timeranked ); #endif } } sw.WriteLine( "
"); sw.Close(); } public static void WriteQuestLeaderboard(string filename, int nranks) { if(QuestRankList == null) return; // force an update of the quest leaderboard rankings needsupdate = true; RefreshQuestRankList(); if ( !Directory.Exists( m_QuestLeaderboardSaveDirectory ) ) Directory.CreateDirectory( m_QuestLeaderboardSaveDirectory ); WriteQuestLeaderboardXml(filename + ".xml", nranks); WriteQuestLeaderboardHtml(filename + ".html", nranks); } [Usage( "QuestLeaderboardSave [filename [minutes[nentries]]][off]" )] [Description( "Periodically save .xml quest leaderboard information to the specified file" )] public static void QuestLeaderboardSave_OnCommand( CommandEventArgs e ) { if(e.Arguments.Length > 0) { if(m_QuestLeaderboardTimer != null) m_QuestLeaderboardTimer.Stop(); if(e.Arguments[0].ToLower() != "off") { m_QuestLeaderboardFile = e.Arguments[0]; if(e.Arguments.Length > 1) { try { m_QuestLeaderboardSaveInterval = TimeSpan.FromMinutes(double.Parse(e.Arguments[1])); } catch{} } if(e.Arguments.Length > 2) { try { m_QuestLeaderboardSaveRanks = int.Parse(e.Arguments[2]); } catch{} } m_QuestLeaderboardTimer = new QuestLeaderboardTimer(m_QuestLeaderboardFile, m_QuestLeaderboardSaveInterval, m_QuestLeaderboardSaveRanks); m_QuestLeaderboardTimer.Start(); } } if(m_QuestLeaderboardTimer != null && m_QuestLeaderboardTimer.Running) { e.Mobile.SendMessage("Quest Leaderboard is saving to {0} every {1} minutes. Nranks = {2}", m_QuestLeaderboardFile, m_QuestLeaderboardSaveInterval.TotalMinutes, m_QuestLeaderboardSaveRanks); } else { e.Mobile.SendMessage("Quest Leaderboard saving is off."); } } public static void QuestLBSSerialize( GenericWriter writer ) { // version writer.Write( (int) 0 ); // version 0 if(m_QuestLeaderboardTimer != null && m_QuestLeaderboardTimer.Running) { writer.Write((bool)true); } else writer.Write((bool)false); writer.Write(m_QuestLeaderboardSaveInterval); writer.Write(m_QuestLeaderboardSaveRanks); writer.Write(m_QuestLeaderboardFile); } public static void QuestLBSDeserialize(GenericReader reader) { int version = reader.ReadInt(); switch(version) { case 0: bool running = reader.ReadBool(); m_QuestLeaderboardSaveInterval = reader.ReadTimeSpan(); m_QuestLeaderboardSaveRanks = reader.ReadInt(); m_QuestLeaderboardFile = reader.ReadString(); if(running) { if(m_QuestLeaderboardTimer != null) m_QuestLeaderboardTimer.Stop(); m_QuestLeaderboardTimer = new QuestLeaderboardTimer(m_QuestLeaderboardFile, m_QuestLeaderboardSaveInterval, m_QuestLeaderboardSaveRanks); m_QuestLeaderboardTimer.Start(); } break; } } // added the duration timer that begins on spawning private class QuestLeaderboardTimer : Timer { private string m_filename; private int m_nranks; public QuestLeaderboardTimer( string filename, TimeSpan delay, int nranks ) : base( delay, delay ) { m_filename = filename; m_nranks = nranks; Priority = TimerPriority.FiveSeconds; } protected override void OnTick() { WriteQuestLeaderboard(m_filename, m_nranks); } } public class TopQuestPlayersGump : Gump { private XmlQuestPoints m_attachment; public TopQuestPlayersGump(XmlQuestPoints attachment) : base( 0,0) { if(QuestRankList == null) return; m_attachment = attachment; int numberToDisplay = 20; int height = numberToDisplay*20 + 65; // prepare the page AddPage( 0 ); int width = 740; #if(FACTIONS) width = 790; #endif AddBackground( 0, 0, width, height, 5054 ); AddAlphaRegion( 0, 0, width, height ); AddImageTiled( 20, 20, width - 40, height - 45, 0xBBC ); AddLabel( 20, 2, 55, "Top Quest Player Rankings" ); // guild filter AddLabel( 40, height - 20, 55, "Filter by Guild" ); string filter = null; if(m_attachment != null) filter = m_attachment.guildFilter; AddImageTiled( 140, height - 20, 160, 19, 0xBBC ); AddTextEntry( 140, height - 20, 160, 19, 0, 200, filter ); AddButton( 20, height - 20, 0x15E1, 0x15E5, 200, GumpButtonType.Reply, 0 ); // name filter AddLabel( 340, height - 20, 55, "Filter by Name" ); // string nfilter = null; if(m_attachment != null) nfilter = m_attachment.nameFilter; AddImageTiled( 440, height - 20, 160, 19, 0xBBC ); AddTextEntry( 440, height - 20, 160, 19, 0, 100, nfilter ); AddButton( 320, height - 20, 0x15E1, 0x15E5, 100, GumpButtonType.Reply, 0 ); RefreshQuestRankList(); int xloc = 23; AddLabel( xloc, 20, 0, "Name" ); xloc += 177; AddLabel( xloc, 20, 0, "Guild" ); #if(FACTIONS) xloc += 35; AddLabel( xloc, 20, 0, "Faction" ); xloc += 15; #endif xloc += 50; AddLabel( xloc, 20, 0, "Points" ); xloc += 50; AddLabel( xloc, 20, 0, "Quests" ); xloc += 50; //AddLabel( xloc, 20, 0, "" ); xloc += 70; AddLabel( xloc, 20, 0, "Rank" ); xloc += 45; AddLabel( xloc, 20, 0, "Change" ); xloc += 45; AddLabel( xloc, 20, 0, "Time at Rank" ); // go through the sorted list and display the top ranked players int y = 40; int count = 0; for(int i= 0; i= numberToDisplay) break; QuestRankEntry r = QuestRankList[i]; if(r == null) continue; XmlQuestPoints a = r.QuestPointsAttachment; if(a == null) continue; if(r.Quester != null && !r.Quester.Deleted && r.Rank > 0 && a != null && !a.Deleted) { string guildname = null; if(r.Quester.Guild != null) guildname = r.Quester.Guild.Abbreviation; #if(FACTIONS) string factionname = null; if(r.Quester is PlayerMobile && ((PlayerMobile)r.Quester).FactionPlayerState != null) factionname = ((PlayerMobile)r.Quester).FactionPlayerState.Faction.ToString(); #endif // check for any ranking change and update rank date if(r.Rank != a.Rank) { a.WhenRanked = DateTime.UtcNow; if(a.Rank > 0) a.DeltaRank = a.Rank - r.Rank; a.Rank = r.Rank; } // check for guild filter if(m_attachment != null && m_attachment.guildFilter != null && m_attachment.guildFilter.Length > 0) { // parse the comma separated list string [] args = m_attachment.guildFilter.Split(','); if(args != null) { bool found = false; foreach(string arg in args) { if(arg != null && guildname == arg.Trim()) { found = true; break; } } if(!found) continue; } } // check for name filter if(m_attachment != null && m_attachment.nameFilter != null && m_attachment.nameFilter.Length > 0) { // parse the comma separated list string [] args = m_attachment.nameFilter.Split(','); if(args != null) { bool found = false; foreach(string arg in args) { if(arg != null && r.Quester.Name != null && (r.Quester.Name.ToLower().IndexOf(arg.Trim().ToLower()) >= 0)) { found = true; break; } } if(!found) continue; } } count++; TimeSpan timeranked = DateTime.UtcNow - a.WhenRanked; int days = (int)timeranked.TotalDays; int hours = (int)(timeranked.TotalHours - days*24); int mins = (int)(timeranked.TotalMinutes - ((int)timeranked.TotalHours)*60); string quests = "???"; try { quests = a.QuestsCompleted.ToString(); } catch{} xloc = 23; AddLabel( xloc, y, 0, r.Quester.Name ?? String.Empty ); xloc += 177; AddLabel( xloc, y, 0, guildname ?? String.Empty ); #if(FACTIONS) xloc += 35; AddLabelCropped( xloc, y, 60, 21, 0, factionname ?? String.Empty ); xloc += 15; #endif xloc += 50; AddLabel( xloc, y, 0, a.Points.ToString() ); xloc += 50; AddLabel( xloc, y, 0, quests ?? String.Empty ); xloc += 50; //AddLabel( xloc, y, 0, "" ); xloc += 70; AddLabel( xloc, y, 0, a.Rank.ToString() ); string label=null; if(days > 0) label += String.Format("{0} days ",days); if(hours > 0) label += String.Format("{0} hours ",hours); if(mins > 0) label += String.Format("{0} mins",mins); if(label == null) { label = "just changed"; } string deltalabel = a.DeltaRank.ToString(); int deltahue = 0; if(a.DeltaRank > 0) { deltalabel = String.Format("+{0}",a.DeltaRank); deltahue = 68; } else if(a.DeltaRank < 0) { deltahue = 33; } xloc += 50; AddLabel( xloc, y, deltahue, deltalabel ); xloc += 40; AddLabel( xloc, y, 0, label); y += 20; } } } public override void OnResponse( NetState state, RelayInfo info ) { if(state == null || state.Mobile == null || info == null) return; // Get the current name if(m_attachment != null) { TextRelay entry = info.GetTextEntry( 200 ); if(entry != null) m_attachment.guildFilter = entry.Text; entry = info.GetTextEntry( 100 ); if(entry != null) m_attachment.nameFilter = entry.Text; } switch(info.ButtonID) { case 100: case 200: { // redisplay the gump state.Mobile.SendGump(new TopQuestPlayersGump(m_attachment)); break; } } } } } }