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,274 @@
using System;
using Server;
using Server.Multis;
using Server.Items;
using Server.Engines.CannedEvil;
using System.Collections.Generic;
namespace Server.Mobiles
{
public class BaseSeaChampion : BaseChampion
{
public override Type[] UniqueList { get { return new Type[] { }; } }
public override Type[] SharedList { get { return new Type[] { }; } }
public override Type[] DecorativeList { get { return new Type[] { }; } }
public override MonsterStatuetteType[] StatueTypes { get { return new MonsterStatuetteType[] { }; } }
public override ChampionSkullType SkullType
{
get
{
return ChampionSkullType.None;
}
}
private DateTime m_NextBoatDamage;
private bool m_InDamageMode;
private Mobile m_Fisher;
public virtual bool CanDamageBoats { get { return false; } }
public virtual TimeSpan BoatDamageCooldown { get { return TimeSpan.MaxValue; } }
public virtual DateTime NextBoatDamage { get { return m_NextBoatDamage; } }
public virtual int MinBoatDamage { get { return 0; } }
public virtual int MaxBoatDamage { get { return 0; } }
public virtual int DamageRange { get { return 15; } }
public override double BonusPetDamageScalar { get { return 1.75; } }
public BaseSeaChampion(Mobile fisher, AIType ai, FightMode fm)
: base(ai, fm)
{
m_NextBoatDamage = DateTime.UtcNow;
m_InDamageMode = false;
m_Fisher = fisher;
m_DamageEntries = new Dictionary<Mobile, int>();
}
public override void OnThink()
{
base.OnThink();
if (m_InDamageMode)
TryDamageBoat();
else if (CanDamageBoats && DateTime.UtcNow >= NextBoatDamage)
m_InDamageMode = true;
}
public override bool OnBeforeDeath()
{
RegisterDamageTo(this);
AwardArtifact(GetArtifact());
return base.OnBeforeDeath();
}
Dictionary<Mobile, int> m_DamageEntries;
public virtual void RegisterDamageTo(Mobile m)
{
if (m == null)
return;
foreach (DamageEntry de in m.DamageEntries)
{
Mobile damager = de.Damager;
Mobile master = damager.GetDamageMaster(m);
if (master != null)
damager = master;
RegisterDamage(damager, de.DamageGiven);
}
}
public void RegisterDamage(Mobile from, int amount)
{
if (from == null || !from.Player)
return;
if (m_DamageEntries.ContainsKey(from))
m_DamageEntries[from] += amount;
else
m_DamageEntries.Add(from, amount);
}
public void AwardArtifact(Item artifact)
{
if (artifact == null)
return;
int totalDamage = 0;
Dictionary<Mobile, int> validEntries = new Dictionary<Mobile, int>();
foreach (KeyValuePair<Mobile, int> kvp in m_DamageEntries)
{
if (IsEligible(kvp.Key, artifact))
{
validEntries.Add(kvp.Key, kvp.Value);
totalDamage += kvp.Value;
}
}
int randomDamage = Utility.RandomMinMax(1, totalDamage);
totalDamage = 0;
foreach (KeyValuePair<Mobile, int> kvp in m_DamageEntries)
{
totalDamage += kvp.Value;
if (totalDamage > randomDamage)
{
GiveArtifact(kvp.Key, artifact);
return;
}
}
if (artifact != null)
artifact.Delete();
}
public void GiveArtifact(Mobile to, Item artifact)
{
if (to == null || artifact == null)
return;
Container pack = to.Backpack;
if (pack == null || !pack.TryDropItem(to, artifact, false))
artifact.Delete();
else
to.SendLocalizedMessage(1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you.
}
public bool IsEligible(Mobile m, Item Artifact)
{
return m.Player && m.Alive && m.InRange(Location, 32) && m.Backpack != null && m.Backpack.CheckHold(m, Artifact, false);
}
public void TryDamageBoat()
{
Mobile focusMob = m_Fisher;
if (focusMob == null || !focusMob.Alive)
focusMob = Combatant as Mobile;
if (focusMob == null || focusMob.AccessLevel > AccessLevel.Player || !InRange(focusMob.Location, DamageRange) || BaseBoat.FindBoatAt(focusMob, focusMob.Map) == null)
return;
BaseBoat boat = BaseBoat.FindBoatAt(focusMob, focusMob.Map);
if (boat != null)
{
int range = DamageRange;
for (int x = X - range; x <= X + range; x++)
{
for (int y = Y - range; y <= Y + range; y++)
{
if (BaseBoat.FindBoatAt(new Point2D(x, y), Map) == boat)
{
DoDamageBoat(boat);
m_NextBoatDamage = DateTime.UtcNow + BoatDamageCooldown;
m_InDamageMode = false;
return;
}
}
}
}
}
public virtual void DoDamageBoat(BaseBoat boat)
{
int damage = Utility.RandomMinMax(MinBoatDamage, MaxBoatDamage);
boat.OnTakenDamage(this, damage);
for (int x = X - 2; x <= X + 2; x++)
{
for (int y = Y - 2; y <= Y + 2; y++)
{
BaseBoat b = BaseBoat.FindBoatAt(new Point2D(x, y), Map);
if (b != null && boat == b)
{
Direction toPush = Direction.North;
if (X < x && x - X > 1)
toPush = Direction.West;
else if (X > x && X - x > 1)
toPush = Direction.East;
else if (Y < y)
toPush = Direction.South;
else if (Y > y)
toPush = Direction.North;
boat.StartMove(toPush, 1, 0x2, boat.SlowDriftInterval, true, false);
//TODO: Message and Sound?
}
}
}
}
public Point3D GetValidPoint(BaseBoat boat, Map map, int distance)
{
if (boat == null || map == null || map == Map.Internal)
return new Point3D(X + Utility.RandomMinMax(-1, 1), Y + Utility.RandomMinMax(-1, 1), Z);
if (distance < 5) distance = 5;
if (distance > 15) distance = 15;
int x = boat.X;
int y = boat.Y;
int z = boat.Z;
int size = boat is BritannianShip ? 4 : 3;
int range = distance - size;
if (range < 1) range = 1;
switch (boat.Facing)
{
default:
case Direction.South:
case Direction.North:
x = Utility.RandomBool() ? Utility.RandomMinMax(x -= distance, x -= (distance - range)) : Utility.RandomMinMax(x += (distance - range), x += distance);
y = Utility.RandomMinMax(y - 8, y + 8);
z = map.GetAverageZ(x, y);
break;
case Direction.East:
case Direction.West:
x = Utility.RandomMinMax(x - 8, x + 8);
y = Utility.RandomBool() ? Utility.RandomMinMax(y -= distance, y -= (distance - range)) : Utility.RandomMinMax(y += (distance - range), y += distance);
z = map.GetAverageZ(x, y);
break;
}
return new Point3D(x, y, z);
}
public BaseSeaChampion(Serial serial)
: base(serial)
{
}
public virtual void OnHitByCannon(IShipCannon cannon, int damage)
{
}
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();
m_NextBoatDamage = DateTime.UtcNow;
m_DamageEntries = new Dictionary<Mobile, int>();
}
}
}

View File

