Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,28 @@
using Server;
using System;
using Server.Mobiles;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class BaseTownCryerGump : BaseGump
{
public TownCrier Cryer { get; private set; }
public BaseTownCryerGump(PlayerMobile pm, TownCrier cryer)
: base(pm, 50, 50)
{
Cryer = cryer;
}
public override void AddGumpLayout()
{
AddPage(0);
AddBackground(0, 0, 854, 700, 0x24AE);
AddImage(156, 35, 0x266C);
AddBackground(40, 130, 770, 470, 0x2486);
}
}
}

View File

@@ -0,0 +1,105 @@
using Server;
using System;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class CreateCityEntryGump : BaseTownCryerGump
{
public TownCryerCityEntry Entry { get; set; }
public bool Edit { get; private set; }
public City City { get; private set; }
public CreateCityEntryGump(PlayerMobile pm, TownCrier cryer, City city, TownCryerCityEntry entry = null)
: base(pm, cryer)
{
Entry = entry;
City = city;
if (Entry != null)
{
Edit = true;
}
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
AddHtmlLocalized(57, 155, 100, 20, 1158040, false, false); // City:
AddHtmlLocalized(110, 155, 200, 20, CityLoyaltySystem.GetCityLocalization(City), false, false);
AddHtmlLocalized(57, 185, 50, 20, 1158027, false, false); // Author:
AddLabel(110, 185, 0, Entry != null ? Entry.Author : User.Name);
AddHtmlLocalized(58, 215, 100, 20, 1158026, false, false); // Headline:
AddBackground(58, 235, 740, 20, 0x2486);
AddTextEntry(59, 235, 739, 20, 0, 1, Entry != null ? Entry.Title : "");
AddHtmlLocalized(58, 265, 150, 20, 1158028, false, false); // Body Paragraph 1:
AddBackground(58, 285, 740, 40, 0x2486);
AddTextEntry(59, 285, 739, 40, 0, 2, Entry != null ? Entry.Body : "");
AddBackground(155, 330, 20, 20, 0x2486);
AddHtmlLocalized(58, 330, 150, 20, 1158031, false, false); // Expiry (in days):
AddTextEntry(155, 330, 19, 20, 0, 3, "");
AddImage(85, 425, 0x5EF);
AddButton(40, 615, 0x601, 0x602, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(73, 615, 150, 20, 1077787, false, false); // Submit
}
public override void OnResponse(RelayInfo info)
{
if (info.ButtonID == 1)
{
string headline = info.GetTextEntry(1).Text;
string body = info.GetTextEntry(2).Text;
string exp = info.GetTextEntry(3).Text;
int expires = Utility.ToInt32(exp);
if (Entry == null)
{
Entry = new TownCryerCityEntry(User, City, expires, headline, body);
}
else
{
Entry.Title = headline;
Entry.Body = body;
if (expires >= 1 && expires <= 14)
{
Entry.Expires = DateTime.Now + TimeSpan.FromDays(expires);
}
}
if (expires < 1 || expires > 14)
{
User.SendLocalizedMessage(1158042); // The expiry can be between 1 and 14 days. Please check your entry and try again.
}
else if (string.IsNullOrEmpty(headline) || string.IsNullOrEmpty(body) || headline.Length < 3 || body.Length < 5)
{
User.SendLocalizedMessage(1158032); // The expiry can be between 1 and 30 days. Please check your entry and try again.
}
else
{
if (!Edit)
{
TownCryerSystem.AddEntry(Entry);
}
User.SendLocalizedMessage(1158039); // Your entry has been submitted.
BaseGump.SendGump(new TownCryerGump(User, Cryer, 0, TownCryerGump.GumpCategory.City));
return;
}
Refresh();
}
}
}
}

View File

@@ -0,0 +1,111 @@
using Server;
using System;
using Server.Mobiles;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class CreateEMEntryGump : BaseTownCryerGump
{
public TownCryerModeratorEntry Entry { get; set; }
public bool Edit { get; private set; }
public CreateEMEntryGump(PlayerMobile pm, TownCrier cryer, TownCryerModeratorEntry entry = null)
: base(pm, cryer)
{
Entry = entry;
if (Entry != null)
{
Edit = true;
}
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
AddHtmlLocalized(58, 150, 100, 20, 1158027, false, false); // Author:
AddLabel(105, 150, 0, String.Format("EM {0}", User.Name));
AddHtmlLocalized(58, 180, 100, 20, 1158026, false, false); // Headline:
AddBackground(58, 200, 740, 20, 0x2486);
AddTextEntry(59, 200, 739, 20, 0, 1, Entry != null ? Entry.Title : "");
AddHtmlLocalized(58, 220, 120, 20, 1158028, false, false); // Body Paragraph 1:
AddBackground(58, 240, 740, 40, 0x2486);
AddTextEntry(59, 240, 739, 40, 0, 2, Entry != null ? Entry.Body1 : "");
AddHtmlLocalized(58, 280, 120, 20, 1158029, false, false); // Body Paragraph 2:
AddBackground(58, 300, 740, 40, 0x2486);
AddTextEntry(59, 300, 739, 40, 0, 3, Entry != null ? Entry.Body2 : "");
AddHtmlLocalized(58, 340, 120, 20, 1158030, false, false); // Body Paragraph 3:
AddBackground(58, 360, 740, 40, 0x2486);
AddTextEntry(59, 360, 739, 40, 0, 4, Entry != null ? Entry.Body3 : "");
AddBackground(155, 405, 20, 20, 0x2486);
AddHtmlLocalized(58, 405, 100, 20, 1158031, false, false); // Expiry (in days):
AddTextEntry(156, 405, 19, 20, 0, 5, "");
AddImage(85, 425, 0x5EF);
AddButton(40, 615, 0x601, 0x602, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(63, 615, 150, 20, 1077787, false, false); // Submit
}
public override void OnResponse(RelayInfo info)
{
if (info.ButtonID == 1)
{
string headline = info.GetTextEntry(1).Text;
string body1 = info.GetTextEntry(2).Text;
string body2 = info.GetTextEntry(3).Text;
string body3 = info.GetTextEntry(4).Text;
string exp = info.GetTextEntry(5).Text;
int expires = Utility.ToInt32(exp);
if (Entry == null)
{
Entry = new TownCryerModeratorEntry(User, expires, headline, body1, body2, body3);
}
else
{
Entry.Title = headline;
Entry.Body1 = body1;
Entry.Body2 = body2;
Entry.Body3 = body3;
if (expires >= 1 && expires <= 30)
{
Entry.Expires = DateTime.Now + TimeSpan.FromDays(expires);
}
}
if(expires < 1 || expires > 30)
{
User.SendLocalizedMessage(1158033); // The expiry can be between 1 and 30 days. Please check your entry and try again.
}
else if (string.IsNullOrEmpty(headline) || string.IsNullOrEmpty(body1) || headline.Length < 5 || body1.Length < 5)
{
User.SendLocalizedMessage(1158032); // You have made an illegal entry. Check your entries and try again.
}
else
{
if (!Edit)
{
TownCryerSystem.AddEntry(Entry);
}
User.SendLocalizedMessage(1158039); // Your entry has been submitted.
BaseGump.SendGump(new TownCryerGump(User, Cryer, 0, TownCryerGump.GumpCategory.EventModerator));
return;
}
Refresh();
}
}
}
}

View File

@@ -0,0 +1,201 @@
using Server;
using System;
using Server.Mobiles;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class CreateGreetingEntryGump : BaseTownCryerGump
{
public TownCryerGreetingEntry Entry { get; set; }
public bool Edit { get; private set; }
public CreateGreetingEntryGump(PlayerMobile pm, TownCrier cryer, TownCryerGreetingEntry entry = null)
: base(pm, cryer)
{
Entry = entry;
if (Entry != null)
{
Edit = true;
_Headline = Entry.Title != null ? Entry.Title.String : String.Empty;
_Body = Entry.Body1 != null ? Entry.Body1.String : String.Empty;
_Body2 = Entry.Body2 != null ? Entry.Body2 : String.Empty;
_Body3 = Entry.Body3 != null ? Entry.Body3 : String.Empty;
_Link = Entry.Link;
_LinkText = Entry.LinkText;
}
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
AddHtmlLocalized(58, 140, 100, 20, 1158027, false, false); // Author:
AddLabel(105, 140, 0, String.Format("{1} {0}", User.Name, User.AccessLevel.ToString()));
AddHtmlLocalized(58, 160, 100, 20, 1158026, false, false); // Headline:
AddBackground(58, 180, 740, 20, 0x2486);
AddTextEntry(59, 180, 739, 20, 0, 1, Entry != null ? Entry.Title.ToString() : _Headline);
AddHtmlLocalized(58, 200, 120, 20, 1158028, false, false); // Body Paragraph 1:
AddBackground(58, 220, 740, 40, 0x2486);
AddTextEntry(59, 220, 739, 40, 0, 2, _Body);
AddHtmlLocalized(58, 270, 120, 20, 1158029, false, false); // Body Paragraph 2:
AddBackground(58, 290, 740, 40, 0x2486);
AddTextEntry(59, 290, 739, 40, 0, 3, _Body2);
AddHtmlLocalized(58, 340, 120, 20, 1158030, false, false); // Body Paragraph 3:
AddBackground(58, 360, 740, 40, 0x2486);
AddTextEntry(59, 360, 739, 40, 0, 4, _Body3);
AddHtml(58, 410, 250, 20, "Link:", false, false);
AddBackground(58, 430, 740, 40, 0x2486);
AddTextEntry(59, 430, 739, 40, 0, 5, _Link);
AddHtml(58, 480, 250, 20, "Link Text:", false, false);
AddBackground(58, 500, 740, 40, 0x2486);
AddTextEntry(59, 500, 739, 40, 0, 6, _LinkText);
if (!Edit)
{
AddBackground(155, 550, 20, 20, 0x2486);
AddHtmlLocalized(58, 550, 100, 20, 1158031, false, false); // Expiry (in days):
AddTextEntry(156, 550, 19, 20, 0, 7, _Expires);
}
AddButton(40, 615, 0x601, 0x602, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(63, 615, 150, 20, 1077787, false, false); // Submit
}
private void HandleText(RelayInfo info)
{
TextRelay relay = info.GetTextEntry(1);
if (relay != null && !string.IsNullOrEmpty(relay.Text))
{
_Headline = relay.Text.Trim();
}
relay = info.GetTextEntry(2);
if (relay != null && !string.IsNullOrEmpty(relay.Text))
{
_Body = relay.Text.Trim();
}
relay = info.GetTextEntry(3);
if (relay != null && !string.IsNullOrEmpty(relay.Text))
{
_Body2 = relay.Text.Trim();
}
relay = info.GetTextEntry(4);
if (relay != null && !string.IsNullOrEmpty(relay.Text))
{
_Body3 = relay.Text.Trim();
}
relay = info.GetTextEntry(5);
if (relay != null && !string.IsNullOrEmpty(relay.Text))
{
_Link = relay.Text.Trim();
}
relay = info.GetTextEntry(6);
if (relay != null && !string.IsNullOrEmpty(relay.Text))
{
_LinkText = relay.Text.Trim();
}
relay = info.GetTextEntry(7);
if (relay != null && !string.IsNullOrEmpty(relay.Text))
{
_Expires = relay.Text.Trim();
}
}
private string _Headline;
private string _Body;
private string _Body2;
private string _Body3;
private string _Expires;
private string _Link;
private string _LinkText;
public override void OnResponse(RelayInfo info)
{
if (info.ButtonID == 1)
{
HandleText(info);
var headline = _Headline;
var body = _Body;
var body2 = _Body2;
var body3 = _Body3;
var exp = _Expires;
var link = _Link;
var linkText = _LinkText;
int expires = -1;
if (!String.IsNullOrEmpty(exp))
{
expires = Utility.ToInt32(exp);
}
if (Entry == null)
{
Entry = new TownCryerGreetingEntry(headline, body, body2, body3, expires, link, linkText, true);
}
else
{
Entry.Title = headline;
Entry.Body1 = body;
Entry.Body2 = body2;
Entry.Body3 = body3;
Entry.Link = link;
Entry.LinkText = linkText;
if (expires >= 1 && expires <= 30)
{
Entry.Expires = DateTime.Now + TimeSpan.FromDays(expires);
}
}
if(!Edit && (expires < 1 || expires > 30))
{
User.SendLocalizedMessage(1158033); // The expiry can be between 1 and 30 days. Please check your entry and try again.
}
else if (string.IsNullOrEmpty(headline) || string.IsNullOrEmpty(body) || headline.Length < 5 || body.Length < 5)
{
User.SendLocalizedMessage(1158032); // You have made an illegal entry. Check your entries and try again.
}
else
{
if (!Edit)
{
TownCryerSystem.AddEntry(Entry);
User.SendLocalizedMessage(1158039); // Your entry has been submitted.
}
else
{
User.SendMessage("Your edited entry has been submitted.");
}
return;
}
Refresh();
}
}
}
}

View File

@@ -0,0 +1,135 @@
using Server;
using System;
using Server.Mobiles;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class CreateGuildEntryGump : BaseTownCryerGump
{
public TownCryerGuildEntry Entry { get; set; }
public bool Edit { get; private set; }
public CreateGuildEntryGump(PlayerMobile pm, TownCrier cryer, TownCryerGuildEntry entry = null)
: base(pm, cryer)
{
Entry = entry;
if (Entry != null)
{
Edit = true;
}
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
AddHtmlLocalized(58, 150, 100, 20, 1158027, false, false); // Author:
AddLabel(105, 150, 0, String.Format("{0}", Entry != null ? Entry.Author : User.Name));
AddHtmlLocalized(58, 170, 100, 20, 1158055, false, false); // Guild:
AddLabel(105, 170, 0, Entry != null && Entry.Guild != null ? Entry.Guild.Name : "Unknown");
AddHtmlLocalized(58, 190, 100, 20, 1158026, false, false); // Headline:
AddBackground(58, 210, 740, 20, 0x2486);
AddTextEntry(59, 210, 739, 20, 0, 1, Entry != null ? Entry.Title : "");
AddBackground(138, 240, 20, 20, 0x2486);
AddHtmlLocalized(58, 240, 100, 20, 1158056, false, false); // Event Month:
AddTextEntry(139, 240, 19, 20, 0, 2, Entry != null ? Entry.EventTime.Month.ToString() : "", 2);
AddBackground(323, 240, 20, 20, 0x2486);
AddHtmlLocalized(258, 240, 150, 20, 1158057, false, false); // Event Day:
AddTextEntry(324, 240, 19, 20, 0, 3, Entry != null ? Entry.EventTime.Day.ToString() : "", 2);
AddBackground(529, 240, 20, 20, 0x2486);
AddHtmlLocalized(458, 240, 150, 20, 1158058, false, false); // Event Time:
AddTextEntry(530, 240, 19, 20, 0, 4, Entry != null ? Entry.EventTime.Hour.ToString() : "", 2);
AddHtmlLocalized(58, 260, 150, 20, 1158059, false, false); // Event Timezone:
AddLabel(155, 260, 0, TimeZoneInfo.Local.StandardName);
AddHtmlLocalized(58, 290, 150, 20, 1158060, false, false); // Event Description:
AddBackground(58, 310, 740, 40, 0x2486);
AddTextEntry(59, 310, 739, 40, 0, 5, Entry != null ? Entry.Body : "");
AddHtmlLocalized(58, 370, 150, 20, 1158061, false, false); // Event Meeting Place:
AddBackground(58, 390, 740, 40, 0x2486);
AddTextEntry(59, 390, 739, 40, 0, 6, Entry != null ? Entry.EventLocation : "");
AddImage(85, 425, 0x5EF);
AddButton(40, 615, 0x601, 0x602, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(73, 615, 150, 20, 1077787, false, false); // Submit
}
public override void OnResponse(RelayInfo info)
{
if (info.ButtonID == 1)
{
string headline = info.GetTextEntry(1).Text;
string m = info.GetTextEntry(2).Text;
string d = info.GetTextEntry(3).Text;
string t = info.GetTextEntry(4).Text;
string desc = info.GetTextEntry(5).Text;
string meet = info.GetTextEntry(6).Text;
DateTime dt = DateTime.Now;
bool illegalDate = false;
int year = dt.Year;
if (Utility.ToInt32(m) < DateTime.Now.Month)
{
year++;
}
if (Entry == null)
{
if (!DateTime.TryParse(String.Format("{0}/{1}/{2} {3}:00:00", m, d, year.ToString(), t), out dt)) // bad format
{
illegalDate = true;
dt = DateTime.MinValue;
}
Entry = new TownCryerGuildEntry(User, dt, meet, headline, desc);
}
else
{
Entry.Title = headline;
Entry.Body = desc;
Entry.EventLocation = meet;
if (DateTime.TryParse(String.Format("{0}/{1}/{2} {3}:00:00", m, d, year.ToString(), t), out dt))
{
Entry.EventTime = dt;
}
}
if (string.IsNullOrEmpty(headline) || string.IsNullOrEmpty(desc) || string.IsNullOrEmpty(meet))
{
User.SendLocalizedMessage(1158062); // All fields must be populated. Please check your entries and try again.
}
else if (illegalDate)
{
User.SendLocalizedMessage(1158032); // You have made an illegal entry. Check your entries and try again.
}
else
{
if (!Edit)
{
TownCryerSystem.AddEntry(Entry);
}
User.SendLocalizedMessage(1158039); // Your entry has been submitted.
BaseGump.SendGump(new TownCryerGump(User, Cryer, 0, TownCryerGump.GumpCategory.Guild));
return;
}
Refresh();
}
}
}
}

View File

@@ -0,0 +1,41 @@
using Server;
using System;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class TownCryerCityGump : BaseTownCryerGump
{
public TownCryerCityEntry Entry { get; private set; }
public TownCryerCityGump(PlayerMobile pm, TownCrier cryer, TownCryerCityEntry entry)
: base(pm, cryer)
{
Entry = entry;
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
AddHtml(57, 155, 724, 20, Entry.Title, false, false);
AddHtmlLocalized(57, 180, 724, 20, 1154760, Entry.Author, 0, false, false); // By: ~1_NAME~
AddHtml(57, 215, 724, 205, Entry.Body, false, false);
AddImage(85, 425, 0x5EF);
}
public override void OnResponse(RelayInfo info)
{
if (info.ButtonID == 0)
{
var gump = new TownCryerGump(User, Cryer);
gump.Category = TownCryerGump.GumpCategory.City;
BaseGump.SendGump(gump);
}
}
}
}

