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,77 @@
using System;
using Server;
using Server.Mobiles;
using Server.Engines.Points;
using System.Collections.Generic;
using System.Linq;
namespace Server.Engines.CityLoyalty
{
[PropertyObject]
public class CityDefinition
{
[CommandProperty(AccessLevel.GameMaster)]
public City City { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public Point3D StoneLocation { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public Point3D TradeMinisterLocation { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public Point3D HeraldLocation { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public Point3D GuardsmanLocation { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public Point3D BoardLocation { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public string Name { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public int LocalizedName { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public int BattleMessage { get; private set; }
private Region _Region;
[CommandProperty(AccessLevel.GameMaster)]
public Region Region
{
get
{
if (_Region == null)
{
_Region = Region.Regions.FirstOrDefault(r => r.Name == Name && r.Map == CityLoyaltySystem.SystemMap);
if(_Region == null)
Console.WriteLine("WARNING: Region for {0} not found!", Name);
}
return _Region;
}
}
public override string ToString()
{
return "...";
}
public CityDefinition(City city, Point3D stoneLoc, Point3D tradeloc, Point3D heraldLoc, Point3D guardsmanloc, Point3D boardloc, string name, int locname, int battleloc)
{
City = city;
StoneLocation = stoneLoc;
TradeMinisterLocation = tradeloc;
HeraldLocation = heraldLoc;
GuardsmanLocation = guardsmanloc;
BoardLocation = boardloc;
Name = name;
LocalizedName = locname;
BattleMessage = battleloc;
}
}
}

View File

@@ -0,0 +1,191 @@
using System;
using Server;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Engines.Points;
using System.Collections.Generic;
using System.Linq;
namespace Server.Engines.CityLoyalty
{
[PropertyObject]
public class CityLoyaltyEntry : PointsEntry
{
[CommandProperty(AccessLevel.GameMaster)]
public int Love { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Hate { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Neutrality { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public CityTitle Titles { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool IsCitizen { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public City City { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public string CustomTitle { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool ShowGainMessage { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public LoyaltyRating LoyaltyRating
{
get
{
return CityLoyaltySystem.GetCityInstance(City).GetLoyaltyRating(Player, this);
}
}
private bool _Utilizing;
[CommandProperty(AccessLevel.GameMaster)]
public bool UtilizingTradeDeal
{
get
{
return _Utilizing;
}
set
{
if (Player == null)
return;
if (!_Utilizing && value)
TradeDealExpires = DateTime.UtcNow + TimeSpan.FromHours(CityLoyaltySystem.TradeDealUtilizationPeriod);
if (_Utilizing && !value)
{
BuffInfo.RemoveBuff(Player, BuffIcon.CityTradeDeal);
CityLoyaltySystem.RemoveTradeDeal(Player);
if (Player.NetState != null)
{
Player.SendLocalizedMessage(1154074); // The benefit from your City's Trade Deal has expired! Visit the City Stone to reclaim it.
}
Player.Delta(MobileDelta.WeaponDamage);
}
_Utilizing = value;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public DateTime TradeDealExpires { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool TradeDealExpired { get { return TradeDealExpires < DateTime.UtcNow; } }
public CityLoyaltyEntry(PlayerMobile pm, City city) : base(pm)
{
City = city;
ShowGainMessage = true;
}
public override string ToString()
{
return String.Format("{0} {1}", City.ToString(), IsCitizen ? "[Citizen]" : String.Empty);
}
public void DeclareCitizenship()
{
IsCitizen = true;
AddTitle(CityTitle.Citizen);
}
public void RenounceCitizenship()
{
foreach (int i in Enum.GetValues(typeof(CityTitle)))
{
Player.RemoveRewardTitle(CityLoyaltySystem.GetTitleLocalization(Player, (CityTitle)i, City), true);
}
CustomTitle = null;
Player.RemoveRewardTitle(1154017, true);
IsCitizen = false;
Titles = CityTitle.None;
}
public virtual void AddTitle(CityTitle title)
{
if ((Titles & title) == 0)
{
int loc = CityLoyaltySystem.GetTitleLocalization(Player, title, City);
Player.AddRewardTitle(loc);
Titles |= title;
Player.SendLocalizedMessage(1073625, String.Format("#{0}", loc.ToString())); // The title "~1_TITLE~" has been bestowed upon you.
}
}
public void CheckTradeDeal()
{
if (TradeDealExpired)
{
UtilizingTradeDeal = false;
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1);
writer.Write(ShowGainMessage);
writer.Write(Love);
writer.Write(Hate);
writer.Write(Neutrality);
writer.Write((int)Titles);
writer.Write(TradeDealExpires);
writer.Write(_Utilizing);
writer.Write(CustomTitle);
writer.Write(IsCitizen);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
ShowGainMessage = reader.ReadBool();
goto case 0;
case 0:
{
if (version == 0)
{
ShowGainMessage = true;
}
Love = reader.ReadInt();
Hate = reader.ReadInt();
Neutrality = reader.ReadInt();
Titles = (CityTitle)reader.ReadInt();
TradeDealExpires = reader.ReadDateTime();
_Utilizing = reader.ReadBool();
CustomTitle = reader.ReadString();
CheckTradeDeal();
IsCitizen = reader.ReadBool();
}
break;
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,659 @@
using System;
using Server;
using Server.Mobiles;
using Server.Items;
using System.Collections.Generic;
using System.Globalization;
using Server.Accounting;
using System.Linq;
using Server.Gumps;
namespace Server.Engines.CityLoyalty
{
[PropertyObject]
public class CityElection
{
public static readonly int VotePeriod = 7;
public static readonly int NominationDeadline = 24;
[CommandProperty(AccessLevel.GameMaster)]
public CityLoyaltySystem City { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool ElectionEnded { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool Ongoing { get { return CanNominate() || CanVote(); } }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime AutoPickGovernor { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public string Time1
{
get { return StartTimes.Length > 0 ? StartTimes[0].ToShortDateString() : "Empty"; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Time2
{
get { return StartTimes.Length > 1 ? StartTimes[1].ToShortDateString() : "Empty"; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Time3
{
get { return StartTimes.Length > 2 ? StartTimes[2].ToShortDateString() : "Empty"; }
}
[CommandProperty(AccessLevel.GameMaster)]
public string Time4
{
get { return StartTimes.Length > 3 ? StartTimes[3].ToShortDateString() : "Empty"; }
}
public List<BallotEntry> Candidates { get; set; }
public DateTime[] StartTimes { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool ForceStart
{
get { return false; }
set
{
if (value)
{
if (Ongoing)
EndElection();
StartTimes = new DateTime[1];
StartTimes[0] = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
}
}
}
public override string ToString()
{
return "...";
}
public CityElection(CityLoyaltySystem city)
{
City = city;
ElectionEnded = true;
Candidates = new List<BallotEntry>();
GetDefaultStartTimes();
}
public bool TryNominate(PlayerMobile pm)
{
CityLoyaltyEntry pentry = City.GetPlayerEntry<CityLoyaltyEntry>(pm);
if (pm.Young)
pm.SendMessage("Young players cannot be nominated for the ballot!");
else if (!City.IsCitizen(pm) || pentry == null)
pm.SendLocalizedMessage(1153890); // You must be a citizen of this City to nominate yourself for the ballot!
else if (City.GetLoyaltyRating(pm) < LoyaltyRating.Adored)
pm.SendLocalizedMessage(1153891); // You must at least be adored within the City to nominate yourself for the ballot.
else
{
Account a = pm.Account as Account;
for (int i = 0; i < a.Length; i++)
{
Mobile m = a[i];
if(!(m is PlayerMobile))
continue;
BallotEntry ballot = Candidates.FirstOrDefault(entry => entry.Player == m);
if (ballot != null && m is PlayerMobile)
{
pm.SendLocalizedMessage(ballot.Endorsements.Count > 0 ? 1153917 : 1153889); // A character from this account is currently endorsed for Candidacy and cannot be nominated. // A character from this account has already been nominated to run for office.
return false; // A character from this account has already been nominated to run for office.
}
ballot = Candidates.FirstOrDefault(entry => entry.Endorsements.Contains(m));
if (ballot != null && m is PlayerMobile)
{
pm.SendLocalizedMessage(1153892); // A character from this account has already endorsed a nominee!
return false;
}
}
Candidates.Add(new BallotEntry(pm, pentry.Love, pentry.Hate));
pm.PrivateOverheadMessage(Network.MessageType.Regular, 0x3B2, 1153905, pm.NetState); // *You etch your name into the stone*
pm.SendLocalizedMessage(1154087); // You have 24 hours to get your nomination endorsed. If you do not get an endorsement within that period you will need to re-nominate yourself.
return true;
}
return false;
}
public bool TryEndorse(PlayerMobile pm, PlayerMobile nominee)
{
if (pm.Young)
pm.SendMessage("Young players cannot endorose an nominee!");
else if (!City.IsCitizen(pm))
pm.SendLocalizedMessage(1153893); // You must be a citizen of this City to endorse a nominee for the ballot!
else
{
Account a = pm.Account as Account;
for (int i = 0; i < a.Length; i++)
{
Mobile m = a[i];
if(!(m is PlayerMobile))
continue;
BallotEntry ballot = Candidates.FirstOrDefault(entry => entry.Endorsements.Contains(m as PlayerMobile));
if (m is PlayerMobile && ballot != null)
{
pm.SendLocalizedMessage(1153892); // A character from this account has already endorsed a nominee!
return false;
}
BallotEntry ballot2 = Candidates.FirstOrDefault(entry => entry.Player == m);
if (m is PlayerMobile && ballot2 != null)
{
pm.SendLocalizedMessage(1153912); // A character from this account is currently nominated for candidacy and cannot offer an endorsement.
return false;
}
}
BallotEntry pentry = Candidates.FirstOrDefault(e => e.Player == nominee);
if (pentry != null)
{
//<CENTER>Are you sure you wish to endorse this nominee? All endorsements are final and cannot be changed!</CENTER>
pm.SendGump(new ConfirmCallbackGump(pm, null, 1154091, pentry, null, (m, o) =>
{
BallotEntry e = o as BallotEntry;
e.Endorsements.Add(m as PlayerMobile);
m.PrivateOverheadMessage(Network.MessageType.Regular, 0x3B2, 1153913, m.NetState); // *You etch your endorsement for the nominee into the stone*
}));
return true;
}
}
return false;
}
public bool TryVote(PlayerMobile voter, PlayerMobile candidate)
{
if (!CanVote())
voter.SendLocalizedMessage(1153919); // The stone is not currently accepting votes.
else if (voter.Young)
voter.SendMessage("Young players cannot vote in a city election!");
else if (!City.IsCitizen(voter))
voter.SendLocalizedMessage(1153894); // You must be a citizen of this City to vote!
else if (City.GetLoyaltyRating(voter) < LoyaltyRating.Respected)
voter.SendLocalizedMessage(1154579); // You must be at least respected within the city to vote.
else
{
Account a = voter.Account as Account;
for (int i = 0; i < a.Length; i++)
{
Mobile m = a[i];
if (m is PlayerMobile && Candidates.FirstOrDefault(e => e.Votes.Contains(m)) != null)
{
voter.SendLocalizedMessage(1153922); // This account has already cast a vote in this election. You may only vote once.
return false;
}
}
BallotEntry pentry = Candidates.FirstOrDefault(e => e.Player == candidate);
if (pentry != null)
{
//<CENTER>Are you sure you wish to cast your vote for this candidate? All votes are final and cannot be changed!</CENTER>
voter.SendGump(new ConfirmCallbackGump(voter, null, 1153921, pentry, null, (m, o) =>
{
BallotEntry e = o as BallotEntry;
e.Votes.Add(voter);
m.PrivateOverheadMessage(Network.MessageType.Regular, 0x3B2, 1153923, voter.NetState); // *You etch your vote into the stone*
}));
}
}
return false;
}
public void TryWithdraw(PlayerMobile pm)
{
BallotEntry entry = Candidates.FirstOrDefault(e => e.Player == pm);
if (entry != null)
{
//Are you sure you wish to withdrawal?
pm.SendGump(new ConfirmCallbackGump(pm, null, 1153918, entry, null, (m, o) =>
{
BallotEntry e = (BallotEntry)o;
if (Candidates.Contains(e))
{
Candidates.Remove(e);
m.PrivateOverheadMessage(Network.MessageType.Regular, 0x3B2, 1153911, m.NetState); // *You smudge your name off the stone*
}
}));
}
else
pm.SendLocalizedMessage(1153924); // You are not currently on any ballot to withdraw from.
}
public double GetStanding(BallotEntry entry)
{
if (Candidates.Contains(entry))
{
if (entry.Votes.Count <= 0)
return 0.0;
return (entry.Votes.Count / GetTotalVotes()) * 100;
}
return 0.0;
}
public int GetTotalVotes()
{
int votes = 0;
Candidates.ForEach(c =>
{
votes += c.Votes.Count;
});
return votes;
}
public void OnTick()
{
foreach(DateTime dt in StartTimes)
{
if (dt.Year == DateTime.Now.Year && DateTime.Now.Month == dt.Month && DateTime.Now.Day > 14 && !ElectionEnded)
{
EndElection();
}
else if (dt.Year == DateTime.Now.Year && DateTime.Now.Month == dt.Month && DateTime.Now.Day == dt.Day && ElectionEnded)
{
StartNewElection();
}
}
if (City.Governor == null && AutoPickGovernor != DateTime.MinValue && DateTime.Now > AutoPickGovernor)
{
if (City.GovernorElect != null)
{
if (Candidates.Count > 0)
{
BallotEntry entry = Candidates.FirstOrDefault(c => c.Player == City.GovernorElect);
if (entry != null)
Candidates.Remove(entry);
}
City.GovernorElect = null;
}
if (Candidates.Count > 0)
{
Candidates.Sort();
City.GovernorElect = Candidates[0].Player;
}
AutoPickGovernor = DateTime.MinValue;
}
if (CanNominate())
{
Candidates.ForEach(entry =>
{
if (entry.TimeOfNomination + TimeSpan.FromHours(NominationDeadline) < DateTime.Now && entry.Endorsements.Count == 0)
Candidates.Remove(entry);
});
}
}
public void StartNewElection()
{
ElectionEnded = false;
Candidates.Clear();
Candidates.TrimExcess();
AutoPickGovernor = DateTime.MinValue;
}
private static int[] _Periods = { 3, 6, 9, 12 };
public void GetDefaultStartTimes()
{
StartTimes = new DateTime[4];
for(int i = 0; i < _Periods.Length; i++)
{
DateTime dt = new DateTime(DateTime.Now.Year, _Periods[i], 1);
if (dt < DateTime.Now)
dt = new DateTime(dt.Year + 1, dt.Month, dt.Day);
StartTimes[i] = dt;
}
}
public static DateTime[] ValidateStartTimes(Mobile m, int[] times)
{
if (times != null && times.Length > 0)
{
DateTime[] starttimes = new DateTime[times.Length];
for (int i = 0; i < times.Length; i++)
{
int month = times[i];
if (month <= 0 || month > 12)
{
m.SendMessage("Invalid month for #{0}. It must be between 0 and 12.", i + 1);
return null;
}
DateTime dt = new DateTime(DateTime.Now.Year, month, 1);
if (dt < DateTime.Now)
dt = new DateTime(dt.Year + 1, dt.Month, dt.Day);
starttimes[i] = dt;
}
if (CheckConflict(starttimes))
{
m.SendMessage("times are too close to another start time. Please try again.");
return null;
}
return starttimes;
}
return null;
}
public static bool CheckConflict(DateTime[] times)
{
if (times == null || times.Length == 0)
return false;
for(int i = 0; i < times.Length; i++)
{
DateTime t = times[i];
for (int j = 0; j < times.Length; j++)
{
if (i == j)
continue;
if ((times[j] > t && times[j] - t < TimeSpan.FromDays(30)) || times[j] < t && t - times[j] < TimeSpan.FromDays(30))
return true;
}
}
return false;
}
public DateTime NextElection()
{
if (CanNominate() || CanVote())
return DateTime.MinValue;
DateTime closest = DateTime.MinValue;
foreach (DateTime dt in StartTimes)
{
if (DateTime.Now < dt)
{
if (closest == DateTime.MinValue || dt - DateTime.Now < closest - DateTime.Now)
{
closest = dt;
}
}
}
return closest;
}
public bool CanNominate()
{
DateTime until = DateTime.MinValue;
return CanNominate(out until);
}
public bool CanNominate(out DateTime until)
{
until = DateTime.Now;
foreach (DateTime dt in StartTimes)
{
if (dt.Year == DateTime.Now.Year && DateTime.Now.Month == dt.Month && DateTime.Now <= dt.AddDays(VotePeriod))
{
until = dt.AddDays(VotePeriod);
return true;
}
}
return false;
}
public bool CanVote()
{
DateTime until = DateTime.MinValue;
return CanVote(out until);
}
public bool CanVote(out DateTime until)
{
until = DateTime.Now;
foreach (DateTime dt in StartTimes)
{
if (dt.Year == DateTime.Now.Year && DateTime.Now.Month == dt.Month && DateTime.Now > dt.AddDays(VotePeriod) && DateTime.Now <= dt.AddDays(VotePeriod * 2))
{
until = dt.AddDays(VotePeriod * 2);
return true;
}
}
return false;
}
public void EndElection()
{
ElectionEnded = true;
if (Candidates.Count > 0)
{
Candidates.Sort();
City.GovernorElect = Candidates[0].Player;
AutoPickGovernor = DateTime.Now + TimeSpan.FromDays(7);
}
if (City.GovernorElect == null)
{
City.PendingGovernor = true;
AutoPickGovernor = DateTime.Now + TimeSpan.FromDays(Utility.RandomMinMax(2, 4));
if (City.Stone != null)
City.Stone.InvalidateProperties();
}
for(int i = 0; i < StartTimes.Length; i++)
{
DateTime dt = StartTimes[i];
if (dt == DateTime.MinValue)
continue;
if (dt < DateTime.Now)
dt = new DateTime(dt.Year + 1, dt.Month, dt.Day);
}
}
public void OnRejectOffice(PlayerMobile pm)
{
BallotEntry entry = Candidates.FirstOrDefault(c => c.Player == pm);
if (entry != null)
Candidates.Remove(entry);
AutoPickGovernor = DateTime.Now + TimeSpan.FromDays(Utility.RandomMinMax(2, 4));
}
public void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write(ElectionEnded);
writer.Write(AutoPickGovernor);
writer.Write(StartTimes.Length);
foreach (DateTime dt in StartTimes)
writer.Write(dt);
writer.Write(Candidates.Count);
Candidates.ForEach(entry => entry.Serialize(writer));
}
public CityElection(CityLoyaltySystem city, GenericReader reader)
{
City = city;
Candidates = new List<BallotEntry>();
int version = reader.ReadInt();
ElectionEnded = reader.ReadBool();
AutoPickGovernor = reader.ReadDateTime();
int c = reader.ReadInt();
StartTimes = new DateTime[c];
for (int i = 0; i < c; i++)
{
DateTime time = reader.ReadDateTime();
if (time < DateTime.Now && ElectionEnded)
time = new DateTime(time.Year + 1, time.Month, time.Day);
StartTimes[i] = time;
}
c = reader.ReadInt();
for (int i = 0; i < c; i++)
{
BallotEntry entry = new BallotEntry(reader);
if (entry.Player != null)
Candidates.Add(entry);
}
}
}
public class BallotEntry : IComparable<BallotEntry>
{
public PlayerMobile Player { get; set; }
public DateTime TimeOfNomination { get; set; }
public int Love { get; set; }
public int Hate { get; set; }
public List<PlayerMobile> Endorsements { get; set; }
public List<PlayerMobile> Votes { get; set; }
public BallotEntry(PlayerMobile pm, int love, int hate)
{
Player = pm;
TimeOfNomination = DateTime.Now;
Love = love;
Hate = hate;
Endorsements = new List<PlayerMobile>();
Votes = new List<PlayerMobile>();
}
public int CompareTo(BallotEntry entry)
{
if (Player == null)
return -1;
if (Votes.Count > entry.Votes.Count)
return 1;
else if (Votes.Count < entry.Votes.Count)
return -1;
else
{
if (Love > entry.Love || Hate < entry.Hate)
return 1;
else if (Love == entry.Love && Hate == entry.Hate && Utility.RandomBool())
return 1;
else
return -1;
}
}
public void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write(Player);
writer.Write(TimeOfNomination);
writer.Write(Love);
writer.Write(Hate);
writer.Write(Endorsements.Count);
Endorsements.ForEach(p => writer.Write(p));
writer.Write(Votes.Count);
Votes.ForEach(p => writer.Write(p));
}
public BallotEntry(GenericReader reader)
{
Endorsements = new List<PlayerMobile>();
Votes = new List<PlayerMobile>();
int version = reader.ReadInt();
Player = reader.ReadMobile() as PlayerMobile;
TimeOfNomination = reader.ReadDateTime();
Love = reader.ReadInt();
Hate = reader.ReadInt();
int c = reader.ReadInt();
for (int i = 0; i < c; i++)
{
PlayerMobile p = reader.ReadMobile() as PlayerMobile;
if (p != null)
Endorsements.Add(p);
}
c = reader.ReadInt();
for (int i = 0; i < c; i++)
{
PlayerMobile p = reader.ReadMobile() as PlayerMobile;
if (p != null)
Votes.Add(p);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,233 @@
using Server;
using System;
using Server.Mobiles;
using Server.Targeting;
using Server.Gumps;
using Server.Network;
using Server.Multis;
namespace Server.Items
{
public abstract class InterchangeableAddonDeed : BaseAddonDeed
{
// This will need to be further implemented in any derived class
public override BaseAddon Addon { get { return null; } }
public abstract int EastID { get; }
public abstract int SouthID { get; }
public InterchangeableAddonDeed()
{
}
public override void OnDoubleClick(Mobile from)
{
if ( IsChildOf( from.Backpack ) )
from.Target = new InternalTarget( this );
else
from.SendLocalizedMessage( 1042001 ); // That must be in your pack for you to use it.
}
private class InternalTarget : Target
{
public InterchangeableAddonDeed Deed { get; set; }
public InternalTarget(InterchangeableAddonDeed deed) : base( -1, true, TargetFlags.None )
{
Deed = deed;
}
protected override void OnTarget( Mobile from, object targeted )
{
IPoint3D p = targeted as IPoint3D;
Map map = from.Map;
if(p == null || map == null || Deed.Deleted)
return;
AddonFitResult result = AddonFitResult.Valid;
if(Deed.IsChildOf(from.Backpack))
{
BaseHouse house = null;
if ( !map.CanFit( p.X, p.Y, p.Z, 16, false, true, false ) )
result = AddonFitResult.Blocked;
else if ( !BaseAddon.CheckHouse( from, new Point3D(p), map, 16, ref house ) )
result = AddonFitResult.NotInHouse;
else
{
bool east = BaseAddon.IsWall(p.X - 1, p.Y, p.Z, map);
bool south = BaseAddon.IsWall(p.X, p.Y - 1, p.Z, map);
if(!south && !east)
result = AddonFitResult.NoWall;
else if (south && east)
from.SendGump(new AddonInterchangeableGump(from, Deed, p, map));
else
{
BaseAddon addon = Deed.DeployAddon(east, p, map);
house.Addons[addon] = from;
}
}
switch (result)
{
default: break;
case AddonFitResult.Blocked: from.SendLocalizedMessage(500269); break; // You cannot build that there.
case AddonFitResult.NotInHouse: from.SendLocalizedMessage(500274); break; // You can only place this in a house that you own!
case AddonFitResult.NoWall: from.SendLocalizedMessage(500268); break; // This object needs to be mounted on something.
}
}
else
{
from.SendLocalizedMessage( 1042001 ); // That must be in your pack for you to use it.
}
}
}
public virtual BaseAddon DeployAddon(bool east, IPoint3D p, Map map)
{
BaseAddon addon = Addon;
if(addon != null)
{
if(addon is InterchangeableAddon)
((InterchangeableAddon)addon).EastFacing = east;
Server.Spells.SpellHelper.GetSurfaceTop( ref p );
addon.MoveToWorld(new Point3D(p), map);
Delete();
}
return addon;
}
public InterchangeableAddonDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public abstract class InterchangeableAddon : BaseAddon
{
private bool _EastFacing;
[CommandProperty(AccessLevel.GameMaster)]
public bool EastFacing
{
get
{
return _EastFacing;
}
set
{
if(Components.Count == 1)
{
if(value)
{
Components[0].ItemID = EastID;
}
else
{
Components[0].ItemID = SouthID;
}
}
_EastFacing = value;
}
}
public abstract int EastID { get; }
public abstract int SouthID { get; }
// This will need to be further implemented in any derived class
public override BaseAddonDeed Deed { get { return null; } }
public InterchangeableAddon(bool eastface = true, int loc = 0)
{
if(loc != 0)
AddComponent(new LocalizedAddonComponent(eastface ? EastID : SouthID, loc), 0, 0, 0);
else
AddComponent(new AddonComponent(eastface ? EastID : SouthID), 0, 0, 0);
}
public InterchangeableAddon(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class AddonInterchangeableGump : Gump
{
public InterchangeableAddonDeed Deed { get; private set; }
public IPoint3D Point { get; private set; }
public Map Map { get; private set; }
public AddonInterchangeableGump(Mobile user, InterchangeableAddonDeed deed, IPoint3D p, Map map) : base(50, 50)
{
Deed = deed;
Point = p;
Map = map;
AddGumpLayout();
}
public void AddGumpLayout()
{
AddBackground(0, 0, 300, 200, 2600);
AddHtmlLocalized(0, 15, 300, 16, 1152360, false, false); // <CENTER>Choose a banner:</CENTER>
Rectangle2D b = ItemBounds.Table[Deed.EastID];
AddItem(70 - b.Width / 2 - b.X, 75 - b.Height / 2 - b.Y, Deed.EastID);
b = ItemBounds.Table[Deed.SouthID];
AddItem(180 - b.Width / 2 - b.X, 75 - b.Height / 2 - b.Y, Deed.SouthID);
AddButton(75, 50, 2103, 2104, 1, GumpButtonType.Reply, 0);
AddButton(205, 50, 2103, 2104, 2, GumpButtonType.Reply, 0);
}
public override void OnResponse(NetState state, RelayInfo info)
{
if (!state.Mobile.InRange(Point, 3))
{
state.Mobile.SendLocalizedMessage(500251); // That location is too far away.
}
else if (info.ButtonID == 1)
{
Deed.DeployAddon(true, Point, Map);
}
else if (info.ButtonID == 2)
{
Deed.DeployAddon(false, Point, Map);
}
}
}
}

View File

@@ -0,0 +1,122 @@
using Server.Items;
using Server.Mobiles;
using Server.Targeting;
using System;
using System.Collections.Generic;
namespace Server.Engines.CityLoyalty
{
public class CityBanner : InterchangeableAddon
{
public override BaseAddonDeed Deed { get { return new CityBannerDeed(City); } }
public override bool ForceShowProperties { get { return true; } }
[CommandProperty(AccessLevel.GameMaster)]
public City City { get; private set; }
public override int EastID { get { return SouthID + 9; } }
public override int SouthID { get { return BannerInfo[City][0]; } }
[Constructable]
public CityBanner(City city)
: base(true, BannerInfo[city][1])
{
City = city;
}
public static Dictionary<City, int[]> BannerInfo { get; set; }
public static void Initialize()
{
BannerInfo = new Dictionary<City, int[]>();
//ID Cliloc
BannerInfo[City.Moonglow] = new int[] { 0x4B63, 1098171 };
BannerInfo[City.Britain] = new int[] { 0x4B64, 1098172 };
BannerInfo[City.Jhelom] = new int[] { 0x4B65, 1098173 };
BannerInfo[City.Yew] = new int[] { 0x4B66, 1098174 };
BannerInfo[City.Minoc] = new int[] { 0x4B67, 1098175 };
BannerInfo[City.Trinsic] = new int[] { 0x4B62, 1098170 };
BannerInfo[City.SkaraBrae] = new int[] { 0x4B6A, 1098178 };
BannerInfo[City.NewMagincia] = new int[] { 0x4B69, 1098177 };
BannerInfo[City.Vesper] = new int[] { 0x4B68, 1098176 };
}
public CityBanner(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write((int)City);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
City = (City)reader.ReadInt();
}
}
public class CityBannerDeed : InterchangeableAddonDeed
{
public override BaseAddon Addon { get { return new CityBanner(City); } }
public override int LabelNumber { get { return CityBanner.BannerInfo[City][1]; } }
public override int EastID { get { return SouthID + 9; } }
public override int SouthID { get { return CityBanner.BannerInfo[City][0]; } }
[CommandProperty(AccessLevel.GameMaster)]
public City City { get; private set; }
[Constructable]
public CityBannerDeed(City city)
{
City = city;
LootType = LootType.Blessed;
}
public override void OnDoubleClick(Mobile from)
{
if (IsChildOf(from.Backpack))
{
CityLoyaltySystem sys = CityLoyaltySystem.GetCityInstance(this.City);
if (CityLoyaltySystem.HasCitizenship(from, this.City) && sys.GetLoyaltyRating(from) >= LoyaltyRating.Commended)
{
base.OnDoubleClick(from);
}
else
from.SendLocalizedMessage(1152361, String.Format("#{0}", CityLoyaltySystem.GetCityLocalization(this.City))); // You are not sufficiently loyal to ~1_CITY~ to use this.
}
}
public CityBannerDeed(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write((int)City);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
City = (City)reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,95 @@
using System;
using Server;
using Server.Mobiles;
using System.Collections.Generic;
using Server.Engines.CityLoyalty;
using System.Linq;
namespace Server.Items
{
public class BoxOfRopes : Container
{
public City City { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public CityLoyaltySystem CitySystem { get { return CityLoyaltySystem.GetCityInstance(City); } set { } }
public override int LabelNumber { get { return 1152262; } } // a box of ropes
public BoxOfRopes(City city) : base(3650)
{
Hue = 1944;
Movable = false;
City = city;
if (CitySystem != null && CitySystem.Captain != null)
CitySystem.Captain.Box = this;
}
public override void OnDoubleClick(Mobile from)
{
if (CityLoyaltySystem.Enabled && CityLoyaltySystem.IsSetup() && from.InRange(this.Location, 3))
{
if (_Cooldown == null || !_Cooldown.ContainsKey(from) || _Cooldown[from] < DateTime.UtcNow)
{
var rope = new GuardsmansRope();
from.AddToBackpack(rope);
from.SendLocalizedMessage(1152263); // You take a rope from the chest. Use it to arrest rioters and subdued raiders.
if (_Cooldown == null)
_Cooldown = new Dictionary<Mobile, DateTime>();
_Cooldown[from] = DateTime.UtcNow + TimeSpan.FromSeconds(60);
}
else
from.SendLocalizedMessage(1152264); // You must wait a moment before taking another rope.
}
else
from.PrivateOverheadMessage(Server.Network.MessageType.Regular, 0x3B2, 1019045, from.NetState); // I can't reach that.
}
public static Dictionary<Mobile, DateTime> _Cooldown { get; set; }
public static void Defrag()
{
if (_Cooldown == null)
return;
List<Mobile> list = new List<Mobile>(_Cooldown.Keys);
foreach (Mobile m in list.Where(mob => _Cooldown[mob] < DateTime.UtcNow))
_Cooldown.Remove(m);
list.Clear();
list.TrimExcess();
}
public BoxOfRopes(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write((int)City);
Defrag();
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
City = (City)reader.ReadInt();
if (CitySystem != null && CitySystem.Captain != null)
CitySystem.Captain.Box = this;
}
}
}

View File

@@ -0,0 +1,184 @@
using System;
using Server;
using Server.Mobiles;
using System.Collections.Generic;
using Server.Engines.CityLoyalty;
using System.Linq;
using Server.Prompts;
using Server.ContextMenus;
namespace Server.Items
{
public class CityMessageBoard : BasePlayerBB
{
public City City { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public CityLoyaltySystem CitySystem { get { return CityLoyaltySystem.GetCityInstance(City); } set { } }
public override int LabelNumber { get { return 1027774; } } // bulletin board
public override bool Public { get { return true; } }
public override bool ForceShowProperties { get { return true; } }
[Constructable]
public CityMessageBoard(City city, int id) : base(id)
{
Movable = false;
City = city;
}
public override bool CanPostGreeting(Server.Multis.BaseHouse house, Mobile m)
{
var sys = CitySystem;
return sys != null && (m.AccessLevel >= AccessLevel.GameMaster || sys.Governor == m);
}
public override void OnDoubleClick(Mobile from)
{
if (!CityLoyaltySystem.Enabled || CitySystem == null)
return;
if (CitySystem.IsCitizen(from, true))
{
if (from.InRange(this.Location, 3))
{
from.SendGump(new PlayerBBGump(from, null, this, 0));
}
else
{
from.PrivateOverheadMessage(Server.Network.MessageType.Regular, 0x3B2, 1019045, from.NetState);
}
}
else
{
from.SendLocalizedMessage(1154275); // Only Citizens of this City may use this.
}
}
/*public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
if (!CityLoyaltySystem.Enabled || CitySystem == null || !CitySystem.IsGovernor(from))
return;
list.Add(new SimpleContextMenuEntry(from, 1154912, m => // Set New Announcement
{
if (m.Prompt != null)
m.SendLocalizedMessage(1079166); // You already have a text entry request pending.
else if (CitySystem.Herald != null)
{
m.SendMessage("Enter message board headline:");
m.BeginPrompt(
(mob, text) =>
{
if (Server.Guilds.BaseGuildGump.CheckProfanity(text, 150))
{
CitySystem.Herald.Announcement = text;
}
else
mob.SendLocalizedMessage(1112587); // Invalid entry.
},
(mob, text) =>
{
mob.SendMessage("Herald message unchanged.");
});
}
}, enabled: CitySystem.Herald != null));
list.Add(new SimpleContextMenuEntry(from, 1154913, m => // Set Headline
{
if (m.Prompt != null)
m.SendLocalizedMessage(1079166); // You already have a text entry request pending.
else
{
m.SendMessage("Enter message board headline:");
m.BeginPrompt(
(mob, text) =>
{
if (Server.Guilds.BaseGuildGump.CheckProfanity(text, 150))
{
if (String.IsNullOrEmpty(text))
{
CitySystem.Headline = null;
CitySystem.Body = null;
CitySystem.PostedOn = DateTime.Now;
mob.SendMessage("{0} message board headline removed!", CitySystem.Definition.Name);
}
else
{
CitySystem.Headline = text;
CitySystem.PostedOn = DateTime.Now;
mob.SendMessage("{0} message board headline changed!", CitySystem.Definition.Name);
}
}
else
mob.SendLocalizedMessage(1112587); // Invalid entry.
},
(mob, text) =>
{
mob.SendMessage("Message headline unchanged.");
});
}
}));
list.Add(new SimpleContextMenuEntry(from, 1154914, m => // Set Body
{
if (m.Prompt != null)
m.SendLocalizedMessage(1079166); // You already have a text entry request pending.
else
{
m.SendMessage("Enter message board body:");
m.BeginPrompt(
(mob, text) =>
{
if (Server.Guilds.BaseGuildGump.CheckProfanity(text, 150))
{
if (String.IsNullOrEmpty(text))
{
CitySystem.Body = null;
CitySystem.PostedOn = DateTime.Now;
mob.SendMessage("{0} message board body removed!", CitySystem.Definition.Name);
}
else
{
CitySystem.Body = text;
CitySystem.PostedOn = DateTime.Now;
mob.SendMessage("{0} message board body removed!", CitySystem.Definition.Name);
}
}
else
mob.SendLocalizedMessage(1112587); // Invalid entry.
},
(mob, text) =>
{
mob.SendMessage("Message body unchanged.");
});
}
}));
}*/
public CityMessageBoard(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write((int)City);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
City = (City)reader.ReadInt();
CitySystem.Board = this;
}
}
}

View File

@@ -0,0 +1,260 @@
using System;
using Server;
using Server.Mobiles;
using Server.Items;
using System.Collections.Generic;
using System.Globalization;
using Server.ContextMenus;
using Server.Targeting;
using Server.Gumps;
namespace Server.Engines.CityLoyalty
{
public class CityStone : Item
{
[CommandProperty(AccessLevel.GameMaster)]
public CityLoyaltySystem City { get; set; }
public List<BallotBox> Boxes { get; set; }
public CityStone(CityLoyaltySystem city) : base(0xED4)
{
City = city;
Movable = false;
City.Stone = this;
}
public override void OnDoubleClick(Mobile from)
{
if (CityLoyaltySystem.Enabled && CityLoyaltySystem.IsSetup() && from is PlayerMobile && from.InRange(from.Location, 3))
{
if (from is PlayerMobile && City != null && City.IsCitizen(from))
BaseGump.SendGump(new CityStoneGump(from as PlayerMobile, City));
else
from.SendLocalizedMessage(1153888); // Only Citizens of this City may use the Election Stone.
}
}
public override void AddNameProperty(ObjectPropertyList list)
{
if(City != null)
list.Add(1153887, String.Format("#{0}", CityLoyaltySystem.GetCityLocalization(City.City)));
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (!CityLoyaltySystem.Enabled || City == null)
return;
if (City.GovernorElect != null)
list.Add(1154066, City.GovernorElect.Name); // Governor-Elect: ~1_NAME~
else
list.Add(1154067, City.PendingGovernor ? "#1154102" : City.Governor != null ? City.Governor.Name : "#1154072"); // Governor: ~1_NAME~
if (City.Election != null)
{
DateTime dt;
if (City.Election.CanNominate(out dt))
list.Add(1155756, dt.ToShortDateString()); // Nomination period ends after: ~1_DATE~
if (City.Election.CanVote(out dt))
list.Add(1155757, dt.ToShortDateString()); // Voting Period Ends After: ~1_DATE~
}
list.Add(1154023, City.Treasury > 0 ? City.Treasury.ToString("N0", CultureInfo.GetCultureInfo("en-US")) : City.Treasury.ToString()); // City Treasury Balance: ~1_AMT~
list.Add(1154059, String.Format("#{0}", City.ActiveTradeDeal == TradeDeal.None ? 1011051 : (int)City.ActiveTradeDeal - 12)); // Current Trade Deal: ~1_GUILD~
list.Add(1154907, City.CompletedTrades.ToString(CultureInfo.GetCultureInfo("en-US"))); // Trade Orders Delivered: ~1_val~
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
if (!CityLoyaltySystem.Enabled || City == null)
return;
if (!City.IsCitizen(from))
{
if (City.Herald != null)
City.Herald.SayTo(from, 1154061, City.Definition.Name); // Only citizens of ~1_CITY~ may use the City Stone!
else
from.SendLocalizedMessage(1154061, City.Definition.Name); // Only citizens of ~1_CITY~ may use the City Stone!
return;
}
list.Add(new SimpleContextMenuEntry(from, 1154018, m => // Grant Citizen Title
{
if(City.IsGovernor(m))
{
m.SendLocalizedMessage(1154027); // Which Citizen do you wish to bestow a title?
m.BeginTarget(10, false, TargetFlags.None, (mob, targeted) =>
{
PlayerMobile pm = targeted as PlayerMobile;
if (pm != null)
{
if (City.IsCitizen(pm))
{
BaseGump.SendGump(new PlayerTitleGump(mob as PlayerMobile, pm, City));
}
else
mob.SendLocalizedMessage(1154029); // You may only bestow a title on citizens of this city!
}
else
mob.SendLocalizedMessage(1154028); // You can only bestow a title on a player!
});
}
}, enabled: City.IsGovernor(from)));
list.Add(new SimpleContextMenuEntry(from, 1154031, m => // Open Trade Deal
{
if (City.IsGovernor(m))
{
BaseGump.SendGump(new ChooseTradeDealGump(m as PlayerMobile, City));
}
}, enabled: City.IsGovernor(from)));
list.Add(new SimpleContextMenuEntry(from, 1154277, m => // Open Inventory WTF is this?
{
if (m is PlayerMobile && City.IsGovernor(m))
{
BaseGump.SendGump(new OpenInventoryGump((PlayerMobile)m, City));
}
}, enabled: City.IsGovernor(from)));
list.Add(new SimpleContextMenuEntry(from, 1154278, m => // Place Ballot Box
{
if (City.IsGovernor(m))
{
if (Boxes != null && Boxes.Count >= CityLoyaltySystem.MaxBallotBoxes)
{
m.SendMessage("You have reached the maximum amount of ballot boxes in your city.");
return;
}
m.SendMessage("Where would you like to place a ballot box?");
m.BeginTarget(3, true, TargetFlags.None, (mob, targeted) =>
{
if (targeted is IPoint3D)
{
IPoint3D p = targeted as IPoint3D;
Server.Spells.SpellHelper.GetSurfaceTop(ref p);
BallotBox box = new BallotBox();
if (CheckLocation(m, box, p))
{
box.Owner = m;
box.Movable = false;
if (Boxes == null)
Boxes = new List<BallotBox>();
Boxes.Add(box);
box.MoveToWorld(new Point3D(p), this.Map);
m.SendMessage("{0} of {1} ballot boxes placed.", Boxes.Count.ToString(), CityLoyaltySystem.MaxBallotBoxes.ToString());
}
else
box.Delete();
}
});
}
}, enabled: City.IsGovernor(from)));
list.Add(new SimpleContextMenuEntry(from, 1154060, m => // Utilize Trade Deal
{
City.TryUtilizeTradeDeal(from);
}, enabled: City.ActiveTradeDeal != TradeDeal.None));
CityLoyaltyEntry entry = City.GetPlayerEntry<CityLoyaltyEntry>(from);
list.Add(new SimpleContextMenuEntry(from, 1154019, m => // Remove City Title
{
if (entry != null && entry.CustomTitle != null)
{
entry.CustomTitle = null;
if(m is PlayerMobile)
((PlayerMobile)m).RemoveRewardTitle(1154017, true);
m.SendMessage("City Title removed.");
}
}, enabled: entry != null && entry.CustomTitle != null));
list.Add(new SimpleContextMenuEntry(from, 1154068, m => // Accept Office
{
if (m is PlayerMobile && m == City.GovernorElect && City.Governor == null)
{
BaseGump.SendGump(new AcceptOfficeGump(m as PlayerMobile, City));
}
}, enabled: City.GovernorElect == from && City.Governor == null && City.GetLoyaltyRating(from) >= LoyaltyRating.Unknown));
}
public bool CheckLocation(Mobile m, BallotBox box, IPoint3D p)
{
Region r = Region.Find(new Point3D(p), this.Map);
if (!r.IsPartOf(City.Definition.Region))
{
m.SendMessage("You can only place a ballot box within the {0} city limits!", City.Definition.Name);
return false;
}
if (!box.DropToWorld(new Point3D(p), this.Map))
{
m.SendMessage("You cannot place a ballot box there!");
return false;
}
return true;
}
public CityStone(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write((int)City.City);
writer.Write(Boxes == null ? 0 : Boxes.Count);
if (Boxes != null)
{
Boxes.ForEach(b => writer.Write(b));
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
City = CityLoyaltySystem.GetCityInstance((City)reader.ReadInt());
if(City != null)
City.Stone = this;
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
BallotBox box = reader.ReadItem() as BallotBox;
if (box != null)
{
if (Boxes == null)
Boxes = new List<BallotBox>();
Boxes.Add(box);
}
}
}
}
}

View File

@@ -0,0 +1,70 @@
using System;
using Server;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
using Server.Targeting;
namespace Server.Items
{
public class GuardsmansRope : BaseDecayingItem
{
public override int LabelNumber { get { return 1152261; } } // guardsman's rope
public override int Lifespan { get { return 3600; } }
public GuardsmansRope() : base(0x14F8)
{
Hue = 1944;
}
public override void OnDoubleClick(Mobile from)
{
if (IsChildOf(from.Backpack))
{
from.SendLocalizedMessage(1152244); // What would you like to arrest?
from.BeginTarget(10, false, TargetFlags.None, (m, targeted) =>
{
if (targeted is Raider)
{
Raider raider = targeted as Raider;
if (raider.InRange(m.Location, 1))
{
if (raider.TryArrest(from))
Delete();
}
else
m.SendLocalizedMessage(1152242); // You cannot reach that.
}
else
m.SendLocalizedMessage(1152243); // You cannot arrest that.
});
}
else
from.SendLocalizedMessage(1116249); // That must be in your backpack for you to use it.
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
}
public GuardsmansRope(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,213 @@
using System;
using Server;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Items;
using Server.Misc;
using Server.Prompts;
using Server.Network;
using System.Collections.Generic;
namespace Server.Engines.CityLoyalty
{
public class CityHerald : BaseCreature
{
public City City { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public CityLoyaltySystem CitySystem { get { return CityLoyaltySystem.GetCityInstance(City); } set { } }
public override bool IsInvulnerable { get { return true; } }
private string _Announcement;
[CommandProperty(AccessLevel.GameMaster)]
public string Announcement
{
get
{
return _Announcement;
}
set
{
if (String.IsNullOrEmpty(value))
{
AnnouncementExpires = DateTime.MinValue;
if (Timer != null)
{
Timer.Stop();
Timer = null;
}
}
if (value != _Announcement)
{
AnnouncementExpires = DateTime.UtcNow + TimeSpan.FromHours(CityLoyaltySystem.AnnouncementPeriod);
if (Timer != null)
Timer.Stop();
Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3), DoAnnouncement);
Timer.Start();
}
_Announcement = value;
if (_Announcement != null)
DoAnnouncement();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public DateTime AnnouncementExpires { get; set; }
public Timer Timer { get; set; }
[Constructable]
public CityHerald(City city) : base(AIType.AI_Vendor, FightMode.None, 10, 1, .4, .2)
{
City = city;
SpeechHue = 0x3B2;
Female = Utility.RandomDouble() > 0.75;
Blessed = true;
Name = Female ? NameList.RandomName("female") : NameList.RandomName("male");
Title = "the city herald";
Body = Female ? 0x191 : 0x190;
HairItemID = Race.RandomHair(Female);
FacialHairItemID = Race.RandomFacialHair(Female);
HairHue = Race.RandomHairHue();
Hue = Race.RandomSkinHue();
SetStr(150);
SetInt(50);
SetDex(150);
EquipItem(new Doublet(1157));
EquipItem(new FancyShirt(1908));
EquipItem(new FeatheredHat(1157));
EquipItem(new LongPants(1908));
var boots = new Boots();
boots.Hue = 2012;
EquipItem(boots);
EquipItem(new GoldRing());
CantWalk = true;
}
public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
{
base.GetContextMenuEntries( from, list );
list.Add(new DonateGoldEntry(from, this));
}
private class DonateGoldEntry : ContextMenuEntry
{
public CityHerald Herald { get; private set; }
public Mobile Player { get; private set; }
public DonateGoldEntry(Mobile player, CityHerald herald) : base(1156237, 3) // Donate Gold
{
Player = player;
Herald = herald;
Enabled = player.InRange(herald.Location, 5);
}
public override void OnClick()
{
if (Player.Prompt != null)
{
Player.SendLocalizedMessage(1079166); // You already have a text entry request pending.
}
else
{
Player.SendLocalizedMessage(1155865); // Enter amount to deposit:
Player.BeginPrompt(
(from, text) =>
{
int amount = Utility.ToInt32(text);
if (amount > 0)
{
if (Banker.Withdraw(from, amount, true))
{
CityLoyaltySystem.GetCityInstance(Herald.City).AddToTreasury(from, amount, true);
Herald.SayTo(from, 1152926); // The City thanks you for your generosity!
}
else
from.SendLocalizedMessage(1155867); // The amount entered is invalid. Verify that there are sufficient funds to complete this transaction.
}
else
from.SendLocalizedMessage(1155867); // The amount entered is invalid. Verify that there are sufficient funds to complete this transaction.
},
(from, text) =>
{
from.SendLocalizedMessage(1155867); // The amount entered is invalid. Verify that there are sufficient funds to complete this transaction.
});
}
}
}
public void DoAnnouncement()
{
if (!String.IsNullOrEmpty(_Announcement))
{
PublicOverheadMessage(MessageType.Regular, 0x3B2, 502976); // Hear ye! Hear ye!
Timer.DelayCall(TimeSpan.FromSeconds(3), () =>
{
PublicOverheadMessage(MessageType.Regular, 0x3B2, false, _Announcement);
});
}
if (DateTime.UtcNow > AnnouncementExpires)
{
AnnouncementExpires = DateTime.MinValue;
if (Timer != null)
{
Timer.Stop();
Timer = null;
}
}
}
public CityHerald(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write((int)City);
writer.Write(_Announcement);
writer.Write(AnnouncementExpires);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
City = (City)reader.ReadInt();
_Announcement = reader.ReadString();
AnnouncementExpires = reader.ReadDateTime();
if (CitySystem != null)
CitySystem.Herald = this;
if (DateTime.UtcNow < AnnouncementExpires)
{
Timer = Timer.DelayCall(TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3), DoAnnouncement);
Timer.Start();
}
}
}
}

View File

@@ -0,0 +1,221 @@
using Server.Items;
using Server.Mobiles;
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using System.Globalization;
using Server.Gumps;
using System.Linq;
namespace Server.Engines.CityLoyalty
{
public class GuardCaptain : BaseCreature
{
[CommandProperty(AccessLevel.GameMaster)]
public City City { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public BoxOfRopes Box { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime NextShout { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public CityLoyaltySystem CitySystem { get { return CityLoyaltySystem.GetCityInstance(City); } set { } }
public override bool IsInvulnerable { get { return true; } }
private Dictionary<PlayerMobile, DateTime> _BannerCooldown;
[Constructable]
public GuardCaptain(City city) : base(AIType.AI_Vendor, FightMode.None, 10, 1, 0.2, 0.4)
{
City = city;
Female = Utility.RandomDouble() > 0.75;
Blessed = true;
Name = Female ? NameList.RandomName("female") : NameList.RandomName("male");
Title = "the guard captain";
Body = Female ? 0x191 : 0x190;
HairItemID = Race.RandomHair(Female);
FacialHairItemID = Race.RandomFacialHair(Female);
HairHue = Race.RandomHairHue();
Hue = Race.RandomSkinHue();
SetStr(150);
SetInt(50);
SetDex(150);
SetWearable(new ShortPants(1508));
if (Female)
SetWearable(new FemaleStuddedChest());
else
SetWearable(new PlateChest());
SetWearable(new BodySash(1326));
SetWearable(new Halberd());
CantWalk = true;
}
public override void OnMovement(Mobile m, Point3D oldLocation)
{
if (CitySystem != null && m is PlayerMobile && InRange(m.Location, 2))
{
Raider raider = ((PlayerMobile)m).AllFollowers.FirstOrDefault(mob => mob is Raider && mob.InRange(this.Location, 2)) as Raider;
if (raider != null)
{
CitySystem.AwardLove(m, 1000);
SayTo(m, 1152250, m.Name); // Thank you, ~1_name~, for your assistance during these difficult times.
raider.Delete();
}
}
base.OnMovement(m, oldLocation);
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> entries)
{
base.GetContextMenuEntries(from, entries);
if(from is PlayerMobile)
entries.Add(new InternalEntry(from as PlayerMobile, this));
}
public class InternalEntry : ContextMenuEntry
{
public PlayerMobile Player { get; set; }
public GuardCaptain Guard { get; set; }
public InternalEntry(PlayerMobile from, GuardCaptain guard)
: base(1152366, 3) // City Banner
{
Player = from;
Guard = guard;
Enabled = CityLoyaltySystem.HasCitizenship(from, Guard.City);
}
public override void OnClick()
{
CityLoyaltySystem thisSystem = CityLoyaltySystem.GetCityInstance(Guard.City);
CityLoyaltySystem theirSystem = CityLoyaltySystem.GetCitizenship(Player);
Guard.CheckBannerCooldown();
if (theirSystem != null && thisSystem != null && CityLoyaltySystem.HasCitizenship(Player, Guard.City))
{
if(Guard.IsInBannerCooldown(Player))
Guard.SayTo(Player, 1152364, String.Format("#{0}", CityLoyaltySystem.BannerLocalization(thisSystem.City))); // I have quite a backlog of orders and I cannot satisfy your request for a ~1_ITEM~ right now.
if (theirSystem.GetLoyaltyRating(Player) < LoyaltyRating.Adored)
Guard.SayTo(Player, 1152363, String.Format("#{0}", CityLoyaltySystem.GetCityLocalization(thisSystem.City))); // I apologize, but you are not well-enough renowned in the city of ~1_CITY~ to make this purchase.
else
{
string args = String.Format("#{0}\t{1}", CityLoyaltySystem.BannerLocalization(thisSystem.City), CityLoyaltySystem.BannerCost.ToString("N0", CultureInfo.GetCultureInfo("en-US")));
Player.SendGump(new ConfirmCallbackGump(Player, 1049004, 1152365, Player, args, Guard.OnConfirm));
}
}
}
}
private void OnConfirm(Mobile m, object o)
{
PlayerMobile pm = m as PlayerMobile;
if(pm != null)
{
if (Banker.Withdraw(pm, CityLoyaltySystem.BannerCost))
{
CityBannerDeed deed = new CityBannerDeed(City);
CitySystem.AddToTreasury(m, CityLoyaltySystem.BannerCost);
if(pm.Backpack == null || !pm.Backpack.TryDropItem(pm, deed, false))
{
pm.BankBox.DropItem(deed);
pm.SendMessage("The deed has been placed in your bank box.");
}
else
pm.SendMessage("The deed has been placed in your backpack.");
AddToCooldown(pm);
}
else
SayTo(pm, 1152302); // I am afraid your bank box does not contain the funds needed to complete this transaction.
}
}
public void AddToCooldown(PlayerMobile pm)
{
if (_BannerCooldown == null)
_BannerCooldown = new Dictionary<PlayerMobile, DateTime>();
_BannerCooldown[pm] = DateTime.UtcNow + TimeSpan.FromHours(CityLoyaltySystem.BannerCooldownDuration);
}
public bool IsInBannerCooldown(PlayerMobile m)
{
if (_BannerCooldown != null && m is PlayerMobile)
{
if (_BannerCooldown.ContainsKey((PlayerMobile)m))
return _BannerCooldown[m] > DateTime.UtcNow;
}
return false;
}
public void CheckBannerCooldown()
{
if (_BannerCooldown == null || _BannerCooldown.Count == 0)
return;
List<PlayerMobile> list = new List<PlayerMobile>(_BannerCooldown.Keys);
foreach (PlayerMobile pm in list)
{
if (_BannerCooldown[pm] < DateTime.UtcNow)
_BannerCooldown.Remove(pm);
}
list.Clear();
list.TrimExcess();
}
public override void OnThink()
{
base.OnThink();
if (NextShout < DateTime.UtcNow)
{
Say(Utility.Random(1152252, 6));
NextShout = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(45, 65));
}
}
public GuardCaptain(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write((int)City);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
City = (City)reader.ReadInt();
if (CitySystem != null)
CitySystem.Captain = this;
}
}
}

View File

@@ -0,0 +1,166 @@
using System;
using Server;
using Server.Items;
using System.Linq;
using Server.Network;
using Server.Engines.CityLoyalty;
namespace Server.Mobiles
{
public class Raider : BaseCreature
{
public DateTime DeleteTime { get; set; }
public override bool Commandable { get { return false; } }
public override bool ReduceSpeedWithDamage { get { return false; } }
public override bool AlwaysMurderer { get { return true; } }
[Constructable]
public Raider()
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Title = "the raider";
Hue = Utility.RandomSkinHue();
Utility.AssignRandomHair(this);
SetStr(150, 200);
SetDex(125, 150);
SetInt(95, 110);
SetHits(400, 650);
SetDamage(21, 28);
if (this.Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
EquipItem(new Skirt(Utility.RandomNeutralHue()));
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
EquipItem(new ShortPants(Utility.RandomNeutralHue()));
}
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 45, 55);
SetResistance(ResistanceType.Fire, 45, 55);
SetResistance(ResistanceType.Cold, 45, 55);
SetResistance(ResistanceType.Poison, 45, 55);
SetResistance(ResistanceType.Energy, 45, 55);
SetSkill(SkillName.MagicResist, 50.0, 75.5);
SetSkill(SkillName.Archery, 90.0, 105.5);
SetSkill(SkillName.Tactics, 90.0, 105.5);
SetSkill(SkillName.Anatomy, 90.0, 105.5);
Fame = 7500;
Karma = -7500;
SetWearable(new TricorneHat());
SetWearable(new LeatherArms());
SetWearable(new FancyShirt());
SetWearable(new Cutlass());
SetWearable(new Boots(Utility.RandomNeutralHue()));
SetWearable(new GoldEarrings());
Item bow;
switch (Utility.Random(4))
{
default:
case 0: bow = new CompositeBow(); PackItem(new Arrow(25)); break;
case 1: bow = new Crossbow(); PackItem(new Bolt(25)); break;
case 2: bow = new Bow(); PackItem(new Arrow(25)); break;
case 3: bow = new HeavyCrossbow(); PackItem(new Bolt(25)); break;
}
SetWearable(bow);
ControlSlots = 0;
}
public bool TryArrest(Mobile m)
{
if (ControlMaster != null)
{
m.SendLocalizedMessage(1152247); // That person is already under arrest.
}
else if (m is PlayerMobile && ((PlayerMobile)m).AllFollowers.FirstOrDefault(mob => mob is Raider) != null)
{
m.SendLocalizedMessage(1152249); // You already have a prisoner.
}
else if (Hits > ((double)HitsMax / 10))
{
m.SendLocalizedMessage(1152229); // That person won't sit still for it! A more aggressive approach is in order.
m.NonlocalOverheadMessage(MessageType.Regular, 0x3B2, 1152237, String.Format("{0}\t{1}", m.Name, this.Name, "raider"));
}
else
{
DeleteTime = DateTime.UtcNow + TimeSpan.FromHours(1);
SetControlMaster(m);
IsBonded = false;
ControlTarget = m;
ControlOrder = OrderType.Follow;
m.SendLocalizedMessage(1152236, this.Name); // You arrest the ~1_name~. Take the criminal to the guard captain.
m.NonlocalOverheadMessage(MessageType.Regular, 0x3B2, 1152238, String.Format("{0}\t{1}", m.Name, this.Name));
return true;
}
return false;
}
public override void OnThink()
{
base.OnThink();
CheckDelete();
}
public void CheckDelete()
{
if (DeleteTime != DateTime.MinValue && DateTime.UtcNow > DeleteTime)
{
if (ControlMaster != null && ControlMaster.NetState != null)
{
ControlMaster.SendLocalizedMessage(1152248); // You did not take your prisoner to the Guard Captain in time.
}
Delete();
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 2);
}
public Raider(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
Timer.DelayCall(TimeSpan.FromSeconds(10), CheckDelete);
writer.Write(DeleteTime);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
DeleteTime = reader.ReadDateTime();
}
}
}

View File

@@ -0,0 +1,226 @@
using System;
using Server;
using Server.Mobiles;
using Server.Items;
using System.Collections.Generic;
using System.Linq;
using Server.Commands;
using Server.Regions;
namespace Server.Engines.CityLoyalty
{
public class CityLoyaltySetup
{
public static void Initialize()
{
if (CityLoyaltySystem.Enabled)
{
CommandSystem.Register("SetupCityLoyaltySystem", AccessLevel.GameMaster, Setup);
CommandSystem.Register("DeleteCityLoyaltySystem", AccessLevel.GameMaster, Delete);
}
}
public static void Delete(CommandEventArgs e)
{
Mobile m = e.Mobile;
CityLoyaltySystem.Cities.ForEach(city =>
{
if (city.Stone != null) city.Stone.Delete();
if (city.Herald != null) city.Herald.Delete();
if (city.Captain != null)
{
if (city.Captain.Box != null)
city.Captain.Box.Delete();
city.Captain.Delete();
}
if (city.Minister != null)
{
if (city.Minister.DonationCrate != null)
city.Minister.DonationCrate.Delete();
if (city.Minister.DonationPost != null)
city.Minister.DonationPost.Delete();
city.Minister.Delete();
}
});
}
public static void Setup(CommandEventArgs e)
{
Mobile m = e.Mobile;
TradeMinister minister;
CityHerald herald;
GuardCaptain capt;
CityStone stone;
CityItemDonation itemdonation;
CityPetDonation petdonation;
BoxOfRopes box;
CityMessageBoard board;
foreach (int c in Enum.GetValues(typeof(City)))
{
City city = (City)c;
CityLoyaltySystem sys = null;
switch (city)
{
case City.Moonglow: sys = CityLoyaltySystem.Moonglow; break;
case City.Britain: sys = CityLoyaltySystem.Britain; break;
case City.Jhelom: sys = CityLoyaltySystem.Jhelom; break;
case City.Yew: sys = CityLoyaltySystem.Yew; break;
case City.Minoc: sys = CityLoyaltySystem.Minoc; break;
case City.Trinsic: sys = CityLoyaltySystem.Trinsic; break;
case City.SkaraBrae: sys = CityLoyaltySystem.SkaraBrae; break;
case City.NewMagincia: sys = CityLoyaltySystem.NewMagincia; break;
case City.Vesper: sys = CityLoyaltySystem.Vesper; break;
}
if (sys != null)
{
minister = new TradeMinister(sys.City);
herald = new CityHerald(sys.City);
capt = new GuardCaptain(sys.City);
stone = new CityStone(sys);
itemdonation = new CityItemDonation(sys.City, minister);
petdonation = new CityPetDonation(sys.City, minister);
box = new BoxOfRopes(sys.City);
board = new CityMessageBoard(sys.City, 0xA0C5);
if (!HasType(sys, minister.GetType()))
{
sys.Minister = minister;
minister.MoveToWorld(sys.Definition.TradeMinisterLocation, CityLoyaltySystem.SystemMap);
}
else
minister.Delete();
if (!HasType(sys, herald.GetType()))
{
sys.Herald = herald;
herald.MoveToWorld(sys.Definition.HeraldLocation, CityLoyaltySystem.SystemMap);
}
else
herald.Delete();
if (!HasType(sys, capt.GetType()))
{
sys.Captain = capt;
capt.MoveToWorld(sys.Definition.GuardsmanLocation, CityLoyaltySystem.SystemMap);
}
else
capt.Delete();
if (!HasType(sys, stone.GetType()))
{
sys.Stone = stone;
stone.MoveToWorld(sys.Definition.StoneLocation, CityLoyaltySystem.SystemMap);
}
else
stone.Delete();
if (!HasType(sys, itemdonation.GetType()))
itemdonation.MoveToWorld(new Point3D(sys.Definition.TradeMinisterLocation.X, sys.Definition.TradeMinisterLocation.Y - 1, sys.Definition.TradeMinisterLocation.Z), CityLoyaltySystem.SystemMap);
else
itemdonation.Delete();
if (!HasType(sys, petdonation.GetType()))
petdonation.MoveToWorld(new Point3D(sys.Definition.TradeMinisterLocation.X, sys.Definition.TradeMinisterLocation.Y - 2, sys.Definition.TradeMinisterLocation.Z), CityLoyaltySystem.SystemMap);
else
petdonation.Delete();
if (!HasType(sys, box.GetType()))
box.MoveToWorld(new Point3D(sys.Definition.GuardsmanLocation.X, sys.Definition.GuardsmanLocation.Y - 1, sys.Definition.GuardsmanLocation.Z), CityLoyaltySystem.SystemMap);
else
box.Delete();
if (!HasType(sys, board.GetType()))
{
board.MoveToWorld(sys.Definition.BoardLocation, CityLoyaltySystem.SystemMap);
sys.Board = board;
}
else
board.Delete();
sys.CanUtilize = true;
m.SendMessage("{0} setup!", sys.Definition.Name);
}
}
for (int i = 0; i < 3; i++)
{
string name;
Point3D p;
switch (i)
{
default:
case 0:
name = "Ocllo";
p = new Point3D(3674, 2648, 0);
break;
case 1:
name = "Nujel'm";
p = new Point3D(3765, 1219, 0);
break;
case 2:
name = "Serpent's Hold";
p = new Point3D(3017, 3452, 15);
break;
}
Region r = Region.Regions.FirstOrDefault(reg => reg.Map == Map.Felucca && reg.Name == name);
if (r != null)
{
var slim = new SlimTheFence();
if (!HasType(r, slim.GetType()))
slim.MoveToWorld(p, Map.Felucca);
else
slim.Delete();
}
else
Console.WriteLine("WARNING: {0} Region not found!", name);
}
}
public static bool HasType(CityLoyaltySystem system, Type t)
{
return HasType(system.Definition.Region, t);
}
public static bool HasType(Region r, Type t)
{
if (r == null)
return false;
if (t.IsSubclassOf(typeof(Mobile)))
{
foreach (Mobile m in r.GetEnumeratedMobiles())
{
if (m.GetType() == t)
return true;
}
}
else if (t.IsSubclassOf(typeof(Item)))
{
foreach (Item i in r.GetEnumeratedItems())
{
if (i.GetType() == t)
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,313 @@
using System;
using Server;
using Server.Mobiles;
using Server.Gumps;
using Server.Engines.Points;
using System.Collections.Generic;
using Server.Targeting;
using Server.Items;
namespace Server.Engines.CityLoyalty
{
public class CityDonationItem : Item
{
[CommandProperty(AccessLevel.GameMaster)]
public CityLoyaltySystem CitySystem { get { return CityLoyaltySystem.GetCityInstance(City); } set { } }
public City City { get; protected set; }
[CommandProperty(AccessLevel.GameMaster)]
public TradeMinister Minister { get; set; }
public Dictionary<Type, int> Table { get; protected set; }
public virtual bool Animals { get { return false; } }
public CityDonationItem(City city, TradeMinister minister, int itemid) : base(itemid)
{
City = city;
Minister = minister;
Movable = false;
}
public override void OnDoubleClick(Mobile from)
{
if (!CityLoyaltySystem.IsSetup())
return;
if(Animals && Table != null && Table.Count > 0)
{
from.Target = new InternalTarget(this);
from.SendLocalizedMessage(1152936); // Which animal do you wish to donate?
}
else if (!Animals)
{
SendMessageTo(from, 1152928); // If you wish to donate to the City simply drop the items into the crate.
}
}
public override bool OnDragDrop(Mobile from, Item dropped)
{
if (!CityLoyaltySystem.IsSetup())
return false;
if(!Animals && Table != null && Table.Count > 0)
{
int love = 0;
if (dropped is Container)
{
List<Item> items = new List<Item>(dropped.Items);
foreach (Item item in items)
{
love += CheckTurnin(item);
}
items.Clear();
items.TrimExcess();
}
else
{
love = CheckTurnin(dropped);
}
if (love > 0)
{
CityLoyaltySystem.GetCityInstance(City).AwardLove(from, love);
SendMessageTo(from, 1152926); // The City thanks you for your generosity!
return !(dropped is Container);
}
else
{
SendMessageTo(from, 1152927); // Your generosity is appreciated but the City does not require this item.
return false;
}
}
return false;
}
private int CheckTurnin(Item item)
{
Type dropType = item.GetType();
int love = 0;
foreach (KeyValuePair<Type, int> kvp in Table)
{
Type checkType = kvp.Key;
if (checkType == dropType || dropType.IsSubclassOf(checkType))
{
CityLoyaltySystem sys = CityLoyaltySystem.GetCityInstance(City);
if (sys != null)
{
// TODO: If anything adds to treasure, change this
if (item is MaritimeCargo)
{
AddToTreasury(sys, (MaritimeCargo)item);
}
item.Delete();
love = Table[checkType] * item.Amount;
break;
}
}
}
return love;
}
private void AddToTreasury(CityLoyaltySystem system, MaritimeCargo cargo)
{
if (system != null)
{
if (cargo.City == City)
{
system.AddToTreasury(null, cargo.GetAwardAmount() * 1000);
}
else
{
system.AddToTreasury(null, 100);
}
}
}
private class InternalTarget : Target
{
public CityDonationItem Item { get; private set; }
public InternalTarget(CityDonationItem item) : base(3, false, TargetFlags.None)
{
Item = item;
}
protected override void OnTarget(Mobile from, object targeted)
{
if(targeted is BaseCreature)
{
BaseCreature bc = targeted as BaseCreature;
Type t = bc.GetType();
if(bc.Controlled && !bc.Summoned && bc.GetMaster() == from)
{
if(Item.Table.ContainsKey(t))
{
CityLoyaltySystem sys = CityLoyaltySystem.GetCityInstance(Item.City);
if(sys != null)
{
bc.Delete();
sys.AwardLove(from, Item.Table[t]);
Item.SendMessageTo(from, 1152926); // The City thanks you for your generosity!
}
}
else
Item.SendMessageTo(from, 1152929); // That does not look like an animal the City is in need of.
}
else
Item.SendMessageTo(from, 1152930); // Erm. Uhh. I don't think that'd enjoy the stables much...
}
else
Item.SendMessageTo(from, 1152930); // Erm. Uhh. I don't think that'd enjoy the stables much...
}
}
private void SendMessageTo(Mobile m, int message)
{
if (Minister != null)
Minister.SayTo(m, message);
else
m.SendLocalizedMessage(message);
}
public CityDonationItem(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write((int)City);
writer.Write(Minister);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
City = (City)reader.ReadInt();
Minister = reader.ReadMobile() as TradeMinister;
}
}
public class CityItemDonation : CityDonationItem
{
[Constructable]
public CityItemDonation(City city, TradeMinister minister) : base(city, minister, 0xE3C)
{
Table = ItemTable;
if (CitySystem != null && CitySystem.Minister != null)
CitySystem.Minister.DonationCrate = this;
}
public static Dictionary<Type, int> ItemTable { get; set; }
public static void Configure()
{
ItemTable = new Dictionary<Type, int>();
ItemTable.Add(typeof(BaseWoodBoard), 10);
ItemTable.Add(typeof(BaseIngot), 10);
ItemTable.Add(typeof(BaseHides), 10);
ItemTable.Add(typeof(BaseLeather), 10);
ItemTable.Add(typeof(RawRibs), 10);
ItemTable.Add(typeof(BreadLoaf), 10);
ItemTable.Add(typeof(RawFishSteak), 10);
ItemTable.Add(typeof(BaseCrabAndLobster), 15);
ItemTable.Add(typeof(BasePotion), 15);
ItemTable.Add(typeof(Bow), 20);
ItemTable.Add(typeof(Crossbow), 20);
ItemTable.Add(typeof(MaritimeCargo), 50);
}
public CityItemDonation(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
Table = ItemTable;
if (CitySystem != null && CitySystem.Minister != null)
CitySystem.Minister.DonationCrate = this;
}
}
public class CityPetDonation : CityDonationItem
{
public override bool Animals { get { return true; } }
[Constructable]
public CityPetDonation(City city, TradeMinister minister) : base(city, minister, 0x14E7)
{
Table = PetTable;
if (CitySystem != null && CitySystem.Minister != null)
CitySystem.Minister.DonationPost = this;
}
public static Dictionary<Type, int> PetTable { get; set; }
public static void Configure()
{
PetTable = new Dictionary<Type, int>();
PetTable.Add(typeof(Dog), 10);
PetTable.Add(typeof(Cat), 10);
PetTable.Add(typeof(Cow), 10);
PetTable.Add(typeof(Goat), 10);
PetTable.Add(typeof(Horse), 10);
PetTable.Add(typeof(Sheep), 10);
PetTable.Add(typeof(Pig), 10);
PetTable.Add(typeof(Chicken), 10);
}
public CityPetDonation(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
Table = PetTable;
if (CitySystem != null && CitySystem.Minister != null)
CitySystem.Minister.DonationPost = this;
}
}
}

View File

@@ -0,0 +1,326 @@
using System;
using Server;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
using Server.Gumps;
namespace Server.Items
{
public abstract class CityBook : Item
{
public abstract int Title { get; }
public abstract int Content { get; }
public CityBook() : base(4030)
{
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if(Title > 0)
list.Add(Title);
list.Add(1154760, "Adamu Edom"); // By: ~1_NAME~
}
public override void OnDoubleClick(Mobile m)
{
if (IsChildOf(m.Backpack))
{
Gump g = new Gump(150, 150);
g.AddImage(0, 0, 30236);
g.AddHtmlLocalized(110, 30, 350, 630, Content, false, false);
m.SendGump(g);
}
}
public static CityBook GetRandom()
{
switch (Utility.Random(9))
{
default:
case 0: return new LoyaltyBookBritain();
case 1: return new LoyaltyBookYew();
case 2: return new LoyaltyBookMoonglow();
case 3: return new LoyaltyBookNewMagincia();
case 4: return new LoyaltyBookVesper();
case 5: return new LoyaltyBookSkaraBrae();
case 6: return new LoyaltyBookJhelom();
case 7: return new LoyaltyBookMinoc();
case 8: return new LoyaltyBookTrinsic();
}
}
public CityBook(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LoyaltyBookYew : CityBook
{
public override int Title { get { return 1153933; } }
public override int Content { get { return 1152698; } }
[Constructable]
public LoyaltyBookYew()
{
}
public LoyaltyBookYew(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LoyaltyBookJhelom : CityBook
{
public override int Title { get { return 1153934; } }
public override int Content { get { return 1153436; } }
[Constructable]
public LoyaltyBookJhelom()
{
}
public LoyaltyBookJhelom(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LoyaltyBookMoonglow : CityBook
{
public override int Title { get { return 1153935; } }
public override int Content { get { return 1153437; } }
[Constructable]
public LoyaltyBookMoonglow()
{
}
public LoyaltyBookMoonglow(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LoyaltyBookTrinsic : CityBook
{
public override int Title { get { return 1153727; } }
public override int Content { get { return 1151755; } }
[Constructable]
public LoyaltyBookTrinsic()
{
}
public LoyaltyBookTrinsic(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LoyaltyBookMinoc : CityBook
{
public override int Title { get { return 1153728; } }
public override int Content { get { return 1152317; } }
[Constructable]
public LoyaltyBookMinoc()
{
}
public LoyaltyBookMinoc(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LoyaltyBookNewMagincia : CityBook
{
public override int Title { get { return 1153008; } }
public override int Content { get { return 1153723; } }
[Constructable]
public LoyaltyBookNewMagincia()
{
}
public LoyaltyBookNewMagincia(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LoyaltyBookVesper : CityBook
{
public override int Title { get { return 1153012; } }
public override int Content { get { return 1153724; } }
[Constructable]
public LoyaltyBookVesper()
{
}
public LoyaltyBookVesper(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LoyaltyBookSkaraBrae : CityBook
{
public override int Title { get { return 0; } }
public override int Content { get { return 1153725; } }
[Constructable]
public LoyaltyBookSkaraBrae()
{
}
public LoyaltyBookSkaraBrae(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
public class LoyaltyBookBritain : CityBook
{
public override int Title { get { return 1153726; } }
public override int Content { get { return 1151754; } }
[Constructable]
public LoyaltyBookBritain()
{
}
public LoyaltyBookBritain(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using Server;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
namespace Server.Items
{
public class ExpiredVoucher : Item
{
public override int LabelNumber { get { return 1151749; } } // Expired Voucher for a Free Drink at the Fortune's Fire Casino
[Constructable]
public ExpiredVoucher()
: base(0x2831)
{
}
public ExpiredVoucher(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,35 @@
using System;
using Server;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
namespace Server.Items
{
public class ForgedArtwork : Item
{
public override int LabelNumber { get { return 1151750; } } // Forged Artwork from King Blackthorn's Collection
[Constructable]
public ForgedArtwork() : base(Utility.Random(0x1224, 5))
{
Weight = 10;
}
public ForgedArtwork(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using Server;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
namespace Server.Items
{
public class LittleBlackBook : Item
{
public override int LabelNumber { get { return 1151751; } } // Slim the Fence's little black book
[Constructable]
public LittleBlackBook()
: base(4030)
{
Hue = 1932;
}
public LittleBlackBook(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using Server;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
using Server.Gumps;
namespace Server.Items
{
public class MysteriousNote : Item
{
public override int LabelNumber { get { return 1151753; } } // A Mysterious Note
[Constructable]
public MysteriousNote()
: base(0x14ED)
{
}
public override void OnDoubleClick(Mobile from)
{
Gump g = new Gump(100, 100);
g.AddBackground(0, 0, 404, 325, 9380);
/*You unfurl the parchment, it appears to be a handwritten note*<br><br>Taking up delivery of goods fer
* the crown are ya? Well...maybe yer interested in a bit of something fer yerself? Look fer me in Felucca...
* the taverns of Ocllo, Nujelm, & Serpent's Hold if ye want to fence yer goods.<br><br>-A Friend*/
g.AddHtmlLocalized(37, 50, 340, 225, 1151735, 0xC63, false, true);
from.SendGump(g);
}
public MysteriousNote(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using Server;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
namespace Server.Items
{
public class RewardSign : Sign, IEngravable
{
public string EngravedText { get; set; }
[Constructable]
public RewardSign() : base((SignType)Utility.RandomMinMax(31, 58), Utility.RandomBool() ? SignFacing.North : SignFacing.West)
{
Movable = true;
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (!String.IsNullOrEmpty(EngravedText))
{
list.Add(1072305, EngravedText); // Engraved: ~1_INSCRIPTION~
}
}
public RewardSign(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(EngravedText);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
EngravedText = reader.ReadString();
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using Server;
using Server.Mobiles;
using Server.Engines.CityLoyalty;
namespace Server.Items
{
public class SlimsShadowVeil : LeatherMempo
{
public override int LabelNumber { get { return 1154906; } } // Slim's Shadow Veil
[Constructable]
public SlimsShadowVeil()
{
Hue = 1932;
Attributes.CastSpeed = 1;
}
public SlimsShadowVeil(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,162 @@
using System;
using Server;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Engines.Points;
using Server.Targeting;
using Server.Gumps;
using System.Collections.Generic;
using Server.Items;
using Server.Misc;
namespace Server.Engines.CityLoyalty
{
public class SlimTheFence : BaseCreature
{
public override bool IsInvulnerable { get { return true; } }
[Constructable]
public SlimTheFence() : base(AIType.AI_Vendor, FightMode.None, 10, 1, .4, .2)
{
Body = 0x190;
SpeechHue = 0x3B2;
Blessed = true;
Name = "Slim";
Title = "the Fence";
HairItemID = 8264;
FacialHairItemID = 8269;
HairHue = 1932;
FacialHairHue = 1932;
Hue = Race.RandomSkinHue();
SetStr(150);
SetInt(50);
SetDex(150);
EquipItem(new JinBaori(1932));
EquipItem(new FancyShirt(1932));
EquipItem(new LongPants(1));
var boots = new Boots();
boots.Hue = 1;
EquipItem(boots);
CantWalk = true;
}
public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
{
base.GetContextMenuEntries( from, list );
list.Add(new TurnInEntry(from, this));
}
private class TurnInEntry : ContextMenuEntry
{
public SlimTheFence Slim { get; private set; }
public Mobile Player { get; private set; }
public TurnInEntry(Mobile player, SlimTheFence slim) : base(1151729, 3) // Turn in a trade order
{
Player = player;
Slim = slim;
Enabled = CityTradeSystem.HasTrade(Player);
}
public override void OnClick()
{
if (CityTradeSystem.HasTrade(Player))
{
Player.Target = new InternalTarget(Slim);
Player.SendLocalizedMessage(1151730); // Target the trade order you wish to turn in.
}
}
private class InternalTarget : Target
{
public SlimTheFence Slim { get; private set; }
public InternalTarget(SlimTheFence slim) : base(-1, false, TargetFlags.None)
{
Slim = slim;
}
protected override void OnTarget(Mobile from, object targeted)
{
TradeOrderCrate order = targeted as TradeOrderCrate;
if(order != null)
{
if (CityLoyaltySystem.CityTrading.TryTurnInToSlim(from, order, Slim))
{
if (order.Entry != null && order.Entry.Distance > 0)
{
from.AddToBackpack(Slim.GiveAward());
from.SendLocalizedMessage(1073621); // Your reward has been placed in your backpack.
}
Titles.AwardKarma(from, -100, true);
}
}
else
{
from.SendLocalizedMessage(1151731); // That is not a valid trade order. Please try again.
from.Target = new InternalTarget(Slim);
}
}
}
}
private Item GiveAward()
{
if (0.05 > Utility.RandomDouble())
{
switch (Utility.Random(4))
{
case 0: return new ExpiredVoucher();
case 1: return new ForgedArtwork();
case 2: return new LittleBlackBook();
case 3: return new SlimsShadowVeil();
}
}
switch (Utility.Random(3))
{
default:
case 0:
return new Skeletonkey();
case 1:
Item item = Loot.RandomArmorOrShieldOrWeaponOrJewelry(false, false, true);
int min, max;
TreasureMapChest.GetRandomItemStat(out min, out max, 1.0);
RunicReforging.GenerateRandomItem(item, 0, min, max, this.Map);
return item;
case 2:
return ScrollOfTranscendence.CreateRandom(1, 10);
}
}
public SlimTheFence(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,343 @@
using System;
using Server;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Engines.Points;
using Server.Targeting;
using Server.Gumps;
using Server.Network;
using System.Collections.Generic;
using Server.Items;
using Server.Misc;
namespace Server.Engines.CityLoyalty
{
public class TradeMinister : BaseCreature
{
[CommandProperty(AccessLevel.GameMaster)]
public City City { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public CityLoyaltySystem CitySystem { get { return CityLoyaltySystem.GetCityInstance(City); } set { } }
[CommandProperty(AccessLevel.GameMaster)]
public CityItemDonation DonationCrate { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public CityPetDonation DonationPost { get; set; }
public override bool IsInvulnerable { get { return true; } }
[Constructable]
public TradeMinister(City city) : base(AIType.AI_Vendor, FightMode.None, 10, 1, .4, .2)
{
City = city;
SpeechHue = 0x3B2;
Female = Utility.RandomDouble() > 0.75;
Blessed = true;
Name = Female ? NameList.RandomName("female") : NameList.RandomName("male");
Title = "the minister of trade";
Body = Female ? 0x191 : 0x190;
HairItemID = Race.RandomHair(Female);
FacialHairItemID = Race.RandomFacialHair(Female);
HairHue = Race.RandomHairHue();
Hue = Race.RandomSkinHue();
SetStr(150);
SetInt(50);
SetDex(150);
EquipItem(new Cloak(1157));
EquipItem(new BodySash(1326));
var chest = new ChainChest();
chest.Hue = 1908;
EquipItem(chest);
var boots = new ThighBoots();
boots.Hue = 1908;
EquipItem(boots);
EquipItem(new GoldRing());
Ministers.Add(this);
CantWalk = true;
}
public override void OnDoubleClick(Mobile from)
{
if(from.InRange(this.Location, 4))
{
from.SendGump(new InternalGump());
}
}
public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
{
base.GetContextMenuEntries( from, list );
list.Add(new TradeOrderEntry(from, this));
list.Add(new TurnInEntry(from, this));
}
private class TradeOrderEntry : ContextMenuEntry
{
public TradeMinister Minister { get; private set; }
public Mobile Player { get; private set; }
public TradeOrderEntry(Mobile player, TradeMinister minister) : base(1114453, 5) // Get Trade Order
{
Player = player;
Minister = minister;
Enabled = !CityTradeSystem.HasTrade(Player);
}
public override void OnClick()
{
if (!CityTradeSystem.HasTrade(Player))
{
Player.SendGump(new InternalTradeOrderGump(Player as PlayerMobile, Minister));
}
}
}
private class TurnInEntry : ContextMenuEntry
{
public TradeMinister Minister { get; private set; }
public Mobile Player { get; private set; }
public TurnInEntry(Mobile player, TradeMinister minister) : base(1151729, 3) // Turn in a trade order
{
Player = player;
Minister = minister;
Enabled = CityTradeSystem.HasTrade(Player);
}
public override void OnClick()
{
if (CityTradeSystem.HasTrade(Player))
{
Player.Target = new InternalTarget(Minister);
Player.SendLocalizedMessage(1151730); // Target the trade order you wish to turn in.
}
}
private class InternalTarget : Target
{
public TradeMinister Minister { get; private set; }
public InternalTarget(TradeMinister minister) : base(-1, false, TargetFlags.None)
{
Minister = minister;
}
protected override void OnTarget(Mobile from, object targeted)
{
TradeOrderCrate order = targeted as TradeOrderCrate;
if(order != null)
{
if (CityLoyaltySystem.CityTrading.TryTurnIn(from, order, Minister))
{
if (order.Entry != null && order.Entry.Distance > 0)
{
from.AddToBackpack(Minister.GiveReward(order.Entry));
from.SendLocalizedMessage(1073621); // Your reward has been placed in your backpack.
}
Titles.AwardKarma(from, 100, true);
}
}
else
{
from.SendLocalizedMessage(1151731); // That is not a valid trade order. Please try again.
from.Target = new InternalTarget(Minister);
}
}
}
}
private Item GiveReward(TradeEntry entry)
{
if (0.01 > Utility.RandomDouble())
{
switch (Utility.Random(2))
{
default:
case 0: return CityBook.GetRandom();
case 1: return new RewardSign();
}
}
else
{
switch (Utility.Random(2))
{
default:
case 1: return RandomResource(entry);
case 2: return ScrollOfTranscendence.CreateRandom(1, 10);
}
}
}
private Item RandomResource(TradeEntry entry)
{
int amount = 40;
if (entry.Details.Count > 1)
amount = 40 + Utility.RandomMinMax(10, entry.Details.Count * 20);
switch (Utility.Random(4))
{
case 0:
switch (Utility.Random(9))
{
case 0: return new IronIngot(amount);
case 1: return new DullCopperIngot(amount);
case 2: return new ShadowIronIngot(amount);
case 3: return new CopperIngot(amount);
case 4: return new BronzeIngot(amount);
case 5: return new GoldIngot(amount);
case 6: return new AgapiteIngot(amount);
case 7: return new VeriteIngot(amount);
case 8: return new ValoriteIngot(amount);
}
break;
case 1:
switch (Utility.Random(4))
{
case 0: return new Leather(amount);
case 1: return new SpinedLeather(amount);
case 2: return new HornedLeather(amount);
case 3: return new BarbedLeather(amount);
}
break;
case 2:
switch (Utility.Random(7))
{
case 0: return new Board(amount);
case 1: return new OakBoard(amount);
case 2: return new AshBoard(amount);
case 3: return new YewBoard(amount);
case 4: return new BloodwoodBoard(amount);
case 5: return new HeartwoodBoard(amount);
case 6: return new FrostwoodBoard(amount);
}
break;
case 3:
Item item = Loot.Construct(SkillHandlers.Imbuing.IngredTypes[Utility.Random(SkillHandlers.Imbuing.IngredTypes.Length)]);
amount /= 10;
if (item != null && item.Stackable)
item.Amount = amount;
return item;
}
return null;
}
private class InternalGump : Gump
{
public InternalGump() : base(40, 40)
{
AddBackground(0, 0, 500, 400, 9380);
AddHtmlLocalized(30, 50, 400, 16, 1152962, 0x4800, false, false); // City Trade Minister
AddHtmlLocalized(30, 80, 440, 320, 1152963, 0x001F, false, false);
}
}
public class InternalTradeOrderGump : Gump
{
public TradeMinister Minister { get; private set; }
public PlayerMobile User { get; set; }
public InternalTradeOrderGump(PlayerMobile user, TradeMinister minister)
: base(100, 100)
{
Minister = minister;
User = user;
AddGumpLayout();
}
public void AddGumpLayout()
{
AddBackground(0, 0, 370, 420, 9300);
AddHtmlLocalized(10, 30, 350, 18, 1114513, "#1114454", 0x3442, false, false); // An Offer For a trade Order
/*
* Greetings! His majesty thanks you for furthering the economic interests of the City!
* The Trade Association hath decreed that all goods shall be transported without the use of magic,
* for fear that use of such magics will corrupt the quality of the goods held within.
* Be forewarned! The life of a trader is sure to be met with peril as highwayman and pirates
* alike seek to profit a bit of coin for the goods. Good luck!
*/
AddHtmlLocalized(10, 61, 350, 162, 1114455, 0x10, false, false);
/*
* <i>Should you accept this trade order your ability to magically teleport to another location will be disabled.
* You may cancel the trade order at any time by accessing the context menu on the trade crate by single left clicking</i>
*/
AddHtmlLocalized(10, 225, 350, 90, 1151721, 0x3442, false, false);
AddButton(10, 390, 4005, 4007, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(50, 390, 100, 20, 1049011, 0x10, false, false); // I Accept!
AddButton(330, 390, 4017, 4019, 0, GumpButtonType.Reply, 0);
AddHtmlLocalized(220, 390, 100, 20, 1114514, "#1006045", 0x4000, false, false); // Cancel
}
public override void OnResponse(NetState state, RelayInfo info)
{
if (info.ButtonID == 1)
{
if (!Minister.InRange(User, 5))
{
User.SendLocalizedMessage(500295); // You are too far away to do that.
}
else
{
CityLoyaltySystem.CityTrading.TryOfferTrade(User, Minister);
}
}
}
}
public TradeMinister(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write((int)City);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
City = (City)reader.ReadInt();
if (CitySystem != null)
CitySystem.Minister = this;
Ministers.Add(this);
}
public static void Configure()
{
Ministers = new List<TradeMinister>();
}
public static List<TradeMinister> Ministers { get; private set; }
}
}

View File

@@ -0,0 +1,344 @@
using System;
using System.Collections.Generic;
using Server;
using Server.ContextMenus;
using Server.Items;
using Server.Gumps;
using System.Linq;
using Server.Network;
using Server.Engines.SeasonalEvents;
namespace Server.Engines.CityLoyalty
{
public class TradeOrderCrate : Container
{
public override int LabelNumber { get { return CityTradeSystem.KrampusEncounterActive ? 1123594 : base.LabelNumber; } }
[CommandProperty(AccessLevel.GameMaster)]
public TradeEntry Entry { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public Mobile Owner { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public bool Fulfilled
{
get
{
if(Entry == null)
return false;
foreach (var details in Entry.Details)
{
if (GetAmount(details.ItemType) < details.Amount)
return false;
}
return true;
}
}
[CommandProperty(AccessLevel.GameMaster)]
public DateTime Expires { get; set; }
public bool Expired { get { return Expires < DateTime.UtcNow; } }
public override int DefaultMaxWeight { get { return 1000; } }
public TradeOrderCrate(Mobile from, TradeEntry entry)
: base(GetID())
{
Owner = from;
Entry = entry;
if (CityTradeSystem.KrampusEncounterActive)
{
Weight = 10.0;
Hue = Utility.Random(100);
}
Expires = DateTime.UtcNow + TimeSpan.FromHours(CityTradeSystem.CrateDuration);
}
private static int GetID()
{
if (CityTradeSystem.KrampusEncounterActive)
{
return Utility.Random(0x46A2, 6);
}
return Utility.Random(0xE3C, 4);
}
public override int DefaultGumpID
{
get
{
switch(ItemID)
{
default:
return base.DefaultGumpID;
case 0x46A2:
return 0x11B;
case 0x46A3:
return 0x11C;
case 0x46A4:
return 0x11D;
case 0x46A5:
case 0x46A6:
return 0x11E;
}
}
}
public override bool DisplaysContent { get { return false; } }
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
list.Add(1151737, String.Format("#{0}", CityLoyaltySystem.CityLocalization(Entry.Destination))); // Destination City: ~1_city~
list.Add(1076255); // NO-TRADE
int weight = Items.Sum(x => x.Amount);
list.Add(1072241, "{0}\t{1}\t{2}\t{3}", Items.Count, DefaultMaxItems, weight, DefaultMaxWeight); // Contents: ~1_COUNT~/~2_MAXCOUNT items, ~3_WEIGHT~/~4_MAXWEIGHT~ stones
list.Add(1072210, "75"); // Weight reduction: ~1_PERCENTAGE~%
if (Entry.Details != null)
{
for (int i = 0; i < Entry.Details.Count; i++)
{
if(Utility.ToInt32(Entry.Details[i].Name) > 0)
list.Add(1116453 + i, String.Format("#{0}\t{1}\t{2}", Entry.Details[i].Name, GetAmount(Entry.Details[i].ItemType), Entry.Details[i].Amount)); // ~1_val~: ~2_val~/~3_val~
else
list.Add(1116453 + i, String.Format("{0}\t{1}\t{2}", Entry.Details[i].Name, GetAmount(Entry.Details[i].ItemType), Entry.Details[i].Amount)); // ~1_val~: ~2_val~/~3_val~
}
}
if (!Expired)
{
int hours = (int)Math.Max(1, (Expires - DateTime.UtcNow).TotalHours);
list.Add(1153090, hours.ToString()); // Lifespan: ~1_val~ hours
}
}
public override void Delete()
{
CityLoyaltySystem.CityTrading.RemoveCrate(Owner, this);
base.Delete();
}
public override bool TryDropItem(Mobile from, Item item, bool message)
{
if(Entry == null)
return false;
if(TryAddItem(from, item, message))
return base.TryDropItem(from, item, message);
return false;
}
public bool TryAddItem(Mobile from, Item item, bool message = true)
{
bool canAdd = false;
foreach (var details in Entry.Details)
{
if (item.GetType() == details.ItemType)
{
int hasAmount = GetAmount(item.GetType());
if (hasAmount + item.Amount > details.Amount)
{
if (message)
from.SendLocalizedMessage(1151726); // You are trying to add too many of this item to the trade order. Only add the required quantity
break;
}
else
{
canAdd = true;
break;
}
}
}
if (!canAdd && message)
from.SendLocalizedMessage(1151725); // This trade order does not require this item.
return canAdd;
}
public override int GetTotal(TotalType type)
{
if (type == TotalType.Weight)
{
int weight = base.GetTotal(type);
if (weight > 0)
return (int)Math.Max(1, (base.GetTotal(type) * .25));
}
return base.GetTotal(type);
}
public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
{
base.GetContextMenuEntries(from, list);
if(IsChildOf(from.Backpack))
{
list.Add(new FillFromPackEntry(this, from));
list.Add(new CancelOrderEntry(this, from));
}
}
private class FillFromPackEntry : ContextMenuEntry
{
public TradeOrderCrate Crate { get; private set; }
public Mobile Player { get; private set; }
public FillFromPackEntry(TradeOrderCrate crate, Mobile player) : base(1154908, 3) // Fill from pack
{
Crate = crate;
Player = player;
}
public override void OnClick()
{
if(Crate.IsChildOf(Player.Backpack) && !Crate.Deleted && Crate.Entry != null)
{
foreach (TradeEntry.TradeDetails detail in Crate.Entry.Details)
{
Item[] items = Player.Backpack.FindItemsByType(detail.ItemType);
foreach (Item item in items)
{
if (item.Amount == 1 && Crate.TryAddItem(Player, item, false))
Crate.DropItem(item);
}
}
}
}
}
private class CancelOrderEntry : ContextMenuEntry
{
public TradeOrderCrate Crate { get; private set; }
public Mobile Player { get; private set; }
public CancelOrderEntry(TradeOrderCrate crate, Mobile player) : base(1151727, 3) // cancel trade order
{
Crate = crate;
Player = player;
}
public override void OnClick()
{
Player.CloseGump(typeof(CancelTradeOrderGump));
Player.SendGump(new CancelTradeOrderGump(Crate, Player));
}
}
public override bool OnDroppedOnto(Mobile from, Item target)
{
from.SendLocalizedMessage(1076254); // That item cannot be dropped.
return false;
}
public override bool OnDroppedInto(Mobile from, Container target, Point3D p)
{
if (target == from.Backpack)
return base.OnDroppedInto(from, target, p);
from.SendLocalizedMessage(1076254); // That item cannot be dropped.
return false;
}
public override bool OnDragDropInto(Mobile from, Item item, Point3D p)
{
from.SendLocalizedMessage(1076254); // That item cannot be dropped.
return false;
}
public override bool OnDroppedToWorld(Mobile from, Point3D point)
{
from.SendLocalizedMessage(1076254); // That item cannot be dropped.
return false;
}
public override bool AllowSecureTrade(Mobile from, Mobile to, Mobile newOwner, bool accepted)
{
from.SendLocalizedMessage(1076256); // That item cannot be traded.
return false;
}
public TradeOrderCrate(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(Owner);
writer.Write(Expires);
Entry.Serialize(writer);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int v = reader.ReadInt();
Owner = reader.ReadMobile();
Expires = reader.ReadDateTime();
Entry = new TradeEntry(reader);
}
}
public class CancelTradeOrderGump : Gump
{
public TradeOrderCrate Crate { get; private set; }
public Mobile Player { get; private set; }
public CancelTradeOrderGump(TradeOrderCrate crate, Mobile player)
: base(100, 100)
{
Crate = crate;
Player = player;
AddPage(0);
AddBackground(0, 0, 291, 93, 0x13BE);
AddImageTiled(5, 5, 280, 60, 0xA40);
AddHtmlLocalized(9, 9, 272, 60, 1151728, 0x7FFF, false, false); // Are you sure you wish to cancel this trade order? All contents of the trade crate will be placed in your backpack.
AddButton(160, 67, 0xFB7, 0xFB8, 1, GumpButtonType.Reply, 0);
AddHtmlLocalized(195, 69, 120, 20, 1006044, 0x7FFF, false, false); // OKAY
AddButton(5, 67, 0xFB1, 0xFB2, 0, GumpButtonType.Reply, 0);
AddHtmlLocalized(40, 69, 100, 20, 1060051, 0x7FFF, false, false); // CANCEL
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID == 1)
{
if (Crate != null && Crate.IsChildOf(Player.Backpack))
{
CityTradeSystem.CancelTradeOrder(Player, Crate);
}
}
}
}
}

View File

@@ -0,0 +1,146 @@
using System;
using Server;
using Server.Mobiles;
using Server.ContextMenus;
using System.Collections.Generic;
namespace Server.Engines.CityLoyalty
{
[PropertyObject]
public class TradeEntry
{
[CommandProperty(AccessLevel.GameMaster)]
public City Origin { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public City Destination { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Kills { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Distance { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime LastAmbush { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public string TurnIn
{
get
{
string str = "";
Details.ForEach(d =>
{
str += d.ItemType.Name + ", ";
});
return str;
}
}
public List<TradeDetails> Details { get; set; }
public TradeEntry(City destination, City origin, int distance)
{
Origin = origin;
Destination = destination;
Distance = distance;
Details = new List<TradeDetails>();
}
public override string ToString()
{
return "...";
}
public int CalculateGold()
{
if (Distance == 0)
return 0;
int gold = 0;
Details.ForEach(d =>
{
gold += d.Worth * 3;
});
return Math.Max(CityTradeSystem.TurnInGold, gold + (Distance * 10) + Math.Min(25000, (Kills * 500)));
}
public class TradeDetails
{
public Type ItemType { get; set; }
public int Amount { get; set; }
public int Worth { get; set; }
public string Name { get; set; }
public TradeDetails(Type type, int worth, int amount, string fallbackname)
{
ItemType = type;
Worth = worth;
Amount = amount;
Name = CityLoyaltySystem.CityTrading.GetNameFor(type, fallbackname);
}
public TradeDetails(GenericReader reader)
{
int version = reader.ReadInt();
ItemType = ScriptCompiler.FindTypeByName(reader.ReadString());
Worth = reader.ReadInt();
Amount = reader.ReadInt();
Name = reader.ReadString();
}
public void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write(ItemType.Name);
writer.Write(Worth);
writer.Write(Amount);
writer.Write(Name);
}
}
public TradeEntry(GenericReader reader)
{
int version = reader.ReadInt();
Origin = (City)reader.ReadInt();
Destination = (City)reader.ReadInt();
LastAmbush = reader.ReadDateTime();
Kills = reader.ReadInt();
Distance = reader.ReadInt();
Details = new List<TradeDetails>();
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
Details.Add(new TradeDetails(reader));
}
}
public void Serialize(GenericWriter writer)
{
writer.Write(0);
writer.Write((int)Origin);
writer.Write((int)Destination);
writer.Write(LastAmbush);
writer.Write(Kills);
writer.Write(Distance);
writer.Write(Details.Count);
Details.ForEach(d => d.Serialize(writer));
}
}
}

View File

@@ -0,0 +1,833 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Engines.Points;
using Server.Engines;
using Server.Items;
using Server.Multis;
using Server.Regions;
using Server.Engines.SeasonalEvents;
namespace Server.Engines.CityLoyalty
{
public enum TradeTitle
{
Trader = 1151739,
Exporter = 1151741,
Broker = 1151743,
Tycoon = 1151745,
Smuggler = 1151747,
Magnate = 1155481
}
public class CityTradeSystem : PointsSystem
{
public static readonly int TurnInGold = Config.Get("CityTrading.TurnInGold", 10000);
public static readonly int CrateDuration = Config.Get("CityTrading.CrateDuration", 24);
public static readonly int AmbushWaitDuration = Config.Get("CityTrading.AmbushWaitDuration", 5);
public static readonly int AmbusherDelete = Config.Get("CityTrading.AmbusherDelete", 10);
public override TextDefinition Name { get { return new TextDefinition("City Trading"); } }
public override PointsType Loyalty { get { return PointsType.CityTrading; } }
public override bool AutoAdd { get { return false; } }
public override double MaxPoints { get { return double.MaxValue; } }
public override bool ShowOnLoyaltyGump { get { return false; } }
public static bool KrampusEncounterActive { get { return KrampusEncounter.Enabled && KrampusEncounter.Encounter != null; } }
public static Dictionary<Mobile, TradeOrderCrate> ActiveTrades { get; private set; }
public static Dictionary<BaseCreature, DateTime> Ambushers { get; private set; }
public CityTradeSystem()
{
ActiveTrades = new Dictionary<Mobile, TradeOrderCrate>();
_NameBuffer = new Dictionary<Type, string>();
}
public override PointsEntry GetSystemEntry(PlayerMobile pm)
{
return new CityTradeEntry(pm);
}
public int GetMaxTrades(Mobile m)
{
CityTradeEntry entry = GetPlayerEntry<CityTradeEntry>(m as PlayerMobile);
if(entry == null)
return 1;
return Math.Min(8, Math.Max(1, (entry.Completed / 25) + 1));
}
public static bool HasTrade(Mobile from)
{
return ActiveTrades.ContainsKey(from);
}
public bool HasTurnIn(Mobile from, TradeMinister minister)
{
if(from == null || minister == null || !ActiveTrades.ContainsKey(from) || ActiveTrades[from] == null)
return false;
TradeOrderCrate crate = ActiveTrades[from];
return crate.Entry != null && crate.Entry.Origin != minister.City;
}
public bool TryOfferTrade(Mobile from, TradeMinister minister)
{
if(from == null || from.Backpack == null)
return true;
if (ActiveTrades.ContainsKey(from))
{
minister.SayTo(from, 1151722); // It appears you are already delivering a trade order. Deliver your current order before requesting another.
}
else if (KrampusEncounterActive && (KrampusEncounter.Encounter.Krampus != null || KrampusEncounter.Encounter.KrampusSpawning))
{
var p = KrampusEncounter.Encounter.SpawnLocation;
var map = KrampusEncounter.Encounter.SpawnMap;
minister.SayTo(
from,
1158790,
String.Format("{0}\t{1}",
WorldLocationInfo.GetLocationString(p, map),
Sextant.GetCoords(p, map)), 1150);
// Take notice! The vile Krampus has been spotted near ~2_where~ at ~1_coords~! New Trade Orders are suspended until Krampus has been defeated!
}
else
{
City origin = minister.City;
City destination;
do
{
destination = CityLoyaltySystem.GetRandomCity();
}
while (destination == origin);
int distance = GetDistance(minister, destination);
int trades = Utility.RandomMinMax(1, GetMaxTrades(from));
TradeEntry entry = new TradeEntry(destination, origin, distance);
TradeOrderCrate crate = new TradeOrderCrate(from, entry);
GetPlayerEntry<CityTradeEntry>(from as PlayerMobile, true);
for (int i = 0; i < trades; i++)
{
int worth = 1;
string name = null;
Type t = GetRandomTrade(origin, destination, ref worth, ref name);
if (t != null)
{
int amount = Utility.RandomList(5, 10, 15, 20);
entry.Details.Add(new TradeEntry.TradeDetails(t, worth, amount, name));
}
else
{
minister.SayTo(from, "There are no trades available at this time.");
return false;
}
}
if (from.Backpack == null || !from.Backpack.TryDropItem(from, crate, false))
{
crate.Delete();
from.SendLocalizedMessage(114456); // Your backpack cannot hold the Trade Order. Free up space and speak to the Trade Minister again.
}
ActiveTrades[from] = crate;
return true;
}
return false;
}
public bool TryTurnIn(Mobile from, TradeOrderCrate order, Mobile turninMobile)
{
if (order == null || from == null || turninMobile == null || order.Entry == null)
return false;
TradeEntry entry = order.Entry;
TradeMinister minister = turninMobile as TradeMinister;
if(from.AccessLevel == AccessLevel.Player && minister != null && minister.City != entry.Destination)
turninMobile.SayTo(from, 1151738, String.Format("#{0}", CityLoyaltySystem.GetCityLocalization(entry.Destination))); // Begging thy pardon, but those goods are destined for the City of ~1_city~
else if(!order.Fulfilled)
turninMobile.SayTo(from, 1151732); // This trade order has not been fulfilled. Fill the trade order with all necessary items and try again.
else
{
CityLoyaltySystem.OnTradeComplete(from, order.Entry);
CityTradeEntry pentry = GetPlayerEntry<CityTradeEntry>(from as PlayerMobile);
if (pentry != null)
{
pentry.Points++;
pentry.DistanceTraveled += entry.Distance;
pentry.Completed++;
CheckTitle(pentry);
}
order.Delete();
return true;
}
return false;
}
public bool TryTurnInToSlim(Mobile from, TradeOrderCrate order, SlimTheFence slim)
{
if (order == null || from == null || slim == null || order.Entry == null)
return false;
TradeEntry entry = order.Entry;
if (!order.Fulfilled)
slim.SayTo(from, 1151732); // This trade order has not been fulfilled. Fill the trade order with all necessary items and try again.
else
{
CityLoyaltySystem.OnSlimTradeComplete(from, order.Entry);
CityTradeEntry pentry = GetPlayerEntry<CityTradeEntry>(from as PlayerMobile, true);
if (pentry != null)
{
pentry.Points++;
pentry.DistanceTraveled += entry.Distance;
pentry.CompletedSlim++;
CheckTitle(pentry);
}
slim.SayTo(from, 1151736); // Haha! These goods will fetch me quite a bit o' coin! Thanks fer yer help! Here's a little something I was able to get me hands on...
order.Delete();
return true;
}
return false;
}
public void CheckTitle(CityTradeEntry entry)
{
switch (entry.Completed)
{
case 1: entry.Player.AddRewardTitle((int)TradeTitle.Trader); break;
case 25: entry.Player.AddRewardTitle((int)TradeTitle.Exporter); break;
case 50: entry.Player.AddRewardTitle((int)TradeTitle.Broker); break;
case 100: entry.Player.AddRewardTitle((int)TradeTitle.Tycoon); break;
case 150: entry.Player.AddRewardTitle((int)TradeTitle.Magnate); break;
}
if(entry.CompletedSlim == 50)
entry.Player.AddRewardTitle((int)TradeTitle.Smuggler);
}
public override void OnPlayerAdded(PlayerMobile m)
{
m.Backpack.DropItem(new MysteriousNote());
m.PrivateOverheadMessage(Server.Network.MessageType.Regular, 1150, 1151734, m.NetState); // *A passerby slips a rolled bit of parchment into your hand...*
}
public static void CancelTradeOrder(Mobile from, TradeOrderCrate crate)
{
if (from == null)
from = crate.Owner;
if (from != null)
{
crate.Items.ForEach(i =>
{
from.Backpack.DropItem(i);
});
CityTradeEntry entry = CityLoyaltySystem.CityTrading.GetPlayerEntry<CityTradeEntry>(from as PlayerMobile, true);
if (entry != null)
entry.Canceled++;
}
crate.Delete();
}
private Dictionary<Type, string> _NameBuffer;
public string GetNameFor(Type t, string fallbackname)
{
if (_NameBuffer.ContainsKey(t))
return _NameBuffer[t];
Item item = Loot.Construct(t);
if (item != null)
{
string name;
if (item.Name != null)
{
name = item.Name;
}
else
{
name = item.LabelNumber.ToString();
}
_NameBuffer[t] = name;
item.Delete();
return name;
}
Console.WriteLine("WARNING: Using Fallback name for: {0}", t.Name);
return fallbackname;
}
public void RemoveCrate(Mobile from, TradeOrderCrate crate)
{
if(ActiveTrades.ContainsKey(from))
{
ActiveTrades.Remove(from);
}
}
public static void OnPublicMoongateUsed(Mobile from)
{
if (ActiveTrades.ContainsKey(from))
{
ActiveTrades[from].Entry.Distance = 0;
}
}
public static int GetDistance(TradeMinister origin, City destination)
{
TradeMinister destMinister = TradeMinister.Ministers.FirstOrDefault(m => m.City == destination);
if(destMinister != null)
{
return (int)origin.GetDistanceToSqrt(destMinister.Location);
}
return 0;
}
public static Type GetRandomTrade(City originCity, City dest, ref int worth, ref string name)
{
Region region = CityLoyaltySystem.GetCityInstance(originCity).Definition.Region;
List<BaseVendor> list = new List<BaseVendor>(region.GetEnumeratedMobiles().OfType<BaseVendor>().Where(bv => bv.GetBuyInfo() != null && bv.GetBuyInfo().Length > 0));
if (list.Count == 0)
return null;
do
{
BaseVendor vendor = list[Utility.Random(list.Count)];
IBuyItemInfo[] buyInfo = vendor.GetBuyInfo();
GenericBuyInfo info = buyInfo[Utility.Random(buyInfo.Length)] as GenericBuyInfo;
if (!(info is BeverageBuyInfo) && !(info is AnimalBuyInfo) && info != null && info.Type != null && info.Args == null && info.Price < 5000)
{
list.Clear();
list.TrimExcess();
worth = info.Price;
name = info.Name;
return info.Type;
}
else
list.Remove(vendor);
}
while (list.Count > 0);
list.Clear();
list.TrimExcess();
return null;
}
public static void OnTick()
{
List<TradeOrderCrate> crates = new List<TradeOrderCrate>(ActiveTrades.Values);
List<BaseCreature> toDelete = new List<BaseCreature>();
foreach (var c in crates)
{
if (c.Expired)
{
CancelTradeOrder(c.Owner, c);
}
else if (c.Entry != null)
{
CheckAmbush(c);
}
}
if (Ambushers != null)
{
foreach (KeyValuePair<BaseCreature, DateTime> kvp in Ambushers)
{
if (kvp.Value < DateTime.UtcNow)
toDelete.Add(kvp.Key);
}
toDelete.ForEach(bc =>
{
if (!bc.Deleted)
bc.Delete();
Ambushers.Remove(bc);
});
}
toDelete.Clear();
toDelete.TrimExcess();
crates.Clear();
crates.TrimExcess();
}
public static void CheckAmbush(TradeOrderCrate crate)
{
if (crate == null || crate.Deleted || crate.Entry == null || crate.Expired || crate.Entry.LastAmbush + TimeSpan.FromMinutes(AmbushWaitDuration) > DateTime.UtcNow)
return;
if (crate.RootParentEntity is Mobile && !((Mobile)crate.RootParentEntity).Region.IsPartOf<GuardedRegion>())
{
Mobile m = crate.RootParentEntity as Mobile;
if (m.NetState != null && m.Map != null && m.Map != Map.Internal)
{
double chance = crate.Entry.LastAmbush == DateTime.MinValue ? 0.25 : .05;
if (chance > Utility.RandomDouble())
{
double dif = (double)(Math.Min(7200, m.SkillsTotal) + m.RawStr + m.RawInt + m.RawDex) / 10000;
m.RevealingAction();
SpawnCreatures(m, dif);
crate.Entry.LastAmbush = DateTime.UtcNow;
}
}
}
}
public static void SpawnCreatures(Mobile m, double difficulty)
{
BaseBoat boat = BaseBoat.FindBoatAt(m.Location, m.Map);
Type[] types = GetCreatureType(m, boat != null);
if (types == null)
{
return;
}
int amount = Utility.RandomMinMax(3, 5);
for (int i = 0; i < amount; i++)
{
BaseCreature bc = Activator.CreateInstance(types[Utility.Random(types.Length)]) as BaseCreature;
if (bc != null)
{
if (KrampusEncounterActive)
{
bc.Name = "An Icy Creature";
}
Rectangle2D zone;
if (boat != null)
{
if (boat.Facing == Direction.North || boat.Facing == Direction.South)
{
if (Utility.RandomBool())
{
zone = new Rectangle2D(boat.X - 7, m.Y - 4, 3, 3);
}
else
{
zone = new Rectangle2D(boat.X + 4, m.Y - 4, 3, 3);
}
}
else
{
if (Utility.RandomBool())
{
zone = new Rectangle2D(m.X + 4, boat.Y - 7, 3, 3);
}
else
{
zone = new Rectangle2D(m.X + 4, boat.Y + 4, 3, 3);
}
}
}
else
{
zone = new Rectangle2D(m.X - 3, m.Y - 3, 6, 6);
}
Point3D p = m.Location;
if (m.Map != null)
{
for (int j = 0; j < 25; j++)
{
Point3D check = m.Map.GetRandomSpawnPoint(zone);
if (CanFit(check.X, check.Y, check.Z, m.Map, bc))
{
p = check;
break;
}
}
}
foreach (Skill sk in bc.Skills.Where(s => s.Base > 0))
{
sk.Base += sk.Base * (difficulty);
}
bc.RawStr += (int)(bc.RawStr * difficulty);
bc.RawInt += (int)(bc.RawInt * difficulty);
bc.RawDex += (int)(bc.RawDex * difficulty);
if (bc.HitsMaxSeed == -1)
bc.HitsMaxSeed = bc.RawStr;
if (bc.StamMaxSeed == -1)
bc.StamMaxSeed = bc.RawDex;
if (bc.ManaMaxSeed == -1)
bc.ManaMaxSeed = bc.RawInt;
bc.HitsMaxSeed += (int)(bc.HitsMaxSeed * difficulty);
bc.StamMaxSeed += (int)(bc.StamMaxSeed * difficulty);
bc.ManaMaxSeed += (int)(bc.ManaMaxSeed * difficulty);
bc.Hits = bc.HitsMaxSeed;
bc.Stam = bc.RawDex;
bc.Mana = bc.RawInt;
bc.PhysicalResistanceSeed += (int)(bc.PhysicalResistanceSeed * (difficulty / 3));
bc.FireResistSeed += (int)(bc.FireResistSeed * (difficulty / 3));
bc.ColdResistSeed += (int)(bc.ColdResistSeed * (difficulty / 3));
bc.PoisonResistSeed += (int)(bc.PoisonResistSeed * (difficulty / 3));
bc.EnergyResistSeed += (int)(bc.EnergyResistSeed * (difficulty / 3));
bc.IsAmbusher = true;
if (Ambushers == null)
Ambushers = new Dictionary<BaseCreature, DateTime>();
Ambushers.Add(bc, DateTime.UtcNow + TimeSpan.FromMinutes(AmbusherDelete));
bc.MoveToWorld(p, m.Map);
Timer.DelayCall(() => bc.Combatant = m);
}
}
m.LocalOverheadMessage(Server.Network.MessageType.Regular, 1150, 1155479); // *Your keen senses alert you to an incoming ambush of attackers!*
m.SendLocalizedMessage(1049330, "", 0x22); // You have been ambushed! Fight for your honor!!!
}
public static Type[] GetCreatureType(Mobile m, bool wet)
{
if (KrampusEncounterActive)
{
return KrampusEncounter.Encounter.GetCreatureTypes(m, wet);
}
return wet ? _SeaTypes : _LandTypes;
}
public override void ProcessKill(Mobile victim, Mobile damager)
{
if (victim is BaseCreature && Ambushers != null && Ambushers.ContainsKey((BaseCreature)victim))
{
if (ActiveTrades.ContainsKey(damager))
{
TradeOrderCrate crate = ActiveTrades[damager];
if (crate.Entry != null)
crate.Entry.Kills++;
}
Ambushers.Remove((BaseCreature)victim);
}
}
private static Type[] _SeaTypes =
{
typeof(SeaSerpent), typeof(DeepSeaSerpent), typeof(Kraken), typeof(WaterElemental)
};
private static Type[] _LandTypes =
{
typeof(Troll), typeof(Ettin), typeof(GiantSpider), typeof(Brigand)
};
public static bool CanFit(int x, int y, int z, Map map, Mobile mob, int height = 16, bool checkMobiles = true, bool requireSurface = true)
{
if (map == null || map == Map.Internal)
return false;
if (x < 0 || y < 0 || x >= map.Width || y >= map.Height)
return false;
bool hasSurface = false;
bool canswim = mob.CanSwim;
bool cantwalk = mob.CantWalk;
LandTile lt = map.Tiles.GetLandTile(x, y);
int lowZ = 0, avgZ = 0, topZ = 0;
bool surface, impassable;
map.GetAverageZ(x, y, ref lowZ, ref avgZ, ref topZ);
TileFlag landFlags = TileData.LandTable[lt.ID & TileData.MaxLandValue].Flags;
impassable = (landFlags & TileFlag.Impassable) != 0;
bool wet = (landFlags & TileFlag.Wet) != 0;
if (cantwalk && !wet)
{
impassable = true;
}
if (canswim && wet)
{
impassable = false;
}
if (impassable && avgZ > z && (z + height) > lowZ)
return false;
else if (!impassable && z == avgZ && !lt.Ignored)
hasSurface = true;
StaticTile[] staticTiles = map.Tiles.GetStaticTiles(x, y, true);
for (int i = 0; i < staticTiles.Length; ++i)
{
ItemData id = TileData.ItemTable[staticTiles[i].ID & TileData.MaxItemValue];
surface = id.Surface;
impassable = id.Impassable;
wet = (id.Flags & TileFlag.Wet) != 0;
if (cantwalk && !wet)
{
impassable = true;
}
if (canswim && wet)
{
surface = true;
impassable = false;
}
if ((surface || impassable) && (staticTiles[i].Z + id.CalcHeight) > z && (z + height) > staticTiles[i].Z)
return false;
else if (surface && !impassable && z == (staticTiles[i].Z + id.CalcHeight))
hasSurface = true;
}
IPooledEnumerable eable = map.GetItemsInRange(new Point3D(x, y, z), 0);
foreach(Item item in eable)
{
if (item.ItemID < 0x4000)
{
ItemData id = item.ItemData;
surface = id.Surface;
impassable = id.Impassable;
wet = (id.Flags & TileFlag.Wet) != 0;
if (cantwalk && !wet)
{
impassable = true;
}
if (canswim && wet)
{
surface = true;
impassable = false;
}
if ((surface || impassable) && (item.Z + id.CalcHeight) > z && (z + height) > item.Z)
{
eable.Free();
return false;
}
else if (surface && !impassable && !item.Movable && z == (item.Z + id.CalcHeight))
{
hasSurface = true;
}
}
}
eable.Free();
if (checkMobiles)
{
eable = map.GetMobilesInRange(new Point3D(x, y, z), 0);
foreach(Mobile m in eable)
{
if (m.AccessLevel == AccessLevel.Player || !m.Hidden)
{
if ((m.Z + 16) > z && (z + height) > m.Z)
{
eable.Free();
return false;
}
}
}
eable.Free();
}
return !requireSurface || hasSurface;
}
[PropertyObject]
public class CityTradeEntry : PointsEntry
{
[CommandProperty(AccessLevel.GameMaster)]
public int Canceled { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int DistanceTraveled { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Completed { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int CompletedSlim { get; set; }
public CityTradeEntry(PlayerMobile pm) : base(pm)
{
}
public override string ToString()
{
return "...";
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1);
writer.Write(Canceled);
writer.Write(DistanceTraveled);
writer.Write(Completed);
writer.Write(Ambushers == null ? 0 : Ambushers.Count);
if (Ambushers != null)
{
foreach (KeyValuePair<BaseCreature, DateTime> kvp in Ambushers)
{
writer.Write(kvp.Key);
writer.Write(kvp.Value);
}
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
Canceled = reader.ReadInt();
DistanceTraveled = reader.ReadInt();
Completed = reader.ReadInt();
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
BaseCreature bc = reader.ReadMobile() as BaseCreature;
DateTime dt = reader.ReadDateTime();
if (bc != null)
{
if (dt < DateTime.UtcNow)
bc.Delete();
else
{
if (Ambushers == null)
Ambushers = new Dictionary<BaseCreature, DateTime>();
bc.IsAmbusher = true;
Ambushers[bc] = dt;
}
}
}
if (version == 0)
{
Timer.DelayCall(() =>
{
if (Player.RemoveRewardTitle(2303807, true))
Player.AddRewardTitle(1151739);
});
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
writer.Write(ActiveTrades.Count);
foreach (KeyValuePair<Mobile, TradeOrderCrate> kvp in ActiveTrades)
{
writer.Write(kvp.Key);
writer.Write(kvp.Value);
}
writer.Write(_NameBuffer.Count);
foreach (KeyValuePair<Type, string> kvp in _NameBuffer)
{
writer.Write(kvp.Key.Name);
writer.Write(kvp.Value);
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
Mobile m = reader.ReadMobile();
TradeOrderCrate crate = reader.ReadItem() as TradeOrderCrate;
if (m != null && crate != null)
ActiveTrades[m] = crate;
}
_NameBuffer = new Dictionary<Type, string>();
count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
Type t = ScriptCompiler.FindTypeByName(reader.ReadString());
string name = reader.ReadString();
if (t != null)
_NameBuffer[t] = name;
}
}
}
}