@@ -0,0 +1,776 @@
using System;
using Server;
using Server.Multis;
using System.Collections.Generic;
using Server.Items;
using Server.Misc;
using System.Linq;
namespace Server.Mobiles
{
public class Charydbis : BaseSeaChampion
{
public static readonly TimeSpan SpawnRate = TimeSpan.FromSeconds(30);
public static readonly TimeSpan TeleportRate = TimeSpan.FromSeconds(60);
public static readonly int SpawnMax = 25;
private List<Mobile> m_Tentacles = new List<Mobile>();
private DateTime m_NextSpawn;
private DateTime m_NextTeleport;
public override bool CanDamageBoats { get { return true; } }
public override TimeSpan BoatDamageCooldown { get { return TimeSpan.FromSeconds(Utility.RandomMinMax(45, 80)); } }
public override int MinBoatDamage { get { return 5; } }
public override int MaxBoatDamage { get { return 15; } }
public override int DamageRange { get { return 10; } }
public override int Meat { get { return 5; } }
public override double TreasureMapChance { get { return .50; } }
public override int TreasureMapLevel { get { return 7; } }
public override Type[] UniqueList { get { return new Type[] { typeof(FishermansHat), typeof(FishermansVest), typeof(FishermansEelskinGloves), typeof(FishermansTrousers) }; } }
public override Type[] SharedList { get { return new Type[] { typeof(HelmOfVengence), typeof(RingOfTheSoulbinder), typeof(RuneEngravedPegLeg), typeof(CullingBlade) }; } }
public override Type[] DecorativeList { get { return new Type[] { typeof(EnchantedBladeDeed), typeof(EnchantedVortexDeed) }; } }
[CommandProperty(AccessLevel.GameMaster)]
public int Tentacles { get { return m_Tentacles.Count; } }
[Constructable]
public Charydbis() : this(null) { }
public Charydbis(Mobile fisher)
: base(fisher, AIType.AI_Mage, FightMode.Closest)
{
RangeFight = 8;
Name = "charydbis";
Body = 1244;
BaseSoundID = 353;
m_NextSpawn = DateTime.UtcNow + SpawnRate;
m_NextTeleport = DateTime.UtcNow + TeleportRate;
CanSwim = true;
CantWalk = true;
SetStr(533, 586);
SetDex(113, 131);
SetInt(110, 155);
SetHits(30000);
SetMana(8000);
SetDamage(24, 33);
SetDamageType(ResistanceType.Physical, 50);
SetDamageType(ResistanceType.Energy, 50);
SetResistance(ResistanceType.Physical, 70, 80);
SetResistance(ResistanceType.Fire, 70, 80);
SetResistance(ResistanceType.Cold, 45, 55);
SetResistance(ResistanceType.Poison, 80, 90);
SetResistance(ResistanceType.Energy, 60, 70);
SetSkill(SkillName.Wrestling, 120.1, 121.2);
SetSkill(SkillName.Tactics, 120.15, 123.1);
SetSkill(SkillName.MagicResist, 165.2, 178.7);
SetSkill(SkillName.Anatomy, 111.0, 111.7);
SetSkill(SkillName.Magery, 134.6, 140.5);
SetSkill(SkillName.EvalInt, 200.8, 243.6);
SetSkill(SkillName.Meditation, 565);
Fame = 32000;
Karma = -32000;
if (IsSoulboundEnemies)
IsSoulbound = true;
}
public void AddTentacle(Mobile tent)
{
if (!m_Tentacles.Contains(tent))
m_Tentacles.Add(tent);
}
public void RemoveTentacle(Mobile tent)
{
if (m_Tentacles.Contains(tent))
m_Tentacles.Remove(tent);
}
public override void OnThink()
{
base.OnThink();
if (m_NextSpawn < DateTime.UtcNow && m_Tentacles.Count < SpawnMax)
SpawnTentacle();
if (m_NextTeleport < DateTime.UtcNow)
DoTeleport();
}
private Point3D m_LastLocation;
private Map m_LastMap;
public void DoTeleport()
{
var combatant = Combatant as Mobile;
if (combatant == null)
{
m_NextTeleport = DateTime.UtcNow + TeleportRate;
return;
}
m_LastLocation = Location;
m_LastMap = Map;
DoTeleportEffects(m_LastLocation, m_LastMap);
Hidden = true;
Internalize();
DoAreaLightningAttack(combatant);
Timer.DelayCall<Mobile>(TimeSpan.FromSeconds(3), FinishTeleport, combatant);
m_NextTeleport = DateTime.UtcNow + TeleportRate;
}
public void FinishTeleport(Mobile combatant)
{
Point3D focusLoc;
if (combatant == null || combatant.Map == null)
{
focusLoc = Location;
}
else
{
focusLoc = combatant.Location;
}
Map map = m_LastMap;
Point3D newLoc = Point3D.Zero;
BaseBoat boat = BaseBoat.FindBoatAt(focusLoc, map);
for (int i = 0; i < 25; i++)
{
if (boat != null)
{
newLoc = GetValidPoint(boat, map, 10);
}
else
{
int x = focusLoc.X + Utility.RandomMinMax(-12, 12);
int y = focusLoc.Y + Utility.RandomMinMax(-12, 12);
int z = map.GetAverageZ(x, y);
newLoc = new Point3D(x, y, z);
}
LandTile t = map.Tiles.GetLandTile(newLoc.X, newLoc.Y);
if (!Spells.SpellHelper.CheckMulti(new Point3D(newLoc.X, newLoc.Y, newLoc.Z), map) && IsSeaTile(t))
break;
}
if (newLoc == Point3D.Zero || GetDistanceToSqrt(newLoc) > 15)
newLoc = m_LastLocation;
DoTeleportEffects(newLoc, map);
Hidden = false;
Timer.DelayCall(TimeSpan.FromSeconds(.5), new TimerStateCallback(TimedMoveToWorld), new object[] { newLoc, map, combatant });
}
public void TimedMoveToWorld(object o)
{
object[] ojs = (object[])o;
Point3D pnt = (Point3D)ojs[0];
Map map = ojs[1] as Map;
Mobile focus = ojs[2] as Mobile;
MoveToWorld(pnt, map);
Combatant = focus;
DoAreaLightningAttack(focus);
}
public void DoAreaLightningAttack(Mobile focus)
{
if (focus == null)
return;
BaseBoat boat = BaseBoat.FindBoatAt(focus, focus.Map);
if (boat != null)
{
foreach (var mob in boat.GetMobilesOnBoard().Where(m => CanBeHarmful(m, false) && m.Alive))
{
double damage = Math.Max(40, Utility.RandomMinMax(50, 100) * ((double)Hits / (double)HitsMax));
mob.BoltEffect(0);
AOS.Damage((Mobile)mob, this, (int)damage, false, 0, 0, 0, 0, 0, 0, 100, false, false, false);
mob.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head);
}
}
}
public void DoTeleportEffects(Point3D p, Map map)
{
for (int x = -2; x <= 2; x++)
{
for (int y = -2; y <= 2; y++)
{
if (Math.Abs(x) == 2 && Math.Abs(y) == 2)
continue;
Point3D pnt = new Point3D(p.X + x, p.Y + y, Map.GetAverageZ(p.X + x, p.Y + y));
Effects.SendLocationEffect(pnt, map, 0x3728, 16, 4);
}
}
Effects.PlaySound(p, map, 0x025);
Effects.PlaySound(p, map, 0x026);
Effects.PlaySound(p, map, 0x027);
}
private bool m_HasPushed;
public override void DoDamageBoat(BaseBoat boat)
{
if (boat == null)
return;
m_HasPushed = false;
IPoint2D pnt = boat;
if (Combatant != null && boat.Contains(Combatant))
pnt = Combatant;
Direction dir = Utility.GetDirection(this, pnt);
Point3DList path = new Point3DList();
for (int i = 0; i < DamageRange; i++)
{
int x = 0, y = 0;
switch ((int)dir)
{
case (int)Direction.Running:
case (int)Direction.North: { y -= i; break; }
case 129:
case (int)Direction.Right: { y -= i; x += i; break; }
case 130:
case (int)Direction.East: { x += i; break; }
case 131:
case (int)Direction.Down: { x += i; y += i; break; }
case 132:
case (int)Direction.South: { y += i; break; }
case 133:
case (int)Direction.Left: { y += i; x -= i; break; }
case 134:
case (int)Direction.West: { x -= i; break; }
case (int)Direction.ValueMask:
case (int)Direction.Up: { x -= i; y -= i; break; }
}
path.Add(X + x, Y + y, Z);
}
new EffectsTimer(this, path, dir, DamageRange);
}
public void OnTick(Point3DList path, Direction dir, int i)
{
if (path.Count > i)
{
Point3D point = path[i];
int o = i - 1;
Server.Effects.PlaySound(point, Map, 278);
Server.Effects.PlaySound(point, Map, 279);
for (int rn = 0; rn < (o * 2) + 1; rn++)
{
int y = 0, x = 0, y2 = 0, x2 = 0;
bool diag = false;
switch ((int)dir)
{
case (int)Direction.Running:
case (int)Direction.North: { x = x - o + rn; break; }
case 129:
case (int)Direction.Right: { x = x - o + rn; y = y - o + rn; break; }
case 130:
case (int)Direction.East: { y = y - o + rn; break; }
case 131:
case (int)Direction.Down: { y = y - o + rn; x = x + o - rn; break; }
case 132:
case (int)Direction.South: { x = x + o - rn; break; }
case 133:
case (int)Direction.Left: { x = x + o - rn; y = y + o - rn; break; }
case 134:
case (int)Direction.West: { y = y + o - rn; break; }
case (int)Direction.ValueMask:
case (int)Direction.Up: { y = y + o - rn; x = x - o + rn; break; }
}
switch ((int)dir)
{
case 129:
case (int)Direction.Right: { y2++; diag = true; break; }
case 131:
case (int)Direction.Down: { x2--; diag = true; break; }
case 133:
case (int)Direction.Left: { y2--; diag = true; break; }
case (int)Direction.ValueMask:
case (int)Direction.Up: { x2++; diag = true; break; }
default: { break; }
}
Point3D ep = new Point3D(point.X + x, point.Y + y, point.Z);
Point3D ep2 = new Point3D(ep.X + x2, ep.Y + y2, ep.Z);
if (diag && i >= ((2 * path.Count) / 3))
return;
Point3D p;
if (diag && rn < (o * 2))
p = ep2;
else
p = ep;
if (Spells.SpellHelper.CheckMulti(p, Map))
{
BaseBoat boat = BaseBoat.FindBoatAt(p, Map);
if (boat != null && !m_HasPushed)
{
int damage = Utility.RandomMinMax(MinBoatDamage, MaxBoatDamage);
boat.OnTakenDamage(this, damage);
boat.StartMove(dir, 1, 0x2, boat.SlowDriftInterval, true, false);
m_HasPushed = true;
}
continue;
}
LandTile t = Map.Tiles.GetLandTile(x, y);
if (IsSeaTile(t))
{
Mobile spawn = new EffectSpawn();
spawn.MoveToWorld(p, Map);
}
}
}
}
public class EffectSpawn : BaseCreature
{
public EffectSpawn()
: base(AIType.AI_Vendor, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Body = 16;
BaseSoundID = 278;
CantWalk = true;
CanSwim = false;
Frozen = true;
SetHits(150000);
SetResistance(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Fire, 100);
SetResistance(ResistanceType.Cold, 100);
SetResistance(ResistanceType.Poison, 100);
SetResistance(ResistanceType.Energy, 100);
Timer.DelayCall(TimeSpan.FromSeconds(2), new TimerCallback(DoDelete));
}
public override bool DeleteCorpseOnDeath
{
get
{
return true;
}
}
public void DoDelete()
{
if (Alive)
Kill();
}
public override void OnDelete()
{
Effects.SendLocationEffect(Location, Map, 0x352D, 16, 4);
Effects.PlaySound(Location, Map, 0x364);
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3728, 1, 14, 0, 7, 9915, 0);
base.OnDelete();
}
public override bool AutoDispel { get { return true; } }
public override double AutoDispelChance { get { return 1.0; } }
public override bool BardImmune { get { return true; } }
public override bool Unprovokable { get { return true; } }
public override bool Uncalmable { get { return true; } }
public override Poison PoisonImmune { get { return Poison.Lethal; } }
public override int Meat { get { return 1; } }
public EffectSpawn(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();
}
}
private class EffectsTimer : Timer
{
private Direction m_Dir;
private int m_I, m_IMax;
private Point3DList m_Path;
private Charydbis m_Mobile;
public EffectsTimer(Charydbis mobile, Point3DList path, Direction dir, int imax)
: base(TimeSpan.FromSeconds(0.25), TimeSpan.FromSeconds(0.25))
{
m_Dir = dir;
m_I = 1;
m_IMax = imax;
m_Path = path;
m_Mobile = mobile;
Priority = TimerPriority.FiftyMS;
Start();
}
protected override void OnTick()
{
m_Mobile.OnTick(m_Path, m_Dir, m_I);
if (m_I >= m_IMax)
{
Stop();
return;
}
m_I++;
}
}
public void SpawnTentacle()
{
if (Combatant == null)
{
m_NextSpawn = DateTime.UtcNow + SpawnRate;
return;
}
Map map = Map;
List<Mobile> list = new List<Mobile>();
IPooledEnumerable eable = GetMobilesInRange(15);
foreach (Mobile m in eable)
{
if (m == this || !CanBeHarmful(m))
continue;
if (m is BaseCreature && (((BaseCreature)m).Controlled || ((BaseCreature)m).Summoned || ((BaseCreature)m).Team != Team))
list.Add(m);
else if (m.Player)
list.Add(m);
}
eable.Free();
if (list.Count > 0)
{
Mobile spawn = list[Utility.Random(list.Count)];
BaseBoat boat = BaseBoat.FindBoatAt(spawn, map);
Point3D loc = spawn.Location;
for (int i = 0; i < 25; i++)
{
Point3D spawnLoc = Point3D.Zero;
if (boat != null)
spawnLoc = GetValidPoint(boat, map, 4);
else
{
int y = Utility.RandomMinMax(loc.X - 10, loc.Y + 10);
int x = Utility.RandomMinMax(loc.X - 10, loc.Y + 10);
int z = map.GetAverageZ(x, y);
spawnLoc = new Point3D(x, y, z);
}
if (Spells.SpellHelper.CheckMulti(spawnLoc, map))
continue;
LandTile t = map.Tiles.GetLandTile(spawnLoc.X, spawnLoc.Y);
if (IsSeaTile(t) && spawnLoc != Point3D.Zero)
{
GiantTentacle tent = new GiantTentacle(this);
tent.MoveToWorld(spawnLoc, map);
tent.Home = tent.Location;
tent.RangeHome = 15;
tent.Team = Team;
if (spawn != this)
tent.Combatant = spawn;
break;
}
}
}
m_NextSpawn = DateTime.UtcNow + SpawnRate;
}
public bool IsSeaTile(LandTile t)
{
return t.Z == -5 && ((t.ID >= 0xA8 && t.ID <= 0xAB) || (t.ID >= 0x136 && t.ID <= 0x137));
}
public override bool OnBeforeDeath()
{
if (Map == Map.Internal)
MoveToWorld(m_LastLocation, m_LastMap);
if (CharydbisSpawner.SpawnInstance != null && CharydbisSpawner.SpawnInstance.Charydbis == this)
CharydbisSpawner.SpawnInstance.OnCharybdisKilled();
return base.OnBeforeDeath();
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
int drop = Utility.RandomMinMax(2, 5);
for (int i = 0; i < drop; i++)
{
Type pieType = m_Pies[Utility.Random(m_Pies.Length)];
Item pie = Loot.Construct(pieType);
if (pie != null)
c.DropItem(pie);
}
drop = Utility.RandomMinMax(2, 5);
for (int i = 0; i < drop; i++)
{
Type steakType = m_Steaks[Utility.Random(m_Steaks.Length)];
Item steak = Loot.Construct(steakType);
if (steak != null)
c.DropItem(steak);
}
c.DropItem(new MessageInABottle(c.Map));
c.DropItem(new SpecialFishingNet());
c.DropItem(new SpecialFishingNet());
c.DropItem(new SpecialFishingNet());
c.DropItem(new SpecialFishingNet());
FishingPole pole = new FishingPole();
BaseRunicTool.ApplyAttributesTo(pole, false, 0, Utility.RandomMinMax(2, 5), 50, 100);
c.DropItem(pole);
#region TOL
if (Core.TOL)
SkillMasteryPrimer.CheckPrimerDrop(this);
#endregion
}
public override void Delete()
{
if (m_Tentacles != null)
{
List<Mobile> tents = new List<Mobile>(m_Tentacles);
for (int i = 0; i < tents.Count; i++)
{
if (tents[i] != null)
tents[i].Kill();
}
}
base.Delete();
}
private Type[] m_Pies = new Type[]
{
typeof(AutumnDragonfishPie),
typeof(BlueLobsterPie),
typeof(BullFishPie),
typeof(CrystalFishPie),
typeof(FairySalmonPie),
typeof(FireFishPie),
typeof(GiantKoiPie),
typeof(GreatBarracudaPie),
typeof(HolyMackerelPie),
typeof(LavaFishPie),
typeof(ReaperFishPie),
typeof(SpiderCrabPie),
typeof(StoneCrabPie),
typeof(SummerDragonfishPie),
typeof(UnicornFishPie),
typeof(YellowtailBarracudaPie),
};
private Type[] m_Steaks = new Type[]
{
typeof(AutumnDragonfishSteak),
typeof(BlueLobsterMeat),
typeof(BullFishSteak),
typeof(CrystalFishSteak),
typeof(FairySalmonSteak),
typeof(FireFishSteak),
typeof(GiantKoiSteak),
typeof(GreatBarracudaSteak),
typeof(HolyMackerelSteak),
typeof(LavaFishSteak),
typeof(ReaperFishSteak),
typeof(SpiderCrabMeat),
typeof(StoneCrabMeat),
typeof(SummerDragonfishSteak),
typeof(UnicornFishSteak),
typeof(YellowtailBarracudaSteak),
};
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 8);
}
public Charydbis(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write(m_Tentacles.Count);
foreach (Mobile tent in m_Tentacles)
writer.Write(tent);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
int cnt = reader.ReadInt();
for (int i = 0; i < cnt; i++)
{
Mobile tent = reader.ReadMobile();
if (tent != null && !tent.Deleted && tent.Alive)
m_Tentacles.Add(tent);
}
m_NextSpawn = DateTime.UtcNow;
}
}
public class GiantTentacle : BaseCreature
{
private Mobile m_Master;
public GiantTentacle(Mobile master) : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
{
if (master is Charydbis)
{
m_Master = master;
((Charydbis)master).AddTentacle(this);
}
Name = "a giant tentacle";
Body = 1245;
BaseSoundID = 0x161;
CanSwim = true;
SetStr(127, 155);
SetDex(66, 85);
SetInt(102, 123);
SetHits(105, 113);
SetDamage(10, 15);
SetDamageType(ResistanceType.Physical, 50);
SetDamageType(ResistanceType.Cold, 50);
SetResistance(ResistanceType.Physical, 35, 45);
SetResistance(ResistanceType.Fire, 10, 25);
SetResistance(ResistanceType.Cold, 10, 25);
SetResistance(ResistanceType.Poison, 60, 70);
SetResistance(ResistanceType.Energy, 5, 10);
SetSkill(SkillName.Wrestling, 52.0, 70.0);
SetSkill(SkillName.Tactics, 0.0);
SetSkill(SkillName.MagicResist, 100.4, 113.5);
SetSkill(SkillName.Anatomy, 1.0, 0.0);
SetSkill(SkillName.Magery, 60.2, 72.4);
SetSkill(SkillName.EvalInt, 60.1, 73.4);
SetSkill(SkillName.Meditation, 100.0);
Fame = 2500;
Karma = -2500;
if (IsSoulboundEnemies)
IsSoulbound = true;
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 1);
}
public override void Delete()
{
if (m_Master != null && m_Master is Charydbis)
((Charydbis)m_Master).RemoveTentacle(this);
base.Delete();
}
public GiantTentacle(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write(m_Master);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_Master = reader.ReadMobile();
}
}
}