View File

@@ -0,0 +1,63 @@
using Server;
using System;
using System.Linq;
using Server.Mobiles;
using Server.Gumps;
using Server.Engines.Quests;
namespace Server.Services.TownCryer
{
public class TownCrierQuestCompleteGump : BaseGump
{
public object Title { get; set; }
public object Body { get; set; }
public int GumpID { get; set; }
public TownCrierQuestCompleteGump(PlayerMobile pm, object title, object body, int id)
: base(pm, 10, 100)
{
Title = title;
Body = body;
GumpID = id;
}
public TownCrierQuestCompleteGump(PlayerMobile pm, BaseQuest quest)
: base(pm, 10, 100)
{
Title = quest.Title;
Body = quest.Complete;
var entry = TownCryerSystem.NewsEntries.FirstOrDefault(e => e.QuestType == quest.GetType());
if (entry != null)
{
GumpID = entry.GumpImage;
}
}
public override void AddGumpLayout()
{
AddBackground(0, 0, 454, 540, 9380);
AddImage(62, 42, GumpID);
if (Title is int)
{
AddHtmlLocalized(0, 392, 454, 20, CenterLoc, String.Format("#{0}", (int)Title), 0, false, false);
}
else if (Title is string)
{
AddHtml(0, 392, 454, 20, Center((string)Title), false, false);
}
if (Body is int)
{
AddHtmlLocalized(27, 417, 390, 73, (int)Body, C32216(0x080808), false, true);
}
else if (Body is string)
{
AddHtml(27, 417, 390, 73, (string)Body, false, true);
}
}
}
}

View File

@@ -0,0 +1,43 @@
using Server;
using System;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class TownCryerEventModeratorGump : BaseTownCryerGump
{
public TownCryerModeratorEntry Entry { get; private set; }
public TownCryerEventModeratorGump(PlayerMobile pm, TownCrier cryer, TownCryerModeratorEntry entry)
: base(pm, cryer)
{
Entry = entry;
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
AddHtml(58, 150, 724, 20, Entry.Title, false, false);
AddHtmlLocalized(58, 180, 724, 20, 1154760, Entry.ModeratorName, 0, false, false); // By: ~1_NAME~
AddHtml(58, 215, 724, 205, Entry.Body1, false, false);
AddHtml(58, 280, 724, 205, Entry.Body2, false, false);
AddHtml(58, 345, 724, 205, Entry.Body3, false, false);
AddImage(85, 425, 0x5EF);
}
public override void OnResponse(RelayInfo info)
{
if (info.ButtonID == 0)
{
var gump = new TownCryerGump(User, Cryer);
gump.Category = TownCryerGump.GumpCategory.EventModerator;
BaseGump.SendGump(gump);
}
}
}
}

View File

@@ -0,0 +1,188 @@
using Server;
using System;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Engines.Quests;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class TownCryerGreetingsGump : BaseTownCryerGump
{
public int Page { get; private set; }
public int Pages { get { return TownCryerSystem.GreetingsEntries.Count; } }
public TownCryerGreetingEntry Entry { get; private set; }
public TownCryerGreetingsGump(PlayerMobile pm, TownCrier cryer, int page = 0)
: base(pm, cryer)
{
Page = page;
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
var list = new List<TownCryerGreetingEntry>(TownCryerSystem.GreetingsEntries);
list.Sort();
Entry = list[0];
if (Page >= 0 && Page < list.Count)
{
Entry = list[Page];
}
int y = 150;
if (Entry.Title != null)
{
if (Entry.Title.Number > 0)
{
AddHtmlLocalized(78, y, 700, 400, Entry.Title.Number, false, false);
}
else
{
AddHtml(78, y, 700, 400, Entry.Title.ToString(), false, false);
}
y += 40;
}
// For now, we're only supporting a cliloc (hard coded greetings per EA) or string (Custom) entries. Not both.
// Html tags will needed to be added when creating the entry, this will not auto format it for you.
if (Entry.Body1.Number > 0)
{
AddHtmlLocalized(78, y, 700, 400, Entry.Body1.Number, false, false);
}
else if (!String.IsNullOrEmpty(Entry.Body1.String))
{
var str = Entry.Body1.String;
if (!String.IsNullOrEmpty(Entry.Body2))
{
if (!str.EndsWith("<br>"))
{
str += " ";
}
str += Entry.Body2;
}
if (!String.IsNullOrEmpty(Entry.Body3))
{
if (!str.EndsWith("<br>"))
{
str += " ";
}
str += Entry.Body3;
}
AddHtml(78, y, 700, 400, str, false, false);
}
if (Entry.Expires != DateTime.MinValue)
{
AddHtmlLocalized(50, 550, 200, 20, 1060658, String.Format("{0}\t{1}", "Created", Entry.Created.ToShortDateString()), 0, false, false);
AddHtmlLocalized(50, 570, 200, 20, 1060659, String.Format("{0}\t{1}", "Expires", Entry.Expires.ToShortDateString()), 0, false, false);
}
AddButton(350, 570, 0x605, 0x606, 1, GumpButtonType.Reply, 0);
AddButton(380, 570, 0x609, 0x60A, 2, GumpButtonType.Reply, 0);
AddButton(430, 570, 0x607, 0x608, 3, GumpButtonType.Reply, 0);
AddButton(455, 570, 0x603, 0x604, 4, GumpButtonType.Reply, 0);
AddHtml(395, 570, 35, 20, Center(String.Format("{0}/{1}", (Page + 1).ToString(), Pages.ToString())), false, false);
AddButton(525, 625, 0x5FF, 0x600, 5, GumpButtonType.Reply, 0);
AddHtmlLocalized(550, 625, 300, 20, 1158386, false, false); // Close and do not show this version again
if (Entry.Link != null)
{
if (!string.IsNullOrEmpty(Entry.LinkText))
{
AddHtml(50, 490, 745, 40, String.Format("<a href=\"{0}\">{1}</a>", Entry.Link, Entry.LinkText), false, false);
}
else
{
AddHtml(50, 490, 745, 40, String.Format("<a href=\"{0}\">{1}</a>", Entry.Link, Entry.Link), false, false);
}
}
/*if (TownCryerSystem.HasCustomEntries())
{
AddButton(40, 615, 0x603, 0x604, 6, GumpButtonType.Reply, 0);
AddHtmlLocalized(68, 615, 300, 20, 1060660, String.Format("{0}\t{1}", "Sort By", Sort.ToString()), 0, false, false);
}*/
if (User.AccessLevel >= AccessLevel.Administrator)
{
if (Entry.CanEdit)
{
AddButton(40, 601, 0x603, 0x604, 7, GumpButtonType.Reply, 0);
AddHtml(68, 601, 300, 20, "Edit Greeting", false, false);
}
AddButton(40, 623, 0x603, 0x604, 8, GumpButtonType.Reply, 0);
AddHtml(68, 623, 300, 20, "New Greeting", false, false);
AddButton(40, 645, 0x603, 0x604, 9, GumpButtonType.Reply, 0);
AddHtml(68, 645, 300, 20, "Entry Props", false, false);
}
ColUtility.Free(list);
}
public override void OnResponse(RelayInfo info)
{
int button = info.ButtonID;
switch (button)
{
case 0: break;
case 1: // <<
Page = 0;
Refresh();
break;
case 2: // <
Page = Math.Max(0, Page - 1);
Refresh();
break;
case 3: // >
Page = Math.Min(Pages - 1, Page + 1);
Refresh();
break;
case 4: // >>
Page = Pages - 1;
Refresh();
break;
case 5: // No Show
TownCryerSystem.AddExempt(User);
break;
case 7:
if (Entry != null)
{
BaseGump.SendGump(new CreateGreetingEntryGump(User, Cryer, Entry));
}
else
{
Refresh();
}
break;
case 8:
BaseGump.SendGump(new CreateGreetingEntryGump(User, Cryer));
break;
case 9:
Refresh();
if (Entry != null)
{
User.SendGump(new PropertiesGump(User, Entry));
}
break;
}
}
}
}

View File

@@ -0,0 +1,57 @@
using Server;
using System;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Guilds;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class TownCryerGuildGump : BaseTownCryerGump
{
public TownCryerGuildEntry Entry { get; private set; }
public TownCryerGuildGump(PlayerMobile pm, TownCrier cryer, TownCryerGuildEntry entry)
: base(pm, cryer)
{
Entry = entry;
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
AddHtml(57, 155, 724, 20, Entry.Title, false, false);
AddHtmlLocalized(57, 180, 724, 20, 1158066, String.Format("{0}, {1}", Entry.Author, Entry.Guild.Name), 0, false, false); // Posted By: ~1_NAME~
AddHtmlLocalized(57, 215, 50, 20, 1158067, false, false); // When:
AddHtmlLocalized(57, 235, 50, 20, 1158068, false, false); // Where:
int time = Entry.EventTime.Hour;
AddLabel(102, 215, 0, String.Format("{0}-{1}-{2} {3}{4} {5}",
Entry.EventTime.Month,
Entry.EventTime.Day,
Entry.EventTime.Year,
time == 0 ? 12 : time > 12 ? time - 12 : time,
Entry.EventTime.Hour >= 12 ? "pm" : "am",
TimeZoneInfo.Local.StandardName));
AddLabel(102, 235, 0, Entry.EventLocation);
AddHtml(57, 270, 724, 205, Entry.Body, false, false);
AddImage(85, 425, 0x5EF);
}
public override void OnResponse(RelayInfo info)
{
if (info.ButtonID == 0)
{
var gump = new TownCryerGump(User, Cryer);
gump.Category = TownCryerGump.GumpCategory.Guild;
BaseGump.SendGump(gump);
}
}
}
}

View File

@@ -0,0 +1,477 @@
using Server;
using System;
using System.Linq;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
using Server.Gumps;
using Server.Guilds;
using Server.Engines.Quests;
namespace Server.Services.TownCryer
{
public class TownCryerGump : BaseTownCryerGump
{
public enum GumpCategory
{
News = 1,
EventModerator,
City,
Guild
}
private City _City;
public GumpCategory Category { get; set; }
public int Page { get; set; }
public int Pages { get; set; }
public City City
{
get { return _City; }
set
{
var city = _City;
if (city != value)
{
_City = value;
SetDefaultCity();
}
}
}
public static Dictionary<PlayerMobile, City> LastCity { get; private set; }
public TownCryerGump(PlayerMobile pm, TownCrier tc, int page = 0, GumpCategory Cartegory = GumpCategory.News)
: base(pm, tc)
{
Page = page;
Category = GumpCategory.News;
SetDefaultCity();
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
switch (Category)
{
case GumpCategory.News:
BuildNewsPage();
break;
case GumpCategory.EventModerator:
BuildEMPage();
break;
case GumpCategory.City:
BuildCityPage();
break;
case GumpCategory.Guild:
BuildGuildPage();
break;
}
AddButton(275, 598, Category == GumpCategory.News ? 0x5F6 : 0x5F5, 0x5F6, 1, GumpButtonType.Reply, 0);
AddButton(355, 598, Category == GumpCategory.EventModerator ? 0x5F4 : 0x5F3, 0x5F4, 2, GumpButtonType.Reply, 0);
AddButton(435, 598, Category == GumpCategory.City ? 0x5F8 : 0x5F7, 0x5F8, 3, GumpButtonType.Reply, 0);
AddButton(515, 598, Category == GumpCategory.Guild ? 0x5F2 : 0x5F1, 0x5F2, 4, GumpButtonType.Reply, 0);
}
private void BuildNewsPage()
{
int perPage = 20;
int y = 170;
int start = Page * perPage;
Pages = (int)Math.Ceiling((double)TownCryerSystem.NewsEntries.Count / (double)perPage);
for (int i = start; i < TownCryerSystem.NewsEntries.Count && i < perPage; i++)
{
var entry = TownCryerSystem.NewsEntries[i];
AddButton(50, y, 0x5FB, 0x5FC, 100 + i, GumpButtonType.Reply, 0);
bool doneQuest = entry.QuestType != null && QuestHelper.CheckDoneOnce(User, entry.QuestType, Cryer, false);
if (entry.Title.Number > 0)
{
AddHtmlLocalized(87, y, 700, 20, entry.Title.Number, doneQuest ? C32216(0x696969) : 0, false, false);
}
else
{
AddLabelCropped(87, y, 700, 20, doneQuest ? 0x3B2 : 0, entry.Title);
}
y += 23;
}
if (TownCryerSystem.NewsEntries.Count > perPage)
{
AddButton(350, 570, 0x605, 0x606, 5, GumpButtonType.Reply, 0);
AddButton(380, 570, 0x609, 0x60A, 6, GumpButtonType.Reply, 0);
AddButton(430, 570, 0x607, 0x608, 7, GumpButtonType.Reply, 0);
AddButton(455, 570, 0x603, 0x604, 8, GumpButtonType.Reply, 0);
AddHtml(395, 570, 35, 20, Center(String.Format("{0}/{1}", (Page + 1).ToString(), (Pages + 1).ToString())), false, false);
}
}
private void BuildEMPage()
{
int perPage = 15;
AddPage(1);
int y = 170;
for (int i = 0; i < TownCryerSystem.ModeratorEntries.Count && i < perPage; i++)
{
var entry = TownCryerSystem.ModeratorEntries[i];
AddButton(50, y, 0x5FB, 0x5FC, 200 + i, GumpButtonType.Reply, 0);
AddLabelCropped(87, y, 631, 20, 0, entry.Title);
if (User.AccessLevel > AccessLevel.Player) // Couselors+ can moderate events
{
AddButton(735, y, 0x5FD, 0x5FE, 2000 + i, GumpButtonType.Reply, 0);
AddButton(760, y, 0x5FF, 0x600, 2500 + i, GumpButtonType.Reply, 0);
}
y += 23;
}
AddButton(320, 525, 0x627, 0x628, 9, GumpButtonType.Reply, 0);
}
private void BuildCityPage()
{
AddButton(233, 150, City == City.Britain ? 0x5E5 : 0x5E4, City == City.Britain ? 0x5E5 : 0x5E4, 10, GumpButtonType.Reply, 0);
AddTooltip(CityLoyaltySystem.GetCityLocalization(City.Britain));
AddButton(280, 150, City == City.Jhelom ? 0x5E7 : 0x5E6, City == City.Jhelom ? 0x5E7 : 0x5E6, 11, GumpButtonType.Reply, 0);
AddTooltip(CityLoyaltySystem.GetCityLocalization(City.Jhelom));
AddButton(327, 150, City == City.Minoc ? 0x5E5 : 0x5E4, City == City.Minoc ? 0x5E5 : 0x5E4, 12, GumpButtonType.Reply, 0);
AddTooltip(CityLoyaltySystem.GetCityLocalization(City.Minoc));
AddButton(374, 150, City == City.Moonglow ? 0x5E3 : 0x5E2, City == City.Moonglow ? 0x5E3 : 0x5E2, 13, GumpButtonType.Reply, 0);
AddTooltip(CityLoyaltySystem.GetCityLocalization(City.Moonglow));
AddButton(418, 150, City == City.NewMagincia ? 0x5DD : 0x5DC, City == City.NewMagincia ? 0x5DD : 0x5DC, 14, GumpButtonType.Reply, 0);
AddTooltip(CityLoyaltySystem.GetCityLocalization(City.NewMagincia));
AddButton(463, 150, City == City.SkaraBrae ? 0x5DF : 0x5DE, City == City.SkaraBrae ? 0x5DF : 0x5DE, 15, GumpButtonType.Reply, 0);
AddTooltip(CityLoyaltySystem.GetCityLocalization(City.SkaraBrae));
AddButton(509, 150, City == City.Trinsic ? 0x5E1 : 0x5E0, City == City.Trinsic ? 0x5E1 : 0x5E0, 16, GumpButtonType.Reply, 0);
AddTooltip(CityLoyaltySystem.GetCityLocalization(City.Trinsic));
AddButton(555, 150, City == City.Vesper ? 0x5ED : 0x5ED, City == City.Vesper ? 0x5ED : 0x5EC, 17, GumpButtonType.Reply, 0);
AddTooltip(CityLoyaltySystem.GetCityLocalization(City.Vesper));
AddButton(601, 150, City == City.Yew ? 0x5E9 : 0x5E8, City == City.Yew ? 0x5E9 : 0x5E8, 18, GumpButtonType.Reply, 0);
AddTooltip(CityLoyaltySystem.GetCityLocalization(City.Yew));
AddHtmlLocalized(0, 260, 854, 20, CenterLoc, String.Format("#{0}", TownCryerSystem.GetCityLoc(this.City)), 0, false, false); // The Latest News from the City of ~1_CITY~
int y = 300;
for (int i = 0; i < TownCryerSystem.CityEntries.Count && i < TownCryerSystem.MaxPerCityGoverrnorEntries; i++)
{
var entry = TownCryerSystem.CityEntries[i];
if (entry.City != this.City)
continue;
AddButton(50, y, 0x5FB, 0x5FC, 300 + i, GumpButtonType.Reply, 0);
AddLabelCropped(87, y, 700, 20, 0, entry.Title);
var city = CityLoyaltySystem.GetCitizenship(User, false);
if ((city != null && city.Governor == User) || User.AccessLevel >= AccessLevel.GameMaster) // Only Governors
{
AddButton(735, y, 0x5FD, 0x5FE, 3000 + i, GumpButtonType.Reply, 0);
AddButton(760, y, 0x5FF, 0x600, 3500 + i, GumpButtonType.Reply, 0);
}
y += 23;
}
AddImage(230, 460, 0x5F0);
}
private void BuildGuildPage()
{
var list = TownCryerSystem.GuildEntries.OrderBy(e => e.EventTime).ToList();
int perPage = 20;
int y = 170;
int start = Page * perPage;
var guild = User.Guild as Guild;
Pages = (int)Math.Ceiling((double)list.Count / (double)perPage);
for (int i = start; i < list.Count && i < perPage; i++)
{
var entry = TownCryerSystem.GuildEntries[i];
AddButton(50, y, 0x5FB, 0x5FC, 400 + TownCryerSystem.GuildEntries.IndexOf(entry), GumpButtonType.Reply, 0);
AddLabelCropped(87, y, 700, 20, 0, entry.FullTitle);
if ((guild == entry.Guild && User.GuildRank != null && User.GuildRank.Rank >= 3) || User.AccessLevel >= AccessLevel.GameMaster) // Only warlords+
{
int index = TownCryerSystem.GuildEntries.IndexOf(entry);
AddButton(735, y, 0x5FD, 0x5FE, 4000 + index, GumpButtonType.Reply, 0);
AddButton(760, y, 0x5FF, 0x600, 4500 + index, GumpButtonType.Reply, 0);
}
y += 23;
}
AddButton(350, 570, 0x605, 0x606, 5, GumpButtonType.Reply, 0);
AddButton(380, 570, 0x609, 0x60A, 6, GumpButtonType.Reply, 0);
AddButton(430, 570, 0x607, 0x608, 7, GumpButtonType.Reply, 0);
AddButton(455, 570, 0x603, 0x604, 8, GumpButtonType.Reply, 0);
AddHtml(395, 570, 35, 20, Center(String.Format("{0}/{1}", (Page + 1).ToString(), (Pages + 1).ToString())), false, false);
}
private void SetDefaultCity()
{
if (LastCity == null || !LastCity.ContainsKey(User))
{
LastCity = new Dictionary<PlayerMobile, City>();
var system = CityLoyaltySystem.GetCitizenship(User, false);
if (system != null)
{
LastCity[User] = system.City;
}
}
else
{
LastCity[User] = _City;
}
}
public override void OnResponse(RelayInfo info)
{
int id = info.ButtonID;
switch (id)
{
case 0: break;
case 1:
case 2:
case 3:
case 4:
{
Category = (GumpCategory)id;
Refresh();
break;
}
case 5: // <<
{
Page = 0;
Refresh();
break;
}
case 6: // <
{
Page = Math.Max(0, Page - 1);
Refresh();
break;
}
case 7: // >
{
Page = Math.Min(Pages, Page + 1);
Refresh();
break;
}
case 8: // >>
{
Page = Pages;
Refresh();
break;
}
case 9: // Learn More - EM Page
{
User.LaunchBrowser(TownCryerSystem.EMEventsPage);
Refresh();
break;
}
case 10:
{
City = City.Britain;
Refresh();
break;
}
case 11:
{
City = City.Jhelom;
Refresh();
break;
}
case 12:
{
City = City.Minoc;
Refresh();
break;
}
case 13:
{
City = City.Moonglow;
Refresh();
break;
}
case 14:
{
City = City.NewMagincia;
Refresh();
break;
}
case 15:
{
City = City.SkaraBrae;
Refresh();
break;
}
case 16:
{
City = City.Trinsic;
Refresh();
break;
}
case 17:
{
City = City.Vesper;
Refresh();
break;
}
case 18:
{
City = City.Yew;
Refresh();
break;
}
default:
{
if (id < 200)
{
id -= 100;
if (id >= 0 && id < TownCryerSystem.NewsEntries.Count)
{
BaseGump.SendGump(new TownCryerNewsGump(User, Cryer, TownCryerSystem.NewsEntries[id]));
}
}
else if (id < 300)
{
id -= 200;
if (id >= 0 && id < TownCryerSystem.ModeratorEntries.Count)
{
BaseGump.SendGump(new TownCryerEventModeratorGump(User, Cryer, TownCryerSystem.ModeratorEntries[id]));
}
}
else if (id < 400)
{
id -= 300;
if (id >= 0 && id < TownCryerSystem.CityEntries.Count)
{
BaseGump.SendGump(new TownCryerCityGump(User, Cryer, TownCryerSystem.CityEntries[id]));
}
}
else if (id < 600)
{
id -= 400;
if (id >= 0 && id < TownCryerSystem.GuildEntries.Count)
{
BaseGump.SendGump(new TownCryerGuildGump(User, Cryer, TownCryerSystem.GuildEntries[id]));
}
}
else if (id < 3000)
{
if (id < 2500)
{
id -= 2000;
if (id >= 0 && id < TownCryerSystem.ModeratorEntries.Count)
{
BaseGump.SendGump(new CreateEMEntryGump(User, Cryer, TownCryerSystem.ModeratorEntries[id]));
}
}
else
{
id -= 2500;
if (id >= 0 && id < TownCryerSystem.ModeratorEntries.Count)
{
TownCryerSystem.ModeratorEntries.RemoveAt(id);
}
Refresh();
}
}
else if (id < 4000)
{
var city = CityLoyaltySystem.GetCitizenship(User, false);
if ((city != null && city.Governor == User) || User.AccessLevel >= AccessLevel.GameMaster) // Only Governors
{
if (id < 3500)
{
id -= 3000;
if (id >= 0 && id < TownCryerSystem.CityEntries.Count)
{
BaseGump.SendGump(new CreateCityEntryGump(User, Cryer, City, TownCryerSystem.CityEntries[id]));
}
}
else
{
id -= 3500;
if (id >= 0 && id < TownCryerSystem.CityEntries.Count)
{
TownCryerSystem.CityEntries.RemoveAt(id);
}
}
}
Refresh();
}
else if (id < 5000)
{
if (id < 4500)
{
id -= 4000;
if (id >= 0 && id < TownCryerSystem.GuildEntries.Count)
{
BaseGump.SendGump(new CreateGuildEntryGump(User, Cryer, TownCryerSystem.GuildEntries[id]));
}
}
else
{
id -= 4500;
if (id >= 0 && id < TownCryerSystem.GuildEntries.Count)
{
TownCryerSystem.GuildEntries.RemoveAt(id);
}
Refresh();
}
}
}
break;
}
}
}
}

