777 lines
25 KiB
C#
777 lines
25 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|