View File

@@ -0,0 +1,69 @@
using Server;
using System;
namespace Server.Mobiles
{
public class BoundSoul : BaseCreature
{
public override bool AlwaysMurderer { get { return true; } }
public BoundSoul()
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "a bound soul";
Body = 0x3CA;
Hue = 0x4001;
SetStr(150, 180);
SetDex(120, 150);
SetInt(20, 40);
SetHits(600, 620);
SetDamage(17, 22);
SetDamageType(ResistanceType.Physical, 10);
SetDamageType(ResistanceType.Cold, 30);
SetDamageType(ResistanceType.Poison, 30);
SetDamageType(ResistanceType.Energy, 30);
SetResistance(ResistanceType.Physical, 80, 95);
SetResistance(ResistanceType.Fire, 30, 40);
SetResistance(ResistanceType.Cold, 20, 30);
SetResistance(ResistanceType.Poison, 70, 80);
SetResistance(ResistanceType.Energy, 30, 40);
SetSkill(SkillName.Wrestling, 100.0, 110.0);
SetSkill(SkillName.Tactics, 110.0);
SetSkill(SkillName.MagicResist, 100.0, 115.0);
Fame = 5000;
Karma = -5000;
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 3);
}
public BoundSoul(Serial serial)
: base(serial)
{
}
public override int TreasureMapLevel { get { return 3; } }
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,508 @@
using Server;
using System;
using System.Collections.Generic;
using Server.Items;
using Server.Misc;
using Server.Regions;
using System.Linq;
namespace Server.Mobiles
{
public class CorgulTheSoulBinder : BaseSeaChampion
{
private DateTime m_NextDismount;
private DateTime m_NextArea;
private DateTime m_NextReturn;
private bool m_HasDone2ndSpawn;
private CorgulAltar m_Altar;
private List<BaseCreature> m_Helpers = new List<BaseCreature>();
public override bool CanDamageBoats { get { return false; } }
public override bool TaintedLifeAura { get { return true; } }
public override int Meat { get { return 5; } }
public override double TreasureMapChance { get { return .25; } }
public override int TreasureMapLevel { get { return 7; } }
public override Poison PoisonImmune { get { return Poison.Deadly; } }
public override bool TeleportsTo { get { return true; } }
public override TimeSpan TeleportDuration { get { return TimeSpan.FromSeconds(Utility.RandomMinMax(10, 50)); } }
public override double TeleportProb { get { return 1.0; } }
public override bool TeleportsPets { get { return true; } }
public override Type[] UniqueList { get { return new Type[] { typeof(CorgulsEnchantedSash), typeof(CorgulsHandbookOnMysticism), typeof(CorgulsHandbookOnTheUndead) }; } }
public override Type[] SharedList { get { return new Type[] { typeof(HelmOfVengence), typeof(RingOfTheSoulbinder), typeof(RuneEngravedPegLeg), typeof(CullingBlade) }; } }
public override Type[] DecorativeList { get { return new Type[] { typeof(EnchantedBladeDeed), typeof(EnchantedVortexDeed) }; } }
public override bool NoGoodies { get { return true; } }
public override bool CanGivePowerscrolls { get { return false; } }
private readonly int _SpawnPerLoc = 15;
private Point3D[] _SpawnLocs =
{
new Point3D(6447, 1262, 10),
new Point3D(6424, 1279, 10),
new Point3D(6406, 1250, 10),
new Point3D(6423, 1220, 10),
new Point3D(6461, 1237, 10),
};
[Constructable]
public CorgulTheSoulBinder()
: this(null)
{
}
public CorgulTheSoulBinder(CorgulAltar altar)
: base(null, AIType.AI_NecroMage, FightMode.Closest)
{
m_Altar = altar;
Name = "Corgul the Soulbinder";
BaseSoundID = 609;
Body = 0x4C;
Hue = 2076;
m_NextDismount = DateTime.UtcNow;
m_NextArea = DateTime.UtcNow;
m_HasDone2ndSpawn = false;
SetStr(800, 900);
SetDex(121, 165);
SetInt(300, 400);
SetMana(4500);
SetHits(65000);
SetDamage(19, 24);
SetDamageType(ResistanceType.Physical, 10);
SetDamageType(ResistanceType.Fire, 10);
SetDamageType(ResistanceType.Cold, 30);
SetDamageType(ResistanceType.Poison, 40);
SetDamageType(ResistanceType.Energy, 10);
SetResistance(ResistanceType.Physical, 50, 60);
SetResistance(ResistanceType.Fire, 80, 90);
SetResistance(ResistanceType.Cold, 85, 95);
SetResistance(ResistanceType.Poison, 80, 90);
SetResistance(ResistanceType.Energy, 80, 90);
SetSkill(SkillName.Wrestling, 110.0, 120.0);
SetSkill(SkillName.Tactics, 110.0, 120.0);
SetSkill(SkillName.Magery, 110.9, 120.0);
SetSkill(SkillName.EvalInt, 110.9, 120.0);
SetSkill(SkillName.Meditation, 110.9, 120.0);
SetSkill(SkillName.Necromancy, 110.9, 120.0);
SetSkill(SkillName.SpiritSpeak, 110.9, 120.0);
Fame = 25000;
Karma = -25000;
m_NextReturn = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(120, 180));
if (IsSoulboundEnemies)
IsSoulbound = true;
}
public double SharedChance { get { return Map != null && Map.Rules == MapRules.FeluccaRules ? .12 : .08; } }
public double DecorativeChance { get { return Map != null && Map.Rules == MapRules.FeluccaRules ? .40 : .25; } }
public override bool OnBeforeDeath()
{
List<DamageStore> rights = GetLootingRights();
Mobile winner = null;
if (rights != null && rights.Count > 0)
{
rights.Sort();
if(rights.Count >= 5)
winner = rights[Utility.Random(5)].m_Mobile;
else if(rights.Count > 1)
winner = rights[Utility.Random(rights.Count)].m_Mobile;
else
winner = rights[0].m_Mobile;
}
if(winner != null)
GiveArtifact(winner, CreateArtifact(UniqueList));
if (IsSoulboundEnemies)
EtherealSandShower.Do(Location, Map, 50, 100, 500);
return base.OnBeforeDeath();
}
public override Item GetArtifact()
{
double random = Utility.RandomDouble();
if (SharedChance >= random)
return CreateArtifact(SharedList);
else if (DecorativeChance >= random)
return CreateArtifact(DecorativeList);
return null;
}
public void SpawnHelpers()
{
foreach (var pnt in _SpawnLocs)
{
for (int i = 0; i < _SpawnPerLoc; i++)
{
BaseCreature bc;
switch (Utility.Random(7))
{
default:
case 0: bc = new BoundSoul(); break;
case 1: bc = new SoulboundApprenticeMage(); break;
case 2: bc = new SoulboundBattleMage(); break;
case 3: bc = new SoulboundPirateCaptain(); break;
case 4: bc = new SoulboundPirateRaider(); break;
case 5: bc = new SoulboundSpellSlinger(); break;
case 6: bc = new SoulboundSwashbuckler(); break;
}
m_Helpers.Add(bc);
SpawnMobile(bc, pnt);
}
}
}
public void SpawnMobile(BaseCreature bc, Point3D p)
{
if(Map == null || bc == null)
{
if(bc != null)
bc.Delete();
return;
}
int x, y, z = 0;
for(int i = 0; i < 25; i++)
{
x = Utility.RandomMinMax(p.X - 4, p.X + 4);
y = Utility.RandomMinMax(p.Y - 4, p.Y + 4);
z = Map.GetAverageZ(x, y);
if (Map.CanSpawnMobile(x, y, z))
{
p = new Point3D(x, y, z);
break;
}
}
bc.MoveToWorld(p, Map);
bc.Home = p;
bc.RangeHome = 5;
}
public override void OnThink()
{
base.OnThink();
if (m_NextReturn < DateTime.UtcNow)
{
Point3D p = CorgulAltar.SpawnLoc;
if (Region.IsPartOf<CorgulRegion>() && !Utility.InRange(Location, p, 15))
{
PlaySound(0x1FE);
FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
Location = p;
ProcessDelta();
PlaySound(0x1FE);
FixedParticles(0x376A, 9, 32, 0x13AF, EffectLayer.Waist);
m_NextReturn = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(120, 180));
}
}
if (Combatant == null)
return;
if (DateTime.UtcNow > m_NextDismount && 0.1 > Utility.RandomDouble())
DoDismount();
else if (DateTime.UtcNow > m_NextArea && 0.1 > Utility.RandomDouble())
DoAreaAttack();
if (!m_HasDone2ndSpawn && m_Helpers.Count > 0)
{
if (m_Helpers.Where(bc => bc.Alive && !bc.Deleted).Count() == 0)
{
Timer.DelayCall(TimeSpan.FromSeconds(5), SpawnHelpers);
m_HasDone2ndSpawn = true;
}
}
}
public void DoDismount()
{
List<Mobile> targets = new List<Mobile>();
IPooledEnumerable eable = GetMobilesInRange(12);
foreach (Mobile mob in eable)
{
if (!CanBeHarmful(mob) || mob == this)
continue;
if (mob is BaseCreature && (((BaseCreature)mob).Controlled || ((BaseCreature)mob).Summoned || ((BaseCreature)mob).Team != Team))
targets.Add(mob);
else if (mob is PlayerMobile && mob.Alive)
targets.Add(mob);
}
eable.Free();
PlaySound(0x2F3);
for (int i = 0; i < targets.Count; ++i)
{
Mobile m = (Mobile)targets[i];
if (m != null && !m.Deleted && m is PlayerMobile)
{
PlayerMobile pm = m as PlayerMobile;
if (pm != null && (pm.Mounted || pm.Flying))
{
pm.SetMountBlock(BlockMountType.DismountRecovery, TimeSpan.FromSeconds(10), true);
}
}
double damage = m.Hits * 0.6;
if (damage < 10.0)
damage = 10.0;
else if (damage > 75.0)
damage = 75.0;
DoHarmful(m);
AOS.Damage(m, this, (int)damage, 100, 0, 0, 0, 0);
if (m.Alive && m.Body.IsHuman && !m.Mounted)
m.Animate(20, 7, 1, true, false, 0);
}
m_NextDismount = DateTime.UtcNow + TimeSpan.FromMinutes(2);
}
public void DoAreaAttack()
{
int range = 18;
new InternalTimer(this, range);
IPooledEnumerable eable = GetMobilesInRange(range);
foreach (Mobile m in eable)
{
if ((m is PlayerMobile || (m is BaseCreature && ((BaseCreature)m).GetMaster() is PlayerMobile)) && CanBeHarmful(m))
Timer.DelayCall(TimeSpan.FromSeconds(1), new TimerStateCallback(DoDamage_Callback), m);
}
eable.Free();
m_NextArea = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(60, 180));
}
public void DoDamage_Callback(object o)
{
Mobile m = (Mobile)o;
if (m != null)
{
DoHarmful(m);
AOS.Damage(m, this, Utility.RandomMinMax(100, 150), 0, 100, 0, 0, 0);
if (Utility.RandomBool())
{
WeaponAbility bleed = WeaponAbility.BleedAttack;
bleed.OnHit(this, m, 0);
}
}
}
public void DoEffect(Point3D p, Map map)
{
int[] effect = new int[] { 14000, 14013 };
Effects.PlaySound(p, map, 0x307);
Effects.SendLocationEffect(p, map, Utility.RandomBool() ? 14000 : 14013, 20);
}
private class InternalTimer : Timer
{
private CorgulTheSoulBinder m_Mobile;
private int m_Tick;
public InternalTimer(CorgulTheSoulBinder mob, int range)
: base(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(100), range)
{
m_Tick = 1;
m_Mobile = mob;
Priority = TimerPriority.FiftyMS;
Start();
}
protected override void OnTick()
{
Geometry.Circle2D(m_Mobile.Location, m_Mobile.Map, m_Tick, new DoEffect_Callback(m_Mobile.DoEffect));
m_Tick++;
}
}
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 6);
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
if (m_Altar != null)
m_Altar.OnBossKilled();
c.DropItem(new MessageInABottle(c.Map));
c.DropItem(new SpecialFishingNet());
c.DropItem(new SpecialFishingNet());
if (m_Helpers != null)
{
foreach (BaseCreature bc in m_Helpers)
{
RegisterDamageTo(bc);
if (bc != null && bc.Alive)
bc.Kill();
}
}
}
public CorgulTheSoulBinder(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)1);
writer.Write(m_HasDone2ndSpawn);
writer.Write(m_Altar);
writer.Write(m_Helpers.Count);
foreach (BaseCreature bc in m_Helpers)
writer.Write(bc);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 1:
m_HasDone2ndSpawn = reader.ReadBool();
goto case 0;
case 0:
m_Altar = reader.ReadItem() as CorgulAltar;
int cnt = reader.ReadInt();
for (int i = 0; i < cnt; i++)
{
BaseCreature bc = reader.ReadMobile() as BaseCreature;
if (bc != null)
m_Helpers.Add(bc);
}
break;
}
m_NextDismount = DateTime.UtcNow;
m_NextArea = DateTime.UtcNow;
}
}
public class EtherealSandShower
{
public static void Do(Point3D center, Map map, int piles, int minAmount, int maxAmount)
{
new GoodiesTimer(center, map, piles, minAmount, maxAmount).Start();
}
private class GoodiesTimer : Timer
{
private readonly Map m_Map;
private readonly Point3D m_Location;
private readonly int m_PilesMax;
private int m_PilesDone = 0;
private readonly int m_MinAmount;
private readonly int m_MaxAmount;
public GoodiesTimer(Point3D center, Map map, int piles, int minAmount, int maxAmount)
: base(TimeSpan.FromSeconds(0.25d), TimeSpan.FromSeconds(0.25d))
{
m_Location = center;
m_Map = map;
m_PilesMax = piles;
m_MinAmount = minAmount;
m_MaxAmount = maxAmount;
}
protected override void OnTick()
{
if (m_PilesDone >= m_PilesMax)
{
Stop();
return;
}
Point3D p = FindGoldLocation(m_Map, m_Location, m_PilesMax / 8);
EtherealSand g = new EtherealSand(m_MinAmount, m_MaxAmount);
g.MoveToWorld(p, m_Map);
switch (Utility.Random(3))
{
case 0: // Fire column
Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), 0x3709, 10, 30, 5052);
Effects.PlaySound(g, g.Map, 0x208);
break;
case 1: // Explosion
Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), 0x36BD, 20, 10, 5044);
Effects.PlaySound(g, g.Map, 0x307);
break;
case 2: // Ball of fire
Effects.SendLocationParticles(EffectItem.Create(g.Location, g.Map, EffectItem.DefaultDuration), 0x36FE, 10, 10, 5052);
break;
}
++m_PilesDone;
}
private static Point3D FindGoldLocation(Map map, Point3D center, int range)
{
int cx = center.X;
int cy = center.Y;
for (int i = 0; i < 20; ++i)
{
int x = cx + Utility.Random(range * 2) - range;
int y = cy + Utility.Random(range * 2) - range;
if ((cx - x) * (cx - x) + (cy - y) * (cy - y) > range * range)
continue;
int z = map.GetAverageZ(x, y);
if (!map.CanFit(x, y, z, 6, false, false))
continue;
int topZ = z;
foreach (Item item in map.GetItemsInRange(new Point3D(x, y, z), 0))
{
topZ = Math.Max(topZ, item.Z + item.ItemData.CalcHeight);
}
return new Point3D(x, y, topZ);
}
return center;
}
}
}
}

