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,71 @@
using Server;
using System;
using Server.Mobiles;
using Server.Items;
using Server.Multis;
namespace Server.Engines.Quests
{
public class BountyQuestObjective : BaseObjective
{
private bool m_Captured;
private Mobile m_CapturedCaptain;
public bool Captured { get { return m_Captured; } set { m_Captured = value; } }
public Mobile CapturedCaptain { get { return m_CapturedCaptain; } set { m_CapturedCaptain = value; } }
public BountyQuestObjective()
{
}
public override bool Update(object obj)
{
Mobile from = (Mobile)obj;
Mobile captain = ((ProfessionalBountyQuest)Quest).Captain;
Mobile quester = Quest.Quester as Mobile;
if (from == null || captain == null)
return false;
Container pack = from.Backpack;
bool inRange = quester != null && quester.InRange(captain.Location, 75);
if (m_Captured && inRange)
return true;
Item item = pack.FindItemByType(typeof(DeathCertificate));
if (item != null && Quest is ProfessionalBountyQuest && ((DeathCertificate)item).Owner != null)
{
item.Delete();
return true;
}
return false;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt((int)1); // version
writer.Write(m_Captured);
writer.Write(m_CapturedCaptain);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
m_Captured = reader.ReadBool();
m_CapturedCaptain = reader.ReadMobile();
Timer.DelayCall(TimeSpan.FromSeconds(10), new TimerCallback(ValidateCaught));
}
private void ValidateCaught()
{
if (m_CapturedCaptain != null && m_CapturedCaptain is PirateCaptain && this.Quest is ProfessionalBountyQuest)
((PirateCaptain)m_CapturedCaptain).Quest = this.Quest as ProfessionalBountyQuest;
}
}
}

View File