View File

@@ -0,0 +1,88 @@
using Server;
using System;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Engines.Quests;
using Server.Gumps;
namespace Server.Services.TownCryer
{
public class TownCryerNewsGump : BaseTownCryerGump
{
public TownCryerNewsEntry Entry { get; private set; }
public TownCryerNewsGump(PlayerMobile pm, TownCrier cryer, TownCryerNewsEntry entry)
: base(pm, cryer)
{
Entry = entry;
}
public override void AddGumpLayout()
{
base.AddGumpLayout();
//AddPage(1);
//AddImageTiled(58, 213, 397, 271, 0x24B2);
if (Entry.Body.Number > 0)
{
AddHtmlLocalized(58, 213, 397, 271, Entry.Body.Number, C32216(0x080808), false, true);
}
else
{
AddHtml(58, 213, 397, 271, Color("#080808", Entry.Body.String), false, true);
}
AddHtmlLocalized(0, 150, 854, 20, CenterLoc, Entry.Title.ToString(), 0, false, false);
AddHtmlLocalized(0, 180, 854, 20, CenterLoc, "#1158084", 0, false, false); // The Town Cryer News Network
AddImage(468, 213, Entry.GumpImage);
AddImage(50, 532, 0x60C);
if (!String.IsNullOrEmpty(Entry.InfoUrl))
{
AddButton(147, 600, 0x627, 0x628, 1, GumpButtonType.Reply, 0);
}
if (Entry.QuestType != null)
{
AddButton(545, 600, 0x629, 0x62A, 2, GumpButtonType.Reply, 0);
}
}
public override void OnResponse(RelayInfo info)
{
switch (info.ButtonID)
{
case 0:
var gump = new TownCryerGump(User, Cryer);
gump.Category = TownCryerGump.GumpCategory.News;
BaseGump.SendGump(gump);
break;
case 1:
User.LaunchBrowser(Entry.InfoUrl);
Refresh();
break;
case 2:
if (QuestHelper.HasQuest(User, Entry.QuestType))
{
Cryer.SayTo(User, 1080107, 1150); // I'm sorry, I have nothing for you at this time.
}
else
{
BaseQuest quest = QuestHelper.Construct(Entry.QuestType) as BaseQuest;
if (quest != null && (!QuestHelper.CheckDoneOnce(User, quest, Cryer, true) || User.AccessLevel > AccessLevel.Player))
{
quest.Owner = User;
quest.Quester = Cryer;
User.CloseGump(typeof(MondainQuestGump));
User.SendGump(new MondainQuestGump(quest));
}
}
break;
}
}
}
}

View File

