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