363 lines
11 KiB
C#
363 lines
11 KiB
C#
using Server;
|
|
using System;
|
|
using Server.Items;
|
|
using Server.Engines.VoidPool;
|
|
|
|
namespace Server.Mobiles
|
|
{
|
|
public class CoraTheSorceress : BaseCreature, IElementalCreature, IAuraCreature
|
|
{
|
|
public ElementType ElementType { get { return ElementType.Chaos; } }
|
|
|
|
public DateTime NextManaDrain { get; set; }
|
|
|
|
public TimeSpan ManaDrainInterval { get { return TimeSpan.FromSeconds(Utility.RandomMinMax(15, 120)); } }
|
|
|
|
[Constructable]
|
|
public CoraTheSorceress() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.1)
|
|
{
|
|
Body = 0x191;
|
|
Name = "Cora";
|
|
Title = "the sorceress";
|
|
|
|
HairItemID = 0x2045;
|
|
HairHue = 452;
|
|
|
|
SetStr(909, 949);
|
|
SetDex(125);
|
|
SetInt(903, 947);
|
|
|
|
SetHits(35000);
|
|
|
|
SetDamage(17, 25);
|
|
|
|
SetDamageType(ResistanceType.Physical, 50);
|
|
SetDamageType(ResistanceType.Energy, 50);
|
|
|
|
SetResistance(ResistanceType.Physical, 52, 67);
|
|
SetResistance(ResistanceType.Fire, 51, 68);
|
|
SetResistance(ResistanceType.Cold, 51, 69);
|
|
SetResistance(ResistanceType.Poison, 51, 70);
|
|
SetResistance(ResistanceType.Energy, 50, 68);
|
|
|
|
SetSkill(SkillName.Wrestling, 100.1, 119.7);
|
|
SetSkill(SkillName.Tactics, 102.3, 118.5);
|
|
SetSkill(SkillName.MagicResist, 101.2, 119.6);
|
|
SetSkill(SkillName.Anatomy, 100.1, 117.5);
|
|
SetSkill(SkillName.Magery, 100.1, 117.5);
|
|
SetSkill(SkillName.EvalInt, 100.1, 117.5);
|
|
|
|
Fame = 32000;
|
|
Karma = -32000;
|
|
|
|
AddAndEquip(new WildStaff(), 1971);
|
|
AddAndEquip(new ThighBoots(), 1910);
|
|
AddAndEquip(new ChainLegs(), 1936);
|
|
AddAndEquip(new LeatherGloves(), 1910);
|
|
AddAndEquip(new LeatherBustierArms(), 1947);
|
|
|
|
SetSpecialAbility(SpecialAbility.DragonBreath);
|
|
SetAreaEffect(AreaEffect.AuraDamage);
|
|
}
|
|
|
|
public override bool AlwaysMurderer { get { return true; } }
|
|
public override bool ClickTitle { get { return false; } }
|
|
public override bool ShowFameTitle { get { return false; } }
|
|
|
|
public void AuraEffect(Mobile m)
|
|
{
|
|
int mana = Utility.Random(1, m.Mana);
|
|
m.Mana -= mana;
|
|
m.SendLocalizedMessage(1153114, mana.ToString()); // Cora drains ~1_VAL~ points of your mana!
|
|
}
|
|
|
|
public override bool TeleportsTo { get { return true; } }
|
|
public override TimeSpan TeleportDuration { get { return TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); } }
|
|
public override double TeleportProb { get { return 1.0; } }
|
|
public override bool TeleportsPets { get { return true; } }
|
|
|
|
public override int GetDeathSound() { return 0x316; }
|
|
|
|
public override void GenerateLoot()
|
|
{
|
|
AddLoot(LootPack.UltraRich, 3);
|
|
AddLoot(LootPack.SuperBoss, 3);
|
|
}
|
|
|
|
private void AddAndEquip(Item item, int hue = 0)
|
|
{
|
|
item.Movable = false;
|
|
item.Hue = hue;
|
|
AddItem(item);
|
|
}
|
|
|
|
public override void OnThink()
|
|
{
|
|
base.OnThink();
|
|
|
|
if (NextManaDrain < DateTime.UtcNow)
|
|
DoManaDrain();
|
|
}
|
|
|
|
public void DoManaDrain()
|
|
{
|
|
Animate(AnimationType.Spell, 1);
|
|
|
|
DoEffects(Direction.North);
|
|
DoEffects(Direction.West);
|
|
DoEffects(Direction.South);
|
|
DoEffects(Direction.East);
|
|
|
|
NextManaDrain = DateTime.UtcNow + ManaDrainInterval;
|
|
}
|
|
|
|
private bool DoEffects(Direction d)
|
|
{
|
|
int x = this.X;
|
|
int y = this.Y;
|
|
int z = this.Z;
|
|
int range = 10;
|
|
int offset = 8;
|
|
|
|
switch (d)
|
|
{
|
|
case Direction.North:
|
|
x = this.X + Utility.RandomMinMax(-offset, offset);
|
|
y = this.Y - range;
|
|
break;
|
|
case Direction.West:
|
|
x = this.X - range;
|
|
y = this.Y + Utility.RandomMinMax(-offset, offset);
|
|
break;
|
|
case Direction.South:
|
|
x = this.X + Utility.RandomMinMax(-offset, offset);
|
|
y = this.Y + range;
|
|
break;
|
|
case Direction.East:
|
|
x = this.X + range;
|
|
y = this.Y + Utility.RandomMinMax(-offset, offset);
|
|
break;
|
|
}
|
|
|
|
for (int i = 0; i < range; i++)
|
|
{
|
|
switch (d)
|
|
{
|
|
case Direction.North: y += i; break;
|
|
case Direction.West: x += i; break;
|
|
case Direction.South: y -= i; break;
|
|
case Direction.East: x -= i; break;
|
|
}
|
|
|
|
z = this.Map.GetAverageZ(x, y);
|
|
Point3D p = new Point3D(x, y, z);
|
|
|
|
if (Server.Spells.SpellHelper.AdjustField(ref p, this.Map, 12, false))/*this.Map.CanFit(x, y, z, 16, false, false, true))/*this.Map.CanSpawnMobile(x, y, z)*/
|
|
{
|
|
MovementPath path = new MovementPath(this, p);
|
|
|
|
if (path.Success)
|
|
{
|
|
DropCrack(path);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void DropCrack(MovementPath path)
|
|
{
|
|
int time = 10;
|
|
int x = this.X;
|
|
int y = this.Y;
|
|
|
|
for (int i = 0; i < path.Directions.Length; ++i)
|
|
{
|
|
Movement.Movement.Offset(path.Directions[i], ref x, ref y);
|
|
IPoint3D p = new Point3D(x, y, this.Map.GetAverageZ(x, y)) as IPoint3D;
|
|
|
|
Timer.DelayCall(TimeSpan.FromMilliseconds(time), new TimerStateCallback(ManaDrainEffects_Callback), new object[] { p, this.Map });
|
|
|
|
time += 200;
|
|
}
|
|
}
|
|
|
|
private void ManaDrainEffects_Callback(object o)
|
|
{
|
|
object[] objs = o as object[];
|
|
IPoint3D p = objs[0] as IPoint3D;
|
|
Map map = objs[1] as Map;
|
|
|
|
var item = new ManaDrainItem(Utility.RandomList(6913, 6915, 6917, 6919), this);
|
|
Spells.SpellHelper.GetSurfaceTop(ref p);
|
|
|
|
item.MoveToWorld(new Point3D(p), this.Map);
|
|
}
|
|
|
|
private class ManaDrainItem : Item
|
|
{
|
|
public Item Static { get; private set; }
|
|
public Mobile Owner { get; private set; }
|
|
|
|
public ManaDrainItem(int id, Mobile owner) : base(id)
|
|
{
|
|
Owner = owner;
|
|
|
|
Movable = false;
|
|
Hue = 1152;
|
|
Timer.DelayCall(TimeSpan.FromSeconds(5), ChangeHue);
|
|
}
|
|
|
|
private void ChangeHue()
|
|
{
|
|
Hue = 1153;
|
|
Static.Hue = 1153;
|
|
|
|
Timer.DelayCall(TimeSpan.FromSeconds(0.5), Delete);
|
|
}
|
|
|
|
public override void Delete()
|
|
{
|
|
if (Static != null)
|
|
Static.Delete();
|
|
|
|
Static = null;
|
|
base.Delete();
|
|
}
|
|
|
|
public override void OnLocationChange(Point3D oldLocation)
|
|
{
|
|
Static = new Static(this.ItemID + 1);
|
|
Static.MoveToWorld(this.Location, this.Map);
|
|
|
|
IPooledEnumerable eable = this.Map.GetMobilesInRange(this.Location, 0);
|
|
|
|
foreach (Mobile m in eable)
|
|
{
|
|
OnMoveOver(m);
|
|
}
|
|
eable.Free();
|
|
}
|
|
|
|
public override bool OnMoveOver(Mobile m)
|
|
{
|
|
if ((m is PlayerMobile || (m is BaseCreature && !((BaseCreature)m).IsMonster)) && m.CanBeHarmful(Owner, false))
|
|
{
|
|
if (m is PlayerMobile && Services.TownCryer.TownCryerSystem.UnderMysteriousPotionEffects((PlayerMobile)m, true))
|
|
{
|
|
m.SayTo(m, 1158288, 1154); // *You resist Cora's attack!*
|
|
}
|
|
else
|
|
{
|
|
m.FixedParticles(0x3779, 10, 25, 5002, EffectLayer.Head);
|
|
m.Mana = 0;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public ManaDrainItem(Serial serial)
|
|
: base(serial)
|
|
{
|
|
}
|
|
|
|
public override void Serialize(GenericWriter writer)
|
|
{
|
|
base.Serialize(writer);
|
|
writer.Write(0);
|
|
|
|
writer.Write(Static);
|
|
}
|
|
|
|
public override void Deserialize(GenericReader reader)
|
|
{
|
|
base.Deserialize(reader);
|
|
int version = reader.ReadInt();
|
|
|
|
Static = reader.ReadItem();
|
|
|
|
if (Static != null)
|
|
Static.Delete();
|
|
|
|
Delete();
|
|
}
|
|
}
|
|
|
|
public override void OnDeath(Container c)
|
|
{
|
|
base.OnDeath(c);
|
|
|
|
if (0.30 > Utility.RandomDouble())
|
|
{
|
|
Mobile m = DemonKnight.FindRandomPlayer(this);
|
|
|
|
if (m != null)
|
|
{
|
|
Item artifact = VoidPoolRewards.DropRandomArtifact();
|
|
|
|
if (artifact != null)
|
|
{
|
|
Container pack = m.Backpack;
|
|
|
|
if (pack == null || !pack.TryDropItem(m, artifact, false))
|
|
m.BankBox.DropItem(artifact);
|
|
|
|
m.SendLocalizedMessage(1062317); // For your valor in combating the fallen beast, a special artifact has been bestowed on you.
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void OnKilledBy(Mobile mob)
|
|
{
|
|
if (Siege.SiegeShard && mob is PlayerMobile)
|
|
{
|
|
int chance = Server.Engines.Despise.DespiseBoss.ArtifactChance + (int)Math.Min(10, ((PlayerMobile)mob).Luck / 180);
|
|
|
|
if (chance >= Utility.Random(100))
|
|
{
|
|
Type t = Server.Engines.Despise.DespiseBoss.Artifacts[Utility.Random(Server.Engines.Despise.DespiseBoss.Artifacts.Length)];
|
|
|
|
if (t != null)
|
|
{
|
|
Item arty = Loot.Construct(t);
|
|
|
|
if (arty != null)
|
|
{
|
|
Container pack = mob.Backpack;
|
|
|
|
if (pack == null || !pack.TryDropItem(mob, arty, false))
|
|
{
|
|
mob.BankBox.DropItem(arty);
|
|
mob.SendMessage("An artifact has been placed in your bankbox!");
|
|
}
|
|
else
|
|
mob.SendLocalizedMessage(1153440); // An artifact has been placed in your backpack!
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public CoraTheSorceress(Serial serial)
|
|
: base(serial)
|
|
{
|
|
}
|
|
|
|
public override void Serialize(GenericWriter writer)
|
|
{
|
|
base.Serialize(writer);
|
|
writer.Write(0);
|
|
}
|
|
|
|
public override void Deserialize(GenericReader reader)
|
|
{
|
|
base.Deserialize(reader);
|
|
int version = reader.ReadInt();
|
|
}
|
|
}
|
|
}
|