@@ -0,0 +1,438 @@
using Server;
using System;
using Server.Items;
using Server.Mobiles;
using Server.Services.TownCryer;
namespace Server.Engines.Quests
{
public class APleaFromMinocQuest : BaseQuest
{
/* A Plea from Minoc */
public override object Title { get { return 1158259; } }
/*The Governor of Minoc has made a plea to any and all of those willing and able to come to defense of the City.
* Cora the Sorcerers has overtaken the Dungeon Covetous and corrupted the creatures that reside within. You hear
* rumors the Governor has authorized the Sheriff of Minoc to bestow great fortune and fame to those who sacrifice
* in the name of the city.*/
public override object Description { get { return 1158260; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Visit the Skara Brae Ranger's Guild and participate in the Huntmaster's Challenge */
public override object Uncomplete { get { return 1158261; } }
/* You have braved the wilds of Britannia and slayed a mighty beast! You have meticulously documented your kill
* and submitted it to the Ranger's Guild for evaluation. If luck was on your side you may indeed have
* the largest quarry for the month...or maybe not. Alas, your bravery has earned you the well deserved title
* of Hunter! May you go fearlessly into the wilderness in search of your next big kill! Well done! */
public override object Complete { get { return 1158378; } }
public override int CompleteMessage { get { return 1156585; } } // You've completed a quest!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public APleaFromMinocQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(1158262)); // A Reward Title Deed
}
public void CompleteQuest()
{
OnCompleted();
Objectives[0].CurProgress++;
TownCryerSystem.CompleteQuest(Owner, 1158275, 1158276, 0x65B);
GiveRewards();
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return Quest.Uncomplete; } }
public InternalObjective()
: base(1)
{
}
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 class ClearingCovetousQuest : BaseQuest
{
/* Clearing Covetous */
public override object Title { get { return 1158263; } }
/*That's right, I'm the Sheriff of Minoc, what can I help you with citizen? What you read in the Town Cryer is true,
* Covetous has become quite dangerous. It seems a vile Sorcerers called Cora has overtaken the dungeon and corrupted
* the creatures within, binding them to her cruel rule. The Lycaeum had been trying to contain her magics within
* the dungeon with something called the "Void Pool" but the mage they sent has not been seen in quite some time.
* The place is dangerous to say the least and requires skilled combatants who will encounter greater success if
* they pool their resources. None the less, the Governor has authorized me to deputize any and all who sacrifice
* on behalf of Minoc and attempt to cleanse Covetous. As you know the mountain is a key strategic resource to
* valuable ore that is vital to Minoc's economy. Prove yourself to the City and you shall not soon be forgotten...*/
public override object Description { get { return 1158264; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Go to the dungeon Covetous Level 1 and defeat the creatures within! */
public override object Uncomplete { get { return 1158266; } }
/* Indeed, you have proven yourself, and with your clearing of the creatures in the upper levels of Covetous Mountain our
* miners can once again return to their normal operations, ensuring the lifeblood of our city is one again flowing. You
* are no doubt brave and strong, but your next task will test your endurance no doubt. As I said, the Lycaeum is keeping
* Cora's power at bay with something called the Void Pool. The magics prevent Cora herself from destroying it, but her
* minions are not bound by that restriction. Only blade and spell can defeat her forces as they try to destroy the Void
* Pool. Defend the Void Pool at all costs and sacrifice for Minoc. Do this and you will no doubt be remembered a hero. */
//public override object Complete { get { return 1158268; } }
public override int CompleteMessage { get { return 1158267; } } // You've cleared enough creatures to allow the miners of
// Minoc to return to their mining operations. Return to the Sheriff and report the news.
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public ClearingCovetousQuest()
{
AddObjective(new SlayObjective(typeof(HeadlessMiner), "headless miners", 40, "Covetous"));
AddObjective(new SlayObjective(typeof(VampireMongbat), "vampire mongbats", 30, "Covetous"));
AddObjective(new SlayObjective(typeof(DazzledHarpy), "dazzled harpies", 20, "Covetous"));
AddObjective(new SlayObjective(typeof(StrangeGazer), "strange gazers", 10, "Covetous"));
AddReward(new BaseReward(1158265)); // A step closer to glory for thy deeds...
}
public override void OnCompleted()
{
base.OnCompleted();
GiveRewards();
}
/*public void CompleteChallenge()
{
OnCompleted();
Objectives[0].CurProgress++;
TownCryerSystem.CompleteQuest(Owner, 1158275, 1158276, 0x65B);
GiveRewards();
}*/
}
public class AForcedSacraficeQuest : BaseQuest
{
/* A Forced Sacrifice */
public override object Title { get { return 1158271; } }
/* Indeed, you have proven yourself, and with your clearing of the creatures in the upper levels of Covetous Mountain our
* miners can once again return to their normal operations, ensuring the lifeblood of our city is one again flowing. You
* are no doubt brave and strong, but your next task will test your endurance no doubt. As I said, the Lycaeum is keeping
* Cora's power at bay with something called the Void Pool. The magics prevent Cora herself from destroying it, but her
* minions are not bound by that restriction. Only blade and spell can defeat her forces as they try to destroy the Void
* Pool. Defend the Void Pool at all costs and sacrifice for Minoc. Do this and you will no doubt be remembered a hero. */
public override object Description { get { return 1158268; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Go to the Void Pool located in Level 2 of Covetous and defend it from Cora's armies! */
public override object Uncomplete { get { return 1158269; } }
//public override object Complete { get { return 1158268; } }
/*You have defended the void pool until your last breath, your sacrifice for Minoc will not be soon forgotten! Return to
* the Sheriff of Minoc and report the news!*/
public override int CompleteMessage { get { return 1158270; } }
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public AForcedSacraficeQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(1158265)); // A step closer to glory for thy deeds...
}
public void CompleteQuest()
{
OnCompleted();
Objectives[0].CurProgress++;
GiveRewards();
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return Quest.Uncomplete; } }
public InternalObjective()
: base(1)
{
}
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 class AForcedSacraficeQuest2 : BaseQuest
{
/* A Forced Sacrifice */
public override object Title { get { return 1158271; } }
/* Despite your failure in protecting the void pool, your efforts have allowed the mages of the Lycaeum to use their
* magics and bind the void pool in an infinite time loop, forever sealing Cora within the dungeon. This is only a
* stopgap measure, however, and Cora cannot be allowed to continue her twisted craft. Now comes the ultimate test,
* you must venture to the deepest level of Dungeon Covetous and slay Cora. It is the only way. Take this, it is all
* the city can offer you in an effort to slay Cora. The City is counting on you. */
public override object Description { get { return 1158272; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Go to the furthest depths of Covetous and slay Cora! */
public override object Uncomplete { get { return 1158273; } }
/*You have slayed the vile sorceress Cora! A powerful mage as she was, her armies will no doubt attempt
* to resurrect their general - for now though Minoc is safe. The economic future of Minoc has been
* secured and for your efforts you are hereby bestowed a great honor!*/
public override object Complete { get { return 1158281; } }
/*You have slayed the sorceress Cora! Return to the Sheriff of Minoc and report the news!*/
public override int CompleteMessage { get { return 1158274; } }
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public AForcedSacraficeQuest2()
{
AddObjective(new SlayObjective(typeof(CoraTheSorceress), "Cora the Sorcerer", 1, "Covetous"));
AddReward(new BaseReward(typeof(HeroOfMincRewardTitleDeed), 1158139)); // A Reward Title Deed
}
public override void OnAccept()
{
base.OnAccept();
if (QuestHelper.TryReceiveQuestItem(Owner, typeof(MysteriousPotion), TimeSpan.FromDays(3)))
{
Owner.AddToBackpack(new MysteriousPotion());
}
}
public void CompleteQuest()
{
TownCryerSystem.CompleteQuest(Owner, 1158280, 1158281, 0x623);
GiveRewards();
Server.Engines.Points.PointsSystem.VoidPool.AwardPoints(Owner, 2000, false, false);
Owner.SendLocalizedMessage(1158282); // For your accomplishments you have been awarded a bonus 2000 Covetous points! Visit Vela in the Town of Cove to redeem them!
}
}
public class SheriffOfMinoc : MondainQuester
{
public override Type[] Quests { get { return new Type[] { typeof(ToolsOfTheTradeQuest) }; } }
public static SheriffOfMinoc TramInstance { get; set; }
public static SheriffOfMinoc FelInstance { get; set; }
public static void Initialize()
{
if (Core.TOL)
{
if (TramInstance == null)
{
TramInstance = new SheriffOfMinoc();
TramInstance.MoveToWorld(new Point3D(2462, 439, 15), Map.Trammel);
TramInstance.Direction = Direction.South;
}
if (FelInstance == null)
{
FelInstance = new SheriffOfMinoc();
FelInstance.MoveToWorld(new Point3D(2462, 439, 15), Map.Felucca);
FelInstance.Direction = Direction.South;
}
}
}
public SheriffOfMinoc()
: base(NameList.RandomName("male"), "the Sheriff of Minoc")
{
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = false;
CantWalk = true;
Body = 0x190;
Hue = Race.RandomSkinHue();
HairItemID = 0;
FacialHairItemID = 0x2041;
FacialHairHue = Race.RandomHairHue();
}
public override void InitOutfit()
{
AddItem(new Backpack());
SetWearable(new ChainCoif());
SetWearable(new ChainChest());
SetWearable(new ChainLegs());
SetWearable(new Boots(), 2012);
SetWearable(new FancyKilt(), 2012);
SetWearable(new RingmailGloves());
SetWearable(new BodySash(), 43);
}
public override void OnDoubleClick(Mobile m)
{
if (m is PlayerMobile)
{
var pm = m as PlayerMobile;
if (QuestHelper.CheckDoneOnce(pm, typeof(APleaFromMinocQuest), this, false))
{
if (CheckProgress(pm))
{
return;
}
AForcedSacraficeQuest2 quest = QuestHelper.GetQuest<AForcedSacraficeQuest2>(pm);
if (quest != null && quest.Completed)
{
quest.CompleteQuest();
return;
}
BaseQuest q = QuestHelper.RandomQuest(pm, new Type[] { typeof(ClearingCovetousQuest) }, this, false);
if (q == null)
{
q = QuestHelper.RandomQuest(pm, new Type[] { typeof(AForcedSacraficeQuest) }, this, false);
if (q == null)
{
q = QuestHelper.RandomQuest(pm, new Type[] { typeof(AForcedSacraficeQuest2) }, this, false);
}
}
if (q != null)
{
pm.CloseGump(typeof(MondainQuestGump));
pm.SendGump(new MondainQuestGump(q));
}
else
{
SayTo(m, 1080107, 0x3B2); // I'm sorry, I have nothing for you at this time.
}
}
else
{
SayTo(m, 1080107, 0x3B2); // I'm sorry, I have nothing for you at this time.
}
}
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (m is PlayerMobile && InRange(m.Location, 5) && !InRange(oldLocation, 5))
{
APleaFromMinocQuest quest = QuestHelper.GetQuest<APleaFromMinocQuest>((PlayerMobile)m);
if (quest != null)
{
quest.CompleteQuest();
}
}
}
private bool CheckProgress(PlayerMobile pm)
{
foreach (var t in _Quests)
{
var quest = QuestHelper.GetQuest(pm, t);
if (quest != null && !quest.Completed)
{
pm.CloseGump(typeof(MondainQuestGump));
pm.SendGump(new MondainQuestGump(quest, MondainQuestGump.Section.InProgress, false));
return true;
}
}
return false;
}
private Type[] _Quests = { typeof(ClearingCovetousQuest), typeof(AForcedSacraficeQuest), typeof(AForcedSacraficeQuest2) };
public SheriffOfMinoc(Serial serial)
: base(serial)
{
}
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();
if (Map == Map.Trammel)
{
TramInstance = this;
}
if (Map == Map.Felucca)
{
FelInstance = this;
}
if (!Core.TOL)
{
Delete();
}
}
}
}

View File

@@ -0,0 +1,83 @@
using Server;
using System;
using Server.Items;
using Server.Mobiles;
using Server.Services.TownCryer;
namespace Server.Engines.Quests
{
public class AVisitToCastleBlackthornQuest : BaseQuest
{
private object _Title = 1158197;
/* A Visit to Castle Blackthorn */
public override object Title { get { return _Title; } }
/*It seems that Castle Blackthorn has some secrets that are worth investigating. Your history on how Blackthorn even became
* king is a little fuzzy. You decide a visit to Castle Blackthorn would be worthwhile.*/
public override object Description { get { return 1158198; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Visit Castle Blackthorn in Northern Britain. */
public override object Uncomplete { get { return 1158199; } }
/* As you cross the bridge Blackthorn's massive castle towers up from the terrain it sits atop. The jet-black stone of her walls
* are foreboding, yet invite your curiosity. Your eyes scan the courtyard and fixate on an incredibly handsome man. You've never
* seen such beauty and style! Their exquisitely apportioned jester suit perfectly toes the line between comedic expression and
* fashion. His hat is masterfully crafted with golden bells matching radiant jewelry that jingles as he swigs from a bottle.
* You decide to follow the jester, who is no doubt headed for the castle bar. */
public override object Complete { get { return 1158203; } }
public override int CompleteMessage { get { return 1156585; } } // You've completed a quest!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public AVisitToCastleBlackthornQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(1158200)); // A step closer to understanding the history of Blackthorn's Rise to the Throne.
}
public static void CheckLocation(PlayerMobile pm, Point3D oldLocation)
{
var quest = QuestHelper.GetQuest<AVisitToCastleBlackthornQuest>(pm);
if (quest != null)
{
quest.OnCompleted();
TownCryerSystem.CompleteQuest(quest.Owner, 1158202, quest.Complete, 0x61B);
quest.Objectives[0].CurProgress++;
quest.GiveRewards();
}
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return Quest.Uncomplete; } }
public InternalObjective()
: base(1)
{
}
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();
}
}
}
}

View File

@@ -0,0 +1,524 @@
using Server;
using System;
using Server.Items;
using Server.Mobiles;
using Server.Services.TownCryer;
using Server.Gumps;
namespace Server.Engines.Quests
{
public class BuriedRichesQuest : BaseQuest
{
/* Buried Riches */
public override object Title { get { return 1158230; } }
/*Treasure Hunting sure does sound like an interesting profession! Think of the riches to be found! You'd have everything
* you've ever dreamed of! The Town Cryer article is fairly vague, however you have heard whispers of a mapmaker in Vesper
* at the Majestic Boat who may know a thing or two about decoding treasure maps.*/
public override object Description { get { return 1158223; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Visit the Skara Brae Ranger's Guild and participate in the Huntmaster's Challenge */
public override object Uncomplete { get { return 1158231; } }
/*The Cartographer seems busy at her desk pouring over stacks of rolled parchment. You decide to break the
* silence with courteous *Ahem**/
public override object Complete { get { return 1158226; } }
public override int CompleteMessage { get { return 1156585; } } // You've completed a quest!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public BuriedRichesQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(1158224)); // A step closer to becoming a treasure hunter.
}
public void CompleteQuest()
{
OnCompleted();
Objectives[0].CurProgress++;
TownCryerSystem.CompleteQuest(Owner, 1158225, Complete, 0x614);
GiveRewards();
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return 1158231; } } // Visit the Legendary Cartographer at the The Majestic Boat in Vesper.
public InternalObjective()
: base(1)
{
}
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 class ToolsOfTheTradeQuest : BaseQuest
{
/* Tools of the Trade */
public override object Title { get { return 1158232; } }
/*A treasure seeker then? There is no telling the lengths someone will go to protect their most prized possessions. Over
* time maps to certain treasure troves have been found and their bounties recovered. The bounty within a treasure chest
* is directly related to the difficulty of deciphering the map and overcoming the protections of the chest itself.
* Cartographers use a variety of terms to describe the difficulty of a map that is drawn. This includes maps that are
* plainly, expertly, adeptly, cleverly, deviously, ingeniously, and diabolically drawn. Even the most basically trained
* cartographer can decode a plainly drawn map. Beyond that, however, some training in cartography is required. Once
* deciphered, the cartographer must find the location within the world and use a digging tool, such as a pickaxe or shovel
* to dig up the chest. Those skilled at mining will have a much easier time finding the chest, but it is not a requirement.
* The chest will be no doubt locked and trapped, so some skill with lockpicking and trap removal is suggested, although
* mages skilled enough may use magical means to unlock and untrap lower end treasure chests. Finally, the chest is likely
* to be guarded by a variety of creatures that will attempt to defend the treasure at all costs. Combat skills are imperative
* to dispatch those creatures safely! Sounds like a challenge? Well it can be, but alas it is also incredibly rewarding and
* you will have a much easier time of it if you recruit other adventures into your budding treasure seeking business. Alas,
* here's a map I had lying around. You can visit the Adventurer's Supplies just on the mainland of Vesper to get some basic
* supplies.*/
public override object Description { get { return 1158227; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Visit the Adventurer's Supplies in Northern Vesper, just across the bridge, and speak to the Master Provisioner
* to get some basic treasure hunting equipment. */
public override object Uncomplete { get { return 1158228; } }
/*The Adventurer's Supplies is a large provisioner with many different types of adventuring equipment available for purchase.
* You spot the shopkeeper the Cartographer described and approach with a friendly greeting!*/
public override object Complete { get { return 1158233; } }
public override int CompleteMessage { get { return 1156585; } } // You've completed a quest!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public ToolsOfTheTradeQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(1158224)); // A step closer to becoming a treasure hunter.
}
public override void OnAccept()
{
base.OnAccept();
if (QuestHelper.TryReceiveQuestItem(Owner, typeof(BuriedRichesTreasureMap), TimeSpan.FromDays(7)))
{
Owner.AddToBackpack(new BuriedRichesTreasureMap(0));
}
}
public void CompleteQuest()
{
OnCompleted();
Objectives[0].CurProgress++;
TownCryerSystem.CompleteQuest(Owner, 1016275, Complete, 0x619);
GiveRewards();
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return 1158228; } } // Visit the Adventurer's Supplies in Northern Vesper, just across the bridge, and speak to the Master Provisioner to get some basic treasure hunting equipment.
public InternalObjective()
: base(1)
{
}
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 class TheTreasureChaseQuest : BaseQuest
{
/* The Treasure Chase */
public override object Title { get { return 1158239; } }
/*Finest provisions in all of Britannia! Right here! *The Provisioner looks you up and down* I've seen your kind before -
* I know that look! You're a treasure seeker! I take it you spoke to the Cartographer then? Of course you have, why else
* would you be visiting Britannia's premiere outfitter of Treasure Hunting supplies! I trust you will be most successful
* with treasure hunting so I'll kit you out with basic supplies free of charge - just remember me when you've become a
* famous treasure hunter!*/
public override object Description { get { return 1158365; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Use the book "Treasure Hunting: A Practical Approach" to help you decode the treasure maps you have been given and those
* that you find during your adventure and use the information contained within the text to aid you in your quest.*/
public override object Uncomplete { get { return 1158238; } }
/*The Adventurer's Supplies is a large provisioner with many different types of adventuring equipment available for purchase.
* You spot the shopkeeper the Cartographer described and approach with a friendly greeting!*/
public override object Complete { get { return 1158233; } }
public override int CompleteMessage { get { return 1158247; } } //You have found the final zealot treasure! There are no doubt riches to be had within! Your experience has earned you a
// reward title that has been placed in your backpack.
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public TheTreasureChaseQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(typeof(TreasureHunterRewardTitleDeed), 1158237)); // Treasure!
}
public override void OnAccept()
{
base.OnAccept();
if (QuestHelper.TryReceiveQuestItem(Owner, typeof(TreasureHuntingBook), TimeSpan.FromDays(7)))
{
var chest = new WoodenChest();
chest.DropItem(new TreasureHuntingBook());
var heals = new GreaterHealPotion();
heals.Amount = 10;
chest.DropItem(heals);
var scrolls = new TelekinisisScroll();
scrolls.Amount = 20;
chest.DropItem(scrolls);
chest.DropItem(new Pickaxe());
chest.DropItem(new TreasureSeekersLockpick());
Owner.Backpack.DropItem(chest);
}
}
public override bool RenderObjective(MondainQuestGump g, bool offer)
{
if (offer)
g.AddHtmlLocalized(130, 45, 270, 16, 1049010, 0xFFFFFF, false, false); // Quest Offer
else
g.AddHtmlLocalized(130, 45, 270, 16, 1046026, 0xFFFFFF, false, false); // Quest Log
g.AddButton(130, 430, 0x2EEF, 0x2EF1, (int)Buttons.PreviousPage, GumpButtonType.Reply, 0);
g.AddButton(275, 430, 0x2EE9, 0x2EEB, (int)Buttons.NextPage, GumpButtonType.Reply, 0);
g.AddHtmlObject(160, 70, 200, 40, Title, BaseQuestGump.DarkGreen, false, false);
g.AddHtmlLocalized(98, 140, 312, 16, 1049073, 0x2710, false, false); // Objective:
g.AddHtmlLocalized(98, 156, 312, 16, 1072208, 0x2710, false, false); // All of the following
g.AddHtmlLocalized(98, 172, 312, 83, 1158234, BaseQuestGump.LightGreen, false, false);
/* Find the location marked on the Treasure Map given to you by the Cartographer and use the supplies the Provisioner
* gave you to recover the treasure.*/
g.AddHtmlLocalized(98, 255, 312, 40, 1158235, BaseQuestGump.LightGreen, false, false);
//Expand your experience as a Treasure Hunter to an Expertly Drawn Map.
g.AddHtmlLocalized(98, 335, 312, 40, 1158236, BaseQuestGump.LightGreen, false, false);
// Complete your experience as a Treasure Hunter by discovering the final treasure hoard.
return true;
}
public void CompleteQuest()
{
OnCompleted();
Objectives[0].CurProgress++;
TownCryerSystem.CompleteQuest(Owner, 1158239, 1158249, 0x655);
/*Another rusted chest emerges from the broken ground at your feet! As you pry it open the brilliant
* shimmer of gold and jewels catches your eye. This map too is highly decorated with ancient runic
* text and marks another location for the hoard. You notice the magical creatures guarding the previous
* hoard were more challenging than the first, and you expect that trend to continue. With greater
* difficulty comes greater reward! On the reverse of the map is a short hand-written note,<br><br><i>For
* those who will come long after and discover this treasure, know you will never truly discover the
* extent of our wealth. If you posses this map you no doubt have some connection to our society, which
* has survived generation after generation. Use this wealth for what we have used it for, to be virtuous
* and good throughout Sosaria...</i><br><br>The note is very cryptic about the origins of these zealots
* and their beliefs, but from what you can gleam they are a long gone organization who's values were
* that of virtue and good. You are warmed by this altruistic purpose and decide to use your wealth to
* promote their cause throughout the realm as you search for other treasures.*/
GiveRewards();
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return 1158231; } } // Visit the Legendary Cartographer at the The Majestic Boat in Vesper.
public InternalObjective()
: base(1)
{
}
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 class LegendaryCartographer : MondainQuester
{
public override Type[] Quests { get { return new Type[] { typeof(ToolsOfTheTradeQuest) }; } }
public static LegendaryCartographer TramInstance { get; set; }
public static LegendaryCartographer FelInstance { get; set; }
public static void Initialize()
{
if (Core.TOL)
{
if (TramInstance == null)
{
TramInstance = new LegendaryCartographer();
TramInstance.MoveToWorld(new Point3D(3005, 811, 0), Map.Trammel);
TramInstance.Direction = Direction.West;
}
if (FelInstance == null)
{
FelInstance = new LegendaryCartographer();
FelInstance.MoveToWorld(new Point3D(3005, 811, 0), Map.Felucca);
FelInstance.Direction = Direction.West;
}
}
}
public LegendaryCartographer()
: base(NameList.RandomName("female"), "the Legendary Cartographer")
{
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = true;
CantWalk = true;
Body = 0x191;
Hue = Race.RandomSkinHue();
HairItemID = 0x2045;
HairHue = 0x8A8;
}
public override void InitOutfit()
{
AddItem(new Backpack());
SetWearable(new Doublet());
SetWearable(new Kilt(), 443);
SetWearable(new ThighBoots(), 1837);
}
public override void OnDoubleClick(Mobile m)
{
if (m is PlayerMobile && !QuestHelper.CheckDoneOnce((PlayerMobile)m, typeof(ToolsOfTheTradeQuest), this, false))
{
m.SendLocalizedMessage(1080107); // I'm sorry, I have nothing for you at this time.
}
else
{
base.OnDoubleClick(m);
}
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (m is PlayerMobile && InRange(m.Location, 5) && !InRange(oldLocation, 5))
{
BuriedRichesQuest quest = QuestHelper.GetQuest<BuriedRichesQuest>((PlayerMobile)m);
if (quest != null)
{
quest.CompleteQuest();
}
}
}
public LegendaryCartographer(Serial serial)
: base(serial)
{
}
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();
if (Map == Map.Trammel)
{
TramInstance = this;
}
if (Map == Map.Felucca)
{
FelInstance = this;
}
if(!Core.TOL)
{
Delete();
}
}
}
public class MasterProvisioner : MondainQuester
{
public override Type[] Quests { get { return new Type[] { typeof(TheTreasureChaseQuest) }; } }
public static MasterProvisioner TramInstance { get; set; }
public static MasterProvisioner FelInstance { get; set; }
public static void Initialize()
{
if (Core.TOL)
{
if (TramInstance == null)
{
TramInstance = new MasterProvisioner();
TramInstance.MoveToWorld(new Point3D(2989, 636, 0), Map.Trammel);
TramInstance.Direction = Direction.West;
}
if (FelInstance == null)
{
FelInstance = new MasterProvisioner();
FelInstance.MoveToWorld(new Point3D(2989, 636, 0), Map.Felucca);
FelInstance.Direction = Direction.West;
}
}
}
public MasterProvisioner()
: base(NameList.RandomName("male"), "the Master Provisioner")
{
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = false;
CantWalk = true;
Body = 0x190;
Hue = Race.RandomSkinHue();
}
public override void InitOutfit()
{
AddItem(new Backpack());
SetWearable(new FancyShirt());
SetWearable(new JinBaori());
SetWearable(new Kilt());
SetWearable(new ThighBoots(), 1908);
SetWearable(new GoldNecklace());
}
public override void OnDoubleClick(Mobile m)
{
if (m is PlayerMobile && QuestHelper.CheckDoneOnce((PlayerMobile)m, typeof(TheTreasureChaseQuest), this, false))
{
m.SendLocalizedMessage(1080107); // I'm sorry, I have nothing for you at this time.
}
else
{
base.OnDoubleClick(m);
}
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (m is PlayerMobile && InRange(m.Location, 5) && !InRange(oldLocation, 5))
{
ToolsOfTheTradeQuest quest = QuestHelper.GetQuest<ToolsOfTheTradeQuest>((PlayerMobile)m);
if (quest != null)
{
quest.CompleteQuest();
}
}
}
public MasterProvisioner(Serial serial)
: base(serial)
{
}
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();
if (Map == Map.Trammel)
{
TramInstance = this;
}
if (Map == Map.Felucca)
{
FelInstance = this;
}
if (!Core.TOL)
{
Delete();
}
}
}
}

View File

@@ -0,0 +1,70 @@
using Server;
using System;
using Server.Items;
using Server.Services.TownCryer;
namespace Server.Engines.Quests
{
public class ExploringTheDeepQuest : BaseQuest
{
/* Exploring the Deep */
public override object Title { get { return 1154327; } }
/*The life of a Shipwreck Salvager does seem exciting! Visiting Hepler Paulson at the Sons of the Sea in the
* City of Trinsic is certainly to be an adventure!*/
public override object Description { get { return 1158127; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Speak to Hepler Paulson at the Sons of the Sea in Trinsic and complete the Exploring the Deep Quest. */
public override object Uncomplete { get { return 1158131; } }
/* You have discovered the secrets of the Wreck of the Ararat and aided in binding the Shadowlords to their tomb within!*/
public override object Complete { get { return 1158136; } }
public override int CompleteMessage { get { return 1156585; } } // You've completed a quest!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public ExploringTheDeepQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(typeof(ExploringTheDeedTitleDeed), 1158142)); // Uncovering the secrets of the deep...
}
public void CompleteQuest()
{
OnCompleted();
Objectives[0].CurProgress++;
TownCryerSystem.CompleteQuest(Owner, this);
GiveRewards();
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return Quest.Uncomplete; } }
public InternalObjective()
: base(1)
{
}
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();
}
}
}
}