@@ -0,0 +1,60 @@
using Server;
using System;
using Server.Engines.Quests;
using Server.Multis;
namespace Server.Items
{
public class BindingPole : Item, IGalleonFixture
{
private BaseQuest m_Quest;
private BaseGalleon m_Galleon;
public BaseQuest Quest
{
get { return m_Quest; }
set { m_Quest = value; }
}
public BaseGalleon Galleon
{
get { return m_Galleon; }
set { m_Galleon = value; }
}
public override int LabelNumber { get { return 1116718; } }
public override void Delete()
{
base.Delete();
if (m_Quest != null)
m_Quest.OnResign(false);
if (m_Galleon != null)
m_Galleon.RemoveFixture(this);
}
public BindingPole(BaseQuest quest) : base(5696)
{
m_Quest = quest;
Movable = false;
}
public BindingPole(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,120 @@
using Server;
using System;
using Server.Engines.Quests;
using Server.Mobiles;
using Server.Targeting;
namespace Server.Items
{
public class BindingRope : Item
{
private Mobile m_BoundMobile;
private ProfessionalBountyQuest m_Quest;
[CommandProperty(AccessLevel.GameMaster)]
public Mobile BoundMobile
{
get { return m_BoundMobile; }
set { m_BoundMobile = value; }
}
public ProfessionalBountyQuest Quest
{
get { return m_Quest; }
set { m_Quest = value; }
}
public override int LabelNumber { get { return 1116717; } }
public BindingRope(ProfessionalBountyQuest quest) : base(5368)
{
m_Quest = quest;
}
public override void OnDoubleClick(Mobile from)
{
if (IsChildOf(from.Backpack) && m_BoundMobile == null)
{
from.Target = new InternalTarget(this);
from.SendLocalizedMessage(1116720); //Who do you want to tie up?
}
}
public void DoDelayedDelete(Mobile from)
{
Timer.DelayCall(TimeSpan.FromSeconds(2.5), new TimerStateCallback(DoDelete), from);
}
public void DoDelete(object o)
{
Mobile from = (Mobile)o;
if (from != null)
from.SendMessage("Your crew uses the rope to bind the captain to the front of your galleon.");
Delete();
}
private class InternalTarget : Target
{
private BindingRope m_Rope;
public InternalTarget(BindingRope rope) : base(2, false, TargetFlags.None)
{
m_Rope = rope;
}
protected override void OnTarget(Mobile from, object targeted)
{
if(targeted is Mobile)
{
if (targeted is PirateCaptain)
{
PirateCaptain cap = (PirateCaptain)targeted;
if(cap.Hits > cap.HitsMax / 10)
{
from.SendLocalizedMessage(1116756); //The pirate seems to have too much fight left to be bound.
}
else if(cap.TryBound(from, m_Rope.Quest))
{
m_Rope.BoundMobile = cap;
m_Rope.Quest.OnBound(cap);
cap.OnBound(m_Rope.Quest);
from.SendLocalizedMessage(1116721); //You begin binding the pirate.
m_Rope.DoDelayedDelete(from);
}
}
else
{
from.SendMessage("They cannot by bound by that!");
}
}
else
{
from.SendMessage("They cannot by bound by that!");
}
}
}
public BindingRope(Serial serial) : base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write(m_BoundMobile);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_BoundMobile = reader.ReadMobile();
}
}
}

View File

@@ -0,0 +1,60 @@
using Server;
using System;
using Server.Mobiles;
using Server.Engines.Quests;
namespace Server.Items
{
public class DeathCertificate : Item
{
public override int LabelNumber { get { return 1116716; } }
private string m_Owner;
[CommandProperty(AccessLevel.GameMaster)]
public string Owner { get { return m_Owner; } }
public DeathCertificate(Mobile owner)
: base(0x14F0)
{
if (owner is PirateCaptain)
{
PirateCaptain capt = (PirateCaptain)owner;
if (capt.PirateName > 0)
m_Owner = String.Format("#{0}\t#{1}\t#{2}", capt.Adjective, capt.Noun, capt.PirateName);
else
m_Owner = String.Format("#{0}\t#{1}\t{2}", capt.Adjective, capt.Noun, Name);
}
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (m_Owner != null)
{
list.Add(1116690, m_Owner);
}
}
public DeathCertificate(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write(m_Owner);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_Owner = reader.ReadString();
}
}
}

View File

@@ -0,0 +1,685 @@
using Server;
using System;
using Server.Items;
using Server.Multis;
using System.Collections.Generic;
using Server.Engines.Quests;
using System.Linq;
namespace Server.Mobiles
{
public class BaseShipCaptain : BaseCreature
{
public static readonly TimeSpan DeleteAfterDeath = TimeSpan.FromMinutes(15);
public static readonly TimeSpan ResumeTime = TimeSpan.FromSeconds(Utility.RandomMinMax(30, 45));
public static readonly TimeSpan DecayRetry = TimeSpan.FromSeconds(30);
private BaseGalleon m_Galleon;
private bool m_OnCourse;
private DateTime m_NextCannonShot;
private DateTime m_NextMoveCheck;
private DateTime m_ActionTime;
private DateTime m_NextCrewCheck;
private SpawnZone m_Zone;
private bool m_Blockade;
private List<Mobile> m_Crew = new List<Mobile>();
[CommandProperty(AccessLevel.GameMaster)]
public BaseGalleon Galleon { get { return m_Galleon; } }
[CommandProperty(AccessLevel.GameMaster)]
public bool OnCourse { get { return m_OnCourse; } }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime NextCannonShot { get { return m_NextCannonShot; } }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime NextMoveCheck { get { return m_NextMoveCheck; } }
[CommandProperty(AccessLevel.GameMaster)]
public DateTime NextCrewCheck { get { return m_NextCrewCheck; } set { m_NextCrewCheck = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public SpawnZone Zone { get { return m_Zone; } set { m_Zone = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public bool Blockade { get { return m_Blockade; } set { m_Blockade = value; } }
public List<Mobile> Crew { get { return m_Crew; } }
[CommandProperty(AccessLevel.GameMaster)]
public virtual bool Aggressive { get { return true; } }
public override bool PlayerRangeSensitive { get { return false; } }
public override double TreasureMapChance { get { return 0.05; } }
public override int TreasureMapLevel { get { return 7; } }
[CommandProperty(AccessLevel.GameMaster)]
public virtual TimeSpan ShootFrequency
{
get
{
return TimeSpan.FromSeconds(Math.Min(20, 20.0 - ((double)m_Crew.Count * 2.5)));
}
}
[Constructable]
public BaseShipCaptain() : this(null) { }
public BaseShipCaptain(BaseGalleon galleon)
: this(galleon, AIType.AI_Melee, FightMode.Weakest, 10, 1, .2, .4)
{
}
public BaseShipCaptain(BaseGalleon galleon, AIType ai, FightMode fm, int per, int range, double passive, double active)
: base(ai, fm, per, range, passive, active)
{
m_Galleon = galleon;
m_OnCourse = true;
m_StopTime = DateTime.MinValue;
if (this.Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
AddItem(new Skirt(Utility.RandomNeutralHue()));
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
AddItem(new ShortPants(Utility.RandomNeutralHue()));
}
SetStr(500, 750);
SetDex(125, 175);
SetInt(61, 75);
SetHits(4500, 5000);
SetDamage(23, 35);
SetSkill(SkillName.Fencing, 115.0, 120.0);
SetSkill(SkillName.Macing, 115.0, 120.0);
SetSkill(SkillName.MagicResist, 115.0, 120.0);
SetSkill(SkillName.Swords, 115.0, 120.0);
SetSkill(SkillName.Tactics, 115.0, 120.0);
SetSkill(SkillName.Wrestling, 115.0, 120.0);
SetSkill(SkillName.Anatomy, 115.0, 120.0);
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);
if (galleon == null)
Timer.DelayCall(TimeSpan.FromSeconds(.5), new TimerCallback(SpawnShip));
}
public void SpawnShip()
{
BaseGalleon gal;
if (this is PirateCaptain)
gal = new OrcishGalleon(Direction.North);
else if (this.Map == Map.Tokuno)
gal = new TokunoGalleon(Direction.North);
else
gal = new GargishGalleon(Direction.North);
var p = Location;
Map map = Map;
// Move this sucka out of the way!
Internalize();
if (gal.CanFit(p, map, gal.ItemID))
{
gal.Owner = this;
gal.MoveToWorld(p, map);
m_Galleon = gal;
Server.Engines.Quests.BountyQuestSpawner.FillHold(m_Galleon);
MoveToWorld(new Point3D(p.X, p.Y - 1, gal.Z + gal.ZSurface), map);
int crewCount = Utility.RandomMinMax(3, 5);
for (int j = 0; j < crewCount; j++)
{
Mobile crew = new PirateCrew();
if (j == 0 && this is PirateCaptain)
crew.Title = "the orc captain";
AddToCrew(crew);
crew.MoveToWorld(new Point3D(gal.X + Utility.RandomList(-1, 1), gal.Y + Utility.RandomList(-1, 0, 1), gal.ZSurface), map);
}
gal.AutoAddCannons(this);
return;
}
else
{
gal.Delete();
Delete();
}
}
public void OnShipDelete()
{
if (this.Alive && !this.Deleted)
Kill();
for (int i = 0; i < m_Crew.Count; i++)
{
Mobile mob = m_Crew[i];
if (mob != null && !mob.Deleted)
mob.Kill();
}
}
public override void Delete()
{
if(BountyQuestSpawner.Instance != null)
BountyQuestSpawner.Instance.HandleDeath(this);
if (m_Galleon != null && !m_Galleon.Deleted)
{
m_Galleon.TimeOfDecay = DateTime.UtcNow + TimeSpan.FromMinutes(30);
Timer.DelayCall(DeleteAfterDeath, new TimerStateCallback(TryDecayGalleon), m_Galleon);
}
base.Delete();
}
public override void OnCombatantChange()
{
if (Combatant == null)
CantWalk = true;
else
CantWalk = false;
base.OnCombatantChange();
}
public void TryDecayGalleon(object obj)
{
BaseGalleon gal = obj as BaseGalleon;
if (gal == null)
return;
if (gal.PlayerCount() > 0)
{
Timer.DelayCall(DecayRetry, new TimerStateCallback(TryDecayGalleon), gal);
return;
}
if (gal != null && !gal.Deleted)
gal.ForceDecay();
}
public void AddToCrew(Mobile mob)
{
if (!m_Crew.Contains(mob))
m_Crew.Add(mob);
}
private DateTime m_StopTime;
private bool m_WillResume;
public void ResumeCourseTimed(TimeSpan ts, bool check)
{
if (!m_WillResume)
{
Timer.DelayCall(ts, new TimerCallback(ResumeCourse));
m_WillResume = true;
}
}
public void ResumeCourse()
{
if (m_Galleon != null)
{
m_Galleon.StartCourse(false, false);
m_WillResume = false;
m_OnCourse = true;
}
}
public override void OnThink()
{
base.OnThink();
if (m_Galleon == null)
return;
if (m_Galleon.Deleted)
OnShipDelete();
// Ship is fucked without his captain!!!
if (!m_Galleon.Contains(this))
return;
if (m_NextCrewCheck < DateTime.UtcNow)
{
CheckCrew();
}
if (!IsInBattle())
{
if (!m_OnCourse)
ResumeCourse();
else if (m_OnCourse && !m_Galleon.IsMoving && m_ActionTime < DateTime.UtcNow)
{
ResumeCourseTimed(ResumeTime, true);
m_ActionTime = DateTime.UtcNow + ResumeTime;
}
return;
}
m_OnCourse = false;
Mobile focusMob = GetFocusMob();
if(m_TargetBoat == null || !InRange(m_TargetBoat.Location, 25))
m_TargetBoat = GetFocusBoat(focusMob);
if (focusMob == null && m_TargetBoat == null)
return;
if (m_NextMoveCheck < DateTime.UtcNow && !m_Galleon.Scuttled && !m_Blockade)
{
Point3D pnt = m_TargetBoat != null ? m_TargetBoat.Location : focusMob.Location;
int dist = (int)GetDistanceToSqrt(pnt);
if (!Aggressive && dist < 25)
MoveBoat(pnt);
else if (Aggressive && dist >= 10 && dist <= 35)
MoveBoat(pnt);
else
{
m_Galleon.StopMove(false);
ResumeCourseTimed(TimeSpan.FromMinutes(2), false); //Loiter
}
}
if (m_TargetBoat != null && !m_TargetBoat.Scuttled)
ShootCannons(focusMob, true);
else
ShootCannons(focusMob, false);
}
private BaseGalleon m_TargetBoat;
public Mobile GetFocusMob()
{
Mobile focus = Combatant as Mobile;
if (focus == null || focus.Deleted || !focus.Alive)
{
int closest = 25;
foreach (Mobile mob in m_Crew)
{
if (mob.Alive && mob.Combatant is Mobile)
{
if (focus == null || (int)focus.GetDistanceToSqrt(mob) < closest)
{
focus = mob.Combatant as Mobile;
closest = (int)focus.GetDistanceToSqrt(mob);
}
}
}
}
return focus;
}
public BaseGalleon GetFocusBoat(Mobile focusMob)
{
if (focusMob == null || focusMob.Deleted || focusMob.Map == null || focusMob.Map == Map.Internal)
return null;
BaseGalleon g = BaseGalleon.FindGalleonAt(focusMob, focusMob.Map);
return g != m_Galleon ? g : null;
}
public void MoveBoat(Point3D p)
{
if (m_Galleon == null || m_Galleon.Contains(p))
return;
int x = p.X;
int y = p.Y;
int speed;
int flee = Aggressive ? 1 : -1;
//Direction d = Utility.GetDirectionTo(p.X, p.Y);
Direction dir = m_Galleon.GetMovementFor(x, y, out speed);
Direction f = m_Galleon.Facing;
if (!Aggressive)
dir = (Direction)(((int)dir + -4) & 0x7);
if (dir == Direction.West || dir == Direction.Left || dir == Direction.South)
{
m_Galleon.Turn(-2 * flee, true);
m_NextMoveCheck = DateTime.UtcNow + TimeSpan.FromSeconds(m_Galleon.TurnDelay);
return;
}
else if (dir == Direction.East || dir == Direction.Down)
{
m_Galleon.Turn(2 * flee, true);
m_NextMoveCheck = DateTime.UtcNow + TimeSpan.FromSeconds(m_Galleon.TurnDelay);
return;
}
m_Galleon.StartMove(dir, true);
}
private Dictionary<IShipCannon, DateTime> m_ShootTable = new Dictionary<IShipCannon, DateTime>();
public void ShootCannons(Mobile focus, bool shootAtBoat)
{
List<Item> cannons = new List<Item>(m_Galleon.Cannons.Where(i => !i.Deleted));
foreach (var cannon in cannons.OfType<IShipCannon>())
{
if (cannon != null)
{
if (m_ShootTable.ContainsKey(cannon) && m_ShootTable[cannon] > DateTime.UtcNow)
continue;
Direction facing = cannon.GetFacing();
if (shootAtBoat && HasTarget(focus, cannon, true))
{
cannon.AmmoType = AmmunitionType.Cannonball;
//cannon.LoadedAmmo = cannon.LoadTypes[0];
}
else if (!shootAtBoat && HasTarget(focus, cannon, false))
{
cannon.AmmoType = AmmunitionType.Grapeshot;
//cannon.LoadedAmmo = cannon.LoadTypes[1];
}
else
{
continue;
}
cannon.Shoot(this);
m_ShootTable[cannon] = DateTime.UtcNow + ShootFrequency + TimeSpan.FromSeconds(Utility.RandomMinMax(0, 3));
}
}
}
private bool HasTarget(Mobile focus, IShipCannon cannon, bool shootatboat)
{
if (cannon == null || cannon.Deleted || cannon.Map == null || cannon.Map == Map.Internal || m_Galleon == null || m_Galleon.Deleted)
return false;
Direction d = cannon.GetFacing();
int xOffset = 0; int yOffset = 0;
int cannonrange = cannon.Range;
int currentRange = 0;
Point3D pnt = cannon.Location;
switch (d)
{
case Direction.North:
xOffset = 0; yOffset = -1; break;
case Direction.South:
xOffset = 0; yOffset = 1; break;
case Direction.West:
xOffset = -1; yOffset = 0; break;
case Direction.East:
xOffset = 1; yOffset = 0; break;
}
int xo = xOffset;
int yo = yOffset;
while (currentRange++ <= cannonrange)
{
xOffset = xo;
yOffset = yo;
for (int i = -1; i <= 1; i++)
{
Point3D newPoint;
if (xOffset == 0)
newPoint = new Point3D(pnt.X + (xOffset + i), pnt.Y + (yOffset * currentRange), pnt.Z);
else
newPoint = new Point3D(pnt.X + (xOffset * currentRange), pnt.Y + (yOffset + i), pnt.Z);
if (shootatboat)
{
BaseGalleon g = BaseGalleon.FindGalleonAt(newPoint, this.Map);
if (g != null && g == m_TargetBoat && g != Galleon)
return true;
}
else
{
if (focus == null)
return false;
if (newPoint.X == focus.X && newPoint.Y == focus.Y)
{
return true;
}
}
}
}
return false;
}
private bool IsInBattle()
{
if (Combatant != null)
return true;
foreach (Mobile mob in m_Crew)
{
if (mob.Alive && mob.Combatant != null)
return true;
}
return false;
}
[CommandProperty(AccessLevel.GameMaster)]
public string AddHoldItem
{
get { return null; }
set
{
string str = value;
Type type = ScriptCompiler.FindTypeByName(str);
if (type != null && (type == typeof(Item) || type.IsSubclassOf(typeof(Item))))
{
Item item = Loot.Construct(type);
if (item != null)
HoldItem = item;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public Item HoldItem
{
get { return null; }
set
{
Item item = value;
if (item != null)
AddItemToHold(item);
}
}
public void AddItemToHold(Item item)
{
if (item == null)
return;
if (m_Galleon != null && m_Galleon.GalleonHold != null)
m_Galleon.GalleonHold.DropItem(item);
else
item.Delete();
}
public void CheckCrew()
{
if (m_Galleon == null || m_Crew == null || Map == null || Map == Map.Internal)
return;
List<Mobile> crew = new List<Mobile>(m_Crew.Where(m => m != null && m.Alive && m.Map != null && m.Map != Map.Internal));
if (m_Galleon.GalleonPilot != null)
crew.Add(m_Galleon.GalleonPilot);
crew.Add(this);
foreach (var crewman in crew)
{
if(!m_Galleon.Contains(crewman))
{
crewman.MoveToWorld(new Point3D(m_Galleon.X + Utility.RandomList(-1, 1), m_Galleon.Y + Utility.RandomList(-1, 0, 1), m_Galleon.ZSurface), this.Map);
}
}
ColUtility.Free(crew);
m_NextCrewCheck = DateTime.UtcNow + TimeSpan.FromMinutes(30);
}
public void CheckBlock(StaticTile tile, Point3D p)
{
BaseBoat check = BaseBoat.FindBoatAt(p, Map);
if (check != null)
CheckBlock(check, p);
}
public void CheckBlock(IEntity e, Point3D loc)
{
if (m_Galleon == null || !m_OnCourse || IsInBattle())
{
return;
}
if (loc == Point3D.Zero)
{
loc = e.Location;
}
BaseBoat check = BaseBoat.FindBoatAt(new Point3D(e), Map);
if ((check != null && check != m_Galleon) || e is BaseCreature)
{
Direction d = Utility.GetDirection(m_Galleon, e);
int blockX = e.X;
int blockY = e.Y;
int x = m_Galleon.X;
int y = m_Galleon.Y;
Direction toMove = Direction.North;
switch (m_Galleon.Facing)
{
case Direction.North:
toMove = blockX > x ? Direction.West : Direction.East;
break;
case Direction.East:
toMove = blockY > y ? Direction.North : Direction.South;
break;
case Direction.South:
toMove = blockX < x ? Direction.East : Direction.West;
break;
case Direction.West:
toMove = blockY < y ? Direction.South : Direction.North;
break;
}
Movement.Movement.Offset(toMove, ref x, ref y);
int speed;
toMove = m_Galleon.GetMovementFor(x, y, out speed);
Timer.DelayCall(TimeSpan.FromSeconds(1), () =>
{
m_Galleon.StartMove(toMove, false);
});
ResumeCourseTimed(TimeSpan.FromSeconds(11), true);
}
}
public BaseShipCaptain(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write(m_Blockade);
writer.Write((int)m_Zone);
writer.Write(m_StopTime);
writer.Write(m_Galleon);
writer.Write(m_OnCourse);
writer.Write(m_Crew.Count);
foreach (Mobile mob in m_Crew)
writer.Write(mob);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_Blockade = reader.ReadBool();
m_Zone = (SpawnZone)reader.ReadInt();
m_StopTime = reader.ReadDateTime();
m_Galleon = reader.ReadItem() as BaseGalleon;
m_OnCourse = reader.ReadBool();
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
Mobile mob = reader.ReadMobile() as Mobile;
if (mob != null && !mob.Deleted && mob.Alive)
m_Crew.Add(mob);
}
if (!m_Blockade)
ResumeCourseTimed(TimeSpan.FromSeconds(15), true);
if (m_Galleon != null)
{
Timer.DelayCall(TimeSpan.FromSeconds(30), CheckCrew);
}
m_NextMoveCheck = DateTime.UtcNow;
m_NextCannonShot = DateTime.UtcNow;
}
}
}

View File

@@ -0,0 +1,89 @@
using Server;
using System;
using Server.Engines.Quests;
using Server.Multis;
using Server.Items;
using System.Collections.Generic;
namespace Server.Mobiles
{
public class GBBigglesby : BaseVendor
{
public override bool IsActiveVendor { get { return false; } }
protected override List<SBInfo> SBInfos { get { return new List<SBInfo>(); } }
public override void InitSBInfo()
{
}
[Constructable]
public GBBigglesby()
: base("the proprietor")
{
Name = "G.B. Bigglesby";
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = false;
Race = Race.Human;
Hue = Race.RandomSkinHue();
Race.RandomHair(this);
HairHue = Race.RandomHairHue();
Item fancyShirt = new FancyShirt();
Item shirt = new Shirt(PirateCaptain.GetRandomShirtHue());
shirt.Layer = Layer.OuterTorso;
AddItem(new Cloak(5));
AddItem(new Cutlass());
AddItem(shirt);
AddItem(fancyShirt);
AddItem(new LongPants());
AddItem(new Boots());
m_NextSay = DateTime.UtcNow;
}
private int m_LastSay;
private DateTime m_NextSay;
public override void OnDoubleClick(Mobile m)
{
if (m_NextSay < DateTime.UtcNow)
{
if (m_LastSay == 0)
{
Say(1152651); //I'm G.B. Bigglesby, proprietor of the G.B. Bigglesby Free Trade Floating Emporium.
m_LastSay = 1;
}
else
{
Say(1152652); //This sea market be me life's work and 'tis me pride and joy..
m_LastSay = 0;
}
m_NextSay = DateTime.UtcNow + TimeSpan.FromSeconds(5);
}
}
public GBBigglesby(Serial serial) : base(serial) { }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_NextSay = DateTime.UtcNow;
}
}
}

View File

@@ -0,0 +1,68 @@
using Server;
using System;
using Server.Items;
using Server.Multis;
using System.Collections.Generic;
using Server.Engines.Quests;
namespace Server.Mobiles
{
public class MerchantCaptain : BaseShipCaptain
{
public override bool Aggressive { get { return false; } }
public override bool InitialInnocent { get { return true; } }
[Constructable]
public MerchantCaptain(BaseGalleon galleon)
: base(galleon, AIType.AI_Melee, FightMode.Aggressor, 1, 10, .2, .4)
{
Title = "the merchant captain";
Hue = Race.RandomSkinHue();
Item hat;
if (Utility.RandomBool())
hat = new WideBrimHat();
else
hat = new TricorneHat();
hat.Hue = Utility.RandomNeutralHue();
AddItem(new Sandals());
AddItem(new FancyShirt(Utility.RandomNeutralHue()));
AddItem(hat);
AddItem(new Cloak(Utility.RandomNeutralHue()));
AddItem(new Dagger());
Utility.AssignRandomHair(this);
Fame = 22000;
Karma = -22000;
if (IsSoulboundEnemies)
IsSoulbound = true;
}
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 2);
}
public MerchantCaptain(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,128 @@
using Server;
using System;
using Server.Items;
using Server.Multis;
using System.Collections.Generic;
using Server.Engines.Quests;
namespace Server.Mobiles
{
public class MerchantCrew : BaseCreature
{
public override bool InitialInnocent { get { return true; } }
public override WeaponAbility GetWeaponAbility()
{
Item weapon = FindItemOnLayer(Layer.TwoHanded);
if (weapon == null)
return null;
if (weapon is BaseWeapon)
{
if (Utility.RandomBool())
return ((BaseWeapon)weapon).PrimaryAbility;
else
return ((BaseWeapon)weapon).SecondaryAbility;
}
return null;
}
[Constructable]
public MerchantCrew()
: base(AIType.AI_Paladin, FightMode.Aggressor, 10, 1, .2, .4)
{
Title = "the merchant";
Hue = Race.RandomSkinHue();
if (this.Female = Utility.RandomBool())
{
Body = 0x191;
Name = NameList.RandomName("female");
AddItem(new Skirt(Utility.RandomNeutralHue()));
}
else
{
Body = 0x190;
Name = NameList.RandomName("male");
AddItem(new ShortPants(Utility.RandomNeutralHue()));
}
bool magery = 0.33 > Utility.RandomDouble();
SetStr(100, 125);
SetDex(125, 150);
SetInt(250, 400);
SetHits(250, 400);
SetDamage(15, 25);
if (magery)
{
ChangeAIType(AIType.AI_Mage);
SetSkill(SkillName.Magery, 100.0, 120.0);
SetSkill(SkillName.EvalInt, 100.0, 120.0);
SetSkill(SkillName.Meditation, 100.0, 120.0);
SetSkill(SkillName.MagicResist, 100.0, 120.0);
}
SetSkill(SkillName.Archery, 100.0, 120.0);
SetSkill(SkillName.Chivalry, 100.0, 120.0);
SetSkill(SkillName.Focus, 100.0, 120.0);
SetSkill(SkillName.Tactics, 100.0, 120.0);
SetSkill(SkillName.Wrestling, 100.0, 120.0);
SetSkill(SkillName.Anatomy, 100.0, 120.0);
SetDamageType(ResistanceType.Physical, 70);
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);
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;
}
AddItem(bow);
AddItem(new TricorneHat());
AddItem(new FancyShirt());
AddItem(new Boots(Utility.RandomNeutralHue()));
AddItem(new GoldEarrings());
Fame = 8000;
Karma = 8000;
if (IsSoulboundEnemies)
IsSoulbound = true;
}
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 2);
}
public MerchantCrew(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,332 @@
using Server;
using System;
using Server.Items;
using Server.Multis;
using System.Collections.Generic;
using Server.Engines.Quests;
namespace Server.Mobiles
{
public class PirateCaptain : BaseShipCaptain
{
public static List<string> m_RedNames;
public static void Initialize()
{
m_RedNames = new List<string>();
foreach (Mobile mob in World.Mobiles.Values)
{
if (mob != null && mob is PlayerMobile && mob.Murderer)
m_RedNames.Add(mob.Name);
}
}
private DateTime m_NextTalk;
private int m_PirateName;
private int m_Adjective;
private int m_Noun;
public int PirateName { get { return m_PirateName; } }
public int Adjective { get { return m_Adjective; } }
public int Noun { get { return m_Noun; } }
public override bool AlwaysMurderer { get { return true; } }
public override bool Commandable { get { return false; } }
#region Bounty Quest
private ProfessionalBountyQuest m_Quest;
private bool m_IsCaught;
[CommandProperty(AccessLevel.GameMaster)]
public bool IsCaught { get { return m_IsCaught; } set { m_IsCaught = value; } }
[CommandProperty(AccessLevel.GameMaster)]
public ProfessionalBountyQuest Quest { get { return m_Quest; } set { m_Quest = value; } }
#endregion
[Constructable]
public PirateCaptain()
: this(null)
{
}
public PirateCaptain(BaseGalleon galleon)
: base(galleon, AIType.AI_Melee, FightMode.Weakest, 25, 1, .2, .4)
{
PickRandomName();
if(m_PirateName > 0 && (m_PirateName == 1116679 || m_PirateName == 1116680 || m_PirateName == 1116683))
Female = true;
SpeechHue = Utility.RandomDyedHue();
Title = "the dread pirate";
Hue = Race.RandomSkinHue();
Body = Female ? 0x191 : 0x190;
SetStr(500, 750);
SetDex(125, 175);
SetInt(61, 75);
SetHits(4500, 5000);
SetDamage(23, 35);
SetSkill(SkillName.Fencing, 115.0, 120.0);
SetSkill(SkillName.Macing, 115.0, 120.0);
SetSkill(SkillName.MagicResist, 115.0, 120.0);
SetSkill(SkillName.Swords, 115.0, 120.0);
SetSkill(SkillName.Tactics, 115.0, 120.0);
SetSkill(SkillName.Wrestling, 115.0, 120.0);
SetSkill(SkillName.Anatomy, 115.0, 120.0);
Item hat;
Item fancyShirt = new FancyShirt();
Item shirt = new Shirt(GetRandomShirtHue());
shirt.Layer = Layer.OuterTorso;
if (Utility.RandomBool())
hat = new Bandana();
else
hat = new TricorneHat();
hat.Hue = Utility.RandomNeutralHue();
AddItem(new Boots());
AddItem(shirt);
AddItem(fancyShirt);
AddItem(hat);
AddItem(new Cloak(Utility.RandomNeutralHue()));
switch (Utility.Random(7))
{
case 0: AddItem(new Longsword()); break;
case 1: AddItem(new Cutlass()); break;
case 2: AddItem(new Broadsword()); break;
case 5: AddItem(new Dagger()); break;
}
Utility.AssignRandomHair(this);
Fame = 22000;
Karma = -22000;
if (IsSoulboundEnemies)
IsSoulbound = true;
}
public static int GetRandomShirtHue()
{
return Utility.RandomMinMax(2498, 2644);
}
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 2);
}
public void PickRandomName()
{
m_Adjective = Utility.RandomMinMax(1116631, 1116650);
m_Noun = Utility.RandomMinMax(1116651, 1116670);
if (m_RedNames.Count == 0 || 0.90 > Utility.RandomDouble())
m_PirateName = Utility.RandomMinMax(1116671, 1116686);
else
{
m_PirateName = -1;
Name = GetRandomRedName();
}
}
public string GetRandomRedName()
{
return m_RedNames[Utility.Random(m_RedNames.Count)];
}
public override void AddNameProperties(ObjectPropertyList list)
{
string args;
if(m_PirateName > 0)
args = String.Format("#{0}\t#{1}\t#{2}", m_Adjective, m_Noun, m_PirateName);
else
args = String.Format("#{0}\t#{1}\t{2}", m_Adjective, m_Noun, Name);
list.Add(1116690, args);
}
public override void OnThink()
{
base.OnThink();
if (!IsCaught || m_NextTalk > DateTime.UtcNow)
return;
IPooledEnumerable eable = this.GetMobilesInRange(7);
foreach(Mobile mob in eable)
{
if (mob is PlayerMobile)
{
OnTalk();
break;
}
}
eable.Free();
}
public void OnTalk()
{
Say(Utility.RandomMinMax(1149701, 1149720));
m_NextTalk = DateTime.UtcNow + TimeSpan.FromMinutes(1);
}
#region Quest Stuff
public bool TryBound(Mobile from, BaseQuest quest)
{
if (from == null || Galleon == null || !Galleon.Contains(this) || quest == null)
return false;
if (m_IsCaught)
{
from.SendMessage("That pirate is already bound to a ship!");
return false;
}
Combatant = null;
Warmode = false;
m_IsCaught = true;
return true;
}
public void OnBound(ProfessionalBountyQuest quest)
{
if (quest == null || quest.Pole == null)
return;
BindingPole pole = quest.Pole;
int x = pole.X;
int y = pole.Y;
while (x == pole.X && y == pole.Y)
{
x = Utility.RandomMinMax(pole.X - 1, pole.X + 1);
y = Utility.RandomMinMax(pole.Y - 1, pole.Y + 1);
}
Frozen = true;
Item toDisarm = FindItemOnLayer(Layer.OneHanded);
if (toDisarm == null || !toDisarm.Movable)
toDisarm = FindItemOnLayer(Layer.TwoHanded);
if (toDisarm != null)
{
if (Backpack != null)
Backpack.DropItem(toDisarm);
else
toDisarm.Delete();
}
m_Quest = quest;
if (quest != null && quest.Galleon != null)
quest.Galleon.CapturedCaptain = this;
Timer.DelayCall(TimeSpan.FromSeconds(2.5), new TimerStateCallback(MoveCaptainToShip), new object[] { x, y, pole });
}
private void MoveCaptainToShip(object obj)
{
object[] objs = (object[])obj;
int x = (int)objs[0];
int y = (int)objs[1];
Item pole = objs[2] as Item;
if (pole != null)
MoveToWorld(new Point3D(x, y, pole.Z), pole.Map);
Blessed = true;
Title = "[Captured Captain]";
}
public override bool OnBeforeDeath()
{
List<PlayerMobile> hasQuest = new List<PlayerMobile>();
List<DamageStore> rights = GetLootingRights();
for (int i = 0; i < rights.Count; i++)
{
if (!rights[i].m_HasRight)
continue;
Mobile mob = rights[i].m_Mobile;
//if they have the quest and looting rights, give them a certificate
if (mob is PlayerMobile && mob.NetState != null && QuestHelper.GetQuest((PlayerMobile)mob, typeof(ProfessionalBountyQuest)) != null)
hasQuest.Add((PlayerMobile)mob);
}
if (hasQuest.Count > 0)
{
PlayerMobile questee = hasQuest[Utility.Random(hasQuest.Count)];
BaseQuest q = QuestHelper.GetQuest(questee, typeof(ProfessionalBountyQuest));
if (q != null && q is ProfessionalBountyQuest)
{
((ProfessionalBountyQuest)q).OnPirateDeath(this);
questee.AddToBackpack(new DeathCertificate(this));
}
}
if (m_IsCaught && m_Quest != null)
{
for (int i = 0; i < m_Quest.Objectives.Count; i++)
{
if (m_Quest.Objectives[i] is BountyQuestObjective && ((BountyQuestObjective)m_Quest.Objectives[i]).CapturedCaptain == this)
{
((BountyQuestObjective)m_Quest.Objectives[i]).CapturedCaptain = null;
((BountyQuestObjective)m_Quest.Objectives[i]).Captured = false;
m_Quest = null;
}
}
}
return base.OnBeforeDeath();
}
#endregion
public PirateCaptain(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1);
writer.Write(m_IsCaught);
writer.Write(m_Adjective);
writer.Write(m_Noun);
writer.Write(m_PirateName);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_IsCaught = reader.ReadBool();
m_Adjective = reader.ReadInt();
m_Noun = reader.ReadInt();
m_PirateName = reader.ReadInt();
if (IsCaught)
Frozen = true;
m_NextTalk = DateTime.UtcNow;
}
}
}

View File

@@ -0,0 +1,210 @@
using Server;
using System;
using Server.Items;
using Server.Misc;
namespace Server.Mobiles
{
[CorpseName("a glowing orc corpse")]
public class PirateCrew : BaseCreature
{
public override WeaponAbility GetWeaponAbility()
{
Item weapon = FindItemOnLayer(Layer.TwoHanded);
if (weapon == null)
return null;
if (weapon is BaseWeapon)
{
if (Utility.RandomBool())
return ((BaseWeapon)weapon).PrimaryAbility;
else
return ((BaseWeapon)weapon).SecondaryAbility;
}
return null;
}
public override InhumanSpeech SpeechType { get { return InhumanSpeech.Orc; } }
private DateTime m_NextBomb;
private int m_Thrown;
[Constructable]
public PirateCrew() : base(AIType.AI_Melee, FightMode.Closest, 10, 1, .2, .4)
{
Name = "Orcish Crew";
Body = 0.33 > Utility.RandomDouble() ? 0x8C : Utility.RandomList(0xB5, 0xB6);
SetHits(2000);
if (Body == 0x8C) // Mage
{
SetStr(140, 160);
SetDex(130, 150);
SetInt(170, 190);
SetDamage(4, 14);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 30, 40);
SetResistance(ResistanceType.Fire, 30, 40);
SetResistance(ResistanceType.Cold, 20, 30);
SetResistance(ResistanceType.Poison, 30, 40);
SetResistance(ResistanceType.Energy, 30, 40);
ChangeAIType(AIType.AI_Mage);
SetSkill(SkillName.Wrestling, 45.0, 55.0);
SetSkill(SkillName.Tactics, 50.0, 60.0);
SetSkill(SkillName.MagicResist, 65.0, 75.0);
SetSkill(SkillName.Magery, 60.0, 70.0);
SetSkill(SkillName.EvalInt, 60.0, 75.0);
SetSkill(SkillName.Meditation, 70.0, 90.0);
SetSkill(SkillName.Focus, 80.0, 100.0);
}
else if (Body == 0xB6) // Bomber
{
SetStr(150, 200);
SetDex(90, 110);
SetInt(70, 100);
SetDamage(1, 8);
SetDamageType(ResistanceType.Physical, 75);
SetDamageType(ResistanceType.Fire, 25);
SetResistance(ResistanceType.Physical, 20, 30);
SetResistance(ResistanceType.Fire, 30, 40);
SetResistance(ResistanceType.Cold, 15, 25);
SetResistance(ResistanceType.Poison, 15, 25);
SetResistance(ResistanceType.Energy, 20, 30);
SetSkill(SkillName.Wrestling, 60.0, 90.0);
SetSkill(SkillName.Tactics, 70.0, 85.0);
SetSkill(SkillName.MagicResist, 70.0, 85.0);
}
else // Archer
{
SetStr(100, 130);
SetDex(100, 130);
SetInt(30, 70);
SetDamage(5, 7);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 20, 35);
SetResistance(ResistanceType.Fire, 30, 40);
SetResistance(ResistanceType.Cold, 15, 25);
SetResistance(ResistanceType.Poison, 15, 25);
SetResistance(ResistanceType.Energy, 20, 30);
ChangeAIType(AIType.AI_Archer);
SetSkill(SkillName.Tactics, 55.0, 70.0);
SetSkill(SkillName.MagicResist, 50.0, 70.0);
SetSkill(SkillName.Anatomy, 60.0, 85.0);
SetSkill(SkillName.Healing, 60.0, 80.0);
SetSkill(SkillName.Archery, 100.0, 120.0);
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;
}
AddItem(bow);
}
SetSkill(SkillName.DetectHidden, 40.0, 45.0);
Fame = 8000;
Karma = -8000;
if (IsSoulboundEnemies)
IsSoulbound = true;
}
public override void OnActionCombat()
{
if (Body == 0xB6)
{
Mobile combatant = Combatant as Mobile;
if (combatant == null || combatant.Deleted || combatant.Map != Map || !InRange(combatant, 12) || !CanBeHarmful(combatant) || !InLOS(combatant))
return;
if (DateTime.Now >= m_NextBomb)
{
ThrowBomb(combatant);
m_Thrown++;
if (0.75 >= Utility.RandomDouble() && (m_Thrown % 2) == 1) // 75% chance to quickly throw another bomb
m_NextBomb = DateTime.Now + TimeSpan.FromSeconds(3.0);
else
m_NextBomb = DateTime.Now + TimeSpan.FromSeconds(5.0 + (10.0 * Utility.RandomDouble())); // 5-15 seconds
}
}
}
public void ThrowBomb(Mobile m)
{
DoHarmful(m);
MovingParticles(m, 0x1C19, 1, 0, false, true, 0, 0, 9502, 6014, 0x11D, EffectLayer.Waist, 0);
new InternalTimer(m, this).Start();
}
private class InternalTimer : Timer
{
private readonly Mobile m_Mobile;
private readonly Mobile m_From;
public InternalTimer(Mobile m, Mobile from)
: base(TimeSpan.FromSeconds(1.0))
{
m_Mobile = m;
m_From = from;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
m_Mobile.PlaySound(0x11D);
AOS.Damage(m_Mobile, m_From, Utility.RandomMinMax(10, 20), 0, 100, 0, 0, 0);
}
}
public override int TreasureMapLevel { get { return 3; } }
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 2);
}
public PirateCrew(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,155 @@
using Server;
using System;
using Server.Items;
using Server.Multis;
using System.Collections.Generic;
using Server.Engines.Quests;
namespace Server.Mobiles
{
public class SeaMarketOfficer : MondainQuester
{
public override Type[] Quests { get { return new Type[] { typeof(ProfessionalBountyQuest) }; } }
public SeaMarketOfficer()
{
Title = "the officer";
Name = NameList.RandomName("male");
CantWalk = true;
}
public override void InitBody()
{
InitStats(100, 100, 25);
Female = false;
Race = Race.Human;
Hue = Race.RandomSkinHue();
Race.RandomHair(this);
HairHue = Race.RandomHairHue();
SetWearable(new ChainChest(), 1346);
SetWearable(new LeatherGloves(), 1346);
SetWearable(new Necklace(), 1153);
SetWearable(new Bandana());
SetWearable(new Scimitar());
SetWearable(new ThighBoots());
}
public override void OnTalk(PlayerMobile pm)
{
if (!HasQuest(pm))
{
BaseBoat boat = FishQuestHelper.GetBoat(pm);
if (boat != null && boat is BaseGalleon)
{
if (((BaseGalleon)boat).Scuttled)
{
pm.SendLocalizedMessage(1116752); //Your ship is a mess! Fix it first and then we can talk about catching pirates.
}
else
{
ProfessionalBountyQuest q = new ProfessionalBountyQuest((BaseGalleon)boat);
q.Owner = pm;
q.Quester = this;
pm.CloseGump(typeof(MondainQuestGump));
pm.SendGump(new MondainQuestGump(q));
}
}
else
{
SayTo(pm, 1116751); //The ship you are captaining could not take on a pirate ship. Bring a warship if you want this quest.
OnOfferFailed();
}
}
}
public override void Advertise()
{
}
public bool HasQuest(PlayerMobile pm)
{
if (pm.Quests == null)
return false;
for (int i = 0; i < pm.Quests.Count; i++)
{
BaseQuest quest = pm.Quests[i];
if (quest is ProfessionalBountyQuest)
{
if (this == quest.Quester)
{
for (int j = 0; j < quest.Objectives.Count; j++)
{
if (quest.Objectives[j].Update(pm))
quest.Objectives[j].Complete();
}
}
if (quest.Completed)
{
quest.OnCompleted();
pm.SendGump(new MondainQuestGump(quest, MondainQuestGump.Section.Complete, false, true));
}
else
{
pm.SendGump(new MondainQuestGump(quest, MondainQuestGump.Section.InProgress, false));
quest.InProgress();
}
return true;
}
}
return false;
}
public SeaMarketOfficer(Serial serial) : base(serial) { }
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Map == Map.Trammel)
{
TramInstance = this;
}
else if (Map == Map.Felucca)
{
FelInstance = this;
}
}
public static SeaMarketOfficer TramInstance { get; set; }
public static SeaMarketOfficer FelInstance { get; set; }
public static void Initialize()
{
if (Core.HS)
{
if (TramInstance == null)
{
TramInstance = new SeaMarketOfficer();
TramInstance.MoveToWorld(new Point3D(4543, 2299, -1), Map.Trammel);
}
if (FelInstance == null)
{
FelInstance = new SeaMarketOfficer();
FelInstance.MoveToWorld(new Point3D(4543, 2299, -1), Map.Felucca);
}
}
}
}
}

