761 lines
29 KiB
C#
761 lines
29 KiB
C#
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.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|