View File

@@ -0,0 +1,73 @@
using Server;
using System;
using Server.Items;
using Server.Services.TownCryer;
namespace Server.Engines.Quests
{
public class HuntmastersChallengeQuest : BaseQuest
{
/* Huntmaster's Challenge */
public override object Title { get { return 1155726; } }
/*Each month the Ranger's Guild in Skara Brae hosts a contest to see who can hunt Britannia's
* largest creatures! Visit the Skara Brae Ranger's Guild to learn more!*/
public override object Description { get { return 1158132; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Visit the Skara Brae Ranger's Guild and participate in the Huntmaster's Challenge */
public override object Uncomplete { get { return 1158133; } }
/* You have braved the wilds of Britannia and slayed a mighty beast! You have meticulously documented your kill
* and submitted it to the Ranger's Guild for evaluation. If luck was on your side you may indeed have
* the largest quarry for the month...or maybe not. Alas, your bravery has earned you the well deserved title
* of Hunter! May you go fearlessly into the wilderness in search of your next big kill! Well done! */
public override object Complete { get { return 1158378; } }
public override int CompleteMessage { get { return 1156585; } } // You've completed a quest!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public HuntmastersChallengeQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(typeof(HuntmastersQuestRewardTitleDeed), 1158139)); // A Reward Title Deed
}
public void CompleteChallenge()
{
OnCompleted();
Objectives[0].CurProgress++;
TownCryerSystem.CompleteQuest(Owner, this);
GiveRewards();
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return Quest.Uncomplete; } }
public InternalObjective()
: base(1)
{
}
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();
}
}
}
}

View File

@@ -0,0 +1,252 @@
using Server;
using System;
using Server.Items;
using Server.Mobiles;
using Server.Services.TownCryer;
namespace Server.Engines.Quests
{
public class PaladinsOfTrinsic : BaseQuest
{
public override QuestChain ChainID{get {return QuestChain.PaladinsOfTrinsic; } }
public override Type NextQuest { get { return typeof(PaladinsOfTrinsic2); } }
/* The Paladins of Trinsic */
public override object Title { get { return 1158093; } }
/*It seems the Paladins of Trinsic are working hard to see the threats of Shame are kept inside Shame,
* perhaps it would be a good idea to visit their headquarters in Northeast Trinsic.*/
public override object Description { get { return 1158114; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Find the Lord Commander of the Paladins of Trinsic. */
public override object Uncomplete { get { return 1158117; } }
/*You have proven yourself honorable and the Lord Commander has invited you to join the elite order of the Paladin of Trinsic!
* Congratulations, Paladin!*/
public override object Complete { get { return 1158317; } }
public override int CompleteMessage { get { return 1156585; } } // You've completed a quest!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public PaladinsOfTrinsic()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(1158120)); // A unique opportunity to join the Paladins of Trinsic.
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return Quest.Uncomplete; } }
public InternalObjective()
: base(1)
{
}
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 class PaladinsOfTrinsic2 : BaseQuest
{
public override QuestChain ChainID { get { return QuestChain.PaladinsOfTrinsic; } }
/* The Paladins of Trinsic */
public override object Title { get { return 1158093; } }
/*Another who wishes to walk the path of the Paladins of Trinsic? Well you should know the path is not an easy one to walk,
* and only those with the courage to pursue truth are admitted to the order. If you prove you are honorable, then you shall
* join our ranks and gain the prestigious title of Paladin of Trinsic. We are bound by Honor, and thus we stand against
* Shame! To prove yourself you must venture deep within the dungeon Shame and slay the vile within. Succeed in this task
* and you will prove your worth, fail and you will bring to your name what you hope to defeat - Shame.*/
public override object Description { get { return 1158096; } }
/* The way of the Paladin is not for everyone, I understand your decision but hope you reconsider... */
public override object Refuse { get { return 1158102; } }
/* Go to the dungeon Shame and slay the creatures within, only then will you have the Honor of calling thyself a Paladin of
* Trinsic. */
public override object Uncomplete { get { return 1158105; } }
/*You have proven yourself honorable and the Lord Commander has invited you to join the elite order of the Paladin of Trinsic!
* Congratulations, Paladin!*/
public override object Complete { get { return 1158317; } }
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public override int CompleteMessage { get { return 1158108; } }
public bool SentMessage { get; set; }
public PaladinsOfTrinsic2()
{
AddObjective(new SlayObjective(typeof(QuartzElemental), "quartz elemental", 1, "Shame"));
AddObjective(new SlayObjective(typeof(FlameElemental), "flame elemental", 1, "Shame"));
AddObjective(new SlayObjective(typeof(WindElemental), "wind elemental", 1, "Shame"));
AddObjective(new SlayObjective(typeof(UnboundEnergyVortex), "unbound energy vortex", 1, "Shame"));
AddReward(new BaseReward(typeof(PaladinOfTrinsicRewardTitleDeed), 1158099)); // Becoming a Paladin of Trinsic
}
public void CompleteQuest()
{
TownCryerSystem.CompleteQuest(Owner, new PaladinsOfTrinsic());
OnCompleted();
GiveRewards();
QuestHelper.Delay(Owner, typeof(PaladinsOfTrinsic), RestartDelay);
}
}
public class Morz : MondainQuester
{
public override Type[] Quests { get { return new Type[] { typeof(PaladinsOfTrinsic) }; } }
public static Morz TramInstance { get; set; }
public static Morz FelInstance { get; set; }
public static void Initialize()
{
if (Core.TOL)
{
if (TramInstance == null)
{
TramInstance = new Morz();
TramInstance.MoveToWorld(new Point3D(2018, 2745, 30), Map.Trammel);
TramInstance.Direction = Direction.South;
}
if (FelInstance == null)
{
FelInstance = new Morz();
FelInstance.MoveToWorld(new Point3D(2018, 2745, 30), Map.Felucca);
FelInstance.Direction = Direction.South;
}
}
}
public Morz()
: base("Morz", "the Lord Commander")
{
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = false;
CantWalk = true;
Body = 0x190;
Hue = Race.RandomSkinHue();
HairItemID = 0;
FacialHairItemID = 0x204D;
}
public override void InitOutfit()
{
AddItem(new Backpack());
SetWearable(new PlateChest(), 0x8A5);
SetWearable(new PlateLegs(), 0x8A5);
SetWearable(new PlateArms(), 0x8A5);
SetWearable(new PlateGloves(), 0x8A5);
SetWearable(new BodySash(), 1158);
SetWearable(new Cloak(), 1158);
}
public override void OnDoubleClick(Mobile m)
{
if (m is PlayerMobile && m.InRange(Location, 5))
{
PaladinsOfTrinsic quest = QuestHelper.GetQuest((PlayerMobile)m, typeof(PaladinsOfTrinsic)) as PaladinsOfTrinsic;
if (quest != null)
{
quest.GiveRewards();
}
else
{
PaladinsOfTrinsic2 quest2 = QuestHelper.GetQuest((PlayerMobile)m, typeof(PaladinsOfTrinsic2)) as PaladinsOfTrinsic2;
if (quest2 != null)
{
if (quest2.Completed)
{
quest2.CompleteQuest();
}
else
{
m.SendGump(new MondainQuestGump(quest2, MondainQuestGump.Section.InProgress, false));
quest2.InProgress();
}
}
}
}
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if(m is PlayerMobile && InRange(m.Location, 5) && !InRange(oldLocation, 5))
{
PaladinsOfTrinsic2 quest = QuestHelper.GetQuest<PaladinsOfTrinsic2>((PlayerMobile)m);
if(quest != null && !quest.SentMessage && quest.Completed)
{
m.SendLocalizedMessage(1158111); // You have proven yourself Honorable, the Lord Commander looks overjoyed as you approach him triumphantly! Speak to him to claim your reward!
quest.SentMessage = true;
}
}
}
public Morz(Serial serial)
: base(serial)
{
}
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();
if (Map == Map.Trammel)
{
TramInstance = this;
}
else if (Map == Map.Felucca)
{
FelInstance = this;
}
if (!Core.TOL)
Delete();
}
}
}

View File

