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,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);
}
}
}
}
}