View File

@@ -0,0 +1,63 @@
using Server;
using System;
namespace Server.Mobiles
{
public class SoulboundApprenticeMage : EvilMage
{
[Constructable]
public SoulboundApprenticeMage()
{
Title = "the soulbound apprentice mage";
SetStr(115);
SetDex(97);
SetInt(106);
SetHits(128);
SetMana(210);
SetDamage(5, 10);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 20);
SetResistance(ResistanceType.Fire, 21);
SetResistance(ResistanceType.Cold, 22);
SetResistance(ResistanceType.Poison, 20);
SetResistance(ResistanceType.Energy, 25);
SetSkill(SkillName.Wrestling, 40.0, 50.0);
SetSkill(SkillName.MagicResist, 40.0, 50.0);
SetSkill(SkillName.Magery, 60.2, 72.4);
SetSkill(SkillName.EvalInt, 60.1, 73.4);
SetSkill(SkillName.Meditation, 40.0, 50.0);
Fame = 1000;
Karma = -1000;
}
public override void GenerateLoot()
{
AddLoot(LootPack.Rich, 3);
}
public SoulboundApprenticeMage(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,69 @@
using Server;
using System;
namespace Server.Mobiles
{
public class SoulboundBattleMage : EvilMageLord
{
[Constructable]
public SoulboundBattleMage()
{
Title = "the soulbound battle mage";
SetStr(156);
SetDex(101);
SetInt(181);
SetHits(419);
SetMana(619);
SetDamage(12, 17);
SetDamageType(ResistanceType.Physical, 20);
SetDamageType(ResistanceType.Fire, 20);
SetDamageType(ResistanceType.Cold, 20);
SetDamageType(ResistanceType.Poison, 20);
SetDamageType(ResistanceType.Energy, 20);
SetResistance(ResistanceType.Physical, 50, 60);
SetResistance(ResistanceType.Fire, 50, 60);
SetResistance(ResistanceType.Cold, 50, 60);
SetResistance(ResistanceType.Poison, 50, 60);
SetResistance(ResistanceType.Energy, 50, 60);
SetSkill(SkillName.Wrestling, 120.0, 125.0);
SetSkill(SkillName.Tactics, 110.0, 120.0);
SetSkill(SkillName.MagicResist, 100.0, 110.0);
SetSkill(SkillName.Anatomy, 1.0, 0.0);
SetSkill(SkillName.Magery, 105.0, 110.0);
SetSkill(SkillName.EvalInt, 95.0, 100.0);
SetSkill(SkillName.Meditation, 20.0, 30.0);
Fame = 5000;
Karma = -5000;
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 3);
}
public SoulboundBattleMage(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,77 @@
using Server;
using System;
using Server.Items;
namespace Server.Mobiles
{
public class SoulboundPirateCaptain : BaseCreature
{
public override bool ClickTitle { get { return false; } }
public override bool AlwaysMurderer { get { return true; } }
public SoulboundPirateCaptain()
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "a soulbound pirate captain";
Body = 0x190;
Hue = Utility.RandomSkinHue();
Utility.AssignRandomHair(this);
SetStr(150, 200);
SetDex(150);
SetInt(95, 110);
SetHits(450, 600);
SetDamage(20, 28);
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, 100.0, 120.0);
SetSkill(SkillName.Swords, 110.0, 120.0);
SetSkill(SkillName.Tactics, 110.0, 120.0);
SetSkill(SkillName.Anatomy, 110.0, 120.0);
Fame = 8000;
Karma = -8000;
AddItem(new TricorneHat(1));
AddItem(new LeatherArms());
AddItem(new FancyShirt(1));
AddItem(new ShortPants(1));
AddItem(new Cutlass());
AddItem(new Boots(Utility.RandomNeutralHue()));
AddItem(new GoldEarrings());
}
public override void GenerateLoot()
{
AddLoot(LootPack.UltraRich, 3);
}
public SoulboundPirateCaptain(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,107 @@
using Server;
using System;
using Server.Items;
namespace Server.Mobiles
{
public class SoulboundPirateRaider : BaseCreature
{
public override bool ClickTitle { get { return false; } }
public override bool AlwaysMurderer { 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 SoulboundPirateRaider()
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "a soulbound pirate raider";
Body = 0x190;
Hue = Utility.RandomSkinHue();
Utility.AssignRandomHair(this);
SetStr(150, 200);
SetDex(125, 150);
SetInt(95, 110);
SetHits(200, 250);
SetDamage(15, 25);
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 = 2000;
Karma = -2000;
AddItem(new TricorneHat());
AddItem(new LeatherArms());
AddItem(new FancyShirt());
AddItem(new ShortPants());
AddItem(new Cutlass());
AddItem(new Boots(Utility.RandomNeutralHue()));
AddItem(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;
}
AddItem(bow);
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 2);
}
public SoulboundPirateRaider(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,66 @@
using Server;
using System;
namespace Server.Mobiles
{
public class SoulboundSpellSlinger : EvilMageLord
{
[Constructable]
public SoulboundSpellSlinger()
{
Title = "the soulbound spellslinger";
SetStr(120, 130);
SetDex(90, 100);
SetInt(120, 150);
SetHits(190, 200);
SetMana(400, 500);
SetDamage(8, 12);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 30, 40);
SetResistance(ResistanceType.Fire, 30, 40);
SetResistance(ResistanceType.Cold, 30, 40);
SetResistance(ResistanceType.Poison, 30, 40);
SetResistance(ResistanceType.Energy, 30, 40);
SetSkill(SkillName.Wrestling, 90.0, 100.0);
SetSkill(SkillName.Tactics, 80.0, 90.0);
SetSkill(SkillName.MagicResist, 90, 100.0);
SetSkill(SkillName.Anatomy, 1.0, 0.0);
SetSkill(SkillName.Magery, 100.0, 110.0);
SetSkill(SkillName.EvalInt, 80.0, 90.0);
SetSkill(SkillName.Meditation, 20.0, 30.0);
Fame = 3000;
Karma = -3000;
}
public override int TreasureMapLevel { get { return 3; } }
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 1);
}
public SoulboundSpellSlinger(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,78 @@
using Server;
using System;
using Server.Items;
namespace Server.Mobiles
{
public class SoulboundSwashbuckler : BaseCreature
{
public override bool ClickTitle { get { return false; } }
public override bool AlwaysMurderer { get { return true; } }
[Constructable]
public SoulboundSwashbuckler()
: base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
{
Name = "a soulbound swashbuckler";
Body = 0x190;
Hue = Utility.RandomSkinHue();
Utility.AssignRandomHair(this);
SetStr(120, 130);
SetDex(105, 115);
SetInt(95, 110);
SetHits(100, 125);
SetDamage(12, 18);
SetDamageType(ResistanceType.Physical, 100);
SetResistance(ResistanceType.Physical, 30, 40);
SetResistance(ResistanceType.Fire, 30, 40);
SetResistance(ResistanceType.Cold, 30, 40);
SetResistance(ResistanceType.Poison, 30, 40);
SetResistance(ResistanceType.Energy, 30, 40);
SetSkill(SkillName.MagicResist, 25.0, 47.5);
SetSkill(SkillName.Swords, 65.0, 87.5);
SetSkill(SkillName.Tactics, 65.0, 87.5);
SetSkill(SkillName.Anatomy, 65.0, 87.5);
Fame = 2000;
Karma = -2000;
AddItem(new Bandana());
AddItem(new LeatherArms());
AddItem(new FancyShirt());
AddItem(new ShortPants());
AddItem(new Cutlass());
AddItem(new Boots(Utility.RandomNeutralHue()));
AddItem(new SilverEarrings());
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 1);
}
public SoulboundSwashbuckler(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,374 @@
using System;
using Server;
using Server.Multis;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class Osiredon : BaseSeaChampion
{
public static readonly TimeSpan SpawnRate = TimeSpan.FromSeconds(30);
public static readonly int SpawnMax = 25;
private List<Mobile> m_Eels = new List<Mobile>();
private DateTime m_NextSpawn;
private DateTime m_NextSpecial;
private DateTime m_NextWaterBall;
public override bool CanDamageBoats { get { return true; } }
public override bool TaintedLifeAura { get { return true; } }
public override TimeSpan BoatDamageCooldown { get { return TimeSpan.FromSeconds(120); } }
public override int MinBoatDamage { get { return 3; } }
public override int MaxBoatDamage { get { return 8; } }
public override int DamageRange { get { return 2; } }
public override int Meat { get { return 5; } }
public override ScaleType ScaleType { get { return ScaleType.All; } }
public override int Scales { get { return 20; } }
public override double TreasureMapChance { get { return .50; } }
public override int TreasureMapLevel { get { return 7; } }
public override Type[] UniqueList { get { return new Type[] { typeof(EnchantedCoralBracelet), typeof(WandOfThunderingGlory), typeof(LeviathanHideBracers), typeof(SmilingMoonBlade) }; } }
public override Type[] SharedList { get { return new Type[] { typeof(MiniSoulForgeDeed) }; } }
public override Type[] DecorativeList { get { return new Type[] { typeof(EnchantedBladeDeed), typeof(EnchantedVortexDeed) }; } }
public override bool NoGoodies { get { return true; } }
[Constructable]
public Osiredon()
: this(null)
{
}
public Osiredon(Mobile fisher)
: base(fisher, AIType.AI_NecroMage, FightMode.Closest)
{
Name = "osiredon the scalis enforcer";
Body = 1068;
BaseSoundID = 589;
Combatant = fisher;
m_NextSpawn = DateTime.UtcNow + SpawnRate;
m_NextSpecial = DateTime.UtcNow;
m_NextWaterBall = DateTime.UtcNow;
CanSwim = true;
CantWalk = true;
SetStr(805, 900);
SetDex(121, 165);
SetInt(125, 137);
SetMana(4000);
SetHits(75000);
SetDamage(19, 26);
SetDamageType(ResistanceType.Physical, 40);
SetDamageType(ResistanceType.Cold, 30);
SetDamageType(ResistanceType.Energy, 30);
SetResistance(ResistanceType.Physical, 80, 90);
SetResistance(ResistanceType.Fire, 80, 90);
SetResistance(ResistanceType.Cold, 85, 95);
SetResistance(ResistanceType.Poison, 80, 90);
SetResistance(ResistanceType.Energy, 80, 90);
SetSkill(SkillName.Wrestling, 122.9, 128.0);
SetSkill(SkillName.Tactics, 127.7, 132.9);
SetSkill(SkillName.MagicResist, 120.9, 129.4);
SetSkill(SkillName.Necromancy, 122.9, 128.0);
SetSkill(SkillName.SpiritSpeak, 160.1, 220.0);
SetSkill(SkillName.Magery, 120.1, 129.4);
SetSkill(SkillName.EvalInt, 100.1, 120.0);
SetSkill(SkillName.DetectHidden, 100.0);
Fame = 25000;
Karma = -25000;
if (IsSoulboundEnemies)
IsSoulbound = true;
}
public void AddEel(Mobile eel)
{
if (!m_Eels.Contains(eel) && eel is ParasiticEel)
m_Eels.Add(eel);
}
public void RemoveEel(Mobile eel)
{
if (m_Eels.Contains(eel))
m_Eels.Remove(eel);
}
public override void DoDamageBoat(BaseBoat boat)
{
DoAreaExplosion();
base.DoDamageBoat(boat);
}
public override void OnDamagedBySpell(Mobile from)
{
base.OnDamagedBySpell(from);
if (m_NextSpawn < DateTime.UtcNow && m_Eels.Count < SpawnMax && 0.25 > Utility.RandomDouble())
SpawnEel(from);
}
public override void OnGotMeleeAttack(Mobile attacker)
{
base.OnGotMeleeAttack(attacker);
if (attacker.Weapon is BaseRanged && m_NextSpawn < DateTime.UtcNow && m_Eels.Count < SpawnMax && 0.25 > Utility.RandomDouble())
SpawnEel(attacker);
}
public override void OnThink()
{
base.OnThink();
if (m_NextSpecial < DateTime.UtcNow)
DoAreaExplosion();
}
public override void OnActionCombat()
{
Mobile combatant = this.Combatant as Mobile;
if (combatant == null || combatant.Deleted || combatant.Map != this.Map || !this.InRange(combatant, 12) || !this.CanBeHarmful(combatant) || !this.InLOS(combatant))
return;
if (DateTime.UtcNow >= this.m_NextWaterBall)
{
double damage = combatant.Hits * 0.3;
if (damage < 10.0)
damage = 10.0;
else if (damage > 40.0)
damage = 40.0;
this.DoHarmful(combatant);
this.MovingParticles(combatant, 0x36D4, 5, 0, false, false, 195, 0, 9502, 3006, 0, 0, 0);
AOS.Damage(combatant, this, (int)damage, 100, 0, 0, 0, 0);
if (combatant is PlayerMobile && combatant.Mount != null)
{
(combatant as PlayerMobile).SetMountBlock(BlockMountType.DismountRecovery, TimeSpan.FromSeconds(10), true);
}
m_NextWaterBall = DateTime.UtcNow + TimeSpan.FromMinutes(1);
}
}
public void SpawnEel(Mobile m)
{
Map map = this.Map;
int x = m.X; int y = m.Y; int z = m.Z;
Point3D loc = m.Location;
for (int j = 0; j < 3; j++)
{
for (int i = 0; i < 25; i++)
{
x = Utility.RandomMinMax(loc.X - 1, loc.X + 1);
y = Utility.RandomMinMax(loc.Y - 1, loc.Y + 1);
if (Spells.SpellHelper.CheckMulti(new Point3D(x, y, m.Z), map) || map.CanSpawnMobile(x, y, z))
{
ParasiticEel eel = new ParasiticEel(this);
eel.MoveToWorld(new Point3D(x, y, loc.Z), map);
if (m is PlayerMobile)
eel.Combatant = m;
break;
}
}
}
m_NextSpawn = DateTime.UtcNow + SpawnRate;
}
public void DoAreaExplosion()
{
List<Mobile> toExplode = new List<Mobile>();
IPooledEnumerable eable = this.GetMobilesInRange(8);
foreach (Mobile mob in eable)
{
if (!CanBeHarmful(mob, false) || mob == this || (mob is BaseCreature && ((BaseCreature)mob).GetMaster() == this))
continue;
if (mob.Player)
toExplode.Add(mob);
if (mob is BaseCreature && (((BaseCreature)mob).Controlled || ((BaseCreature)mob).Summoned || ((BaseCreature)mob).Team != this.Team))
toExplode.Add(mob);
}
eable.Free();
foreach (Mobile mob in toExplode)
{
mob.FixedParticles(0x36BD, 20, 10, 5044, EffectLayer.Head);
mob.PlaySound(0x307);
int damage = Utility.RandomMinMax(50, 125);
AOS.Damage(mob, this, damage, 0, 100, 0, 0, 0);
}
m_NextSpecial = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(15, 20));
}
public override void OnDeath(Container c)
{
base.OnDeath(c);
FishingPole pole = new FishingPole();
BaseRunicTool.ApplyAttributesTo(pole, false, 0, Utility.RandomMinMax(2, 5), 50, 100);
c.DropItem(pole);
c.DropItem(new MessageInABottle(c.Map));
c.DropItem(new SpecialFishingNet());
c.DropItem(new SpecialFishingNet());
#region TOL
if (Core.TOL)
SkillMasteryPrimer.CheckPrimerDrop(this);
#endregion
}
public override void Delete()
{
if (m_Eels != null)
{
List<Mobile> eels = new List<Mobile>(m_Eels);
for (int i = 0; i < eels.Count; i++)
{
if (eels[i] != null)
eels[i].Kill();
}
}
base.Delete();
}
public override void GenerateLoot()
{
AddLoot(LootPack.SuperBoss, 5);
}
public Osiredon(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();
m_NextSpawn = DateTime.UtcNow;
m_NextSpecial = DateTime.UtcNow;
m_NextWaterBall = DateTime.UtcNow;
}
}
public class ParasiticEel : BaseCreature
{
private Mobile m_Master;
public ParasiticEel(Mobile master)
: base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
{
if (master is Osiredon)
{
m_Master = master;
((Osiredon)master).AddEel(this);
}
Name = "a parasitic eel";
Body = 0x34;
//BaseSoundID = 589;
//TODO: soundid, Body
//CanSwim = true;
//CantWalk = true;
SetStr(80, 125);
SetDex(150, 250);
SetInt(20, 40);
SetHits(100);
SetDamage(4, 12);
SetDamageType(ResistanceType.Physical, 25);
SetDamageType(ResistanceType.Cold, 25);
SetDamageType(ResistanceType.Poison, 50);
SetResistance(ResistanceType.Physical, 20);
SetResistance(ResistanceType.Fire, 10, 25);
SetResistance(ResistanceType.Cold, 10, 25);
SetResistance(ResistanceType.Poison, 99);
SetResistance(ResistanceType.Energy, 5, 10);
SetSkill(SkillName.Wrestling, 52.0, 70.0);
SetSkill(SkillName.Tactics, 0.0);
SetSkill(SkillName.MagicResist, 100.4, 113.5);
SetSkill(SkillName.Anatomy, 1.0, 0.0);
SetSkill(SkillName.Magery, 60.2, 72.4);
SetSkill(SkillName.EvalInt, 60.1, 73.4);
SetSkill(SkillName.Meditation, 100.0);
Fame = 2500;
Karma = -2500;
}
public override Poison PoisonImmune { get { return Poison.Parasitic; } }
public override Poison HitPoison { get { return Poison.Parasitic; } }
public override void Delete()
{
if (m_Master != null && m_Master is Osiredon)
((Osiredon)m_Master).RemoveEel(this);
base.Delete();
}
public override void GenerateLoot()
{
AddLoot(LootPack.FilthyRich, 1);
}
public ParasiticEel(Serial serial)
: base(serial)
{
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write((int)0);
writer.Write(m_Master);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
m_Master = reader.ReadMobile();
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using Server;
namespace Server.Mobiles
{
public class BoatPainter : BaseVendor
{
private List<SBInfo> m_SBInfos = new List<SBInfo>();
protected override List<SBInfo> SBInfos { get { return m_SBInfos; } }
[Constructable]
public BoatPainter()
: base("the boat painter")
{
SetSkill(SkillName.Carpentry, 36.0, 68.0);
}
public override void InitSBInfo()
{
m_SBInfos.Add(new SBBoatPainter());
}
public BoatPainter(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();
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using Server;
namespace Server.Mobiles
{
public class CrabFisher : BaseVendor
{
private List<SBInfo> m_SBInfos = new List<SBInfo>();
protected override List<SBInfo> SBInfos { get { return m_SBInfos; } }
[Constructable]
public CrabFisher()
: base("the crab fisher")
{
SetSkill(SkillName.Fishing, 36.0, 68.0);
}
public override void InitSBInfo()
{
m_SBInfos.Add(new SBCrabFisher());
}
public CrabFisher(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();
}
}
}

View File

@@ -0,0 +1,236 @@
using Server;
using System;
using Server.Items;
using Server.ContextMenus;
using System.Collections.Generic;
using Server.Multis;
using Server.Network;
namespace Server.Mobiles
{
public class DockMaster : BaseVendor
{
public static readonly int DryDockDistance = 300;
public static readonly int DryDockAmount = 2500;
public override bool IsActiveVendor { get { return false; } }
public override bool IsInvulnerable { get { return true; } }
private List<SBInfo> m_SBInfos = new List<SBInfo>();
protected override List<SBInfo> SBInfos { get { return m_SBInfos; } }
public override void InitSBInfo()
{
m_SBInfos.Add(new SBFisherman());
}
[Constructable]
public DockMaster() : base( "the dockmaster" )
{
}
public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> list )
{
base.GetContextMenuEntries(from, list);
list.Add(new DryDockEntry(from, this));
list.Add(new RetrieveHoldEntry(from, this));
}
private class DryDockEntry : ContextMenuEntry
{
private Mobile m_From;
private DockMaster m_DockMaster;
public DryDockEntry(Mobile from, DockMaster dockmaster) : base(1149575, 5)
{
m_From = from;
m_DockMaster = dockmaster;
}
public override void OnClick()
{
var boat = BaseBoat.GetBoat(m_From);
if (boat != null && m_DockMaster.InRange(boat.Location, 100))
boat.BeginDryDock(m_From, m_DockMaster);
else
m_DockMaster.SayTo(m_From, 502581); //I cannot find the ship!
}
}
private class RetrieveHoldEntry : ContextMenuEntry
{
private Mobile m_From;
private DockMaster m_DockMaster;
public RetrieveHoldEntry(Mobile from, DockMaster dockmaster)
: base(1116504, 5)
{
m_From = from;
m_DockMaster = dockmaster;
}
public override void OnClick()
{
if (m_DockMaster.Map == null)
return;
Container pack = m_From.Backpack;
if (pack != null && pack.GetAmount(typeof(Gold)) < DockMaster.DryDockAmount && Banker.GetBalance(m_From) < DryDockAmount)
{
m_DockMaster.PrivateOverheadMessage(MessageType.Regular, m_DockMaster.SpeechHue, 1116506, DockMaster.DryDockAmount.ToString(), m_From.NetState); //The price is ~1_price~ and I will accept nothing less!
return;
}
var boat = BaseBoat.GetBoat(m_From);
if (boat != null && m_DockMaster.InRange(boat.Location, 50))
m_DockMaster.TryRetrieveHold(m_From, boat);
else
m_DockMaster.SayTo(m_From, 502581); //I cannot find the ship!
}
}
public void TryRetrieveHold(Mobile from, BaseBoat boat)
{
for (int i = 0; i < m_Crates.Count; i++) {
if (m_Crates[i].Owner == from) {
from.SendLocalizedMessage(1116516); //Thou must return thy current shipping crate before I can retrieve another shipment for you.
return;
}
}
Container pack = from.Backpack;
Container hold;
if (boat is BaseGalleon)
hold = ((BaseGalleon)boat).GalleonHold;
else
hold = boat.Hold;
if (hold == null || hold.Items.Count == 0)
{
from.SendMessage("Your hold is empty!");
return;
}
ShipCrate crate = new ShipCrate(from, boat);
m_Crates.Add(crate);
if (!pack.ConsumeTotal(typeof(Gold), DryDockAmount))
Banker.Withdraw(from, DryDockAmount);
bool cantMove = false;
List<Item> items = new List<Item>(hold.Items);
foreach (Item item in items)
{
if (item.Movable)
crate.DropItem(item);
else
cantMove = true;
}
Point3D pnt = Point3D.Zero;
if (!CanDropCrate(ref pnt, this.Map))
{
SayTo(from, 1116517); //Arrrgh! My dock has no more room. Please come back later.
from.BankBox.DropItem(crate);
from.SendMessage("Your shipping crate has been placed in your bank box.");
//from.SendMessage("You have 30 minutes to obtain the contents of your shipping crate. You can find it in the wearhouse on the westernmost tip of the floating emproiam");
}
else
{
from.SendLocalizedMessage(1116542, ShipCrate.DT.ToString()); //Yer ship has been unloaded to a crate inside this here warehouse. You have ~1_time~ minutes to get yer goods or it be gone.
crate.MoveToWorld(pnt, this.Map);
}
if (cantMove)
from.SendMessage("We were unable to pack up one or more of the items in your cargo hold.");
}
private Rectangle2D m_Bounds = new Rectangle2D(4561, 2298, 8, 5);
private static List<ShipCrate> m_Crates = new List<ShipCrate>();
public static void RemoveCrate(ShipCrate crate)
{
if (m_Crates.Contains(crate))
m_Crates.Remove(crate);
}
private bool CanDropCrate(ref Point3D pnt, Map map)
{
for (int i = 0; i < 45; i++)
{
int x = Utility.Random(m_Bounds.X, m_Bounds.Width);
int y = Utility.Random(m_Bounds.Y, m_Bounds.Height);
int z = -2;
bool badSpot = false;
Point3D p = new Point3D(x, y, z);
IPooledEnumerable eable = map.GetItemsInRange(pnt, 0);
foreach (Item item in eable)
{
if (item != null && item is Container && !item.Movable)
{
badSpot = true;
break;
}
}
eable.Free();
if (!badSpot)
{
pnt = p;
return true;
}
}
return false;
}
public BaseBoat GetBoatInRegion(Mobile from)
{
if (this.Map == null || this.Map == Map.Internal || this.Region == null)
return null;
foreach (Rectangle3D rec in this.Region.Area)
{
IPooledEnumerable eable = this.Map.GetItemsInBounds(new Rectangle2D(rec.Start.X, rec.Start.Y, rec.Width, rec.Height));
foreach (Item item in eable)
{
if (item is BaseBoat && ((BaseBoat)item).Owner == from && InRange(item.Location, DryDockDistance))
{
eable.Free();
return (BaseBoat)item;
}
}
eable.Free();
}
return null;
}
public DockMaster(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,56 @@
using System;
using System.Collections.Generic;
using Server;
namespace Server.Mobiles
{
public class DocksAlchemist : BaseVendor
{
private List<SBInfo> m_SBInfos = new List<SBInfo>();
protected override List<SBInfo> SBInfos { get { return m_SBInfos; } }
public override NpcGuild NpcGuild { get { return NpcGuild.MagesGuild; } }
[Constructable]
public DocksAlchemist() : base( "the alchemist" )
{
SetSkill(SkillName.Alchemy, 85.0, 100.0);
SetSkill(SkillName.TasteID, 65.0, 88.0);
}
public override void InitSBInfo()
{
m_SBInfos.Add(new SBDocksAlchemist());
}
public override VendorShoeType ShoeType
{
get { return Utility.RandomBool() ? VendorShoeType.Shoes : VendorShoeType.Sandals; }
}
public override void InitOutfit()
{
base.InitOutfit();
AddItem( new Server.Items.HalfApron() );
}
public DocksAlchemist( 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();
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class SBDocksAlchemist : SBInfo
{
private List<GenericBuyInfo> m_BuyInfo = new InternalBuyInfo();
private IShopSellInfo m_SellInfo = new InternalSellInfo();
public SBDocksAlchemist()
{
}
public override IShopSellInfo SellInfo { get { return m_SellInfo; } }
public override List<GenericBuyInfo> BuyInfo { get { return m_BuyInfo; } }
public class InternalBuyInfo : List<GenericBuyInfo>
{
public InternalBuyInfo()
{
Add( new GenericBuyInfo( "1116302", typeof( Saltpeter ), 167, 20, 16954, 1150 ) );
Add(new GenericBuyInfo(typeof(RefreshPotion), 15, 10, 0xF0B, 0));
Add(new GenericBuyInfo(typeof(AgilityPotion), 15, 10, 0xF08, 0));
Add(new GenericBuyInfo(typeof(NightSightPotion), 15, 10, 0xF06, 0));
Add(new GenericBuyInfo(typeof(LesserHealPotion), 15, 10, 0xF0C, 0));
Add(new GenericBuyInfo(typeof(StrengthPotion), 15, 10, 0xF09, 0));
Add(new GenericBuyInfo(typeof(LesserPoisonPotion), 15, 10, 0xF0A, 0));
Add(new GenericBuyInfo(typeof(LesserCurePotion), 15, 10, 0xF07, 0));
Add(new GenericBuyInfo(typeof(LesserExplosionPotion), 21, 10, 0xF0D, 0));
Add(new GenericBuyInfo(typeof(MortarPestle), 8, 10, 0xE9B, 0));
Add(new GenericBuyInfo(typeof(BlackPearl), 5, 20, 0xF7A, 0));
Add(new GenericBuyInfo(typeof(Bloodmoss), 5, 20, 0xF7B, 0));
Add(new GenericBuyInfo(typeof(Garlic), 3, 20, 0xF84, 0));
Add(new GenericBuyInfo(typeof(Ginseng), 3, 20, 0xF85, 0));
Add(new GenericBuyInfo(typeof(MandrakeRoot), 3, 20, 0xF86, 0));
Add(new GenericBuyInfo(typeof(Nightshade), 3, 20, 0xF88, 0));
Add(new GenericBuyInfo(typeof(SpidersSilk), 3, 20, 0xF8D, 0));
Add(new GenericBuyInfo(typeof(SulfurousAsh), 3, 20, 0xF8C, 0));
Add(new GenericBuyInfo(typeof(Bottle), 5, 100, 0xF0E, 0));
Add(new GenericBuyInfo(typeof(HeatingStand), 2, 100, 0x1849, 0));
Add(new GenericBuyInfo("1041060", typeof(HairDye), 37, 10, 0xEFF, 0));
Add(new GenericBuyInfo(typeof(HeatingStand), 2, 100, 0x1849, 0)); // This is on OSI :-P
}
}
public class InternalSellInfo : GenericSellInfo
{
public InternalSellInfo()
{
Add( typeof( Saltpeter ), 10 );
Add(typeof(BlackPearl), 3);
Add(typeof(Bloodmoss), 3);
Add(typeof(MandrakeRoot), 2);
Add(typeof(Garlic), 2);
Add(typeof(Ginseng), 2);
Add(typeof(Nightshade), 2);
Add(typeof(SpidersSilk), 2);
Add(typeof(SulfurousAsh), 2);
Add(typeof(Bottle), 3);
Add(typeof(MortarPestle), 4);
Add(typeof(HairDye), 19);
Add(typeof(NightSightPotion), 7);
Add(typeof(AgilityPotion), 7);
Add(typeof(StrengthPotion), 7);
Add(typeof(RefreshPotion), 7);
Add(typeof(LesserCurePotion), 7);
Add(typeof(LesserHealPotion), 7);
Add(typeof(LesserPoisonPotion), 7);
Add(typeof(LesserExplosionPotion), 10);
}
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using Server.Items;
using Server.Targeting;
namespace Server.Mobiles
{
public class SBBoatPainter : SBInfo
{
private List<GenericBuyInfo> m_BuyInfo = new InternalBuyInfo();
private IShopSellInfo m_SellInfo = new InternalSellInfo();
public SBBoatPainter()
{
}
public override IShopSellInfo SellInfo { get { return m_SellInfo; } }
public override List<GenericBuyInfo> BuyInfo { get { return m_BuyInfo; } }
public class InternalBuyInfo : List<GenericBuyInfo>
{
public InternalBuyInfo()
{
Add(new GenericBuyInfo("Boat Paint", typeof(BoatPaint), 6256, 20, 4011, 276, new object[] { 276 }));
Add(new GenericBuyInfo("Boat Paint", typeof(BoatPaint), 6256, 20, 4011, 396, new object[] { 396 }));
Add(new GenericBuyInfo("Boat Paint", typeof(BoatPaint), 6256, 20, 4011, 516, new object[] { 516 }));
Add(new GenericBuyInfo("Boat Paint", typeof(BoatPaint), 6256, 20, 4011, 1900, new object[] { 1900 }));
Add(new GenericBuyInfo("Boat Paint", typeof(BoatPaint), 6256, 20, 4011, 251, new object[] { 251 }));
Add(new GenericBuyInfo("Boat Paint", typeof(BoatPaint), 6256, 20, 4011, 246, new object[] { 246 }));
Add(new GenericBuyInfo("Boat Paint", typeof(BoatPaint), 6256, 20, 4011, 2213, new object[] { 2213 }));
Add(new GenericBuyInfo("Boat Paint", typeof(BoatPaint), 6256, 20, 4011, 36, new object[] { 36 }));
Add(new GenericBuyInfo("Boat Paint Remover", typeof(BoatPaintRemover), 6256, 20, 4011, 0));
}
}
public class InternalSellInfo : GenericSellInfo
{
public InternalSellInfo()
{
Add(typeof(LobsterTrap), 10);
}
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class SBCrabFisher : SBInfo
{
private List<GenericBuyInfo> m_BuyInfo = new InternalBuyInfo();
private IShopSellInfo m_SellInfo = new InternalSellInfo();
public SBCrabFisher()
{
}
public override IShopSellInfo SellInfo { get { return m_SellInfo; } }
public override List<GenericBuyInfo> BuyInfo { get { return m_BuyInfo; } }
public class InternalBuyInfo : List<GenericBuyInfo>
{
public InternalBuyInfo()
{
Add(new GenericBuyInfo("empty lobster trap", typeof(LobsterTrap), 137, 500, 17615, 0));
}
}
public class InternalSellInfo : GenericSellInfo
{
public InternalSellInfo()
{
Add(typeof(LobsterTrap), 10);
Add(typeof(AppleCrab), 10);
Add(typeof(BlueCrab), 10);
Add(typeof(DungeonessCrab), 10);
Add(typeof(KingCrab), 10);
Add(typeof(RockCrab), 10);
Add(typeof(SnowCrab), 10);
Add(typeof(StoneCrab), 250);
Add(typeof(SpiderCrab), 250);
Add(typeof(TunnelCrab), 2500);
Add(typeof(VoidCrab), 2500);
Add(typeof(CrustyLobster), 10);
Add(typeof(FredLobster), 10);
Add(typeof(HummerLobster), 10);
Add(typeof(RockLobster), 10);
Add(typeof(ShovelNoseLobster), 10);
Add(typeof(SpineyLobster), 10);
Add(typeof(BlueLobster), 250);
Add(typeof(BloodLobster), 2500);
Add(typeof(DreadLobster), 2500);
Add(typeof(VoidLobster), 2500);
Add(typeof(StoneCrabMeat), 100);
Add(typeof(SpiderCrabMeat), 100);
Add(typeof(BlueLobsterMeat), 100);
}
}
}
}

View File

@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class SBSeaMarketTavernKeeper : SBInfo
{
private List<GenericBuyInfo> m_BuyInfo = new InternalBuyInfo();
private IShopSellInfo m_SellInfo = new InternalSellInfo();
public SBSeaMarketTavernKeeper()
{
}
public override IShopSellInfo SellInfo { get { return m_SellInfo; } }
public override List<GenericBuyInfo> BuyInfo { get { return m_BuyInfo; } }
public class InternalBuyInfo : List<GenericBuyInfo>
{
public InternalBuyInfo()
{
Add(new GenericBuyInfo("1116299", typeof(MentoSeasoning), 1002, 10, 2454, 95));
Add(new GenericBuyInfo("1116338", typeof(SamuelsSecretSauce), 1007, 10, 2463, 1461));
Add(new GenericBuyInfo("1116300", typeof(DarkTruffle), 1001, 10, 3352, 1908));
Add( new BeverageBuyInfo( typeof( BeverageBottle ), BeverageType.Ale, 7, 20, 0x99F, 0 ) );
Add( new BeverageBuyInfo( typeof( BeverageBottle ), BeverageType.Wine, 7, 20, 0x9C7, 0 ) );
Add( new BeverageBuyInfo( typeof( BeverageBottle ), BeverageType.Liquor, 7, 20, 0x99B, 0 ) );
Add( new BeverageBuyInfo( typeof( Jug ), BeverageType.Cider, 13, 20, 0x9C8, 0 ) );
Add( new BeverageBuyInfo( typeof( Pitcher ), BeverageType.Milk, 7, 20, 0x9F0, 0 ) );
Add( new BeverageBuyInfo( typeof( Pitcher ), BeverageType.Ale, 11, 20, 0x1F95, 0 ) );
Add( new BeverageBuyInfo( typeof( Pitcher ), BeverageType.Cider, 11, 20, 0x1F97, 0 ) );
Add( new BeverageBuyInfo( typeof( Pitcher ), BeverageType.Liquor, 11, 20, 0x1F99, 0 ) );
Add( new BeverageBuyInfo( typeof( Pitcher ), BeverageType.Wine, 11, 20, 0x1F9B, 0 ) );
Add( new BeverageBuyInfo( typeof( Pitcher ), BeverageType.Water, 11, 20, 0x1F9D, 0 ) );
Add( new GenericBuyInfo( typeof( BreadLoaf ), 6, 10, 0x103B, 0 ) );
Add( new GenericBuyInfo( typeof( CheeseWheel ), 21, 10, 0x97E, 0 ) );
Add( new GenericBuyInfo( typeof( CookedBird ), 17, 20, 0x9B7, 0 ) );
Add( new GenericBuyInfo( typeof( LambLeg ), 8, 20, 0x160A, 0 ) );
Add( new GenericBuyInfo( typeof( ChickenLeg ), 5, 20, 0x1608, 0 ) );
Add( new GenericBuyInfo( typeof( Ribs ), 7, 20, 0x9F2, 0 ) );
Add( new GenericBuyInfo( typeof( WoodenBowlOfCarrots ), 3, 20, 0x15F9, 0 ) );
Add( new GenericBuyInfo( typeof( WoodenBowlOfCorn ), 3, 20, 0x15FA, 0 ) );
Add( new GenericBuyInfo( typeof( WoodenBowlOfLettuce ), 3, 20, 0x15FB, 0 ) );
Add( new GenericBuyInfo( typeof( WoodenBowlOfPeas ), 3, 20, 0x15FC, 0 ) );
Add( new GenericBuyInfo( typeof( EmptyPewterBowl ), 2, 20, 0x15FD, 0 ) );
Add( new GenericBuyInfo( typeof( PewterBowlOfCorn ), 3, 20, 0x15FE, 0 ) );
Add( new GenericBuyInfo( typeof( PewterBowlOfLettuce ), 3, 20, 0x15FF, 0 ) );
Add( new GenericBuyInfo( typeof( PewterBowlOfPeas ), 3, 20, 0x1601, 0 ) );
Add( new GenericBuyInfo( typeof( PewterBowlOfPotatos ), 3, 20, 0x1601, 0 ) );
Add( new GenericBuyInfo( typeof( WoodenBowlOfStew ), 3, 20, 0x1604, 0 ) );
Add( new GenericBuyInfo( typeof( WoodenBowlOfTomatoSoup ), 3, 20, 0x1606, 0 ) );
Add( new GenericBuyInfo( typeof( ApplePie ), 7, 20, 0x1041, 0 ) ); //OSI just has Pie, not Apple/Fruit/Meat
Add( new GenericBuyInfo( "1016450", typeof( Chessboard ), 2, 20, 0xFA6, 0 ) );
Add( new GenericBuyInfo( "1016449", typeof( CheckerBoard ), 2, 20, 0xFA6, 0 ) );
Add( new GenericBuyInfo( typeof( Backgammon ), 2, 20, 0xE1C, 0 ) );
Add(new GenericBuyInfo(typeof(Dices), 2, 20, 0xFA7, 0));
Add( new GenericBuyInfo( "1041243", typeof( ContractOfEmployment ), 1252, 20, 0x14F0, 0 ) );
Add( new GenericBuyInfo( "a barkeep contract", typeof( BarkeepContract ), 1252, 20, 0x14F0, 0 ) );
if ( Multis.BaseHouse.NewVendorSystem )
Add( new GenericBuyInfo( "1062332", typeof( VendorRentalContract ), 1252, 20, 0x14F0, 0x672 ) );
/*if ( Map == Tokuno )
{
Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E8, 0 ) );
Add( new GenericBuyInfo( typeof( Wasabi ), 2, 20, 0x24E9, 0 ) );
Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2836, 0 ) );
Add( new GenericBuyInfo( typeof( BentoBox ), 6, 20, 0x2837, 0 ) );
Add( new GenericBuyInfo( typeof( GreenTeaBasket ), 2, 20, 0x284B, 0 ) );
}*/
}
}
public class InternalSellInfo : GenericSellInfo
{
public InternalSellInfo()
{
Add( typeof( WoodenBowlOfCarrots ), 1 );
Add( typeof( WoodenBowlOfCorn ), 1 );
Add( typeof( WoodenBowlOfLettuce ), 1 );
Add( typeof( WoodenBowlOfPeas ), 1 );
Add( typeof( EmptyPewterBowl ), 1 );
Add( typeof( PewterBowlOfCorn ), 1 );
Add( typeof( PewterBowlOfLettuce ), 1 );
Add( typeof( PewterBowlOfPeas ), 1 );
Add( typeof( PewterBowlOfPotatos ), 1 );
Add( typeof( WoodenBowlOfStew ), 1 );
Add( typeof( WoodenBowlOfTomatoSoup ), 1 );
Add( typeof( BeverageBottle ), 3 );
Add( typeof( Jug ), 6 );
Add( typeof( Pitcher ), 5 );
Add( typeof( GlassMug ), 1 );
Add( typeof( BreadLoaf ), 3 );
//Add( typeof( CheeseWheel ), 12 );
//Add( typeof( Ribs ), 6 );
//Add( typeof( Peach ), 1 );
//Add( typeof( Pear ), 1 );
//Add( typeof( Grapes ), 1 );
//Add( typeof( Apple ), 1 );
//Add( typeof( Banana ), 1 );
Add( typeof( Candle ), 3 );
Add( typeof( Chessboard ), 1 );
Add( typeof( CheckerBoard ), 1 );
Add( typeof( Backgammon ), 1 );
Add( typeof( Dices ), 1 );
Add( typeof( ContractOfEmployment ), 626 );
}
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using Server;
namespace Server.Mobiles
{
public class SeaMarketTavernKeeper : BaseVendor
{
private List<SBInfo> m_SBInfos = new List<SBInfo>();
protected override List<SBInfo> SBInfos{ get { return m_SBInfos; } }
[Constructable]
public SeaMarketTavernKeeper() : base( "the tavern keeper" )
{
}
public override void InitSBInfo()
{
m_SBInfos.Add(new SBSeaMarketTavernKeeper());
}
public override void InitOutfit()
{
base.InitOutfit();
AddItem( new Server.Items.HalfApron() );
}
public SeaMarketTavernKeeper( 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();
}
}
}