@@ -0,0 +1,604 @@
using Server;
using System;
using Server.Items;
using Server.Mobiles;
using Server.Engines.Quests;
using Server.Network;
using Server.Gumps;
using Server.Services.TownCryer;
namespace Server.Engines.Quests
{
public class RoyalBritannianGuardOrders : BaseJournal
{
public override TextDefinition Title { get { return 1158159; } } // Royal Britannian Guard Orders
public override TextDefinition Body { get { return 1158160; } }
/*ROYAL BRITANNIAN GUARD<br>MINISTRY OF PRISONS DETACHMENT<br><br>ORIGINAL ORDERS<br>ROYAL BRITANNIAN GUARD<br>WRONG PRISON
* DIVISION<br><br>From: COMMAND, RBG Yew<br>To: Lieutenant Bennet Yardley, RBG Yew<br><br>Subject: Wrong Prison Treasure
* Expedition<br><br>1. RBG Intelligence has indicated the presence of highly prized cache of weapons stashed within the
* deepest confinements of the Prison Dungeon Wrong. Intelligence indicates these weapons were confiscated at the time of
* various assassination attempts among the prisoners before the prison was lost.<br><br>2. Official cover story remains in
* place - no outside interference expected and only official RBG personnel are permitted entry.<br><br>3. Interview with
* former prison officials indicate weapons under heavy lock and key, suggest specialist assignment of lock picking skills
* and tools.<br><br>*The remainder of the document is illegible**/
public override int LabelNumber { get { return 1158171; } } // orders
[Constructable]
public RoyalBritannianGuardOrders()
{
LootType = LootType.Blessed;
}
public RoyalBritannianGuardOrders(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class CorpseOfBennetYardley : Item, IConditionalVisibility
{
public static CorpseOfBennetYardley TramInstance { get; set; }
public static CorpseOfBennetYardley FelInstance { get; set; }
public static void Initialize()
{
if (Core.TOL)
{
if (TramInstance == null)
{
TramInstance = new CorpseOfBennetYardley();
TramInstance.MoveToWorld(new Point3D(5688, 653, 0), Map.Trammel);
}
if (FelInstance == null)
{
FelInstance = new CorpseOfBennetYardley();
FelInstance.MoveToWorld(new Point3D(5688, 653, 0), Map.Felucca);
}
}
}
public override bool ForceShowProperties { get { return true; } }
public override int LabelNumber { get { return 1158168; } }
public CorpseOfBennetYardley()
: base(Utility.Random(0xECA, 9))
{
Movable = false;
}
public bool CanBeSeenBy(PlayerMobile pm)
{
if (pm.AccessLevel > AccessLevel.Player)
return true;
var quest = QuestHelper.GetQuest<RightingWrongQuest4>(pm);
return quest != null && !quest.Completed;
}
public override void OnDoubleClick(Mobile from)
{
if (from is PlayerMobile && from.InRange(Location, 2))
{
var quest = QuestHelper.GetQuest<RightingWrongQuest4>((PlayerMobile)from);
if (from is PlayerMobile && quest != null && !quest.Completed)
{
quest.Objectives[0].CurProgress++;
quest.OnCompleted();
Visible = false;
Visible = true;
}
}
}
public CorpseOfBennetYardley(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
if (Map == Map.Trammel)
{
TramInstance = this;
}
else if (Map == Map.Felucca)
{
FelInstance = this;
}
if (!Core.TOL)
Delete();
}
}
public class TreasureHuntingBook : Item
{
[Constructable]
public TreasureHuntingBook()
: base(0xFBE)
{
LootType = LootType.Blessed;
}
public override void OnDoubleClick(Mobile m)
{
if (m is PlayerMobile && IsChildOf(m.Backpack))
{
m.CloseGump(typeof(InternalGump));
BaseGump.SendGump(new InternalGump((PlayerMobile)m));
}
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
list.Add(1158253); // Treasure Hunting: A Practical Approach
list.Add(1154760, "#1158254"); // By: Vespyr Jones
}
public class InternalGump : BaseGump
{
public InternalGump(PlayerMobile pm)
: base(pm, 10, 10)
{
}
public override void AddGumpLayout()
{
AddImage(0, 0, 0x761C);
AddImage(112, 40, 0x655);
AddHtmlLocalized(113, 350, 342, 280, 1158255, C32216(0x080808), false, true);
}
}
public TreasureHuntingBook(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class BuriedRichesTreasureMap : TreasureMap
{
public TreasureMapChest Chest { get; set; }
public BuriedRichesTreasureMap(int level)
: base(level, Map.Trammel)
{
LootType = LootType.Blessed;
}
public override void Decode(Mobile from)
{
if (QuestHelper.HasQuest<TheTreasureChaseQuest>((PlayerMobile)from))
{
from.CheckSkill(SkillName.Cartography, 0, 100);
Decoder = from;
DisplayTo(from);
from.SendLocalizedMessage(1158243); // Your time studying Treasure Hunting: A Practical Approach helps you decode the map...
}
else
{
from.PrivateOverheadMessage(MessageType.Regular, 0x21, 1157850, from.NetState); // *You don't make anything of it.*
//m.PrivateOverheadMessage(MessageType.Regular, 1154, 1158244, m.NetState); // *You decide to visit the Provisioner at the Adventurer's Supplies in Vesper before trying to decode the map...*
}
}
public override void DisplayTo(Mobile m)
{
base.DisplayTo(m);
m.PlaySound(0x41A);
m.PrivateOverheadMessage(MessageType.Regular, 1154, 1157722, "Cartography", m.NetState); // *Your proficiency in ~1_SKILL~ reveals more about the item*
if (m is PlayerMobile && Level == 0)
{
m.CloseGump(typeof(InternalGump));
BaseGump.SendGump(new InternalGump((PlayerMobile)m, this));
}
}
public override void OnChestOpened(Mobile from, TreasureMapChest chest)
{
if (from is PlayerMobile)
{
var quest = QuestHelper.GetQuest<TheTreasureChaseQuest>((PlayerMobile)from);
if (quest != null)
{
if (Level == 0)
{
TownCryerSystem.CompleteQuest((PlayerMobile)from, 1158239, 1158251, 0x655);
/*Your eyes widen as you pry open the old chest and reveal the treasure within! Even this small cache
* excites you as the thought of bigger and better treasure looms on the horizon! The map is covered
* in ancient runes and marks the location of another treasure hoard. You carefully furl the map and
* set off on your next adventure!*/
from.SendLocalizedMessage(1158245, "", 0x23); // You have found the first zealot treasure! As you dig up the chest a leather bound case appears to contain an additional map. You place it in your backpack for later examination.
chest.DropItem(new BuriedRichesTreasureMap(1));
}
else
{
from.SendLocalizedMessage(1158246, "", 0x23); // You have found the second zealot treasure! As you dig up the chest a leather bound case appears to contain an additional map. You place it in your backpack for later examination.
quest.CompleteQuest();
}
}
}
}
public override void OnBeginDig(Mobile from)
{
if (Completed)
{
from.SendLocalizedMessage(503028); // The treasure for this map has already been found.
}
else if (Decoder != from)
{
from.SendLocalizedMessage(503031); // You did not decode this map and have no clue where to look for the treasure.
}
else if (!from.CanBeginAction(typeof(TreasureMap)))
{
from.SendLocalizedMessage(503020); // You are already digging treasure.
}
else if (from.Map != Facet)
{
from.SendLocalizedMessage(1010479); // You seem to be in the right place, but may be on the wrong facet!
}
else if (from is PlayerMobile && !QuestHelper.HasQuest<TheTreasureChaseQuest>((PlayerMobile)from))
{
from.SendLocalizedMessage(1158257); // You must be on the "The Treasure Chase" quest offered via the Town Cryer to dig up this treasure.
}
else
{
from.SendLocalizedMessage(503033); // Where do you wish to dig?
from.Target = new TreasureMap.DigTarget(this);
}
}
protected override bool HasRequiredSkill(Mobile from)
{
return true;
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (Level == 0)
{
list.Add(1158229); // A mysterious treasure map personally given to you by the Legendary Cartographer in Vesper
}
else
{
list.Add(1158256); // A mysterious treasure map recovered from a treasure hoard
}
}
private class InternalGump : BaseGump
{
public BuriedRichesTreasureMap Map { get; set; }
public InternalGump(PlayerMobile pm, BuriedRichesTreasureMap map)
: base(pm, 10, 10)
{
Map = map;
}
public override void AddGumpLayout()
{
AddBackground(0, 0, 454, 400, 9380);
AddHtmlLocalized(177, 53, 235, 20, CenterLoc, "#1158240", C32216(0xA52A2A), false, false); // A Mysterious Treasure Map
AddHtmlLocalized(177, 80, 235, 40, CenterLoc, Map.Level == 0 ? "#1158241" : "#1158250", C32216(0xA52A2A), false, false); // Given to you by the Master Cartographer
/*The Cartographer has given you a mysterious treasure map and offered you some tips on how to go about
* recovering the treasure. As the Cartographer leaned in and handed you the furled parchment, she told
* you of the origins of this mysterious document. "Legend has it..." she tells you, "this map is the
* lost treasure of an ancient Sosarian Order of Zealots. I'm told over the centuries they would bury
* small portions of their treasure throughout the Britannian countryside in an effort to thwart any
* attempts to recover the hoard in its entirety." Your eyes widen at the thought of a massive treasure
* hoard and you can't wait to find it!*/
AddHtmlLocalized(177, 122, 235, 228, 1158242, true, true);
AddItem(85, 120, 0x14EB, 0);
}
}
public BuriedRichesTreasureMap(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write(Chest);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
Chest = reader.ReadItem() as TreasureMapChest;
}
}
public class TreasureSeekersLockpick : Lockpick
{
public override int LabelNumber { get { return 1158258; } }
public TreasureSeekersLockpick()
{
ItemID = 0x14FD;
}
protected override void BeginLockpick(Mobile from, ILockpickable item)
{
if (from is PlayerMobile &&
item.Locked &&
QuestHelper.HasQuest<TheTreasureChaseQuest>((PlayerMobile)from) &&
item is TreasureMapChest &&
((TreasureMapChest)item).TreasureMap is BuriedRichesTreasureMap)
{
var chest = (TreasureMapChest)item;
from.PlaySound(0x241);
Timer.DelayCall(TimeSpan.FromMilliseconds(200), () =>
{
if (item.Locked && from.InRange(chest.GetWorldLocation(), 1))
{
from.CheckTargetSkill(SkillName.Lockpicking, item, 0, 100);
// Success! Pick the lock!
from.PrivateOverheadMessage(MessageType.Regular, 1154, 1158252, from.NetState); // *Your recent study of Treasure Hunting helps you pick the lock...*
chest.SendLocalizedMessageTo(from, 502076); // The lock quickly yields to your skill.
from.PlaySound(0x4A);
item.LockPick(from);
}
});
}
else
{
base.BeginLockpick(from, item);
}
}
public TreasureSeekersLockpick(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class MysteriousPotion : Item
{
public override int LabelNumber { get { return 1158286; } } // A Mysterious Potion
public MysteriousPotion()
: base(0xF06)
{
}
public override void OnDoubleClick(Mobile m)
{
if (m is PlayerMobile)
{
var pm = m as PlayerMobile;
if (QuestHelper.HasQuest<AForcedSacraficeQuest2>(pm))
{
if (!TownCryerSystem.UnderMysteriousPotionEffects(pm))
{
pm.SendGump(new ConfirmCallbackGump(pm, 1158286, 1158287, null, null, confirm: (mob, o) =>
{
TownCryerSystem.AddMysteriousPotionEffects(mob);
mob.FixedParticles(0x376A, 9, 32, 5007, EffectLayer.Waist);
mob.PlaySound(0x1E3);
BasePotion.PlayDrinkEffect(mob);
Delete();
}));
}
else
{
pm.SendLocalizedMessage(1158289); // You have already used this.
}
}
else
{
pm.SendLocalizedMessage(1158285); // You must be on the "A Forced Sacrifice" quest to use this item.
}
}
}
public MysteriousPotion(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class PaladinCorpse : Container
{
public static PaladinCorpse TramInstance { get; set; }
public static PaladinCorpse FelInstance { get; set; }
public static void Initialize()
{
if (Core.TOL)
{
if (TramInstance == null)
{
TramInstance = new PaladinCorpse();
TramInstance.MoveToWorld(new Point3D(5396, 118, 0), Map.Trammel);
}
if (FelInstance == null)
{
FelInstance = new PaladinCorpse();
FelInstance.MoveToWorld(new Point3D(5396, 118, 0), Map.Felucca);
}
}
}
public override int LabelNumber { get { return 1158135; } } // the remains of a would-be paladin
public override bool HandlesOnMovement { get { return true; } }
public override bool IsDecoContainer { get { return false; } }
public PaladinCorpse()
: base(0x9F1E)
{
DropItem(new WouldBePaladinChronicles());
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (InRange(m.Location, 2) && !InRange(oldLocation, 2))
{
PrivateOverheadMessage(Server.Network.MessageType.Regular, 1154, 1158137, m.NetState); // *You notice the skeleton clutching a small journal...*
}
}
public PaladinCorpse(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
if (Map == Map.Trammel)
{
TramInstance = this;
}
else if (Map == Map.Felucca)
{
FelInstance = this;
}
if (!Core.TOL)
Delete();
}
}
public class WouldBePaladinChronicles : BaseJournal
{
public override int LabelNumber { get { return 1094837; } } // a journal
public override TextDefinition Title { get { return null; } }
public override TextDefinition Body { get { return 1158138; } }
/**the text is mostly a journal chronicling the adventures of a man who wished to join the Paladins of Trinsic.
* Of particular note is the final entry...*<br><br>This is the most shameful entry I will write...for I have fallen
* short of my goal. My only hope is my failures will serve to assist those who come after me with the courage to
* pursue the truth, and with my notes they will find success. I have found strange crystals on the corpses of the
* creatures I slay here. When I touch the crystal, I can feel it absorbed into my being. A growing voice inside me
* compels me to altars located throughout the dungeon. When the voice within grew loud enough I could no longer
* ignore it, I touched my hand to the altar and before me a grand champion stood! I was quick to react to the
* crushing blow my newly summoned opponent sought to deliver, and I was victorious! Alas, the deeper into the
* dungeon I explored, the more powerful the altar champions become and now I find myself in this dire situation....
* To anyone who reads this...do me the honor and defeat the three champions and slay the unbound energy vortexes that
* inhabit the deepest depths of this place...for I feel my time here is shor...*/
public WouldBePaladinChronicles()
{
Movable = false;
}
public override void OnDoubleClick(Mobile m)
{
m.SendGump(new BaseJournalGump(Title, Body));
}
public WouldBePaladinChronicles(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,194 @@
using Server;
using System;
namespace Server.Items
{
public class HuntmastersQuestRewardTitleDeed : BaseRewardTitleDeed
{
public override TextDefinition Title { get { return new TextDefinition(1158140); } } // Hunter
[Constructable]
public HuntmastersQuestRewardTitleDeed()
{
}
public HuntmastersQuestRewardTitleDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class PaladinOfTrinsicRewardTitleDeed : BaseRewardTitleDeed
{
public override TextDefinition Title { get { return new TextDefinition(1158090); } } // Paladin of Trinsic
[Constructable]
public PaladinOfTrinsicRewardTitleDeed()
{
}
public PaladinOfTrinsicRewardTitleDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class RightingWrongRewardTitleDeed : BaseRewardTitleDeed
{
public override TextDefinition Title { get { return new TextDefinition(1158161); } } // Warden of Wrong
[Constructable]
public RightingWrongRewardTitleDeed()
{
}
public RightingWrongRewardTitleDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class TreasureHunterRewardTitleDeed : BaseRewardTitleDeed
{
public override TextDefinition Title { get { return new TextDefinition(1158389); } } // Treasure Hunter
[Constructable]
public TreasureHunterRewardTitleDeed()
{
}
public TreasureHunterRewardTitleDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class HeroOfMincRewardTitleDeed : BaseRewardTitleDeed
{
public override TextDefinition Title { get { return new TextDefinition(1158278); } } // Hero of Minoc
[Constructable]
public HeroOfMincRewardTitleDeed()
{
}
public HeroOfMincRewardTitleDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class DespiseTitleDeed : BaseRewardTitleDeed
{
public override TextDefinition Title { get { return new TextDefinition(1158303); } } // The Battle of Wisps TODO: Correct cliloc
[Constructable]
public DespiseTitleDeed()
{
}
public DespiseTitleDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
public class ExploringTheDeedTitleDeed : BaseRewardTitleDeed
{
public override TextDefinition Title { get { return new TextDefinition(1154505); } } // Salvager of the Deep
[Constructable]
public ExploringTheDeedTitleDeed()
{
}
public ExploringTheDeedTitleDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,388 @@
using Server;
using System;
using Server.Items;
using Server.Mobiles;
using Server.Services.TownCryer;
namespace Server.Engines.Quests
{
public class RightingWrongQuest : BaseQuest
{
/* Righting Wrong */
public override object Title { get { return 1158150; } }
/*The situation at the Prison Dungeon Wrong seems to have gotten out of control. The article mentioned the Royal
* Britannian' Guard has started contracting adventuring groups to handle the situation. Perhaps it would be
* prudent to inquire about opportunities with the Guard at the Court of Truth in Yew.*/
public override object Description { get { return 1158151; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Inquire about the events at Wrong with the Royal Britannian Guard at the Court of Truth in Yew. */
public override object Uncomplete { get { return 1158152; } }
public override object Complete { get { return 1158170; } }
/*You have brought Justice to the forgotten prison dungeon Wrong! The Royal Britannian Guard thanks you for your service,
* and for not leaving the Lieutenant behind. You fought bravely this day and escaped the prison. As a thank you for your
* service, and a testament to your accomplishment, you have been granted the title Warden of Wrong!*/
public override int CompleteMessage { get { return 1158291; } } // You've found the Royal Guard Captain! Speak to him to learn more!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public RightingWrongQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(1158153)); // A unique opportunity with the Royal Britannian Guard
}
public override void GiveRewards()
{
base.GiveRewards();
QuestHelper.Delay(Owner, typeof(RightingWrongQuest), RestartDelay);
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return Quest.Uncomplete; } }
public InternalObjective()
: base(1)
{
}
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 class RightingWrongQuest2 : BaseQuest
{
public override QuestChain ChainID { get { return QuestChain.RightingWrong; } }
public override Type NextQuest { get { return typeof(RightingWrongQuest3); } }
/* Righting Wrong */
public override object Title { get { return 1158150; } }
/*Another wanna-be guardsman expecting to wrangle this mess? You should know that inside Wrong there are many terrors.
* Lizardman have squatted in the entire prison, eaten most of the prisoners and staff. The few staff that are left have
* gone mad. If you expect to make it as a Guardsman you are going to need to thin out the heard. Head inside and kill
* the creatures within!*/
public override object Description { get { return 1158155; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Go inside the prison dungeon Wrong and slay the creatures within! */
public override object Uncomplete { get { return 1158156; } }
/* Well then, I guess you aren't as useless as you look. Made quick work of the Lizards, that's fine work indeed!
* Your next test is going to require you travel deeper into the prison. Seems there is an ogre who has taken to mastering
* his cooking skills at the expense of the former prisoners. The Guard can't have that, so you need to go in there and make
* sure this cook is prepping his last meal! */
public override object Complete { get { return 1158157; } }
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public RightingWrongQuest2()
{
AddObjective(new SlayObjective(typeof(LizardmanDefender), "lizardman defenders", 5));
AddObjective(new SlayObjective(typeof(LizardmanSquatter), "lizardman squatters", 5));
AddObjective(new SlayObjective(typeof(CaveTrollWrong), "cave trolls", 5));
AddObjective(new SlayObjective(typeof(HungryOgre), "hungry ogres", 5));
AddReward(new BaseReward(1158167)); // A step closer to righting Wrong
}
}
public class RightingWrongQuest3 : BaseQuest
{
public override QuestChain ChainID { get { return QuestChain.RightingWrong; } }
public override Type NextQuest { get { return typeof(RightingWrongQuest4); } }
/* Righting Wrong */
public override object Title { get { return 1158150; } }
/* Well then, I guess you aren't as useless as you look. Made quick work of the Lizards, that's fine work indeed!
* Your next test is going to require you travel deeper into the prison. Seems there is an ogre who has taken to mastering
* his cooking skills at the expense of the former prisoners. The Guard can't have that, so you need to go in there and make
* sure this cook is prepping his last meal! */
public override object Description { get { return 1158157; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Go inside the prison dungeon Wrong and slay Fezzik the Ogre Cook */
public override object Uncomplete { get { return 1158158; } }
/* Looks like Fezzik won't be making anymore stew! Hah! Well done! Your final task is going to require you to learn the
* most important lesson of being a Guardsman - we never leave a man behind. One of our comrades was captured by the
* demonic jailers and taken to the prison. You need to get yourself captured by the jailers and taken inside the deepest
* part of the prison. Once inside, find our fallen comrade and escape. Here's a copy of his orders to help you find his corpse. */
public override object Complete { get { return 1158163; } }
//public override int CompleteMessage { get { return 1158291; } } // You've found the Royal Guard Captain! Speak to him to learn more!
public override int AcceptSound { get { return 0x2E8; } }
public RightingWrongQuest3()
{
AddObjective(new SlayObjective(typeof(Fezzik), "fezzik the ogre cook", 1));
AddReward(new BaseReward(1158167)); // A step closer to righting Wrong
}
}
public class RightingWrongQuest4 : BaseQuest
{
public override QuestChain ChainID { get { return QuestChain.RightingWrong; } }
private RoyalBritannianGuardOrders Orders { get; set; }
/* Righting Wrong */
public override object Title { get { return 1158150; } }
/* Looks like Fezzik won't be making anymore stew! Hah! Well done! Your final task is going to require you to learn the
* most important lesson of being a Guardsman - we never leave a man behind. One of our comrades was captured by the
* demonic jailers and taken to the prison. You need to get yourself captured by the jailers and taken inside the deepest
* part of the prison. Once inside, find our fallen comrade and escape. Here's a copy of his orders to help you find his corpse. */
public override object Description { get { return 1158163; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Go inside the prison dungeon Wrong and get yourself captured by the Demonic Jailors. Once inside, find the fallen Guard and escape
* with his corpse. */
public override object Uncomplete { get { return 1158166; } }
/* You have brought Justice to the forgotten prison dungeon Wrong! The Royal Britannian Guard thanks you for your service,
* and for not leaving the Lieutenant behind. You fought bravely this day and escaped the prison. As a thank you for your
* service, and a testament to your accomplishment, you have been granted the title Warden of Wrong! */
public override object Complete { get { return 1158170; } }
public override int CompleteMessage { get { return 1158169; } }
/*You have found the corpse of Lieutenant Bennet Yardley of the Royal Britannian Guard. Unfortunately, it seems there
* is not much left to return to the Field Commander. Regardless, you hold back your urge to become sick and gather his
* remains. Escape the prison and return to the Field Commander.*/
public override int AcceptSound { get { return 0x2E8; } }
public RightingWrongQuest4()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(typeof(RightingWrongRewardTitleDeed), 1158165)); // A Unique Honor from the Royal Britannian Guard
}
public override void OnAccept()
{
base.OnAccept();
Orders = new RoyalBritannianGuardOrders();
Owner.Backpack.DropItem(Orders);
Owner.SendLocalizedMessage(1154489); // You received a Quest Item!
}
public void CompleteQuest()
{
TownCryerSystem.CompleteQuest(Owner, new RightingWrongQuest());
OnCompleted();
GiveRewards();
QuestHelper.Delay(Owner, typeof(RightingWrongQuest2), RestartDelay);
}
public override void RemoveQuest(bool removeChain)
{
base.RemoveQuest(removeChain);
if (Orders != null && !Orders.Deleted)
{
Orders.Delete();
}
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return 1158164; } } // Find the fallen Guard's corpse and escape the prison.
public InternalObjective()
: base(1)
{
}
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 Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
writer.Write(Orders);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
Orders = reader.ReadItem() as RoyalBritannianGuardOrders;
}
}
public class Arnold : MondainQuester
{
public override Type[] Quests { get { return new Type[] { typeof(RightingWrongQuest2) }; } }
public static Arnold TramInstance { get; set; }
public static Arnold FelInstance { get; set; }
public static void Initialize()
{
if (Core.TOL)
{
if (TramInstance == null)
{
TramInstance = new Arnold();
TramInstance.MoveToWorld(new Point3D(363, 913, 0), Map.Trammel);
TramInstance.Direction = Direction.East;
}
if (FelInstance == null)
{
FelInstance = new Arnold();
FelInstance.MoveToWorld(new Point3D(363, 913, 0), Map.Felucca);
FelInstance.Direction = Direction.East;
}
}
}
public Arnold()
: base("Arnold", "the Royal Britannian Guard")
{
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = false;
CantWalk = true;
Body = 0x190;
Hue = Race.RandomSkinHue();
HairItemID = 0x203C;
FacialHairItemID = 0x204C;
HairHue = 0x8A8;
FacialHairHue = 0x8A8;
}
public override void InitOutfit()
{
AddItem(new Backpack());
SetWearable(new ChainChest());
SetWearable(new ThighBoots());
SetWearable(new BodySash(), 1157);
SetWearable(new Epaulette(), 1157);
SetWearable(new ChaosShield());
SetWearable(new Broadsword());
}
public override void OnDoubleClick(Mobile m)
{
if (m is PlayerMobile && m.InRange(Location, 5))
{
RightingWrongQuest4 quest = QuestHelper.GetQuest<RightingWrongQuest4>((PlayerMobile)m);
if (quest != null && quest.Completed)
{
quest.CompleteQuest();
}
else
{
base.OnDoubleClick(m);
}
}
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (m is PlayerMobile && InRange(m.Location, 5) && !InRange(oldLocation, 5))
{
RightingWrongQuest quest = QuestHelper.GetQuest<RightingWrongQuest>((PlayerMobile)m);
if (quest != null)
{
quest.OnCompleted();
quest.GiveRewards();
}
}
}
public Arnold(Serial serial)
: base(serial)
{
}
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();
if (Map == Map.Trammel)
{
TramInstance = this;
}
else if (Map == Map.Felucca)
{
FelInstance = this;
}
if (!Core.TOL)
Delete();
}
}
}

View File

@@ -0,0 +1,186 @@
using Server;
using System;
using Server.Items;
using Server.Mobiles;
using Server.Engines.Points;
using Server.Services.TownCryer;
using Server.Gumps;
namespace Server.Engines.Quests
{
public class WishesOfTheWispQuest : BaseQuest
{
/*Wishes of Wisps*/
public override object Title { get { return 1158296; } }
/*The story of the brothers Andros and Adrian is troubling, yet fascinates you. You have heard rumor of items
* traded by the mysterious wisps. Despite the dangers you decide you should venture to the dungeon Despise.*/
public override object Description { get { return 1158318; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Visit the Dungeon Despise and investigate. */
public override object Uncomplete { get { return 1158297; } }
//public override object Complete { get { return 1158378; } }
public override int CompleteMessage { get { return 1156585; } } // You've completed a quest!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public WishesOfTheWispQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(1158298)); // A step closer to understanding what happened at Despise
}
public void CompleteQuest()
{
OnCompleted();
Objectives[0].CurProgress++;
TownCryerSystem.CompleteQuest(Owner, 1153468, 1158309, 0x65C);
GiveRewards();
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return Quest.Uncomplete; } }
public InternalObjective()
: base(1)
{
}
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 class WhisperingWithWispsQuest : BaseQuest
{
/*Whispering with Wisps*/
public override object Title { get { return 1158300; } }
/*The mysterious wisp seems friendly. You are taken by the mysterious creature and it's iridescent glow. The wisp directs
* you inside the dungeon, but otherwise does not respond to your presence. You feel guided by your karma. Entering the
* dungeon with negative karma will draw you to the depths of despise while entering with positive karma will draw you up
* into the peaceful glades above. You have learned from the wisp you must venture inside the dungeon and seek an Ankh.*/
public override object Description { get { return 1158301; } }
/* You decide against accepting the quest. */
public override object Refuse { get { return 1158130; } }
/* Enter the appropriate level of despise based on your karma. Once inside, find and use an ankh. */
public override object Uncomplete { get { return 1158302; } }
/*You have successfully freed Despise from the eternal feud between Andros and Adrian. Despite your efforts, you no doubt
* believe their strong magics will compel them to battle once again. You rejoice, however, in your small albeit short
* lived victory! The wisp seems eternally grateful and grants you a generous gift!*/
public override object Complete { get { return 1158323; } }
public override int CompleteMessage { get { return 1158322; } }
// You have successfully slayed the brother and freed Despise from their eternal feud! Return to the Wisp outside the dungeon to claim your reward!
public override int AcceptSound { get { return 0x2E8; } }
public override bool DoneOnce { get { return true; } }
public WhisperingWithWispsQuest()
{
AddObjective(new InternalObjective());
AddReward(new BaseReward(typeof(DespiseTitleDeed), 1158139));
}
public override bool RenderObjective(MondainQuestGump g, bool offer)
{
if (offer)
g.AddHtmlLocalized(130, 45, 270, 16, 1049010, 0xFFFFFF, false, false); // Quest Offer
else
g.AddHtmlLocalized(130, 45, 270, 16, 1046026, 0xFFFFFF, false, false); // Quest Log
g.AddButton(130, 430, 0x2EEF, 0x2EF1, (int)Buttons.PreviousPage, GumpButtonType.Reply, 0);
g.AddButton(275, 430, 0x2EE9, 0x2EEB, (int)Buttons.NextPage, GumpButtonType.Reply, 0);
g.AddHtmlObject(160, 70, 200, 40, Title, BaseQuestGump.DarkGreen, false, false);
g.AddHtmlLocalized(98, 140, 312, 16, 1049073, 0x2710, false, false); // Objective:
g.AddHtmlLocalized(98, 156, 312, 16, 1072208, 0x2710, false, false); // All of the following
g.AddHtmlLocalized(98, 172, 312, 83, 1158302, BaseQuestGump.LightGreen, false, false);
/* Enter the appropriate level of despise based on your karma. Once inside, find and use an ankh.*/
g.AddHtmlLocalized(98, 255, 312, 40, 1158305, BaseQuestGump.LightGreen, false, false);
//Using your wisp, posses a creature within the dungeon.
g.AddHtmlLocalized(98, 335, 312, 40, 1158306, BaseQuestGump.LightGreen, false, false);
// Defeat Andros or Adrian in the depths of Despise.
return true;
}
public static void OnBossSlain(Server.Engines.Despise.DespiseBoss boss)
{
foreach (var ds in boss.GetLootingRights())
{
if(ds.m_Mobile is PlayerMobile)
{
var pm = ds.m_Mobile as PlayerMobile;
var quest = QuestHelper.GetQuest<WhisperingWithWispsQuest>(pm);
if(quest != null && !quest.Completed)
{
quest.Objectives[0].CurProgress++;
quest.OnCompleted();
}
}
}
}
public void CompleteQuest()
{
TownCryerSystem.CompleteQuest(Owner, 1158303, 1158323, 0x650);
GiveRewards();
Owner.SendLocalizedMessage(1158326); // For your accomplishments you have been awarded a bonus 1000 Despise points! Trade with the wisp to redeem them!
Server.Engines.Points.PointsSystem.DespiseCrystals.AwardPoints(Owner, 1000, false, false);
}
private class InternalObjective : BaseObjective
{
public override object ObjectiveDescription { get { return Quest.Uncomplete; } }
public InternalObjective()
: base(1)
{
}
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();
}
}
}
}

View File

@@ -0,0 +1,155 @@
using System;
using Server;
namespace Server.Services.TownCryer
{
[PropertyObject]
public class TownCryerGreetingEntry : IComparable<TownCryerGreetingEntry>
{
[CommandProperty(AccessLevel.Administrator)]
public TextDefinition Title { get; set; }
[CommandProperty(AccessLevel.Administrator)]
public TextDefinition Body1 { get; set; }
[CommandProperty(AccessLevel.Administrator)]
public string Body2 { get; set; }
[CommandProperty(AccessLevel.Administrator)]
public string Body3 { get; set; }
[CommandProperty(AccessLevel.Administrator)]
public DateTime Created { get; set; }
[CommandProperty(AccessLevel.Administrator)]
public DateTime Expires { get; set; }
[CommandProperty(AccessLevel.Administrator)]
public string Link { get; set; }
[CommandProperty(AccessLevel.Administrator)]
public string LinkText { get; set; }
[CommandProperty(AccessLevel.Administrator)]
public bool PreLoaded { get; set; }
[CommandProperty(AccessLevel.Administrator)]
public bool CanEdit { get; private set; }
[CommandProperty(AccessLevel.Administrator)]
public bool Expired { get { return Expires != DateTime.MinValue && Expires < DateTime.Now; } }
[CommandProperty(AccessLevel.Administrator)]
public bool Saves { get { return !PreLoaded && Expires != DateTime.MinValue; } }
public TownCryerGreetingEntry(TextDefinition body)
: this(null, body, null, null, -1)
{
}
public TownCryerGreetingEntry(TextDefinition title, TextDefinition body, string link, string linkText)
: this(title, body, null, null, -1, link, linkText)
{
}
public TownCryerGreetingEntry(TextDefinition title, TextDefinition body, string body2, string link, string linkText)
: this(title, body, body2, null, -1, link, linkText)
{
}
public TownCryerGreetingEntry(TextDefinition title, TextDefinition body, int expires, string link, string linkText)
: this(title, body, null, null, expires, link, linkText)
{
}
public TownCryerGreetingEntry(TextDefinition title, TextDefinition body, string body2, string body3, int expires = -1, string link = null, string linkText = null, bool canEdit = false)
{
Title = title;
Body1 = body;
Body2 = body2;
Body3 = body3;
Created = DateTime.Now;
Link = link;
LinkText = linkText;
if (expires > 0)
{
Expires = DateTime.Now + TimeSpan.FromDays(expires);
}
CanEdit = canEdit;
}
public int CompareTo(TownCryerGreetingEntry two)
{
if ((CanEdit || PreLoaded) && !two.CanEdit && !two.PreLoaded)
{
return -1;
}
if ((two.CanEdit || two.PreLoaded) && !CanEdit && !PreLoaded)
{
return 1;
}
if ((CanEdit || PreLoaded) && (two.CanEdit || two.PreLoaded))
{
if (Created > two.Created)
{
return -1;
}
else if (two.Created > Created)
{
return 1;
}
}
return 0;
}
public TownCryerGreetingEntry(GenericReader reader)
{
int version = reader.ReadInt();
switch (version)
{
case 1:
CanEdit = reader.ReadBool();
Body2 = reader.ReadString();
Body3 = reader.ReadString();
goto case 0;
case 0:
Title = TextDefinition.Deserialize(reader);
Body1 = TextDefinition.Deserialize(reader);
Created = reader.ReadDateTime();
Expires = reader.ReadDateTime();
Link = reader.ReadString();
LinkText = reader.ReadString();
break;
}
}
public void Serialize(GenericWriter writer)
{
writer.Write(1);
writer.Write(CanEdit);
writer.Write(Body2);
writer.Write(Body3);
TextDefinition.Serialize(writer, Title);
TextDefinition.Serialize(writer, Body1);
writer.Write(Created);
writer.Write(Expires);
writer.Write(Link);
writer.Write(LinkText);
}
}
}

View File

@@ -0,0 +1,48 @@
using Server;
using System;
using Server.Engines.CityLoyalty;
namespace Server.Services.TownCryer
{
public class TownCryerCityEntry
{
public string Title { get; set; }
public string Body { get; set; }
public string Author { get; set; }
public DateTime Expires { get; set; }
public City City { get; set; }
public bool Expired { get { return Expires < DateTime.Now; } }
public TownCryerCityEntry(Mobile author, City city, int duration, string title, string body)
{
Author = author.Name;
Expires = DateTime.Now + TimeSpan.FromDays(duration);
Title = title;
Body = body;
City = city;
}
public void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write(Title);
writer.Write(Body);
writer.Write(Expires);
writer.Write(Author);
writer.Write((int)City);
}
public TownCryerCityEntry(GenericReader reader)
{
int version = reader.ReadInt();
Title = reader.ReadString();
Body = reader.ReadString();
Expires = reader.ReadDateTime();
Author = reader.ReadString();
City = (City)reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,66 @@
using Server;
using System;
using Server.Guilds;
namespace Server.Services.TownCryer
{
public class TownCryerGuildEntry
{
public string Title { get; set; }
public string FullTitle { get; set; }
public string Body { get; set; }
public string Author { get; set; }
public Guild Guild { get; set; }
public DateTime EventTime { get; set; }
public DateTime Expires { get; private set; }
public string EventLocation { get; set; }
public bool Expired { get { return DateTime.Now + TimeSpan.FromDays(32) < DateTime.Now; } }
public TownCryerGuildEntry(Mobile m, DateTime eventTime, string eventLocation, string title, string body)
{
Guild = m.Guild as Guild;
Title = title;
FullTitle = String.Format("{0}-{1} [{2}] {3}", eventTime.Month, eventTime.Day, Guild.Abbreviation, title);
Body = body;
Author = m.Name;
EventTime = eventTime;
EventLocation = eventLocation;
}
public void GetExpiration()
{
DateTime dt = DateTime.Now.AddMonths(1);
Expires = new DateTime(dt.Year, dt.Month, DateTime.DaysInMonth(dt.Year, dt.Month));
}
public void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write(Title);
writer.Write(FullTitle);
writer.Write(Body);
writer.Write(Author);
writer.Write(Guild);
writer.Write(EventTime);
writer.Write(EventLocation);
writer.Write(Expires);
}
public TownCryerGuildEntry(GenericReader reader)
{
int version = reader.ReadInt();
Title = reader.ReadString();
FullTitle = reader.ReadString();
Body = reader.ReadString();
Author = reader.ReadString();
Guild = reader.ReadGuild() as Guild;
EventTime = reader.ReadDateTime();
EventLocation = reader.ReadString();
Expires = reader.ReadDateTime();
}
}
}

View File

@@ -0,0 +1,50 @@
using Server;
using System;
namespace Server.Services.TownCryer
{
public class TownCryerModeratorEntry
{
public string Title { get; set; }
public string Body1 { get; set; }
public string Body2 { get; set; }
public string Body3 { get; set; }
public DateTime Expires { get; set; }
public string ModeratorName { get; set; }
public bool Expired { get { return Expires < DateTime.Now; } }
public TownCryerModeratorEntry(Mobile m, int duration, string title, string body1, string body2 = null, string body3 = null)
{
Title = title;
Body1 = body1;
Body2 = body2;
Body3 = body3;
ModeratorName = "EM " + m.Name;
Expires = DateTime.Now + TimeSpan.FromDays(duration);
}
public void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write(Title);
writer.Write(Body1);
writer.Write(Body2);
writer.Write(Body3);
writer.Write(Expires);
writer.Write(ModeratorName);
}
public TownCryerModeratorEntry(GenericReader reader)
{
int version = reader.ReadInt();
Title = reader.ReadString();
Body1 = reader.ReadString();
Body2 = reader.ReadString();
Body3 = reader.ReadString();
Expires = reader.ReadDateTime();
ModeratorName = reader.ReadString();
}
}
}

View File

@@ -0,0 +1,23 @@
using Server;
using System;
namespace Server.Services.TownCryer
{
public class TownCryerNewsEntry
{
public TextDefinition Title { get; set; }
public TextDefinition Body { get; set; }
public int GumpImage { get; set; }
public Type QuestType { get; set; }
public string InfoUrl { get; set; }
public TownCryerNewsEntry(TextDefinition title, TextDefinition body, int gumpImage, Type questType, string url)
{
Title = title;
Body = body;
GumpImage = gumpImage;
QuestType = questType;
InfoUrl = url;
}
}
}

View File

@@ -0,0 +1,760 @@
using Server;
using Server.Engines.CityLoyalty;
using Server.Gumps;
using Server.ContextMenus;
using Server.Guilds;
using Server.Mobiles;
using Server.Engines.Quests;
using Server.Commands;
using Server.Engines.Khaldun;
using Server.Items;
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Globalization;
using System.Collections.Generic;
using System.Linq;
namespace Server.Services.TownCryer
{
public static class TownCryerSystem
{
public static bool Enabled { get; set; }
public static readonly int MaxNewsEntries = 100;
public static readonly int MaxPerGuildEntries = 1;
public static readonly int MaxPerCityGoverrnorEntries = 5;
public static readonly int MaxEMEntries = 15;
public static readonly int MinGuildMemberCount = 20;
public static bool UsePreloadedMessages = false;
public static AccessLevel EMAccess = AccessLevel.Counselor;
public static readonly string EMEventsPage = "https://uo.com/live-events/";
private static string PreLoadedPath = "Data/PreLoadedTC.xml";
public static List<TownCryerGreetingEntry> GreetingsEntries { get; private set; }
//public static List<TextDefinition> GreetingsEntries { get; private set; }
public static List<TownCryerNewsEntry> NewsEntries { get; private set; }
public static List<TownCryerModeratorEntry> ModeratorEntries { get; private set; }
public static List<TownCryerCityEntry> CityEntries { get; private set; }
public static List<TownCryerGuildEntry> GuildEntries { get; private set; }
public static List<PlayerMobile> TownCryerExempt { get; private set; }
public static Dictionary<Mobile, DateTime> MysteriousPotionEffects { get; private set; }
public static Timer Timer { get; private set; }
public static bool NewGreeting { get; private set; }
public static void Configure()
{
GreetingsEntries = new List<TownCryerGreetingEntry>();
ModeratorEntries = new List<TownCryerModeratorEntry>();
CityEntries = new List<TownCryerCityEntry>();
GuildEntries = new List<TownCryerGuildEntry>();
NewsEntries = new List<TownCryerNewsEntry>();
TownCryerExempt = new List<PlayerMobile>();
GreetingsEntries.Add(new TownCryerGreetingEntry(1158955));
/*<center>Rising Tide</center><br><br>The Seas call to us once more! A powerful pirate called Hook has
* taken control of the Guild, an organization of cutthroats and brigands engaged in high seas piracy!
* Great peril stands in the way of those brave enough to challenge Hook's vile plan - read the latest
* headlines in the Town Cryer to learn more!<br><br>The realms tinkers have been busy at work and are
* proud to announce advancements in ship to ship ballistics! The cannon firing process has been streamlined
* - from crafting supplies through loading the cannons and lighting the fuse! FIRE IN THE HOLE!
* <br><br>Whether you are celebrating your first year in Britannia or your 22nd we want to extend a
* very special thank you to our veteran players! New veteran rewards are available! New MONSTER STATUETTES
* featuring Krampus, Khal Ankur, and the Krampus Minion, are available! Decorate your home with the WATER
* WHEEL and personalize your clothes with the EMBROIDERY TOOL. Every crafter will want to get their hands
* on the REPAIR BENCH and TINKER BENCH!*/
GreetingsEntries.Add(new TownCryerGreetingEntry(1158757));
/*Fall is approaching and strangeness is afoot in Britannia!<br><br>Britannians are looking skyward in
* search of constellations and other celestial objects using the new telescope!<br><br>The pumpkin patches
* of Britannia once again bearing fruit as the Grimms hold their carveable pumpkins close!<br><br>Visit a
* cemetery to battle against the Butchers and carve new Jack o' Lantern designs!<br><br>Beware the
* skeletons! Zombie skeletons roam the cemeteries!<br><br>Trick or Treat? Shopkeepers and citizens
* alike have new treats to share!<br><br>Strange events worth investigating? A new article from the
* Town Cryer on the new Royal Britannian Guard Detective Branch!*/
GreetingsEntries.Add(new TownCryerGreetingEntry(1158388));
/* Greetings, Avatar!<br><br>Welcome to Britannia! Whether these are your first steps or you are a
* seasoned veteran King Blackthorn welcomes you! The realm is bustling with opportunities for adventure!
* TownCryers can be visited at all banks and points of interest to learn about the latest goings on in
* the realm. Many guilds are actively recruiting members, so be sure to check the Town Cryer guild
* section for the latest recruitment events. <br><br>We wish you the best of luck in your
* <A HREF="https://uo.com/endless-journey/">Endless Journey</A>*/
LoadPreloadedMessages();
}
public static void Initialize()
{
if (Enabled)
{
EventSink.Login += OnLogin;
NewsEntries.Add(new TownCryerNewsEntry(1159262, 1159263, 0x64E, null, "https://uo.com/wiki/ultima-online-wiki/seasonal-events/halloween-treasures-of-the-sea/")); // Forsaken Foes
NewsEntries.Add(new TownCryerNewsEntry(1158944, 1158945, 0x9CEA, null, "https://uo.com/wiki/ultima-online-wiki/combat/pvm-player-versus-monster/rising-tide/")); // Rising Tide
NewsEntries.Add(new TownCryerNewsEntry(1158552, 1158553, 0x6CE, typeof(GoingGumshoeQuest), null)); // Going Gumshoe
NewsEntries.Add(new TownCryerNewsEntry(1158095, 1158097, 0x61E, null, "https://uo.com/")); // Britain Commons
NewsEntries.Add(new TownCryerNewsEntry(1158089, 1158091, 0x60F, null, "https://uo.com/wiki/ultima-online-wiki/gameplay/npc-commercial-transactions/clean-up-britannia/")); // Cleanup Britannia
NewsEntries.Add(new TownCryerNewsEntry(1158098, 1158100, 0x615, null, "https://uo.com/wiki/ultima-online-wiki/gameplay/crafting/bulk-orders/")); // New Bulk Orders
NewsEntries.Add(new TownCryerNewsEntry(1158101, 1158103, 0x616, null, "https://uo.com/wiki/ultima-online-wiki/a-summary-for-returning-players/weapons-armor-and-loot-revamps-2016/")); // 2016 Loot Revamps
NewsEntries.Add(new TownCryerNewsEntry(1158116, 1158118, 0x64F, null, "https://uo.com/wiki/ultima-online-wiki/gameplay/the-virtues/")); // Virtues
NewsEntries.Add(new TownCryerNewsEntry(1158083, 1158085, 0x617, typeof(TamingPetQuest), "https://uo.com/wiki/ultima-online-wiki/skills/animal-taming/animal-training/")); // Animal Training
NewsEntries.Add(new TownCryerNewsEntry(1158086, 1158088, 0x61D, typeof(ExploringTheDeepQuest), null));
NewsEntries.Add(new TownCryerNewsEntry(1158092, 1158094, 0x651, typeof(HuntmastersChallengeQuest), "https://uo.com/wiki/ultima-online-wiki/gameplay/huntmasters-challenge/")); // Huntsmaster Challenge
NewsEntries.Add(new TownCryerNewsEntry(1158104, 1158106, 0x61C, typeof(PaladinsOfTrinsic), "https://uo.com/wiki/ultima-online-wiki/world/dungeons/dungeon-shame/")); // New Shame
NewsEntries.Add(new TownCryerNewsEntry(1158107, 1158109, 0x61A, typeof(RightingWrongQuest), "https://uo.com/wiki/ultima-online-wiki/world/dungeons/dungeon-wrong/")); // New Wrong
if (TreasureMapInfo.NewSystem)
{
NewsEntries.Add(new TownCryerNewsEntry(1158113, 1158115, 0x64C, typeof(BuriedRichesQuest), "https://uo.com/wiki/ultima-online-wiki/gameplay/treasure-maps/")); // New TMaps
}
NewsEntries.Add(new TownCryerNewsEntry(1158119, 1158121, 0x64D, typeof(APleaFromMinocQuest), "https://uo.com/wiki/ultima-online-wiki/world/dungeons/dungeon-covetous/")); // New Covetous
NewsEntries.Add(new TownCryerNewsEntry(1158110, 1158112, 0x64E, typeof(AVisitToCastleBlackthornQuest), "https://uo.com/wiki/ultima-online-wiki/items/artifacts-castle-blackthorn/")); // Castle Blackthorn
NewsEntries.Add(new TownCryerNewsEntry(1158122, 1158124, 0x650, typeof(WishesOfTheWispQuest), "https://uo.com/wiki/ultima-online-wiki/world/dungeons/dungeon-despise-trammel/")); // New Despise
// New greeting, resets all TC hiding
if (NewGreeting)
{
TownCryerExempt.Clear();
}
if (UsePreloadedMessages)
{
CommandSystem.Register("ReloadTCGreetings", AccessLevel.Administrator, Reload_OnCommand);
}
}
}
public static bool IsExempt(Mobile m)
{
return m is PlayerMobile && TownCryerExempt.Contains((PlayerMobile)m);
}
public static void AddExempt(PlayerMobile pm)
{
if (!TownCryerExempt.Contains(pm))
{
TownCryerExempt.Add(pm);
}
}
public static void AddEntry(TownCryerModeratorEntry entry)
{
ModeratorEntries.Add(entry);
CheckTimer();
}
public static void AddEntry(TownCryerCityEntry entry)
{
CityEntries.Add(entry);
CheckTimer();
}
public static void AddEntry(TownCryerGuildEntry entry)
{
GuildEntries.Add(entry);
CheckTimer();
entry.GetExpiration();
}
public static void AddEntry(TownCryerGreetingEntry entry)
{
GreetingsEntries.Add(entry);
CheckTimer();
}
public static void CompleteQuest(PlayerMobile pm, BaseQuest quest)
{
BaseGump.SendGump(new TownCrierQuestCompleteGump(pm, quest));
}
public static void CompleteQuest(PlayerMobile pm, object title, object body, int gumpID)
{
BaseGump.SendGump(new TownCrierQuestCompleteGump(pm, title, body, gumpID));
}
public static void OnLogin(LoginEventArgs e)
{
if (Enabled && e.Mobile is PlayerMobile && !IsExempt(e.Mobile))
{
Timer.DelayCall<PlayerMobile>(TimeSpan.FromSeconds(1), player =>
{
if (HasCustomEntries())
{
BaseGump.SendGump(new TownCryerGreetingsGump(player, null));
}
else
{
IPooledEnumerable eable = player.Map.GetMobilesInRange(player.Location, 25);
foreach (Mobile m in eable)
{
if (m is TownCrier)
{
BaseGump.SendGump(new TownCryerGreetingsGump(player, (TownCrier)m));
break;
}
}
eable.Free();
}
}, (PlayerMobile)e.Mobile);
}
}
public static int CityEntryCount(City city)
{
return CityEntries.Where(x => x.City == city).Count();
}
public static bool HasGuildEntry(Guild g)
{
if (g == null)
return false;
return GuildEntries.Any(x => x.Guild == g);
}
public static bool HasCustomEntries()
{
return GreetingsEntries.Any(x => x.Saves || x.Expires != DateTime.MinValue);
}
public static void CheckTimer()
{
if (ModeratorEntries.Count > 0 ||
CityEntries.Count > 0 ||
GuildEntries.Count > 0 ||
GreetingsEntries.Any(e => e.Expires != DateTime.MinValue) ||
MysteriousPotionEffects != null)
{
if (Timer == null || !Timer.Running)
{
Timer = Timer.DelayCall(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5), CheckExpiredEntries);
Timer.Priority = TimerPriority.OneMinute;
}
}
else if (Timer != null)
{
Timer.Stop();
Timer = null;
}
}
public static void CheckExpiredEntries()
{
for (int i = GreetingsEntries.Count - 1; i >= 0; i--)
{
if (GreetingsEntries[i].Expires != DateTime.MinValue && GreetingsEntries[i].Expired)
GreetingsEntries.RemoveAt(i);
}
for (int i = ModeratorEntries.Count - 1; i >= 0; i--)
{
if (ModeratorEntries[i].Expired)
ModeratorEntries.RemoveAt(i);
}
for (int i = CityEntries.Count - 1; i >= 0; i--)
{
if (CityEntries[i].Expired)
CityEntries.RemoveAt(i);
}
for (int i = GuildEntries.Count - 1; i >= 0; i--)
{
if (GuildEntries[i].Expired)
GuildEntries.RemoveAt(i);
}
if (MysteriousPotionEffects != null)
{
var list = new List<Mobile>(MysteriousPotionEffects.Keys);
foreach (var m in list)
{
if (MysteriousPotionEffects != null && MysteriousPotionEffects.ContainsKey(m) && MysteriousPotionEffects[m] < DateTime.UtcNow)
{
MysteriousPotionEffects.Remove(m);
if (MysteriousPotionEffects.Count == 0)
{
MysteriousPotionEffects = null;
}
}
}
ColUtility.Free(list);
}
CheckTimer();
}
public static bool IsGovernor(PlayerMobile pm, CityLoyaltySystem system)
{
return system != null && system.Governor == pm;
}
public static void GetContextMenus(TownCrier tc, Mobile from, List<ContextMenuEntry> list)
{
if (from is PlayerMobile)
{
var pm = from as PlayerMobile;
if (pm.AccessLevel >= EMAccess)
{
list.Add(new AddGreetingEntry(tc));
list.Add(new UpdateEMEntry(tc));
}
var system = CityLoyaltySystem.GetCitizenship(pm, false);
if (IsGovernor(pm, system))
{
list.Add(new UpdateCityEntry(tc, system.City));
}
Guild g = pm.Guild as Guild;
if (g != null && pm.GuildRank != null && pm.GuildRank.Rank >= 3 && g.Leader == pm && (pm.AccessLevel > AccessLevel.Player || g.Members.Count >= MinGuildMemberCount))
{
list.Add(new UpdateGuildEntry(from, tc));
}
}
}
public static int GetCityLoc(City city)
{
switch (city)
{
default:
case City.Britain: return 1158043;
case City.Jhelom: return 1158044;
case City.Minoc: return 1158045;
case City.Moonglow: return 1158046;
case City.NewMagincia: return 1158047;
case City.SkaraBrae: return 1158048;
case City.Trinsic: return 1158049;
case City.Vesper: return 1158050;
case City.Yew: return 1158051;
}
}
public static bool UnderMysteriousPotionEffects(Mobile m, bool checkQuest = false)
{
return
MysteriousPotionEffects != null && MysteriousPotionEffects.ContainsKey(m) && MysteriousPotionEffects[m] > DateTime.UtcNow &&
(!checkQuest || (m is PlayerMobile && QuestHelper.HasQuest<AForcedSacraficeQuest2>((PlayerMobile)m)));
}
public static void AddMysteriousPotionEffects(Mobile m)
{
if (MysteriousPotionEffects == null)
{
MysteriousPotionEffects = new Dictionary<Mobile, DateTime>();
}
MysteriousPotionEffects[m] = DateTime.UtcNow + TimeSpan.FromDays(3);
CheckTimer();
}
#region Pre-Loaded
private static void LoadPreloadedMessages()
{
if (!Enabled || !UsePreloadedMessages)
return;
if (File.Exists(PreLoadedPath))
{
XmlDocument doc = new XmlDocument();
Utility.WriteConsoleColor(ConsoleColor.Cyan, "*** Loading Pre-Loaded Town Crier Messages...");
try
{
doc.Load(PreLoadedPath);
}
catch (Exception e)
{
Console.WriteLine(e);
Utility.WriteConsoleColor(ConsoleColor.Cyan, "...FAILED! ***");
return;
}
XmlElement root = doc["preloadedTC"];
int good = 0;
int expired = 0;
int errors = 0;
if (root != null)
{
int index = 0;
foreach (XmlElement reg in root.GetElementsByTagName("message"))
{
string title = Utility.GetText(reg["title"], null);
string body = Utility.GetText(reg["body"], null);
DateTime created = GetDateTime(Utility.GetText(reg["created"], null));
DateTime expires = GetDateTime(Utility.GetText(reg["expires"], null));
string link = Utility.GetText(reg["link"], null);
string linktext = Utility.GetText(reg["linktext"], null);
if (title == null)
{
ErrorToConsole("Invalid title", index);
errors++;
}
else if (body == null)
{
ErrorToConsole("Invalid body", index);
errors++;
}
else if (created == DateTime.MinValue)
{
ErrorToConsole("Invalid creation time", index);
errors++;
}
else if (expires > DateTime.Now || expires == DateTime.MinValue)
{
var entry = new TownCryerGreetingEntry(title, body, -1, link, linktext);
entry.PreLoaded = true;
entry.Created = created;
if (expires > created)
{
entry.Expires = expires;
}
TownCryerSystem.AddEntry(entry);
good++;
}
else
{
ErrorToConsole("Expired message", index);
expired++;
}
index++;
}
}
if (expired > 0 || errors > 0)
{
Utility.WriteConsoleColor(ConsoleColor.Cyan, "...Complete! Loaded {0} Pre-Loaded Messages. {1} expired messages and {2} erroneous messages not loaded! ***", good, expired, errors);
}
else
{
Utility.WriteConsoleColor(ConsoleColor.Cyan, "...Complete! Loaded {0} Pre-Loaded Messages. ***", good);
}
}
}
public static void ErrorToConsole(string type, int index)
{
Utility.WriteConsoleColor(ConsoleColor.Red, "[TC Pre-Loaded Message]: {0} for pre-loaded Message #{1}", type, index.ToString());
}
public static DateTime GetDateTime(string text)
{
DateTime datetime = DateTime.MinValue;
try
{
datetime = DateTime.Parse(text, CultureInfo.CreateSpecificCulture("en-US"));
}
catch
{
}
return datetime;
}
[Usage("ReloadTCGreetings")]
[Description("Reloads Pre-Loaded Town Cryer Messages. This enables changes to be made to the PreLoadedTC.xml and show in game without a server restart.")]
public static void Reload_OnCommand(CommandEventArgs e)
{
bool clear = false;
GreetingsEntries.IterateReverse(entry =>
{
if (entry.PreLoaded)
{
GreetingsEntries.Remove(entry);
if (!clear)
clear = true;
}
});
LoadPreloadedMessages();
if (clear)
{
TownCryerExempt.Clear();
}
e.Mobile.SendMessage("Pre-Loaded TC messages re-loaded from {0}!", PreLoadedPath);
}
#endregion
public static void Save(GenericWriter writer)
{
writer.Write(1);
writer.Write(GreetingsEntries.Count);
writer.Write(TownCryerExempt.Count);
foreach (var pm in TownCryerExempt)
writer.Write(pm);
writer.Write(GreetingsEntries.Where(x => x.Saves).Count());
foreach (var e in GreetingsEntries.Where(x => x.Saves))
e.Serialize(writer);
writer.Write(ModeratorEntries.Count);
foreach (var e in ModeratorEntries)
e.Serialize(writer);
writer.Write(CityEntries.Count);
foreach (var e in CityEntries)
e.Serialize(writer);
writer.Write(GuildEntries.Count);
foreach (var e in GuildEntries)
e.Serialize(writer);
writer.Write(MysteriousPotionEffects != null ? MysteriousPotionEffects.Count : 0);
if (MysteriousPotionEffects != null)
{
foreach (var kvp in MysteriousPotionEffects)
{
writer.Write(kvp.Key);
writer.Write(kvp.Value);
}
}
}
public static void Load(GenericReader reader)
{
int version = reader.ReadInt();
int greetingsCount = 0;
switch (version)
{
case 1:
greetingsCount = reader.ReadInt();
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
var pm = reader.ReadMobile() as PlayerMobile;
if (pm != null)
{
AddExempt(pm);
}
}
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
var entry = new TownCryerGreetingEntry(reader);
if (!entry.Expired)
{
GreetingsEntries.Add(entry);
}
}
goto case 0;
case 0:
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
var entry = new TownCryerModeratorEntry(reader);
if (!entry.Expired)
{
ModeratorEntries.Add(entry);
}
}
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
var entry = new TownCryerCityEntry(reader);
if (!entry.Expired)
{
CityEntries.Add(entry);
}
}
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
var entry = new TownCryerGuildEntry(reader);
if (!entry.Expired)
{
GuildEntries.Add(entry);
}
}
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
Mobile m = reader.ReadMobile();
DateTime dt = reader.ReadDateTime();
if (m != null)
{
if (MysteriousPotionEffects == null)
MysteriousPotionEffects = new Dictionary<Mobile, DateTime>();
MysteriousPotionEffects[m] = dt;
}
}
break;
}
if (greetingsCount < GreetingsEntries.Count)
{
NewGreeting = true;
}
CheckTimer();
}
}
public class AddGreetingEntry : ContextMenuEntry
{
public TownCrier Cryer { get; set; }
public AddGreetingEntry(TownCrier cryer)
: base(1011405, 3) // Change Greeting
{
Cryer = cryer;
}
public override void OnClick()
{
if (Owner.From is PlayerMobile && Owner.From.AccessLevel >= AccessLevel.GameMaster)
{
//BaseGump.SendGump(new CreateGreetingEntryGump((PlayerMobile)Owner.From, Cryer));
BaseGump.SendGump(new TownCryerGreetingsGump((PlayerMobile)Owner.From, Cryer));
}
}
}
public class UpdateEMEntry : ContextMenuEntry
{
public TownCrier Cryer { get; set; }
public UpdateEMEntry(TownCrier cryer)
: base(1158022, 3) // Update EM Town Crier
{
Cryer = cryer;
Enabled = TownCryerSystem.ModeratorEntries.Count < TownCryerSystem.MaxEMEntries;
}
public override void OnClick()
{
if (Owner.From is PlayerMobile)
{
if (TownCryerSystem.ModeratorEntries.Count < TownCryerSystem.MaxEMEntries)
{
BaseGump.SendGump(new CreateEMEntryGump((PlayerMobile)Owner.From, Cryer));
}
else
{
Owner.From.SendLocalizedMessage(1158038); // You have reached the maximum entry count. Please remove some and try again.
}
}
}
}
public class UpdateCityEntry : ContextMenuEntry
{
public City City { get; set; }
public TownCrier Cryer { get; set; }
public UpdateCityEntry(TownCrier cryer, City city)
: base(1158023, 3) // Update City Town Crier
{
Cryer = cryer;
City = city;
}
public override void OnClick()
{
if (Owner.From is PlayerMobile)
{
var pm = Owner.From as PlayerMobile;
var system = CityLoyaltySystem.GetCitizenship(pm, false);
if (TownCryerSystem.IsGovernor(pm, system))
{
if (TownCryerSystem.CityEntryCount(system.City) < TownCryerSystem.MaxPerCityGoverrnorEntries)
{
BaseGump.SendGump(new CreateCityEntryGump(pm, Cryer, system.City));
}
else
{
pm.SendLocalizedMessage(1158038); // You have reached the maximum entry count. Please remove some and try again.
}
}
}
}
}
public class UpdateGuildEntry : ContextMenuEntry
{
public TownCrier Cryer { get; set; }
public UpdateGuildEntry(Mobile from, TownCrier cryer)
: base(1158024, 3) // Update Guild Town Crier
{
Cryer = cryer;
Enabled = from.Guild != null && !TownCryerSystem.HasGuildEntry(from.Guild as Guild);
}
public override void OnClick()
{
PlayerMobile pm = Owner.From as PlayerMobile;
if(pm != null)
{
Guild g = pm.Guild as Guild;
if (g != null && pm.GuildRank != null && pm.GuildRank.Rank >= 3 && (pm.AccessLevel > AccessLevel.Player || g.Members.Count >= TownCryerSystem.MinGuildMemberCount))
{
if (TownCryerSystem.HasGuildEntry(g))
{
Owner.From.SendLocalizedMessage(1158038); // You have reached the maximum entry count. Please remove some and try again.
}
else
{
BaseGump.SendGump(new CreateGuildEntryGump(pm, Cryer));
}
}
else
{
pm.SendLocalizedMessage(1158025); // Only Guild Leaders and Warlords of guilds with at least 20 members may post in the Town Cryer.
}
}
}
}
}