View File

@@ -0,0 +1,382 @@
using Server;
using System;
using Server.Mobiles;
using Server.Items;
using Server.Multis;
using System.Collections.Generic;
using Server.Engines.PartySystem;
using Server.Gumps;
namespace Server.Engines.Quests
{
public class ProfessionalBountyQuest : BaseQuest
{
public override object Title { get { return 1116708; } }
public override object Description { get { return 1116709; } }
public override object Refuse { get { return 1116713; } }
public override object Uncomplete { get { return 1116714; } }
public override object Complete { get { return 1116715; } }
private BaseGalleon m_Galleon;
private BindingPole m_Pole;
private BindingRope m_Rope;
private Mobile m_Captain;
private List<Mobile> m_Helpers = new List<Mobile>();
public BaseGalleon Galleon { get { return m_Galleon; } }
public BindingPole Pole { get { return m_Pole; } }
public BindingRope Rope { get { return m_Rope; } }
public Mobile Captain { get { return m_Captain; } set { m_Captain = value; } }
public ProfessionalBountyQuest()
{
AddObjective(new BountyQuestObjective());
}
public ProfessionalBountyQuest(BaseGalleon galleon)
{
m_Galleon = galleon;
AddObjective(new BountyQuestObjective());
AddReward(new BaseReward(1116712)); //The gold listed on the bulletin board and a special reward from the officer if captured alive.
}
public override void OnAccept()
{
base.OnAccept();
AddPole();
if(Owner != null)
{
m_Rope = new BindingRope(this);
Owner.AddToBackpack(m_Rope);
}
}
public void OnBound(BaseCreature captain)
{
if (Owner != null)
{
m_Captain = captain;
CompileHelpersList(captain);
foreach (BaseObjective obj in Objectives)
{
if (obj is BountyQuestObjective)
{
((BountyQuestObjective)obj).Captured = true;
((BountyQuestObjective)obj).CapturedCaptain = captain;
}
}
}
}
public void OnPirateDeath(BaseCreature captain)
{
m_Captain = captain;
CompileHelpersList(captain);
foreach (BaseObjective obj in Objectives)
{
if (obj is BountyQuestObjective)
{
((BountyQuestObjective)obj).Captured = false;
((BountyQuestObjective)obj).CapturedCaptain = null;
}
}
}
private void CompileHelpersList(BaseCreature pirate)
{
if (Owner == null)
return;
Party p = Party.Get(Owner);
List<DamageStore> rights = pirate.GetLootingRights();
IPooledEnumerable eable = pirate.GetMobilesInRange(19);
foreach (Mobile mob in eable)
{
if (mob == Owner || !(mob is PlayerMobile))
continue;
Party mobParty = Party.Get(mob);
//Add party memebers regardless of looting rights
if (p != null && mobParty != null && p == mobParty)
{
m_Helpers.Add(mob);
continue;
}
// add those with looting rights
for (int i = rights.Count - 1; i >= 0; --i)
{
DamageStore ds = rights[i];
if (ds.m_HasRight && ds.m_Mobile == mob)
{
m_Helpers.Add(ds.m_Mobile);
break;
}
}
}
eable.Free();
}
public void AddPole()
{
if(m_Galleon == null)
return;
int dist = m_Galleon.CaptiveOffset;
int xOffset = 0;
int yOffset = 0;
m_Pole = new BindingPole(this);
switch (m_Galleon.Facing)
{
case Direction.North:
xOffset = 0;
yOffset = dist * -1;
break;
case Direction.South:
xOffset = 0;
yOffset = dist * 1;
break;
case Direction.East:
yOffset = 0;
xOffset = dist * 1;
break;
case Direction.West:
xOffset = dist * -1;
yOffset = 0;
break;
}
m_Pole.MoveToWorld(new Point3D(m_Galleon.X + xOffset, m_Galleon.Y + yOffset, m_Galleon.ZSurface), m_Galleon.Map);
m_Galleon.AddFixture(m_Pole);
}
public override void GiveRewards()
{
bool captured = false;
foreach(BaseObjective obj in Objectives)
{
if(obj is BountyQuestObjective && ((BountyQuestObjective)obj).Captured)
{
BountyQuestObjective o = (BountyQuestObjective)obj;
captured = true;
if (o.CapturedCaptain != null && o.CapturedCaptain is PirateCaptain)
{
PirateCaptain p = o.CapturedCaptain as PirateCaptain;
p.Quest = null;
}
o.CapturedCaptain = null;
o.Captured = false;
break;
}
}
if (Owner == null)
return;
m_Helpers.Add(Owner);
int totalAward = 7523;
if(m_Captain != null && BountyQuestSpawner.Bounties.ContainsKey(m_Captain))
totalAward = BountyQuestSpawner.Bounties[m_Captain];
int eachAward = totalAward;
if(m_Helpers.Count > 1)
eachAward = totalAward / m_Helpers.Count;
foreach(Mobile mob in m_Helpers)
{
if(mob.NetState != null || mob == Owner)
{
mob.AddToBackpack(new Gold(eachAward));
if (captured)
{
Item reward = Loot.Construct(m_CapturedRewards[Utility.Random(m_CapturedRewards.Length)]);
if (reward != null)
{
if (reward is RuinedShipPlans)
mob.SendLocalizedMessage(1149838); //Here is something special! It's a salvaged set of orc ship plans. Parts of it are unreadable, but if you could get another copy you might be able to fill in some of the missing parts...
else
mob.SendLocalizedMessage(1149840); //Here is some special cannon ammunition. It's imported!
if (reward is HeavyFlameCannonball || reward is LightFlameCannonball || reward is HeavyFrostCannonball || reward is LightFrostCannonball)
reward.Amount = Utility.RandomMinMax(5, 10);
mob.AddToBackpack(reward);
}
}
mob.SendLocalizedMessage(1149825, String.Format("{0}\t{1}", totalAward, eachAward)); //Here's your share of the ~1_val~ reward money, you get ~2_val~ gold. You've earned it!
}
else
{
foreach (Mobile mobile in m_Helpers)
{
if (mobile != mob && mobile.NetState != null)
mobile.SendLocalizedMessage(1149837, String.Format("{0}\t{1}\t{2}", eachAward, mob.Name, Owner.Name)); //~1_val~ gold is for ~2_val~, I can't find them so I'm giving this to Captain ~3_val~.
}
Owner.AddToBackpack(new Gold(eachAward));
}
}
if(m_Captain != null && m_Captain.Alive)
m_Captain.Delete();
base.GiveRewards();
}
public override void RemoveQuest( bool removeChain )
{
base.RemoveQuest(removeChain);
if (m_Rope != null && !m_Rope.Deleted)
{
m_Rope.Quest = null;
m_Rope.Delete();
}
if (m_Pole != null && !m_Pole.Deleted)
{
m_Pole.Quest = null;
m_Pole.Delete();
}
if (m_Galleon != null)
m_Galleon.CapturedCaptain = null;
}
public override bool RenderObjective(MondainQuestGump g, bool offer)
{
if (offer)
g.AddHtmlLocalized(130, 45, 270, 16, 1049010, 0xFFFFFF, false, false); // Quest Offer
else
g.AddHtmlLocalized(130, 45, 270, 16, 1046026, 0xFFFFFF, false, false); // Quest Log
g.AddButton(130, 430, 0x2EEF, 0x2EF1, (int)Buttons.PreviousPage, GumpButtonType.Reply, 0);
g.AddButton(275, 430, 0x2EE9, 0x2EEB, (int)Buttons.NextPage, GumpButtonType.Reply, 0);
g.AddHtmlObject(160, 70, 330, 16, Title, BaseQuestGump.DarkGreen, false, false);
g.AddHtmlLocalized(98, 140, 312, 16, 1049073, 0x2710, false, false); // Objective:
g.AddHtmlLocalized(98, 156, 312, 16, 1072208, 0x2710, false, false); // All of the following
int offset = 172;
g.AddHtmlLocalized(98, offset, 312, 16, 1116710, 0x2710, false, false); // Capture or kill a pirate listed on the bulletin board.
offset += 16;
g.AddHtmlLocalized(98, offset, 312, 32, 1116711, 0x15F90, false, false); //Return to the officer with the pirate or a death certificate for your reward.
offset += 32;
g.AddHtmlLocalized(98, offset, 312, 32, 1116712, 0x15F90, false, false); //The gold listed on the bulletin board and a special reward from the officer if captured alive.
return true;
}
private Type[] m_CapturedRewards = new Type[]
{
typeof(RuinedShipPlans), typeof(RuinedShipPlans),
typeof(LightFlameCannonball), typeof(HeavyFlameCannonball),
typeof(LightFrostCannonball), typeof(HeavyFrostCannonball),
typeof(LightFlameCannonball), typeof(HeavyFlameCannonball),
typeof(LightFrostCannonball), typeof(HeavyFrostCannonball),
/*typeof(HeavyScatterShot), typeof(LightScatterShot),
typeof(HeavyHotShot), typeof(LightHotShot),
typeof(HeavyFragShot), typeof(LightFragShot)*/
};
public override void Serialize( GenericWriter writer )
{
base.Serialize(writer);
writer.WriteEncodedInt( (int) 0 ); // version
writer.Write(m_Pole);
writer.Write(m_Rope);
writer.Write(m_Captain);
writer.Write(m_Galleon);
writer.Write(m_Helpers.Count);
foreach (Mobile mob in m_Helpers)
writer.Write(mob);
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
m_Pole = reader.ReadItem() as BindingPole;
m_Rope = reader.ReadItem() as BindingRope;
m_Captain = reader.ReadMobile();
m_Galleon = reader.ReadItem() as BaseGalleon;
int count = reader.ReadInt();
for (int i = 0; i < count; i++)
{
Mobile mob = reader.ReadMobile();
if (mob != null)
m_Helpers.Add(mob);
}
if(m_Rope != null)
m_Rope.Quest = this;
if (m_Pole != null)
m_Pole.Quest = this;
else
AddPole();
AddReward(new BaseReward(1116712)); //The gold listed on the bulletin board and a special reward from the officer if captured alive.
}
public bool HasQuest(PlayerMobile pm)
{
if (pm.Quests == null)
return false;
for(int i = 0; i < pm.Quests.Count; i++)
{
BaseQuest quest = pm.Quests[i];
if(quest.Quester == this)
{
for(int j = 0; j < quest.Objectives.Count; j++)
{
if(quest.Objectives[j].Update(pm))
quest.Objectives[j].Complete();
}
if(quest.Completed)
{
quest.OnCompleted();
pm.SendGump( new MondainQuestGump( quest, MondainQuestGump.Section.Complete, false, true ) );
}
else
{
pm.SendGump( new MondainQuestGump( quest, MondainQuestGump.Section.InProgress, false ) );
quest.InProgress();
}
return true;
}
}
return false;
}
}
}