using System; using Server; using System.Collections.Generic; using System.Linq; using Server.Mobiles; using Server.Items; using Server.Spells; using Server.Spells.Necromancy; using Server.Engines.CityLoyalty; namespace Server.Engines.Blackthorn { public class Invader : BaseCreature { public static SkillName RandomSpecialty() { return _Specialties[Utility.Random(_Specialties.Length)]; } private static SkillName[] _Specialties = { SkillName.Swords, SkillName.Fencing, SkillName.Macing, SkillName.Archery, SkillName.Magery, SkillName.Mysticism, SkillName.Spellweaving, SkillName.Bushido, SkillName.Bushido, SkillName.Ninjitsu, SkillName.Chivalry, SkillName.Necromancy, SkillName.Poisoning }; private InvasionType _InvasionType; private SkillName _Specialty; private bool _Sampire; private DateTime _NextSpecial; public override bool AlwaysMurderer { get { return true; } } public override double HealChance { get { return AI == AIType.AI_Melee || AI == AIType.AI_Paladin ? 1.0 : 0.0; } } public override double WeaponAbilityChance { get { return AI == AIType.AI_Melee || AI == AIType.AI_Paladin ? 0.4 : 0.1; } } public override bool CanStealth { get { return _Specialty == SkillName.Ninjitsu; } } public override WeaponAbility GetWeaponAbility() { BaseWeapon wep = Weapon as BaseWeapon; if (wep != null) { return 0.6 > Utility.RandomDouble() ? wep.PrimaryAbility : wep.SecondaryAbility; } return null; } public override bool UseSmartAI { get { return true; } } public virtual bool CanDoSpecial { get { return SpellCaster; } } public virtual double MinSkill { get { return 100.0; } } public virtual double MaxSkill { get { return 120.0; } } public virtual int MinResist { get { return 10; } } public virtual int MaxResist { get { return 20; } } public bool SpellCaster { get { return AI != AIType.AI_Melee && AI != AIType.AI_Ninja && AI != AIType.AI_Samurai && AI != AIType.AI_Paladin; } } [Constructable] public Invader(InvasionType type) : this(RandomSpecialty(), type) { } [Constructable] public Invader(SkillName specialty, InvasionType type) : base(GetAI(specialty), FightMode.Closest, 10, 1, .2, .1) { _Specialty = specialty; _InvasionType = type; if (_Specialty == SkillName.Bushido && Utility.RandomBool()) _Sampire = true; if (Female = Utility.RandomBool()) { //Body = 0x191; Name = NameList.RandomName("female"); } else { //Body = 0x190; Name = NameList.RandomName("male"); } SetBody(); string title; if (_Sampire) { title = "the sampire"; } else if (specialty == SkillName.Magery) { title = "the wizard"; } else { title = String.Format("the {0}", Skills[specialty].Info.Title); if (Female && title.EndsWith("man")) title = title.Substring(0, title.Length - 3) + "woman"; } Title = title; SetStr(120, 170); SetDex(SpellCaster ? 75 : 150); SetInt(SpellCaster ? 1800 : 500); SetHits(800, 1250); if (AI == AIType.AI_Melee) SetDamage(15, 28); else if (!SpellCaster) SetDamage(12, 22); else SetDamage(8, 18); Fame = 8000; Karma = -8000; SetResists(); SetSkills(); EquipSpecialty(); _NextSpecial = DateTime.UtcNow; if (_Sampire) { Timer.DelayCall(TimeSpan.FromSeconds(1), () => { VampiricEmbraceSpell spell = new VampiricEmbraceSpell(this, null); spell.Cast(); }); } SetAreaEffect(AreaEffect.AuraOfEnergy); } public virtual void SetBody() { switch (_Specialty) { default: if (0.75 > Utility.RandomDouble()) Race = Race.Human; else Race = Race.Elf; break; case SkillName.Archery: case SkillName.Spellweaving: Race = Race.Elf; break; } HairItemID = Race.RandomHair(Female); HairHue = Race.RandomHairHue(); FacialHairItemID = Race.RandomFacialHair(Female); FacialHairHue = Race.RandomHairHue(); Hue = Race.RandomSkinHue(); } public virtual void SetResists() { SetResistance(ResistanceType.Physical, MinResist, MaxResist); SetResistance(ResistanceType.Fire, MinResist, MaxResist); SetResistance(ResistanceType.Cold, MinResist, MaxResist); SetResistance(ResistanceType.Poison, MinResist, MaxResist); SetResistance(ResistanceType.Energy, MinResist, MaxResist); } public virtual void SetSkills() { SetSkill(SkillName.Fencing, MinSkill, MaxSkill); SetSkill(SkillName.Macing, MinSkill, MaxSkill); SetSkill(SkillName.MagicResist, MinSkill, MaxSkill); SetSkill(SkillName.Swords, MinSkill, MaxSkill); SetSkill(SkillName.Tactics, MinSkill, MaxSkill); SetSkill(SkillName.Wrestling, MinSkill, MaxSkill); SetSkill(SkillName.Archery, MinSkill, MaxSkill); SetSkill(SkillName.Parry, MinSkill, MaxSkill); if (SpellCaster) { SetSkill(SkillName.Magery, MinSkill, MaxSkill); SetSkill(SkillName.EvalInt, MinSkill, MaxSkill); } if (Skills[_Specialty].Base < MinSkill) SetSkill(_Specialty, MinSkill, MaxSkill); if (_Sampire) { SetSkill(SkillName.Necromancy, MinSkill, MaxSkill); } if (_Sampire || _Specialty == SkillName.Necromancy) { SetSkill(SkillName.SpiritSpeak, MinSkill, MaxSkill); } if (_Specialty == SkillName.Ninjitsu) { SetSkill(SkillName.Hiding, 100); SetSkill(SkillName.Stealth, 100); } } public virtual void EquipSpecialty() { if (AbilityProfile != null && AbilityProfile.HasAbility(SpecialAbility.Heal)) PackItem(new Bandage(Utility.RandomMinMax(10, 25))); SetWearable(new ThighBoots()); SetWearable(new BodySash(), Utility.RandomSlimeHue()); switch (_Specialty) { case SkillName.Chivalry: SetWearable(RandomSwordWeapon()); PaladinEquip(); break; case SkillName.Swords: SetWearable(RandomSwordWeapon()); StandardMeleeEquip(); break; case SkillName.Fencing: SetWearable(RandomFencingWeapon()); StandardMeleeEquip(); break; case SkillName.Macing: SetWearable(RandomMaceWeapon()); StandardMeleeEquip(); break; case SkillName.Archery: SetWearable(RandomArhceryWeapon()); StandardMeleeEquip(); break; case SkillName.Magery: SetWearable(RandomMageWeapon()); StandardMageEquip(); break; case SkillName.Mysticism: SetWearable(RandomMageWeapon()); StandardMageEquip(); break; case SkillName.Spellweaving: SetWearable(RandomMageWeapon()); StandardMageEquip(); break; case SkillName.Necromancy: SetWearable(RandomMageWeapon()); StandardMageEquip(); break; case SkillName.Bushido: BaseWeapon w = RandomSamuraiWeapon() as BaseWeapon; SetWearable(w); SetWearable(new LeatherSuneate()); SetWearable(new LeatherJingasa()); SetWearable(new LeatherDo()); SetWearable(new LeatherHiroSode()); SetWearable(new SamuraiTabi(Utility.RandomNondyedHue())); if (_Sampire) w.WeaponAttributes.HitLeechHits = 100; SetSkill(SkillName.Parry, 120); break; case SkillName.Ninjitsu: SetWearable(RandomNinjaWeapon()); LeatherNinjaBelt belt = new LeatherNinjaBelt(); belt.UsesRemaining = 20; belt.Poison = Poison.Greater; belt.PoisonCharges = 20; SetWearable(belt); for (int i = 0; i < 2; i++) { Fukiya f = new Fukiya(); f.UsesRemaining = 10; f.Poison = Poison.Greater; f.PoisonCharges = 10; f.Movable = false; PackItem(f); } SetWearable(new NinjaTabi()); SetWearable(new LeatherNinjaJacket()); SetWearable(new LeatherNinjaHood()); SetWearable(new LeatherNinjaPants()); SetWearable(new LeatherNinjaMitts()); break; case SkillName.Poisoning: BaseWeapon wep = RandomAssassinWeapon() as BaseWeapon; wep.Poison = Poison.Lethal; wep.PoisonCharges = 100; SetWearable(wep); SetWearable(new LeatherChest()); SetWearable(new LeatherLegs()); SetWearable(new LeatherGloves()); SetWearable(new LeatherGorget()); break; } } private void PaladinEquip() { SetWearable(Loot.Construct(new Type[] { typeof(Bascinet), typeof(Helmet), typeof(PlateHelm) }), 1153); SetWearable(new PlateChest()); SetWearable(new PlateLegs()); SetWearable(new PlateGloves()); SetWearable(new PlateGorget()); SetWearable(new PlateArms()); SetWearable(new MetalKiteShield()); SetSkill(SkillName.Parry, 120); } private void StandardMeleeEquip() { SetWearable(Loot.Construct(new Type[] { typeof(Bascinet), typeof(Helmet), typeof(LeatherCap), typeof(RoyalCirclet) })); SetWearable(new ChainChest()); SetWearable(new ChainLegs()); SetWearable(new RingmailGloves()); SetWearable(new LeatherGorget()); } private void StandardMageEquip() { bool mage = AI == AIType.AI_Mage; SetWearable(new WizardsHat(), mage ? Utility.RandomBlueHue() : Utility.RandomRedHue()); SetWearable(new Robe(), mage ? Utility.RandomBlueHue() : Utility.RandomRedHue()); SetWearable(new LeatherGloves()); } public static AIType GetAI(SkillName skill) { switch (skill) { default: return AIType.AI_Melee; case SkillName.Ninjitsu: return AIType.AI_Ninja; case SkillName.Bushido: return AIType.AI_Samurai; case SkillName.Chivalry: return AIType.AI_Paladin; case SkillName.Magery: return AIType.AI_Mage; case SkillName.Necromancy: return AIType.AI_NecroMage; case SkillName.Spellweaving: return AIType.AI_Spellweaving; case SkillName.Mysticism: return AIType.AI_Mystic; } } public Item RandomSwordWeapon() { if (Race == Race.Elf) return Loot.Construct(new Type[] { typeof(ElvenMachete), typeof(RadiantScimitar) }); return Loot.Construct(new Type[] { typeof(Broadsword), typeof(Longsword), typeof(Katana), typeof(Halberd), typeof(Bardiche), typeof(VikingSword) }); } public Item RandomFencingWeapon() { if(Race == Race.Elf) return Loot.Construct(new Type[] { typeof(Leafblade), typeof(WarCleaver), typeof(AssassinSpike) }); return Loot.Construct(new Type[] { typeof(Kryss), typeof(Spear), typeof(ShortSpear), typeof(Lance), typeof(Pike) }); } public Item RandomMaceWeapon() { return Loot.Construct(new Type[] { typeof(Mace), typeof(WarHammer), typeof(WarAxe), typeof(BlackStaff), typeof(QuarterStaff), typeof(WarMace), typeof(DiamondMace), typeof(Scepter) }); } public Item RandomArhceryWeapon() { if (Race == Race.Elf) return Loot.Construct(new Type[] { typeof(MagicalShortbow), typeof(ElvenCompositeLongbow) }); return Loot.Construct(new Type[] { typeof(Bow), typeof(Crossbow), typeof(HeavyCrossbow), typeof(CompositeBow), typeof(RepeatingCrossbow) }); } public Item RandomMageWeapon() { return Loot.Construct(new Type[] { typeof(Spellbook), typeof(GnarledStaff), typeof(BlackStaff), typeof(QuarterStaff), typeof(WildStaff) }); } public Item RandomSamuraiWeapon() { return Loot.Construct(new Type[] { typeof(Lajatang), typeof(Wakizashi), typeof(NoDachi) }); } public Item RandomNinjaWeapon() { return Loot.Construct(new Type[] { typeof(Wakizashi), typeof(Tessen), typeof(Nunchaku), typeof(Daisho), typeof(Sai), typeof(Tekagi), typeof(Kama), typeof(Katana) }); } public Item RandomAssassinWeapon() { return Loot.Construct(new Type[] { typeof(Cleaver), typeof(ButcherKnife), typeof(Kryss), typeof(Dagger) }); } public override void GetProperties(ObjectPropertyList list) { base.GetProperties(list); list.Add(1154196 + (int)_InvasionType); } public override void OnThink() { base.OnThink(); if (Combatant == null) return; if (CanDoSpecial && InRange(Combatant, 4) && 0.1 > Utility.RandomDouble() && _NextSpecial < DateTime.UtcNow) { DoSpecial(); _NextSpecial = DateTime.UtcNow + TimeSpan.FromSeconds(Utility.RandomMinMax(30, 60)); } else if (_Sampire) { if (0.1 > Utility.RandomDouble() && Weapon is BaseWeapon && !CurseWeaponSpell.IsCursed(this, (BaseWeapon)Weapon)) { CurseWeaponSpell spell = new CurseWeaponSpell(this, null); spell.Cast(); } else if (!TransformationSpellHelper.UnderTransformation(this, typeof(VampiricEmbraceSpell))) { VampiricEmbraceSpell spell = new VampiricEmbraceSpell(this, null); spell.Cast(); } } } private void DoSpecial() { if (this.Map == null || this.Map == Map.Internal) return; Map m = this.Map; for (int i = 0; i < 4; i++) { Timer.DelayCall(TimeSpan.FromMilliseconds(i * 50), o => { Server.Misc.Geometry.Circle2D(this.Location, m, (int)o, (pnt, map) => { Effects.SendLocationEffect(pnt, map, Utility.RandomBool() ? 14000 : 14013, 14, 20, 2018, 0); }); }, i); } Timer.DelayCall(TimeSpan.FromMilliseconds(200), () => { if (m != null) { List list = new List(); IPooledEnumerable eable = m.GetMobilesInRange(this.Location, 4); foreach (Mobile mob in eable) { if (mob.AccessLevel > AccessLevel.Player) continue; if (mob is PlayerMobile || (mob is BaseCreature && ((BaseCreature)mob).GetMaster() is PlayerMobile) && CanBeHarmful(mob)) list.Add(mob); } list.ForEach(mob => { AOS.Damage(mob, this, Utility.RandomMinMax(80, 90), 0, 0, 0, 0, 0, 100, 0); }); list.Clear(); list.TrimExcess(); } }); } public override void GenerateLoot() { this.AddLoot(LootPack.UltraRich, 2); } public Invader(Serial serial) : base(serial) { } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write(0); writer.Write((int)_Specialty); writer.Write((int)_InvasionType); writer.Write(_Sampire); } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); _Specialty = (SkillName)reader.ReadInt(); _InvasionType = (InvasionType)reader.ReadInt(); _Sampire = reader.ReadBool(); _NextSpecial = DateTime.UtcNow; } } public class InvaderCaptain : Invader { public override double MinSkill { get { return 105.0; } } public override double MaxSkill { get { return 130.0; } } public override int MinResist { get { return 20; } } public override int MaxResist { get { return 30; } } [Constructable] public InvaderCaptain(InvasionType type) : base(type) { SetStr(250); SetDex(SpellCaster ? 150 : 200); SetInt(SpellCaster ? 1000 : 5000); SetHits(8000, 12000); if (AI == AIType.AI_Melee) SetDamage(22, 30); else if (!SpellCaster) SetDamage(20, 28); else SetDamage(10, 20); Fame = 48000; Karma = -48000; } public override void OnDeath(Container c) { base.OnDeath(c); var rights = GetLootingRights(); rights.Sort(); List list = rights.Select(x => x.m_Mobile).Where(m => m.InRange(c.Location, 20)).ToList(); if(list.Count > 0) { for (int i = 0; i < 2; i++) { Mobile drop; Item item = InvasionController.CreateItem(list[0]); if (list.Count == 1 || i >= list.Count) drop = list[0]; else drop = list[i]; drop.SendLocalizedMessage(1154530); // You notice the crest of Minax on your fallen foe's equipment and decide it may be of some value... if (drop.Backpack == null || !drop.Backpack.TryDropItem(drop, item, false)) { drop.BankBox.DropItem(item); drop.SendLocalizedMessage(1079730); // // The item has been placed into your bank box. } } } ColUtility.Free(list); } public override void GenerateLoot() { this.AddLoot(LootPack.UltraRich, 2); this.AddLoot(LootPack.SuperBoss, 1); } public InvaderCaptain(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(); } } }