Reorganizes Project (#41)
This commit is contained in:
parent
08bf44af9a
commit
3614a66aee
3499 changed files with 79 additions and 55 deletions
232
Projects/Scripts/Mobiles/Special/Barracoon.cs
Normal file
232
Projects/Scripts/Mobiles/Special/Barracoon.cs
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Server.Engines.CannedEvil;
|
||||
using Server.Items;
|
||||
using Server.Spells.Fifth;
|
||||
using Server.Spells.Seventh;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Barracoon : BaseChampion
|
||||
{
|
||||
[Constructible]
|
||||
public Barracoon() : base(AIType.AI_Melee)
|
||||
{
|
||||
Title = "the piper";
|
||||
Body = 0x190;
|
||||
Hue = 0x83EC;
|
||||
|
||||
SetStr(305, 425);
|
||||
SetDex(72, 150);
|
||||
SetInt(505, 750);
|
||||
|
||||
SetHits(4200);
|
||||
SetStam(102, 300);
|
||||
|
||||
SetDamage(25, 35);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 100);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 60, 70);
|
||||
SetResistance(ResistanceType.Fire, 50, 60);
|
||||
SetResistance(ResistanceType.Cold, 50, 60);
|
||||
SetResistance(ResistanceType.Poison, 40, 50);
|
||||
SetResistance(ResistanceType.Energy, 40, 50);
|
||||
|
||||
SetSkill(SkillName.MagicResist, 100.0);
|
||||
SetSkill(SkillName.Tactics, 97.6, 100.0);
|
||||
SetSkill(SkillName.Wrestling, 97.6, 100.0);
|
||||
|
||||
Fame = 22500;
|
||||
Karma = -22500;
|
||||
|
||||
VirtualArmor = 70;
|
||||
|
||||
AddItem(new FancyShirt(Utility.RandomGreenHue()));
|
||||
AddItem(new LongPants(Utility.RandomYellowHue()));
|
||||
AddItem(new JesterHat(Utility.RandomPinkHue()));
|
||||
AddItem(new Cloak(Utility.RandomPinkHue()));
|
||||
AddItem(new Sandals());
|
||||
|
||||
HairItemID = 0x203B; // Short Hair
|
||||
HairHue = 0x94;
|
||||
}
|
||||
|
||||
public Barracoon(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override ChampionSkullType SkullType => ChampionSkullType.Greed;
|
||||
|
||||
public override Type[] UniqueList => new[] { typeof(FangOfRactus) };
|
||||
|
||||
public override Type[] SharedList => new[]
|
||||
{
|
||||
typeof(EmbroideredOakLeafCloak),
|
||||
typeof(DjinnisRing),
|
||||
typeof(DetectiveBoots),
|
||||
typeof(GuantletsOfAnger)
|
||||
};
|
||||
|
||||
public override Type[] DecorativeList => new[] { typeof(SwampTile), typeof(MonsterStatuette) };
|
||||
|
||||
public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.Slime };
|
||||
|
||||
public override string DefaultName => "Barracoon";
|
||||
|
||||
public override bool AlwaysMurderer => true;
|
||||
public override bool AutoDispel => true;
|
||||
public override double AutoDispelChance => 1.0;
|
||||
public override bool BardImmune => !Core.SE;
|
||||
public override bool Unprovokable => Core.SE;
|
||||
public override bool Uncalmable => Core.SE;
|
||||
public override Poison PoisonImmune => Poison.Deadly;
|
||||
|
||||
public override bool ShowFameTitle => false;
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.UltraRich, 3);
|
||||
}
|
||||
|
||||
public void Polymorph(Mobile m)
|
||||
{
|
||||
if (!m.CanBeginAction<PolymorphSpell>() || !m.CanBeginAction<IncognitoSpell>() || m.IsBodyMod)
|
||||
return;
|
||||
|
||||
IMount mount = m.Mount;
|
||||
|
||||
if (mount != null)
|
||||
mount.Rider = null;
|
||||
|
||||
if (m.Mounted)
|
||||
return;
|
||||
|
||||
if (m.BeginAction<PolymorphSpell>())
|
||||
{
|
||||
Item disarm = m.FindItemOnLayer(Layer.OneHanded);
|
||||
|
||||
if (disarm?.Movable == true)
|
||||
m.AddToBackpack(disarm);
|
||||
|
||||
disarm = m.FindItemOnLayer(Layer.TwoHanded);
|
||||
|
||||
if (disarm?.Movable == true)
|
||||
m.AddToBackpack(disarm);
|
||||
|
||||
m.BodyMod = 42;
|
||||
m.HueMod = 0;
|
||||
|
||||
new ExpirePolymorphTimer(m).Start();
|
||||
}
|
||||
}
|
||||
|
||||
public void SpawnRatmen(Mobile target)
|
||||
{
|
||||
Map map = Map;
|
||||
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
IPooledEnumerable <BaseCreature> eable = GetMobilesInRange<BaseCreature>(10);
|
||||
int rats = eable.Aggregate(0, (c, m) => c + (m is Ratman || m is RatmanArcher || m is RatmanMage ? 1 : 0));
|
||||
eable.Free();
|
||||
|
||||
if (rats >= 16)
|
||||
return;
|
||||
|
||||
PlaySound(0x3D);
|
||||
|
||||
rats = Utility.RandomMinMax(3, 6);
|
||||
|
||||
for (int i = 0; i < rats; ++i)
|
||||
{
|
||||
BaseCreature rat;
|
||||
|
||||
switch (Utility.Random(5))
|
||||
{
|
||||
default:
|
||||
rat = new Ratman();
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
rat = new RatmanArcher();
|
||||
break;
|
||||
case 4:
|
||||
rat = new RatmanMage();
|
||||
break;
|
||||
}
|
||||
|
||||
rat.Team = Team;
|
||||
rat.MoveToWorld(map.GetRandomNearbyLocation(Location), map);
|
||||
rat.Combatant = target;
|
||||
}
|
||||
}
|
||||
|
||||
public void DoSpecialAbility(Mobile target)
|
||||
{
|
||||
if (target?.Deleted != false) //sanity
|
||||
return;
|
||||
|
||||
if (0.6 >= Utility.RandomDouble()) // 60% chance to polymorph attacker into a ratman
|
||||
Polymorph(target);
|
||||
|
||||
if (0.2 >= Utility.RandomDouble()) // 20% chance to more ratmen
|
||||
SpawnRatmen(target);
|
||||
|
||||
if (Hits < 500 && !IsBodyMod) // Baracoon is low on life, polymorph into a ratman
|
||||
Polymorph(this);
|
||||
}
|
||||
|
||||
public override void OnGotMeleeAttack(Mobile attacker)
|
||||
{
|
||||
base.OnGotMeleeAttack(attacker);
|
||||
|
||||
DoSpecialAbility(attacker);
|
||||
}
|
||||
|
||||
public override void OnGaveMeleeAttack(Mobile defender)
|
||||
{
|
||||
base.OnGaveMeleeAttack(defender);
|
||||
|
||||
DoSpecialAbility(defender);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
|
||||
private class ExpirePolymorphTimer : Timer
|
||||
{
|
||||
private Mobile m_Owner;
|
||||
|
||||
public ExpirePolymorphTimer(Mobile owner) : base(TimeSpan.FromMinutes(3.0))
|
||||
{
|
||||
m_Owner = owner;
|
||||
|
||||
Priority = TimerPriority.OneSecond;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (!m_Owner.CanBeginAction<PolymorphSpell>())
|
||||
{
|
||||
m_Owner.BodyMod = 0;
|
||||
m_Owner.HueMod = -1;
|
||||
m_Owner.EndAction<PolymorphSpell>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
330
Projects/Scripts/Mobiles/Special/BaseChampion.cs
Normal file
330
Projects/Scripts/Mobiles/Special/BaseChampion.cs
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Engines.CannedEvil;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public abstract class BaseChampion : BaseCreature
|
||||
{
|
||||
public BaseChampion(AIType aiType, FightMode mode = FightMode.Closest) :
|
||||
base(aiType, mode, 18, 1, 0.1, 0.2)
|
||||
{
|
||||
}
|
||||
|
||||
public BaseChampion(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanMoveOverObstacles => true;
|
||||
public override bool CanDestroyObstacles => true;
|
||||
|
||||
public abstract ChampionSkullType SkullType{ get; }
|
||||
|
||||
public abstract Type[] UniqueList{ get; }
|
||||
public abstract Type[] SharedList{ get; }
|
||||
public abstract Type[] DecorativeList{ get; }
|
||||
public abstract MonsterStatuetteType[] StatueTypes{ get; }
|
||||
|
||||
public virtual bool NoGoodies => false;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
|
||||
public Item GetArtifact()
|
||||
{
|
||||
double random = Utility.RandomDouble();
|
||||
if (0.05 >= random)
|
||||
return CreateArtifact(UniqueList);
|
||||
if (0.15 >= random)
|
||||
return CreateArtifact(SharedList);
|
||||
if (0.30 >= random)
|
||||
return CreateArtifact(DecorativeList);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Item CreateArtifact(Type[] list)
|
||||
{
|
||||
if (list.Length == 0)
|
||||
return null;
|
||||
|
||||
int random = Utility.Random(list.Length);
|
||||
|
||||
Type type = list[random];
|
||||
|
||||
Item artifact = Loot.Construct(type);
|
||||
|
||||
if (artifact is MonsterStatuette statuette && StatueTypes.Length > 0)
|
||||
{
|
||||
statuette.Type = StatueTypes[Utility.Random(StatueTypes.Length)];
|
||||
statuette.LootType = LootType.Regular;
|
||||
}
|
||||
|
||||
return artifact;
|
||||
}
|
||||
|
||||
private PowerScroll CreateRandomPowerScroll()
|
||||
{
|
||||
int level;
|
||||
double random = Utility.RandomDouble();
|
||||
|
||||
if (0.05 >= random)
|
||||
level = 20;
|
||||
else if (0.4 >= random)
|
||||
level = 15;
|
||||
else
|
||||
level = 10;
|
||||
|
||||
return PowerScroll.CreateRandomNoCraft(level, level);
|
||||
}
|
||||
|
||||
public void GivePowerScrolls()
|
||||
{
|
||||
if (Map != Map.Felucca)
|
||||
return;
|
||||
|
||||
List<Mobile> toGive = new List<Mobile>();
|
||||
List<DamageStore> rights = GetLootingRights(DamageEntries, HitsMax);
|
||||
|
||||
for (int i = rights.Count - 1; i >= 0; --i)
|
||||
{
|
||||
DamageStore ds = rights[i];
|
||||
|
||||
if (ds.m_HasRight)
|
||||
toGive.Add(ds.m_Mobile);
|
||||
}
|
||||
|
||||
if (toGive.Count == 0)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < toGive.Count; i++)
|
||||
{
|
||||
Mobile m = toGive[i];
|
||||
|
||||
if (!(m is PlayerMobile))
|
||||
continue;
|
||||
|
||||
bool gainedPath = false;
|
||||
|
||||
int pointsToGain = 800;
|
||||
|
||||
if (VirtueHelper.Award(m, VirtueName.Valor, pointsToGain, ref gainedPath))
|
||||
{
|
||||
if (gainedPath)
|
||||
m.SendLocalizedMessage(1054032); // You have gained a path in Valor!
|
||||
else
|
||||
m.SendLocalizedMessage(1054030); // You have gained in Valor!
|
||||
|
||||
//No delay on Valor gains
|
||||
}
|
||||
}
|
||||
|
||||
// Randomize
|
||||
for (int i = 0; i < toGive.Count; ++i)
|
||||
{
|
||||
int rand = Utility.Random(toGive.Count);
|
||||
Mobile hold = toGive[i];
|
||||
toGive[i] = toGive[rand];
|
||||
toGive[rand] = hold;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
Mobile m = toGive[i % toGive.Count];
|
||||
|
||||
PowerScroll ps = CreateRandomPowerScroll();
|
||||
|
||||
GivePowerScrollTo(m, ps);
|
||||
}
|
||||
}
|
||||
|
||||
public static void GivePowerScrollTo(Mobile m, PowerScroll ps)
|
||||
{
|
||||
if (ps == null || m == null) //sanity
|
||||
return;
|
||||
|
||||
m.SendLocalizedMessage(1049524); // You have received a scroll of power!
|
||||
|
||||
if (!Core.SE || m.Alive)
|
||||
{
|
||||
m.AddToBackpack(ps);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m.Corpse?.Deleted == false)
|
||||
m.Corpse.DropItem(ps);
|
||||
else
|
||||
m.AddToBackpack(ps);
|
||||
}
|
||||
|
||||
if (!(m is PlayerMobile pm))
|
||||
return;
|
||||
|
||||
for (int j = 0; j < pm.JusticeProtectors.Count; ++j)
|
||||
{
|
||||
Mobile prot = pm.JusticeProtectors[j];
|
||||
|
||||
if (prot.Map != pm.Map || prot.Kills >= 5 || prot.Criminal || !JusticeVirtue.CheckMapRegion(pm, prot))
|
||||
continue;
|
||||
|
||||
int chance = 0;
|
||||
|
||||
switch (VirtueHelper.GetLevel(prot, VirtueName.Justice))
|
||||
{
|
||||
case VirtueLevel.Seeker:
|
||||
chance = 60;
|
||||
break;
|
||||
case VirtueLevel.Follower:
|
||||
chance = 80;
|
||||
break;
|
||||
case VirtueLevel.Knight:
|
||||
chance = 100;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chance > Utility.Random(100))
|
||||
{
|
||||
PowerScroll powerScroll = new PowerScroll(ps.Skill, ps.Value);
|
||||
|
||||
prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice!
|
||||
|
||||
if (!Core.SE || prot.Alive)
|
||||
{
|
||||
prot.AddToBackpack(powerScroll);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prot.Corpse?.Deleted == false)
|
||||
prot.Corpse.DropItem(powerScroll);
|
||||
else
|
||||
prot.AddToBackpack(powerScroll);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnBeforeDeath()
|
||||
{
|
||||
if (!NoKillAwards)
|
||||
{
|
||||
GivePowerScrolls();
|
||||
|
||||
if (NoGoodies)
|
||||
return base.OnBeforeDeath();
|
||||
|
||||
Map map = Map;
|
||||
|
||||
if (map != null)
|
||||
for (int x = -12; x <= 12; ++x)
|
||||
for (int y = -12; y <= 12; ++y)
|
||||
{
|
||||
double dist = Math.Sqrt(x * x + y * y);
|
||||
|
||||
if (dist <= 12)
|
||||
new GoodiesTimer(map, X + x, Y + y).Start();
|
||||
}
|
||||
}
|
||||
|
||||
return base.OnBeforeDeath();
|
||||
}
|
||||
|
||||
public override void OnDeath(Container c)
|
||||
{
|
||||
if (Map == Map.Felucca)
|
||||
{
|
||||
//TODO: Confirm SE change or AoS one too?
|
||||
List<DamageStore> rights = GetLootingRights(DamageEntries, HitsMax);
|
||||
List<Mobile> toGive = new List<Mobile>();
|
||||
|
||||
for (int i = rights.Count - 1; i >= 0; --i)
|
||||
{
|
||||
DamageStore ds = rights[i];
|
||||
|
||||
if (ds.m_HasRight)
|
||||
toGive.Add(ds.m_Mobile);
|
||||
}
|
||||
|
||||
if (toGive.Count > 0)
|
||||
toGive[Utility.Random(toGive.Count)].AddToBackpack(new ChampionSkull(SkullType));
|
||||
else
|
||||
c.DropItem(new ChampionSkull(SkullType));
|
||||
}
|
||||
|
||||
base.OnDeath(c);
|
||||
}
|
||||
|
||||
private class GoodiesTimer : Timer
|
||||
{
|
||||
private Map m_Map;
|
||||
private int m_X, m_Y;
|
||||
|
||||
public GoodiesTimer(Map map, int x, int y) : base(TimeSpan.FromSeconds(Utility.RandomDouble() * 10.0))
|
||||
{
|
||||
m_Map = map;
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
int z = m_Map.GetAverageZ(m_X, m_Y);
|
||||
bool canFit = m_Map.CanFit(m_X, m_Y, z, 6, false, false);
|
||||
|
||||
for (int i = -3; !canFit && i <= 3; ++i)
|
||||
{
|
||||
canFit = m_Map.CanFit(m_X, m_Y, z + i, 6, false, false);
|
||||
|
||||
if (canFit)
|
||||
z += i;
|
||||
}
|
||||
|
||||
if (!canFit)
|
||||
return;
|
||||
|
||||
Gold g = new Gold(500, 1000);
|
||||
|
||||
g.MoveToWorld(new Point3D(m_X, m_Y, z), m_Map);
|
||||
|
||||
if (0.5 >= Utility.RandomDouble())
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
162
Projects/Scripts/Mobiles/Special/BaseShieldGuard.cs
Normal file
162
Projects/Scripts/Mobiles/Special/BaseShieldGuard.cs
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
using Server.Guilds;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public abstract class BaseShieldGuard : BaseCreature
|
||||
{
|
||||
public BaseShieldGuard() : base(AIType.AI_Melee, FightMode.Aggressor, 14, 1, 0.8, 1.6)
|
||||
{
|
||||
InitStats(1000, 1000, 1000);
|
||||
Title = "the guard";
|
||||
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
|
||||
if (Female = Utility.RandomBool())
|
||||
{
|
||||
Body = 0x191;
|
||||
Name = NameList.RandomName("female");
|
||||
|
||||
AddItem(new FemalePlateChest());
|
||||
AddItem(new PlateArms());
|
||||
AddItem(new PlateLegs());
|
||||
|
||||
switch (Utility.Random(2))
|
||||
{
|
||||
case 0:
|
||||
AddItem(new Doublet(Utility.RandomNondyedHue()));
|
||||
break;
|
||||
case 1:
|
||||
AddItem(new BodySash(Utility.RandomNondyedHue()));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (Utility.Random(2))
|
||||
{
|
||||
case 0:
|
||||
AddItem(new Skirt(Utility.RandomNondyedHue()));
|
||||
break;
|
||||
case 1:
|
||||
AddItem(new Kilt(Utility.RandomNondyedHue()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Body = 0x190;
|
||||
Name = NameList.RandomName("male");
|
||||
|
||||
AddItem(new PlateChest());
|
||||
AddItem(new PlateArms());
|
||||
AddItem(new PlateLegs());
|
||||
|
||||
switch (Utility.Random(3))
|
||||
{
|
||||
case 0:
|
||||
AddItem(new Doublet(Utility.RandomNondyedHue()));
|
||||
break;
|
||||
case 1:
|
||||
AddItem(new Tunic(Utility.RandomNondyedHue()));
|
||||
break;
|
||||
case 2:
|
||||
AddItem(new BodySash(Utility.RandomNondyedHue()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
if (Utility.RandomBool())
|
||||
Utility.AssignRandomFacialHair(this, HairHue);
|
||||
|
||||
VikingSword weapon = new VikingSword();
|
||||
weapon.Movable = false;
|
||||
AddItem(weapon);
|
||||
|
||||
BaseShield shield = Shield;
|
||||
shield.Movable = false;
|
||||
AddItem(shield);
|
||||
|
||||
PackGold(250, 500);
|
||||
|
||||
Skills.Anatomy.Base = 120.0;
|
||||
Skills.Tactics.Base = 120.0;
|
||||
Skills.Swords.Base = 120.0;
|
||||
Skills.MagicResist.Base = 120.0;
|
||||
Skills.DetectHidden.Base = 100.0;
|
||||
}
|
||||
|
||||
public BaseShieldGuard(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public abstract int Keyword{ get; }
|
||||
public abstract BaseShield Shield{ get; }
|
||||
public abstract int SignupNumber{ get; }
|
||||
public abstract GuildType Type{ get; }
|
||||
|
||||
public override bool HandlesOnSpeech(Mobile from)
|
||||
{
|
||||
if (from.InRange(Location, 2))
|
||||
return true;
|
||||
|
||||
return base.HandlesOnSpeech(from);
|
||||
}
|
||||
|
||||
public override void OnSpeech(SpeechEventArgs e)
|
||||
{
|
||||
if (!e.Handled && e.HasKeyword(Keyword) && e.Mobile.InRange(Location, 2))
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
Mobile from = e.Mobile;
|
||||
|
||||
if (!(from.Guild is Guild g) || g.Type != Type)
|
||||
{
|
||||
Say(SignupNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
Container pack = from.Backpack;
|
||||
BaseShield shield = Shield;
|
||||
Item twoHanded = from.FindItemOnLayer(Layer.TwoHanded);
|
||||
|
||||
if (pack?.FindItemByType(shield.GetType()) != null ||
|
||||
twoHanded != null && shield.GetType().IsInstanceOfType(twoHanded))
|
||||
{
|
||||
Say(1007110); // Why dost thou ask about virtue guards when thou art one?
|
||||
shield.Delete();
|
||||
}
|
||||
else if (from.PlaceInBackpack(shield))
|
||||
{
|
||||
Say(Utility.Random(1007101, 5));
|
||||
Say(1007139); // I see you are in need of our shield, Here you go.
|
||||
from.AddToBackpack(shield);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(502868); // Your backpack is too full.
|
||||
shield.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
base.OnSpeech(e);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Projects/Scripts/Mobiles/Special/CapturedHordeMinion.cs
Normal file
36
Projects/Scripts/Mobiles/Special/CapturedHordeMinion.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
namespace Server.Mobiles
|
||||
{
|
||||
public class CapturedHordeMinion : HordeMinion
|
||||
{
|
||||
[Constructible]
|
||||
public CapturedHordeMinion()
|
||||
{
|
||||
FightMode = FightMode.None;
|
||||
}
|
||||
|
||||
public CapturedHordeMinion(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool InitialInnocent => true;
|
||||
|
||||
public override bool CanBeDamaged()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Projects/Scripts/Mobiles/Special/ChaosGuard.cs
Normal file
38
Projects/Scripts/Mobiles/Special/ChaosGuard.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using Server.Guilds;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class ChaosGuard : BaseShieldGuard
|
||||
{
|
||||
[Constructible]
|
||||
public ChaosGuard()
|
||||
{
|
||||
}
|
||||
|
||||
public ChaosGuard(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int Keyword => 0x22; // *chaos shield*
|
||||
public override BaseShield Shield => new ChaosShield();
|
||||
public override int SignupNumber => 1007140; // Sign up with a guild of chaos if thou art interested.
|
||||
public override GuildType Type => GuildType.Chaos;
|
||||
|
||||
public override bool BardImmune => true;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
79
Projects/Scripts/Mobiles/Special/DarkGuardian.cs
Normal file
79
Projects/Scripts/Mobiles/Special/DarkGuardian.cs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class DarkGuardian : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public DarkGuardian() : base(AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
Body = 78;
|
||||
BaseSoundID = 0x3E9;
|
||||
|
||||
SetStr(125, 150);
|
||||
SetDex(100, 120);
|
||||
SetInt(200, 235);
|
||||
|
||||
SetHits(150, 180);
|
||||
|
||||
SetDamage(43, 48);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 10);
|
||||
SetDamageType(ResistanceType.Cold, 40);
|
||||
SetDamageType(ResistanceType.Energy, 50);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 40, 50);
|
||||
SetResistance(ResistanceType.Fire, 20, 45);
|
||||
SetResistance(ResistanceType.Cold, 50, 60);
|
||||
SetResistance(ResistanceType.Poison, 20, 45);
|
||||
SetResistance(ResistanceType.Energy, 30, 40);
|
||||
|
||||
SetSkill(SkillName.EvalInt, 40.1, 50);
|
||||
SetSkill(SkillName.Magery, 50.1, 60.0);
|
||||
SetSkill(SkillName.Meditation, 85.1, 95.0);
|
||||
SetSkill(SkillName.MagicResist, 50.1, 70.0);
|
||||
SetSkill(SkillName.Tactics, 50.1, 70.0);
|
||||
|
||||
Fame = 5000;
|
||||
Karma = -5000;
|
||||
|
||||
VirtualArmor = 50;
|
||||
PackNecroReg(15, 25);
|
||||
PackItem(new DaemonBone(30));
|
||||
}
|
||||
|
||||
public DarkGuardian(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string CorpseName => "a dark guardians' corpse";
|
||||
public override string DefaultName => "a dark guardian";
|
||||
|
||||
public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead;
|
||||
|
||||
public override int TreasureMapLevel => 2;
|
||||
public override bool BleedImmune => true;
|
||||
public override Poison PoisonImmune => Poison.Lethal;
|
||||
public override bool Unprovokable => true;
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.Rich);
|
||||
AddLoot(LootPack.MedScrolls, 2);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
146
Projects/Scripts/Mobiles/Special/Dummy.cs
Normal file
146
Projects/Scripts/Mobiles/Special/Dummy.cs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a test creature
|
||||
/// You can set its value in game
|
||||
/// It die after 5 minutes, so your test server stay clean
|
||||
/// Create a macro to help your creation "[add Dummy 1 15 7 -1 0.5 2"
|
||||
/// A iTeam of negative will set a faction at random
|
||||
/// Say Kill if you want them to die
|
||||
/// </summary>
|
||||
public class Dummy : BaseCreature
|
||||
{
|
||||
public Timer m_Timer;
|
||||
|
||||
[Constructible]
|
||||
public Dummy(AIType iAI, FightMode iFightMode, int iRangePerception, int iRangeFight, double dActiveSpeed,
|
||||
double dPassiveSpeed) : base(iAI, iFightMode, iRangePerception, iRangeFight, dActiveSpeed, dPassiveSpeed)
|
||||
{
|
||||
Body = 400 + Utility.Random(2);
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
|
||||
Skills.DetectHidden.Base = 100;
|
||||
Skills.MagicResist.Base = 120;
|
||||
|
||||
Team = Utility.Random(3);
|
||||
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
Utility.AssignRandomHair(this, iHue);
|
||||
|
||||
LeatherGloves glv = new LeatherGloves();
|
||||
glv.Hue = iHue;
|
||||
glv.LootType = LootType.Newbied;
|
||||
AddItem(glv);
|
||||
|
||||
Container pack = new Backpack();
|
||||
|
||||
pack.Movable = false;
|
||||
|
||||
AddItem(pack);
|
||||
|
||||
m_Timer = new AutokillTimer(this);
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
public Dummy(Serial serial) : base(serial)
|
||||
{
|
||||
m_Timer = new AutokillTimer(this);
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
|
||||
public override bool HandlesOnSpeech(Mobile from)
|
||||
{
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster)
|
||||
return true;
|
||||
|
||||
return base.HandlesOnSpeech(from);
|
||||
}
|
||||
|
||||
public override void OnSpeech(SpeechEventArgs e)
|
||||
{
|
||||
base.OnSpeech(e);
|
||||
|
||||
if (e.Mobile.AccessLevel >= AccessLevel.GameMaster)
|
||||
if (e.Speech == "kill")
|
||||
{
|
||||
m_Timer.Stop();
|
||||
m_Timer.Delay = TimeSpan.FromSeconds(Utility.Random(1, 5));
|
||||
m_Timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnTeamChange()
|
||||
{
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
Item item = FindItemOnLayer(Layer.OuterTorso);
|
||||
|
||||
if (item != null)
|
||||
item.Hue = jHue;
|
||||
|
||||
item = FindItemOnLayer(Layer.Helm);
|
||||
|
||||
if (item != null)
|
||||
item.Hue = iHue;
|
||||
|
||||
item = FindItemOnLayer(Layer.Gloves);
|
||||
|
||||
if (item != null)
|
||||
item.Hue = iHue;
|
||||
|
||||
item = FindItemOnLayer(Layer.Shoes);
|
||||
|
||||
if (item != null)
|
||||
item.Hue = iHue;
|
||||
|
||||
HairHue = iHue;
|
||||
|
||||
item = FindItemOnLayer(Layer.MiddleTorso);
|
||||
|
||||
if (item != null)
|
||||
item.Hue = iHue;
|
||||
|
||||
item = FindItemOnLayer(Layer.OuterLegs);
|
||||
|
||||
if (item != null)
|
||||
item.Hue = iHue;
|
||||
}
|
||||
|
||||
private class AutokillTimer : Timer
|
||||
{
|
||||
private Dummy m_Owner;
|
||||
|
||||
public AutokillTimer(Dummy owner) : base(TimeSpan.FromMinutes(5.0))
|
||||
{
|
||||
m_Owner = owner;
|
||||
Priority = TimerPriority.FiveSeconds;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Owner.Kill();
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
784
Projects/Scripts/Mobiles/Special/DummySpecific.cs
Normal file
784
Projects/Scripts/Mobiles/Special/DummySpecific.cs
Normal file
|
|
@ -0,0 +1,784 @@
|
|||
using Server.Items;
|
||||
using Server.Spells.First;
|
||||
using Server.Spells.Third;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a test creature
|
||||
/// You can set its value in game
|
||||
/// It die after 5 minutes, so your test server stay clean
|
||||
/// Create a macro to help your creation "[add Dummy 1 15 7 -1 0.5 2"
|
||||
/// A iTeam of negative will set a faction at random
|
||||
/// Say Kill if you want them to die
|
||||
/// </summary>
|
||||
public class DummyMace : Dummy
|
||||
{
|
||||
[Constructible]
|
||||
public DummyMace() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Macer
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
InitStats(125, 125, 90);
|
||||
Skills.Macing.Base = 120;
|
||||
Skills.Anatomy.Base = 120;
|
||||
Skills.Healing.Base = 120;
|
||||
Skills.Tactics.Base = 120;
|
||||
|
||||
// Equip
|
||||
WarHammer war = new WarHammer();
|
||||
war.Movable = true;
|
||||
war.Crafter = this;
|
||||
war.Quality = WeaponQuality.Regular;
|
||||
AddItem(war);
|
||||
|
||||
Boots bts = new Boots();
|
||||
bts.Hue = iHue;
|
||||
AddItem(bts);
|
||||
|
||||
ChainChest cht = new ChainChest();
|
||||
cht.Movable = false;
|
||||
cht.LootType = LootType.Newbied;
|
||||
cht.Crafter = this;
|
||||
cht.Quality = ArmorQuality.Regular;
|
||||
AddItem(cht);
|
||||
|
||||
ChainLegs chl = new ChainLegs();
|
||||
chl.Movable = false;
|
||||
chl.LootType = LootType.Newbied;
|
||||
chl.Crafter = this;
|
||||
chl.Quality = ArmorQuality.Regular;
|
||||
AddItem(chl);
|
||||
|
||||
PlateArms pla = new PlateArms();
|
||||
pla.Movable = false;
|
||||
pla.LootType = LootType.Newbied;
|
||||
pla.Crafter = this;
|
||||
pla.Quality = ArmorQuality.Regular;
|
||||
AddItem(pla);
|
||||
|
||||
Bandage band = new Bandage(50);
|
||||
AddToBackpack(band);
|
||||
}
|
||||
|
||||
public DummyMace(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Macer";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyFence : Dummy
|
||||
{
|
||||
[Constructible]
|
||||
public DummyFence() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Fencer
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
InitStats(125, 125, 90);
|
||||
Skills.Fencing.Base = 120;
|
||||
Skills.Anatomy.Base = 120;
|
||||
Skills.Healing.Base = 120;
|
||||
Skills.Tactics.Base = 120;
|
||||
|
||||
// Equip
|
||||
Spear ssp = new Spear();
|
||||
ssp.Movable = true;
|
||||
ssp.Crafter = this;
|
||||
ssp.Quality = WeaponQuality.Regular;
|
||||
AddItem(ssp);
|
||||
|
||||
Boots snd = new Boots();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem(snd);
|
||||
|
||||
ChainChest cht = new ChainChest();
|
||||
cht.Movable = false;
|
||||
cht.LootType = LootType.Newbied;
|
||||
cht.Crafter = this;
|
||||
cht.Quality = ArmorQuality.Regular;
|
||||
AddItem(cht);
|
||||
|
||||
ChainLegs chl = new ChainLegs();
|
||||
chl.Movable = false;
|
||||
chl.LootType = LootType.Newbied;
|
||||
chl.Crafter = this;
|
||||
chl.Quality = ArmorQuality.Regular;
|
||||
AddItem(chl);
|
||||
|
||||
PlateArms pla = new PlateArms();
|
||||
pla.Movable = false;
|
||||
pla.LootType = LootType.Newbied;
|
||||
pla.Crafter = this;
|
||||
pla.Quality = ArmorQuality.Regular;
|
||||
AddItem(pla);
|
||||
|
||||
Bandage band = new Bandage(50);
|
||||
AddToBackpack(band);
|
||||
}
|
||||
|
||||
public DummyFence(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Fencer";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummySword : Dummy
|
||||
{
|
||||
[Constructible]
|
||||
public DummySword() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Swordsman
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
InitStats(125, 125, 90);
|
||||
Skills.Swords.Base = 120;
|
||||
Skills.Anatomy.Base = 120;
|
||||
Skills.Healing.Base = 120;
|
||||
Skills.Tactics.Base = 120;
|
||||
Skills.Parry.Base = 120;
|
||||
|
||||
// Equip
|
||||
Katana kat = new Katana();
|
||||
kat.Crafter = this;
|
||||
kat.Movable = true;
|
||||
kat.Quality = WeaponQuality.Regular;
|
||||
AddItem(kat);
|
||||
|
||||
Boots bts = new Boots();
|
||||
bts.Hue = iHue;
|
||||
AddItem(bts);
|
||||
|
||||
ChainChest cht = new ChainChest();
|
||||
cht.Movable = false;
|
||||
cht.LootType = LootType.Newbied;
|
||||
cht.Crafter = this;
|
||||
cht.Quality = ArmorQuality.Regular;
|
||||
AddItem(cht);
|
||||
|
||||
ChainLegs chl = new ChainLegs();
|
||||
chl.Movable = false;
|
||||
chl.LootType = LootType.Newbied;
|
||||
chl.Crafter = this;
|
||||
chl.Quality = ArmorQuality.Regular;
|
||||
AddItem(chl);
|
||||
|
||||
PlateArms pla = new PlateArms();
|
||||
pla.Movable = false;
|
||||
pla.LootType = LootType.Newbied;
|
||||
pla.Crafter = this;
|
||||
pla.Quality = ArmorQuality.Regular;
|
||||
AddItem(pla);
|
||||
|
||||
Bandage band = new Bandage(50);
|
||||
AddToBackpack(band);
|
||||
}
|
||||
|
||||
public DummySword(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Swordsman";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyNox : Dummy
|
||||
{
|
||||
[Constructible]
|
||||
public DummyNox() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Nox or Pure Mage
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
InitStats(90, 90, 125);
|
||||
Skills.Magery.Base = 120;
|
||||
Skills.EvalInt.Base = 120;
|
||||
Skills.Inscribe.Base = 100;
|
||||
Skills.Wrestling.Base = 120;
|
||||
Skills.Meditation.Base = 120;
|
||||
Skills.Poisoning.Base = 100;
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content = 0xFFFFFFFFFFFFFFFF;
|
||||
AddItem(book);
|
||||
|
||||
Kilt kilt = new Kilt();
|
||||
kilt.Hue = jHue;
|
||||
AddItem(kilt);
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem(snd);
|
||||
|
||||
SkullCap skc = new SkullCap();
|
||||
skc.Hue = iHue;
|
||||
AddItem(skc);
|
||||
|
||||
// Spells
|
||||
AddSpellAttack(typeof(MagicArrowSpell));
|
||||
AddSpellAttack(typeof(WeakenSpell));
|
||||
AddSpellAttack(typeof(FireballSpell));
|
||||
AddSpellDefense(typeof(WallOfStoneSpell));
|
||||
AddSpellDefense(typeof(HealSpell));
|
||||
}
|
||||
|
||||
public DummyNox(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Nox Mage";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyStun : Dummy
|
||||
{
|
||||
[Constructible]
|
||||
public DummyStun() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Stun Mage
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
InitStats(90, 90, 125);
|
||||
Skills.Magery.Base = 100;
|
||||
Skills.EvalInt.Base = 120;
|
||||
Skills.Anatomy.Base = 80;
|
||||
Skills.Wrestling.Base = 80;
|
||||
Skills.Meditation.Base = 100;
|
||||
Skills.Poisoning.Base = 100;
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content = 0xFFFFFFFFFFFFFFFF;
|
||||
AddItem(book);
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem(lea);
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem(lec);
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem(leg);
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem(lel);
|
||||
|
||||
Boots bts = new Boots();
|
||||
bts.Hue = iHue;
|
||||
AddItem(bts);
|
||||
|
||||
Cap cap = new Cap();
|
||||
cap.Hue = iHue;
|
||||
AddItem(cap);
|
||||
|
||||
// Spells
|
||||
AddSpellAttack(typeof(MagicArrowSpell));
|
||||
AddSpellAttack(typeof(WeakenSpell));
|
||||
AddSpellAttack(typeof(FireballSpell));
|
||||
AddSpellDefense(typeof(WallOfStoneSpell));
|
||||
AddSpellDefense(typeof(HealSpell));
|
||||
}
|
||||
|
||||
public DummyStun(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Stun Mage";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummySuper : Dummy
|
||||
{
|
||||
[Constructible]
|
||||
public DummySuper() : base(AIType.AI_Mage, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Super Mage
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
InitStats(125, 125, 125);
|
||||
Skills.Magery.Base = 120;
|
||||
Skills.EvalInt.Base = 120;
|
||||
Skills.Anatomy.Base = 120;
|
||||
Skills.Wrestling.Base = 120;
|
||||
Skills.Meditation.Base = 120;
|
||||
Skills.Poisoning.Base = 100;
|
||||
Skills.Inscribe.Base = 100;
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content = 0xFFFFFFFFFFFFFFFF;
|
||||
AddItem(book);
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem(lea);
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem(lec);
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem(leg);
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem(lel);
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem(snd);
|
||||
|
||||
JesterHat jhat = new JesterHat();
|
||||
jhat.Hue = iHue;
|
||||
AddItem(jhat);
|
||||
|
||||
Doublet dblt = new Doublet();
|
||||
dblt.Hue = iHue;
|
||||
AddItem(dblt);
|
||||
|
||||
// Spells
|
||||
AddSpellAttack(typeof(MagicArrowSpell));
|
||||
AddSpellAttack(typeof(WeakenSpell));
|
||||
AddSpellAttack(typeof(FireballSpell));
|
||||
AddSpellDefense(typeof(WallOfStoneSpell));
|
||||
AddSpellDefense(typeof(HealSpell));
|
||||
}
|
||||
|
||||
public DummySuper(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Super Mage";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyHealer : Dummy
|
||||
{
|
||||
[Constructible]
|
||||
public DummyHealer() : base(AIType.AI_Healer, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Healer Mage
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
InitStats(125, 125, 125);
|
||||
Skills.Magery.Base = 120;
|
||||
Skills.EvalInt.Base = 120;
|
||||
Skills.Anatomy.Base = 120;
|
||||
Skills.Wrestling.Base = 120;
|
||||
Skills.Meditation.Base = 120;
|
||||
Skills.Healing.Base = 100;
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content = 0xFFFFFFFFFFFFFFFF;
|
||||
AddItem(book);
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem(lea);
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem(lec);
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem(leg);
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem(lel);
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem(snd);
|
||||
|
||||
Cap cap = new Cap();
|
||||
cap.Hue = iHue;
|
||||
AddItem(cap);
|
||||
|
||||
Robe robe = new Robe();
|
||||
robe.Hue = iHue;
|
||||
AddItem(robe);
|
||||
}
|
||||
|
||||
public DummyHealer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Healer";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyAssassin : Dummy
|
||||
{
|
||||
[Constructible]
|
||||
public DummyAssassin() : base(AIType.AI_Melee, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Hybrid Assassin
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
InitStats(105, 105, 105);
|
||||
Skills.Magery.Base = 120;
|
||||
Skills.EvalInt.Base = 120;
|
||||
Skills.Swords.Base = 120;
|
||||
Skills.Tactics.Base = 120;
|
||||
Skills.Meditation.Base = 120;
|
||||
Skills.Poisoning.Base = 100;
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content = 0xFFFFFFFFFFFFFFFF;
|
||||
AddToBackpack(book);
|
||||
|
||||
Katana kat = new Katana();
|
||||
kat.Movable = false;
|
||||
kat.LootType = LootType.Newbied;
|
||||
kat.Crafter = this;
|
||||
kat.Poison = Poison.Deadly;
|
||||
kat.PoisonCharges = 12;
|
||||
kat.Quality = WeaponQuality.Regular;
|
||||
AddToBackpack(kat);
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem(lea);
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem(lec);
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem(leg);
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem(lel);
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem(snd);
|
||||
|
||||
Cap cap = new Cap();
|
||||
cap.Hue = iHue;
|
||||
AddItem(cap);
|
||||
|
||||
Robe robe = new Robe();
|
||||
robe.Hue = iHue;
|
||||
AddItem(robe);
|
||||
|
||||
DeadlyPoisonPotion pota = new DeadlyPoisonPotion();
|
||||
pota.LootType = LootType.Newbied;
|
||||
AddToBackpack(pota);
|
||||
|
||||
DeadlyPoisonPotion potb = new DeadlyPoisonPotion();
|
||||
potb.LootType = LootType.Newbied;
|
||||
AddToBackpack(potb);
|
||||
|
||||
DeadlyPoisonPotion potc = new DeadlyPoisonPotion();
|
||||
potc.LootType = LootType.Newbied;
|
||||
AddToBackpack(potc);
|
||||
|
||||
DeadlyPoisonPotion potd = new DeadlyPoisonPotion();
|
||||
potd.LootType = LootType.Newbied;
|
||||
AddToBackpack(potd);
|
||||
|
||||
Bandage band = new Bandage(50);
|
||||
AddToBackpack(band);
|
||||
}
|
||||
|
||||
public DummyAssassin(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Hybrid Assassin";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[TypeAlias("Server.Mobiles.DummyTheif")]
|
||||
public class DummyThief : Dummy
|
||||
{
|
||||
[Constructible]
|
||||
public DummyThief() : base(AIType.AI_Thief, FightMode.Closest, 15, 1, 0.2, 0.6)
|
||||
{
|
||||
// A Dummy Hybrid Thief
|
||||
int iHue = 20 + Team * 40;
|
||||
int jHue = 25 + Team * 40;
|
||||
|
||||
// Skills and Stats
|
||||
InitStats(105, 105, 105);
|
||||
Skills.Healing.Base = 120;
|
||||
Skills.Anatomy.Base = 120;
|
||||
Skills.Stealing.Base = 120;
|
||||
Skills.ArmsLore.Base = 100;
|
||||
Skills.Meditation.Base = 120;
|
||||
Skills.Wrestling.Base = 120;
|
||||
|
||||
// Equip
|
||||
Spellbook book = new Spellbook();
|
||||
book.Movable = false;
|
||||
book.LootType = LootType.Newbied;
|
||||
book.Content = 0xFFFFFFFFFFFFFFFF;
|
||||
AddItem(book);
|
||||
|
||||
LeatherArms lea = new LeatherArms();
|
||||
lea.Movable = false;
|
||||
lea.LootType = LootType.Newbied;
|
||||
lea.Crafter = this;
|
||||
lea.Quality = ArmorQuality.Regular;
|
||||
AddItem(lea);
|
||||
|
||||
LeatherChest lec = new LeatherChest();
|
||||
lec.Movable = false;
|
||||
lec.LootType = LootType.Newbied;
|
||||
lec.Crafter = this;
|
||||
lec.Quality = ArmorQuality.Regular;
|
||||
AddItem(lec);
|
||||
|
||||
LeatherGorget leg = new LeatherGorget();
|
||||
leg.Movable = false;
|
||||
leg.LootType = LootType.Newbied;
|
||||
leg.Crafter = this;
|
||||
leg.Quality = ArmorQuality.Regular;
|
||||
AddItem(leg);
|
||||
|
||||
LeatherLegs lel = new LeatherLegs();
|
||||
lel.Movable = false;
|
||||
lel.LootType = LootType.Newbied;
|
||||
lel.Crafter = this;
|
||||
lel.Quality = ArmorQuality.Regular;
|
||||
AddItem(lel);
|
||||
|
||||
Sandals snd = new Sandals();
|
||||
snd.Hue = iHue;
|
||||
snd.LootType = LootType.Newbied;
|
||||
AddItem(snd);
|
||||
|
||||
Cap cap = new Cap();
|
||||
cap.Hue = iHue;
|
||||
AddItem(cap);
|
||||
|
||||
Robe robe = new Robe();
|
||||
robe.Hue = iHue;
|
||||
AddItem(robe);
|
||||
|
||||
Bandage band = new Bandage(50);
|
||||
AddToBackpack(band);
|
||||
}
|
||||
|
||||
public DummyThief(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Hybrid Thief";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
645
Projects/Scripts/Mobiles/Special/Harrower.cs
Normal file
645
Projects/Scripts/Mobiles/Special/Harrower.cs
Normal file
|
|
@ -0,0 +1,645 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Items;
|
||||
using Server.Spells;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Harrower : BaseCreature
|
||||
{
|
||||
private static SpawnEntry[] m_Entries =
|
||||
{
|
||||
new SpawnEntry(new Point3D(5242, 945, -40), new Point3D(1176, 2638, 0)), // Destard
|
||||
new SpawnEntry(new Point3D(5225, 798, 0), new Point3D(1176, 2638, 0)), // Destard
|
||||
new SpawnEntry(new Point3D(5556, 886, 30), new Point3D(1298, 1080, 0)), // Despise
|
||||
new SpawnEntry(new Point3D(5187, 615, 0), new Point3D(4111, 432, 5)), // Deceit
|
||||
new SpawnEntry(new Point3D(5319, 583, 0), new Point3D(4111, 432, 5)), // Deceit
|
||||
new SpawnEntry(new Point3D(5713, 1334, -1), new Point3D(2923, 3407, 8)), // Fire
|
||||
new SpawnEntry(new Point3D(5860, 1460, -2), new Point3D(2923, 3407, 8)), // Fire
|
||||
new SpawnEntry(new Point3D(5328, 1620, 0), new Point3D(5451, 3143, -60)), // Terathan Keep
|
||||
new SpawnEntry(new Point3D(5690, 538, 0), new Point3D(2042, 224, 14)), // Wrong
|
||||
new SpawnEntry(new Point3D(5609, 195, 0), new Point3D(514, 1561, 0)), // Shame
|
||||
new SpawnEntry(new Point3D(5475, 187, 0), new Point3D(514, 1561, 0)), // Shame
|
||||
new SpawnEntry(new Point3D(6085, 179, 0), new Point3D(4721, 3822, 0)), // Hythloth
|
||||
new SpawnEntry(new Point3D(6084, 66, 0), new Point3D(4721, 3822, 0)), // Hythloth
|
||||
new SpawnEntry(new Point3D(5499, 2003, 0), new Point3D(2499, 919, 0)), // Covetous
|
||||
new SpawnEntry(new Point3D(5579, 1858, 0), new Point3D(2499, 919, 0)) // Covetous
|
||||
};
|
||||
|
||||
private static readonly double[] m_Offsets =
|
||||
{
|
||||
Math.Cos(000.0 / 180.0 * Math.PI), Math.Sin(000.0 / 180.0 * Math.PI),
|
||||
Math.Cos(040.0 / 180.0 * Math.PI), Math.Sin(040.0 / 180.0 * Math.PI),
|
||||
Math.Cos(080.0 / 180.0 * Math.PI), Math.Sin(080.0 / 180.0 * Math.PI),
|
||||
Math.Cos(120.0 / 180.0 * Math.PI), Math.Sin(120.0 / 180.0 * Math.PI),
|
||||
Math.Cos(160.0 / 180.0 * Math.PI), Math.Sin(160.0 / 180.0 * Math.PI),
|
||||
Math.Cos(200.0 / 180.0 * Math.PI), Math.Sin(200.0 / 180.0 * Math.PI),
|
||||
Math.Cos(240.0 / 180.0 * Math.PI), Math.Sin(240.0 / 180.0 * Math.PI),
|
||||
Math.Cos(280.0 / 180.0 * Math.PI), Math.Sin(280.0 / 180.0 * Math.PI),
|
||||
Math.Cos(320.0 / 180.0 * Math.PI), Math.Sin(320.0 / 180.0 * Math.PI)
|
||||
};
|
||||
|
||||
private Dictionary<Mobile, int> m_DamageEntries;
|
||||
private Item m_GateItem;
|
||||
private List<HarrowerTentacles> m_Tentacles;
|
||||
private Timer m_Timer;
|
||||
|
||||
private bool m_TrueForm;
|
||||
|
||||
[Constructible]
|
||||
public Harrower() : base(AIType.AI_Mage, FightMode.Closest, 18, 1, 0.2, 0.4)
|
||||
{
|
||||
Instances.Add(this);
|
||||
BodyValue = 146;
|
||||
|
||||
SetStr(900, 1000);
|
||||
SetDex(125, 135);
|
||||
SetInt(1000, 1200);
|
||||
|
||||
Fame = 22500;
|
||||
Karma = -22500;
|
||||
|
||||
VirtualArmor = 60;
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 50);
|
||||
SetDamageType(ResistanceType.Energy, 50);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 55, 65);
|
||||
SetResistance(ResistanceType.Fire, 60, 80);
|
||||
SetResistance(ResistanceType.Cold, 60, 80);
|
||||
SetResistance(ResistanceType.Poison, 60, 80);
|
||||
SetResistance(ResistanceType.Energy, 60, 80);
|
||||
|
||||
SetSkill(SkillName.Wrestling, 90.1, 100.0);
|
||||
SetSkill(SkillName.Tactics, 90.2, 110.0);
|
||||
SetSkill(SkillName.MagicResist, 120.2, 160.0);
|
||||
SetSkill(SkillName.Magery, 120.0);
|
||||
SetSkill(SkillName.EvalInt, 120.0);
|
||||
SetSkill(SkillName.Meditation, 120.0);
|
||||
|
||||
m_Tentacles = new List<HarrowerTentacles>();
|
||||
|
||||
m_Timer = new TeleportTimer(this);
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
public Harrower(Serial serial) : base(serial)
|
||||
{
|
||||
Instances.Add(this);
|
||||
}
|
||||
|
||||
public Type[] UniqueList => new[] { typeof(AcidProofRobe) };
|
||||
public Type[] SharedList => new[] { typeof(TheRobeOfBritanniaAri) };
|
||||
public Type[] DecorativeList => new[] { typeof(EvilIdolSkull), typeof(SkullPole) };
|
||||
|
||||
public static List<Harrower> Instances{ get; } = new List<Harrower>();
|
||||
|
||||
public static bool CanSpawn => Instances.Count == 0;
|
||||
|
||||
public override string DefaultName => "the harrower";
|
||||
|
||||
public override bool AutoDispel => true;
|
||||
public override bool Unprovokable => true;
|
||||
public override Poison PoisonImmune => Poison.Lethal;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public override int HitsMax => m_TrueForm ? 65000 : 30000;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public override int ManaMax => 5000;
|
||||
|
||||
public override bool DisallowAllMoves => m_TrueForm;
|
||||
|
||||
public static Harrower Spawn(Point3D platLoc, Map platMap)
|
||||
{
|
||||
if (Instances.Count > 0)
|
||||
return null;
|
||||
|
||||
SpawnEntry entry = m_Entries[Utility.Random(m_Entries.Length)];
|
||||
|
||||
Harrower harrower = new Harrower();
|
||||
|
||||
harrower.MoveToWorld(entry.m_Location, Map.Felucca);
|
||||
|
||||
harrower.m_GateItem = new HarrowerGate(harrower, platLoc, platMap, entry.m_Entrance, Map.Felucca);
|
||||
|
||||
return harrower;
|
||||
}
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.SuperBoss, 2);
|
||||
AddLoot(LootPack.Meager);
|
||||
}
|
||||
|
||||
public void Morph()
|
||||
{
|
||||
if (m_TrueForm)
|
||||
return;
|
||||
|
||||
m_TrueForm = true;
|
||||
|
||||
Name = "the true harrower";
|
||||
BodyValue = 780;
|
||||
Hue = 0x497;
|
||||
|
||||
Hits = HitsMax;
|
||||
Stam = StamMax;
|
||||
Mana = ManaMax;
|
||||
|
||||
ProcessDelta();
|
||||
|
||||
Say(1049499); // Behold my true form!
|
||||
|
||||
Map map = Map;
|
||||
|
||||
if (map != null)
|
||||
for (int i = 0; i < m_Offsets.Length; i += 2)
|
||||
{
|
||||
double rx = m_Offsets[i];
|
||||
double ry = m_Offsets[i + 1];
|
||||
|
||||
int dist = 0;
|
||||
bool ok = false;
|
||||
int x = 0, y = 0, z = 0;
|
||||
|
||||
while (!ok && dist < 10)
|
||||
{
|
||||
int rdist = 10 + dist;
|
||||
|
||||
x = X + (int)(rx * rdist);
|
||||
y = Y + (int)(ry * rdist);
|
||||
z = map.GetAverageZ(x, y);
|
||||
|
||||
if (!(ok = map.CanFit(x, y, Z, 16, false, false)))
|
||||
ok = map.CanFit(x, y, z, 16, false, false);
|
||||
|
||||
if (dist >= 0)
|
||||
dist = -(dist + 1);
|
||||
else
|
||||
dist = -(dist - 1);
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
continue;
|
||||
|
||||
HarrowerTentacles spawn = new HarrowerTentacles(this) { Team = Team };
|
||||
|
||||
spawn.MoveToWorld(new Point3D(x, y, z), map);
|
||||
|
||||
m_Tentacles.Add(spawn);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
Instances.Remove(this);
|
||||
|
||||
base.OnAfterDelete();
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_TrueForm);
|
||||
writer.Write(m_GateItem);
|
||||
writer.WriteMobileList(m_Tentacles);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_TrueForm = reader.ReadBool();
|
||||
m_GateItem = reader.ReadItem();
|
||||
m_Tentacles = reader.ReadStrongMobileList<HarrowerTentacles>();
|
||||
|
||||
m_Timer = new TeleportTimer(this);
|
||||
m_Timer.Start();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void GivePowerScrolls()
|
||||
{
|
||||
List<Mobile> toGive = new List<Mobile>();
|
||||
List<DamageStore> rights = GetLootingRights(DamageEntries, HitsMax);
|
||||
|
||||
for (int i = rights.Count - 1; i >= 0; --i)
|
||||
{
|
||||
DamageStore ds = rights[i];
|
||||
|
||||
if (ds.m_HasRight)
|
||||
toGive.Add(ds.m_Mobile);
|
||||
}
|
||||
|
||||
if (toGive.Count == 0)
|
||||
return;
|
||||
|
||||
// Randomize
|
||||
for (int i = 0; i < toGive.Count; ++i)
|
||||
{
|
||||
int rand = Utility.Random(toGive.Count);
|
||||
Mobile hold = toGive[i];
|
||||
toGive[i] = toGive[rand];
|
||||
toGive[rand] = hold;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
int level;
|
||||
double random = Utility.RandomDouble();
|
||||
|
||||
if (0.1 >= random)
|
||||
level = 25;
|
||||
else if (0.25 >= random)
|
||||
level = 20;
|
||||
else if (0.45 >= random)
|
||||
level = 15;
|
||||
else if (0.70 >= random)
|
||||
level = 10;
|
||||
else
|
||||
level = 5;
|
||||
|
||||
Mobile m = toGive[i % toGive.Count];
|
||||
|
||||
m.SendLocalizedMessage(1049524); // You have received a scroll of power!
|
||||
m.AddToBackpack(new StatCapScroll(225 + level));
|
||||
|
||||
if (m is PlayerMobile pm)
|
||||
for (int j = 0; j < pm.JusticeProtectors.Count; ++j)
|
||||
{
|
||||
Mobile prot = pm.JusticeProtectors[j];
|
||||
|
||||
if (prot.Map != pm.Map || prot.Kills >= 5 || prot.Criminal ||
|
||||
!JusticeVirtue.CheckMapRegion(pm, prot))
|
||||
continue;
|
||||
|
||||
int chance = 0;
|
||||
|
||||
switch (VirtueHelper.GetLevel(prot, VirtueName.Justice))
|
||||
{
|
||||
case VirtueLevel.Seeker:
|
||||
chance = 60;
|
||||
break;
|
||||
case VirtueLevel.Follower:
|
||||
chance = 80;
|
||||
break;
|
||||
case VirtueLevel.Knight:
|
||||
chance = 100;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chance > Utility.Random(100))
|
||||
{
|
||||
prot.SendLocalizedMessage(1049368); // You have been rewarded for your dedication to Justice!
|
||||
prot.AddToBackpack(new StatCapScroll(225 + level));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnBeforeDeath()
|
||||
{
|
||||
if (m_TrueForm)
|
||||
{
|
||||
List<DamageStore> rights = GetLootingRights(DamageEntries, HitsMax);
|
||||
|
||||
for (int i = rights.Count - 1; i >= 0; --i)
|
||||
{
|
||||
DamageStore ds = rights[i];
|
||||
|
||||
if (ds.m_HasRight && ds.m_Mobile is PlayerMobile mobile)
|
||||
PlayerMobile.ChampionTitleInfo.AwardHarrowerTitle(mobile);
|
||||
}
|
||||
|
||||
if (!NoKillAwards)
|
||||
{
|
||||
GivePowerScrolls();
|
||||
|
||||
Map map = Map;
|
||||
|
||||
if (map != null)
|
||||
for (int x = -16; x <= 16; ++x)
|
||||
for (int y = -16; y <= 16; ++y)
|
||||
{
|
||||
double dist = Math.Sqrt(x * x + y * y);
|
||||
|
||||
if (dist <= 16)
|
||||
new GoodiesTimer(map, X + x, Y + y).Start();
|
||||
}
|
||||
|
||||
m_DamageEntries = new Dictionary<Mobile, int>();
|
||||
|
||||
for (int i = 0; i < m_Tentacles.Count; ++i)
|
||||
{
|
||||
Mobile m = m_Tentacles[i];
|
||||
|
||||
if (!m.Deleted)
|
||||
m.Kill();
|
||||
|
||||
RegisterDamageTo(m);
|
||||
}
|
||||
|
||||
m_Tentacles.Clear();
|
||||
|
||||
RegisterDamageTo(this);
|
||||
AwardArtifact(GetArtifact());
|
||||
|
||||
m_GateItem?.Delete();
|
||||
}
|
||||
|
||||
return base.OnBeforeDeath();
|
||||
}
|
||||
|
||||
Morph();
|
||||
return false;
|
||||
}
|
||||
|
||||
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?.Player != true)
|
||||
return;
|
||||
|
||||
m_DamageEntries[from] = amount + (m_DamageEntries.TryGetValue(from, out int value) ? value : 0);
|
||||
|
||||
from.SendMessage($"Total Damage: {m_DamageEntries[from]}");
|
||||
}
|
||||
|
||||
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 validEntries)
|
||||
{
|
||||
totalDamage += kvp.Value;
|
||||
|
||||
if (totalDamage >= randomDamage)
|
||||
{
|
||||
GiveArtifact(kvp.Key, artifact);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
artifact.Delete();
|
||||
}
|
||||
|
||||
public void GiveArtifact(Mobile to, Item artifact)
|
||||
{
|
||||
if (to == null || artifact == null)
|
||||
return;
|
||||
|
||||
Container pack = to.Backpack;
|
||||
|
||||
if (pack?.TryDropItem(to, artifact, false) != true)
|
||||
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?.CheckHold(m, Artifact, false) == true;
|
||||
}
|
||||
|
||||
public Item GetArtifact()
|
||||
{
|
||||
double random = Utility.RandomDouble();
|
||||
if (0.05 >= random)
|
||||
return CreateArtifact(UniqueList);
|
||||
if (0.15 >= random)
|
||||
return CreateArtifact(SharedList);
|
||||
if (0.30 >= random)
|
||||
return CreateArtifact(DecorativeList);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Item CreateArtifact(Type[] list)
|
||||
{
|
||||
if (list.Length == 0)
|
||||
return null;
|
||||
|
||||
int random = Utility.Random(list.Length);
|
||||
|
||||
Type type = list[random];
|
||||
|
||||
return Loot.Construct(type);
|
||||
}
|
||||
|
||||
private class SpawnEntry
|
||||
{
|
||||
public Point3D m_Entrance;
|
||||
public Point3D m_Location;
|
||||
|
||||
public SpawnEntry(Point3D loc, Point3D ent)
|
||||
{
|
||||
m_Location = loc;
|
||||
m_Entrance = ent;
|
||||
}
|
||||
}
|
||||
|
||||
private class TeleportTimer : Timer
|
||||
{
|
||||
private static int[] m_Offsets =
|
||||
{
|
||||
-1, -1,
|
||||
-1, 0,
|
||||
-1, 1,
|
||||
0, -1,
|
||||
0, 1,
|
||||
1, -1,
|
||||
1, 0,
|
||||
1, 1
|
||||
};
|
||||
|
||||
private Mobile m_Owner;
|
||||
|
||||
public TeleportTimer(Mobile owner) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0))
|
||||
{
|
||||
Priority = TimerPriority.TwoFiftyMS;
|
||||
|
||||
m_Owner = owner;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (m_Owner.Deleted)
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
Map map = m_Owner.Map;
|
||||
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
if (0.25 < Utility.RandomDouble())
|
||||
return;
|
||||
|
||||
Mobile toTeleport = m_Owner.GetMobilesInRange(16)
|
||||
.FirstOrDefault(mob => mob != m_Owner && mob.Player && m_Owner.CanBeHarmful(mob) && m_Owner.CanSee(mob));
|
||||
|
||||
if (toTeleport == null)
|
||||
return;
|
||||
|
||||
int offset = Utility.Random(8) * 2;
|
||||
|
||||
Point3D to = m_Owner.Location;
|
||||
|
||||
for (int i = 0; i < m_Offsets.Length; i += 2)
|
||||
{
|
||||
int x = m_Owner.X + m_Offsets[(offset + i) % m_Offsets.Length];
|
||||
int y = m_Owner.Y + m_Offsets[(offset + i + 1) % m_Offsets.Length];
|
||||
|
||||
if (map.CanSpawnMobile(x, y, m_Owner.Z))
|
||||
{
|
||||
to = new Point3D(x, y, m_Owner.Z);
|
||||
break;
|
||||
}
|
||||
|
||||
int z = map.GetAverageZ(x, y);
|
||||
|
||||
if (map.CanSpawnMobile(x, y, z))
|
||||
{
|
||||
to = new Point3D(x, y, z);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Mobile m = toTeleport;
|
||||
|
||||
Point3D from = m.Location;
|
||||
|
||||
m.Location = to;
|
||||
|
||||
SpellHelper.Turn(m_Owner, toTeleport);
|
||||
SpellHelper.Turn(toTeleport, m_Owner);
|
||||
|
||||
m.ProcessDelta();
|
||||
|
||||
Effects.SendLocationParticles(EffectItem.Create(from, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10,
|
||||
2023);
|
||||
Effects.SendLocationParticles(EffectItem.Create(to, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10,
|
||||
5023);
|
||||
|
||||
m.PlaySound(0x1FE);
|
||||
|
||||
m_Owner.Combatant = toTeleport;
|
||||
}
|
||||
}
|
||||
|
||||
private class GoodiesTimer : Timer
|
||||
{
|
||||
private Map m_Map;
|
||||
private int m_X, m_Y;
|
||||
|
||||
public GoodiesTimer(Map map, int x, int y) : base(TimeSpan.FromSeconds(Utility.RandomDouble() * 10.0))
|
||||
{
|
||||
Priority = TimerPriority.TwoFiftyMS;
|
||||
|
||||
m_Map = map;
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
int z = m_Map.GetAverageZ(m_X, m_Y);
|
||||
bool canFit = m_Map.CanFit(m_X, m_Y, z, 6, false, false);
|
||||
|
||||
for (int i = -3; !canFit && i <= 3; ++i)
|
||||
{
|
||||
canFit = m_Map.CanFit(m_X, m_Y, z + i, 6, false, false);
|
||||
|
||||
if (canFit)
|
||||
z += i;
|
||||
}
|
||||
|
||||
if (!canFit)
|
||||
return;
|
||||
|
||||
Gold g = new Gold(750, 1250);
|
||||
|
||||
g.MoveToWorld(new Point3D(m_X, m_Y, z), m_Map);
|
||||
|
||||
if (0.5 >= Utility.RandomDouble())
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
190
Projects/Scripts/Mobiles/Special/HarrowerTentacles.cs
Normal file
190
Projects/Scripts/Mobiles/Special/HarrowerTentacles.cs
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class HarrowerTentacles : BaseCreature
|
||||
{
|
||||
private DrainTimer m_Timer;
|
||||
|
||||
public HarrowerTentacles(Mobile harrower = null) :
|
||||
base(AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
Harrower = harrower;
|
||||
Body = 129;
|
||||
|
||||
SetStr(901, 1000);
|
||||
SetDex(126, 140);
|
||||
SetInt(1001, 1200);
|
||||
|
||||
SetHits(541, 600);
|
||||
|
||||
SetDamage(13, 20);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 20);
|
||||
SetDamageType(ResistanceType.Fire, 20);
|
||||
SetDamageType(ResistanceType.Cold, 20);
|
||||
SetDamageType(ResistanceType.Poison, 20);
|
||||
SetDamageType(ResistanceType.Energy, 20);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 55, 65);
|
||||
SetResistance(ResistanceType.Fire, 35, 45);
|
||||
SetResistance(ResistanceType.Cold, 35, 45);
|
||||
SetResistance(ResistanceType.Poison, 35, 45);
|
||||
SetResistance(ResistanceType.Energy, 35, 45);
|
||||
|
||||
SetSkill(SkillName.Meditation, 100.0);
|
||||
SetSkill(SkillName.MagicResist, 120.1, 140.0);
|
||||
SetSkill(SkillName.Swords, 90.1, 100.0);
|
||||
SetSkill(SkillName.Tactics, 90.1, 100.0);
|
||||
SetSkill(SkillName.Wrestling, 90.1, 100.0);
|
||||
|
||||
Fame = 15000;
|
||||
Karma = -15000;
|
||||
|
||||
VirtualArmor = 60;
|
||||
|
||||
m_Timer = new DrainTimer(this);
|
||||
m_Timer.Start();
|
||||
|
||||
PackReg(50);
|
||||
PackNecroReg(15, 75);
|
||||
}
|
||||
|
||||
public HarrowerTentacles(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string CorpseName => "a tentacles corpse";
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Mobile Harrower{ get; set; }
|
||||
|
||||
public override string DefaultName => "tentacles of the harrower";
|
||||
|
||||
public override bool AutoDispel => true;
|
||||
public override bool Unprovokable => true;
|
||||
public override Poison PoisonImmune => Poison.Lethal;
|
||||
public override bool DisallowAllMoves => true;
|
||||
|
||||
public override void CheckReflect(Mobile caster, ref bool reflect)
|
||||
{
|
||||
reflect = true;
|
||||
}
|
||||
|
||||
public override int GetIdleSound()
|
||||
{
|
||||
return 0x101;
|
||||
}
|
||||
|
||||
public override int GetAngerSound()
|
||||
{
|
||||
return 0x5E;
|
||||
}
|
||||
|
||||
public override int GetDeathSound()
|
||||
{
|
||||
return 0x1C2;
|
||||
}
|
||||
|
||||
public override int GetAttackSound()
|
||||
{
|
||||
return -1; // unknown
|
||||
}
|
||||
|
||||
public override int GetHurtSound()
|
||||
{
|
||||
return 0x289;
|
||||
}
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.FilthyRich, 2);
|
||||
AddLoot(LootPack.MedScrolls, 3);
|
||||
AddLoot(LootPack.HighScrolls, 2);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(Harrower);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Harrower = reader.ReadMobile();
|
||||
|
||||
m_Timer = new DrainTimer(this);
|
||||
m_Timer.Start();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
m_Timer?.Stop();
|
||||
m_Timer = null;
|
||||
|
||||
base.OnAfterDelete();
|
||||
}
|
||||
|
||||
private class DrainTimer : Timer
|
||||
{
|
||||
private HarrowerTentacles m_Owner;
|
||||
|
||||
public DrainTimer(HarrowerTentacles owner) : base(TimeSpan.FromSeconds(5.0), TimeSpan.FromSeconds(5.0))
|
||||
{
|
||||
m_Owner = owner;
|
||||
Priority = TimerPriority.TwoFiftyMS;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (m_Owner.Deleted)
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
IPooledEnumerable<Mobile> eable = m_Owner.GetMobilesInRange<Mobile>(9);
|
||||
|
||||
foreach (Mobile m in eable)
|
||||
{
|
||||
if (m == m_Owner || !(m_Owner.CanBeHarmful(m) || m.Player && m.Alive))
|
||||
continue;
|
||||
|
||||
if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != m_Owner.Team))
|
||||
continue;
|
||||
|
||||
m_Owner.DoHarmful(m);
|
||||
|
||||
m.FixedParticles(0x374A, 10, 15, 5013, 0x455, 0, EffectLayer.Waist);
|
||||
m.PlaySound(0x1F1);
|
||||
|
||||
int drain = Utility.RandomMinMax(14, 30);
|
||||
|
||||
m_Owner.Hits += drain;
|
||||
|
||||
if (m_Owner.Harrower != null)
|
||||
m_Owner.Harrower.Hits += drain;
|
||||
|
||||
m.Damage(drain, m_Owner);
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
219
Projects/Scripts/Mobiles/Special/LordOaks.cs
Normal file
219
Projects/Scripts/Mobiles/Special/LordOaks.cs
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
using System;
|
||||
using Server.Engines.CannedEvil;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class LordOaks : BaseChampion
|
||||
{
|
||||
private BaseCreature m_Queen;
|
||||
private bool m_SpawnedQueen;
|
||||
|
||||
[Constructible]
|
||||
public LordOaks() : base(AIType.AI_Mage, FightMode.Evil)
|
||||
{
|
||||
Body = 175;
|
||||
SetStr(403, 850);
|
||||
SetDex(101, 150);
|
||||
SetInt(503, 800);
|
||||
|
||||
SetHits(3000);
|
||||
SetStam(202, 400);
|
||||
|
||||
SetDamage(21, 33);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 75);
|
||||
SetDamageType(ResistanceType.Fire, 25);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 85, 90);
|
||||
SetResistance(ResistanceType.Fire, 60, 70);
|
||||
SetResistance(ResistanceType.Cold, 60, 70);
|
||||
SetResistance(ResistanceType.Poison, 80, 90);
|
||||
SetResistance(ResistanceType.Energy, 80, 90);
|
||||
|
||||
SetSkill(SkillName.Anatomy, 75.1, 100.0);
|
||||
SetSkill(SkillName.EvalInt, 120.1, 130.0);
|
||||
SetSkill(SkillName.Magery, 120.0);
|
||||
SetSkill(SkillName.Meditation, 120.1, 130.0);
|
||||
SetSkill(SkillName.MagicResist, 100.5, 150.0);
|
||||
SetSkill(SkillName.Tactics, 100.0);
|
||||
SetSkill(SkillName.Wrestling, 100.0);
|
||||
|
||||
Fame = 22500;
|
||||
Karma = 22500;
|
||||
|
||||
VirtualArmor = 100;
|
||||
}
|
||||
|
||||
public LordOaks(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override ChampionSkullType SkullType => ChampionSkullType.Enlightenment;
|
||||
|
||||
public override Type[] UniqueList => new[] { typeof(OrcChieftainHelm) };
|
||||
|
||||
public override Type[] SharedList => new[]
|
||||
{
|
||||
typeof(RoyalGuardSurvivalKnife),
|
||||
typeof(DjinnisRing),
|
||||
typeof(LieutenantOfTheBritannianRoyalGuard),
|
||||
typeof(SamaritanRobe),
|
||||
typeof(DetectiveBoots),
|
||||
typeof(TheMostKnowledgePerson)
|
||||
};
|
||||
|
||||
public override Type[] DecorativeList => new[]
|
||||
{
|
||||
typeof(WaterTile),
|
||||
typeof(WindSpirit),
|
||||
typeof(Pier),
|
||||
typeof(DirtPatch)
|
||||
};
|
||||
|
||||
public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { };
|
||||
|
||||
public override string DefaultName => "Lord Oaks";
|
||||
|
||||
public override bool AutoDispel => true;
|
||||
public override bool CanFly => true;
|
||||
public override bool BardImmune => !Core.SE;
|
||||
public override bool Unprovokable => Core.SE;
|
||||
public override bool Uncalmable => Core.SE;
|
||||
public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead;
|
||||
|
||||
public override Poison PoisonImmune => Poison.Deadly;
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.UltraRich, 5);
|
||||
}
|
||||
|
||||
public void SpawnPixies(Mobile target)
|
||||
{
|
||||
Map map = Map;
|
||||
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
Say(1042154); // You shall never defeat me as long as I have my queen!
|
||||
|
||||
int newPixies = Utility.RandomMinMax(3, 6);
|
||||
|
||||
for (int i = 0; i < newPixies; ++i)
|
||||
{
|
||||
Pixie pixie = new Pixie { Team = Team, FightMode = FightMode.Closest };
|
||||
|
||||
pixie.MoveToWorld(map.GetRandomNearbyLocation(Location), map);
|
||||
pixie.Combatant = target;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetAngerSound()
|
||||
{
|
||||
return 0x2F8;
|
||||
}
|
||||
|
||||
public override int GetIdleSound()
|
||||
{
|
||||
return 0x2F8;
|
||||
}
|
||||
|
||||
public override int GetAttackSound()
|
||||
{
|
||||
return Utility.Random(0x2F5, 2);
|
||||
}
|
||||
|
||||
public override int GetHurtSound()
|
||||
{
|
||||
return 0x2F9;
|
||||
}
|
||||
|
||||
public override int GetDeathSound()
|
||||
{
|
||||
return 0x2F7;
|
||||
}
|
||||
|
||||
public void CheckQueen()
|
||||
{
|
||||
if (Map == null)
|
||||
return;
|
||||
|
||||
if (!m_SpawnedQueen)
|
||||
{
|
||||
Say(1042153); // Come forth my queen!
|
||||
|
||||
m_Queen = new Silvani { Team = Team };
|
||||
m_Queen.MoveToWorld(Location, Map);
|
||||
|
||||
m_SpawnedQueen = true;
|
||||
}
|
||||
else if (m_Queen?.Deleted != false)
|
||||
m_Queen = null;
|
||||
}
|
||||
|
||||
public override void AlterDamageScalarFrom(Mobile caster, ref double scalar)
|
||||
{
|
||||
CheckQueen();
|
||||
|
||||
if (m_Queen != null)
|
||||
{
|
||||
scalar *= 0.1;
|
||||
|
||||
if (0.1 >= Utility.RandomDouble())
|
||||
SpawnPixies(caster);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGaveMeleeAttack(Mobile defender)
|
||||
{
|
||||
base.OnGaveMeleeAttack(defender);
|
||||
|
||||
defender.Damage(Utility.Random(20, 10), this);
|
||||
defender.Stam -= Utility.Random(20, 10);
|
||||
defender.Mana -= Utility.Random(20, 10);
|
||||
}
|
||||
|
||||
public override void OnGotMeleeAttack(Mobile attacker)
|
||||
{
|
||||
base.OnGotMeleeAttack(attacker);
|
||||
|
||||
CheckQueen();
|
||||
|
||||
if (m_Queen != null && 0.1 >= Utility.RandomDouble())
|
||||
SpawnPixies(attacker);
|
||||
|
||||
attacker.Damage(Utility.Random(20, 10), this);
|
||||
attacker.Stam -= Utility.Random(20, 10);
|
||||
attacker.Mana -= Utility.Random(20, 10);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_Queen);
|
||||
writer.Write(m_SpawnedQueen);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_Queen = reader.ReadMobile<BaseCreature>();
|
||||
m_SpawnedQueen = reader.ReadBool();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
92
Projects/Scripts/Mobiles/Special/Mephitis.cs
Normal file
92
Projects/Scripts/Mobiles/Special/Mephitis.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using Server.Engines.CannedEvil;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Mephitis : BaseChampion
|
||||
{
|
||||
[Constructible]
|
||||
public Mephitis() : base(AIType.AI_Melee)
|
||||
{
|
||||
Body = 173;
|
||||
BaseSoundID = 0x183;
|
||||
|
||||
SetStr(505, 1000);
|
||||
SetDex(102, 300);
|
||||
SetInt(402, 600);
|
||||
|
||||
SetHits(3000);
|
||||
SetStam(105, 600);
|
||||
|
||||
SetDamage(21, 33);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 50);
|
||||
SetDamageType(ResistanceType.Poison, 50);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 75, 80);
|
||||
SetResistance(ResistanceType.Fire, 60, 70);
|
||||
SetResistance(ResistanceType.Cold, 60, 70);
|
||||
SetResistance(ResistanceType.Poison, 100);
|
||||
SetResistance(ResistanceType.Energy, 60, 70);
|
||||
|
||||
SetSkill(SkillName.MagicResist, 70.7, 140.0);
|
||||
SetSkill(SkillName.Tactics, 97.6, 100.0);
|
||||
SetSkill(SkillName.Wrestling, 97.6, 100.0);
|
||||
|
||||
Fame = 22500;
|
||||
Karma = -22500;
|
||||
|
||||
VirtualArmor = 80;
|
||||
}
|
||||
|
||||
public Mephitis(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override ChampionSkullType SkullType => ChampionSkullType.Venom;
|
||||
|
||||
public override Type[] UniqueList => new[] { typeof(Calm) };
|
||||
|
||||
public override Type[] SharedList => new[]
|
||||
{
|
||||
typeof(OblivionsNeedle), typeof(ANecromancerShroud), typeof(EmbroideredOakLeafCloak),
|
||||
typeof(TheMostKnowledgePerson)
|
||||
};
|
||||
|
||||
public override Type[] DecorativeList => new[] { typeof(Web), typeof(MonsterStatuette) };
|
||||
|
||||
public override MonsterStatuetteType[] StatueTypes => new[] { MonsterStatuetteType.Spider };
|
||||
|
||||
public override string DefaultName => "Mephitis";
|
||||
|
||||
public override Poison PoisonImmune => Poison.Lethal;
|
||||
public override Poison HitPoison => Poison.Lethal;
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.UltraRich, 4);
|
||||
}
|
||||
|
||||
public override void OnGotMeleeAttack(Mobile attacker)
|
||||
{
|
||||
base.OnGotMeleeAttack(attacker);
|
||||
|
||||
// TODO: Web ability
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
297
Projects/Scripts/Mobiles/Special/Neira.cs
Normal file
297
Projects/Scripts/Mobiles/Special/Neira.cs
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
using System;
|
||||
using Server.Engines.CannedEvil;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Neira : BaseChampion
|
||||
{
|
||||
private const double SpeedBoostScalar = 1.2;
|
||||
|
||||
private bool m_SpeedBoost;
|
||||
|
||||
[Constructible]
|
||||
public Neira() : base(AIType.AI_Mage)
|
||||
{
|
||||
Title = "the necromancer";
|
||||
Body = 401;
|
||||
Hue = 0x83EC;
|
||||
|
||||
SetStr(305, 425);
|
||||
SetDex(72, 150);
|
||||
SetInt(505, 750);
|
||||
|
||||
SetHits(4800);
|
||||
SetStam(102, 300);
|
||||
|
||||
SetDamage(25, 35);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 100);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 25, 30);
|
||||
SetResistance(ResistanceType.Fire, 35, 45);
|
||||
SetResistance(ResistanceType.Cold, 50, 60);
|
||||
SetResistance(ResistanceType.Poison, 30, 40);
|
||||
SetResistance(ResistanceType.Energy, 20, 30);
|
||||
|
||||
SetSkill(SkillName.EvalInt, 120.0);
|
||||
SetSkill(SkillName.Magery, 120.0);
|
||||
SetSkill(SkillName.Meditation, 120.0);
|
||||
SetSkill(SkillName.MagicResist, 150.0);
|
||||
SetSkill(SkillName.Tactics, 97.6, 100.0);
|
||||
SetSkill(SkillName.Wrestling, 97.6, 100.0);
|
||||
|
||||
Fame = 22500;
|
||||
Karma = -22500;
|
||||
|
||||
VirtualArmor = 30;
|
||||
Female = true;
|
||||
|
||||
Item shroud = new HoodedShroudOfShadows();
|
||||
|
||||
shroud.Movable = false;
|
||||
|
||||
AddItem(shroud);
|
||||
|
||||
Scimitar weapon = new Scimitar();
|
||||
|
||||
weapon.Skill = SkillName.Wrestling;
|
||||
weapon.Hue = 38;
|
||||
weapon.Movable = false;
|
||||
|
||||
AddItem(weapon);
|
||||
|
||||
//new SkeletalMount().Rider = this;
|
||||
AddItem(new VirtualMountItem(this));
|
||||
}
|
||||
|
||||
public Neira(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override ChampionSkullType SkullType => ChampionSkullType.Death;
|
||||
|
||||
public override Type[] UniqueList => new[] { typeof(ShroudOfDeciet) };
|
||||
|
||||
public override Type[] SharedList => new[]
|
||||
{
|
||||
typeof(ANecromancerShroud),
|
||||
|
||||
typeof(CaptainJohnsHat)
|
||||
};
|
||||
|
||||
public override Type[] DecorativeList => new[] { typeof(WallBlood), typeof(TatteredAncientMummyWrapping) };
|
||||
|
||||
public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { };
|
||||
|
||||
public override string DefaultName => "Neira";
|
||||
|
||||
public override bool AlwaysMurderer => true;
|
||||
public override bool BardImmune => !Core.SE;
|
||||
public override bool Unprovokable => Core.SE;
|
||||
public override bool Uncalmable => Core.SE;
|
||||
public override Poison PoisonImmune => Poison.Deadly;
|
||||
|
||||
public override bool ShowFameTitle => false;
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.UltraRich, 3);
|
||||
AddLoot(LootPack.Meager);
|
||||
}
|
||||
|
||||
public override bool OnBeforeDeath()
|
||||
{
|
||||
IMount mount = Mount;
|
||||
|
||||
if (mount != null)
|
||||
mount.Rider = null;
|
||||
|
||||
(mount as Mobile)?.Delete();
|
||||
|
||||
return base.OnBeforeDeath();
|
||||
}
|
||||
|
||||
public override void OnDamage(int amount, Mobile from, bool willKill)
|
||||
{
|
||||
CheckSpeedBoost();
|
||||
base.OnDamage(amount, from, willKill);
|
||||
}
|
||||
|
||||
private void CheckSpeedBoost()
|
||||
{
|
||||
if (Hits < HitsMax / 4)
|
||||
{
|
||||
if (!m_SpeedBoost)
|
||||
{
|
||||
ActiveSpeed /= SpeedBoostScalar;
|
||||
PassiveSpeed /= SpeedBoostScalar;
|
||||
m_SpeedBoost = true;
|
||||
}
|
||||
}
|
||||
else if (m_SpeedBoost)
|
||||
{
|
||||
ActiveSpeed *= SpeedBoostScalar;
|
||||
PassiveSpeed *= SpeedBoostScalar;
|
||||
m_SpeedBoost = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGaveMeleeAttack(Mobile defender)
|
||||
{
|
||||
base.OnGaveMeleeAttack(defender);
|
||||
|
||||
if (0.1 >= Utility.RandomDouble()) // 10% chance to drop or throw an unholy bone
|
||||
AddUnholyBone(defender, 0.25);
|
||||
|
||||
CheckSpeedBoost();
|
||||
}
|
||||
|
||||
public override void OnGotMeleeAttack(Mobile attacker)
|
||||
{
|
||||
base.OnGotMeleeAttack(attacker);
|
||||
|
||||
if (0.1 >= Utility.RandomDouble()) // 10% chance to drop or throw an unholy bone
|
||||
AddUnholyBone(attacker, 0.25);
|
||||
}
|
||||
|
||||
public override void AlterDamageScalarFrom(Mobile caster, ref double scalar)
|
||||
{
|
||||
base.AlterDamageScalarFrom(caster, ref scalar);
|
||||
|
||||
if (0.1 >= Utility.RandomDouble()) // 10% chance to throw an unholy bone
|
||||
AddUnholyBone(caster, 1.0);
|
||||
}
|
||||
|
||||
public void AddUnholyBone(Mobile target, double chanceToThrow)
|
||||
{
|
||||
if (Map == null)
|
||||
return;
|
||||
|
||||
if (chanceToThrow >= Utility.RandomDouble())
|
||||
{
|
||||
Direction = GetDirectionTo(target);
|
||||
MovingEffect(target, 0xF7E, 10, 1, true, false, 0x496, 0);
|
||||
new DelayTimer(this, target).Start();
|
||||
}
|
||||
else
|
||||
{
|
||||
new UnholyBone().MoveToWorld(Location, Map);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(1); // version
|
||||
writer.Write(m_SpeedBoost);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
m_SpeedBoost = reader.ReadBool();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class VirtualMount : IMount
|
||||
{
|
||||
private VirtualMountItem m_Item;
|
||||
|
||||
public VirtualMount(VirtualMountItem item)
|
||||
{
|
||||
m_Item = item;
|
||||
}
|
||||
|
||||
Mobile IMount.Rider
|
||||
{
|
||||
get => m_Item.Rider;
|
||||
set { }
|
||||
}
|
||||
|
||||
public virtual void OnRiderDamaged(int amount, Mobile from, bool willKill)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class VirtualMountItem : Item, IMountItem
|
||||
{
|
||||
private VirtualMount m_Mount;
|
||||
|
||||
public VirtualMountItem(Mobile mob)
|
||||
: base(0x3EBB)
|
||||
{
|
||||
Layer = Layer.Mount;
|
||||
|
||||
Movable = false;
|
||||
|
||||
Rider = mob;
|
||||
m_Mount = new VirtualMount(this);
|
||||
}
|
||||
|
||||
public VirtualMountItem(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
m_Mount = new VirtualMount(this);
|
||||
}
|
||||
|
||||
public Mobile Rider{ get; private set; }
|
||||
|
||||
public IMount Mount => m_Mount;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(Rider);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
Rider = reader.ReadMobile();
|
||||
|
||||
if (Rider == null)
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
|
||||
private class DelayTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private Mobile m_Target;
|
||||
|
||||
public DelayTimer(Mobile m, Mobile target) : base(TimeSpan.FromSeconds(1.0))
|
||||
{
|
||||
m_Mobile = m;
|
||||
m_Target = target;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (m_Mobile.CanBeHarmful(m_Target))
|
||||
{
|
||||
m_Mobile.DoHarmful(m_Target);
|
||||
AOS.Damage(m_Target, m_Mobile, Utility.RandomMinMax(10, 20), 100, 0, 0, 0, 0);
|
||||
new UnholyBone().MoveToWorld(m_Target.Location, m_Target.Map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Projects/Scripts/Mobiles/Special/OrderGuard.cs
Normal file
38
Projects/Scripts/Mobiles/Special/OrderGuard.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using Server.Guilds;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class OrderGuard : BaseShieldGuard
|
||||
{
|
||||
[Constructible]
|
||||
public OrderGuard()
|
||||
{
|
||||
}
|
||||
|
||||
public OrderGuard(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int Keyword => 0x21; // *order shield*
|
||||
public override BaseShield Shield => new OrderShield();
|
||||
public override int SignupNumber => 1007141; // Sign up with a guild of order if thou art interested.
|
||||
public override GuildType Type => GuildType.Order;
|
||||
|
||||
public override bool BardImmune => true;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
221
Projects/Scripts/Mobiles/Special/Paragon.cs
Normal file
221
Projects/Scripts/Mobiles/Special/Paragon.cs
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Paragon
|
||||
{
|
||||
public static double ChestChance = .10; // Chance that a paragon will carry a paragon chest
|
||||
public static double ChocolateIngredientChance = .20; // Chance that a paragon will drop a chocolatiering ingredient
|
||||
|
||||
public static Map[] Maps =
|
||||
{
|
||||
Map.Ilshenar
|
||||
};
|
||||
|
||||
private static TimeSpan FastRegenRate = TimeSpan.FromSeconds(.5);
|
||||
private static TimeSpan CPUSaverRate = TimeSpan.FromSeconds(2);
|
||||
|
||||
public static Type[] Artifacts =
|
||||
{
|
||||
typeof(GoldBricks), typeof(PhillipsWoodenSteed),
|
||||
typeof(AlchemistsBauble), typeof(ArcticDeathDealer),
|
||||
typeof(BlazeOfDeath), typeof(BowOfTheJukaKing),
|
||||
typeof(BurglarsBandana), typeof(CavortingClub),
|
||||
typeof(EnchantedTitanLegBone), typeof(GwennosHarp),
|
||||
typeof(IolosLute), typeof(LunaLance),
|
||||
typeof(NightsKiss), typeof(NoxRangersHeavyCrossbow),
|
||||
typeof(OrcishVisage), typeof(PolarBearMask),
|
||||
typeof(ShieldOfInvulnerability), typeof(StaffOfPower),
|
||||
typeof(VioletCourage), typeof(HeartOfTheLion),
|
||||
typeof(WrathOfTheDryad), typeof(PixieSwatter),
|
||||
typeof(GlovesOfThePugilist)
|
||||
};
|
||||
|
||||
public static int Hue = 0x501; // Paragon hue
|
||||
|
||||
// Buffs
|
||||
public static double HitsBuff = 5.0;
|
||||
public static double StrBuff = 1.05;
|
||||
public static double IntBuff = 1.20;
|
||||
public static double DexBuff = 1.20;
|
||||
public static double SkillsBuff = 1.20;
|
||||
public static double SpeedBuff = 1.20;
|
||||
public static double FameBuff = 1.40;
|
||||
public static double KarmaBuff = 1.40;
|
||||
public static int DamageBuff = 5;
|
||||
|
||||
public static void Convert(BaseCreature bc)
|
||||
{
|
||||
if (bc.IsParagon)
|
||||
return;
|
||||
|
||||
bc.Hue = Hue;
|
||||
|
||||
if (bc.HitsMaxSeed >= 0)
|
||||
bc.HitsMaxSeed = (int)(bc.HitsMaxSeed * HitsBuff);
|
||||
|
||||
bc.RawStr = (int)(bc.RawStr * StrBuff);
|
||||
bc.RawInt = (int)(bc.RawInt * IntBuff);
|
||||
bc.RawDex = (int)(bc.RawDex * DexBuff);
|
||||
|
||||
bc.Hits = bc.HitsMax;
|
||||
bc.Mana = bc.ManaMax;
|
||||
bc.Stam = bc.StamMax;
|
||||
|
||||
for (int i = 0; i < bc.Skills.Length; i++)
|
||||
{
|
||||
Skill skill = bc.Skills[i];
|
||||
|
||||
if (skill.Base > 0.0)
|
||||
skill.Base *= SkillsBuff;
|
||||
}
|
||||
|
||||
bc.PassiveSpeed /= SpeedBuff;
|
||||
bc.ActiveSpeed /= SpeedBuff;
|
||||
bc.CurrentSpeed = bc.PassiveSpeed;
|
||||
|
||||
bc.DamageMin += DamageBuff;
|
||||
bc.DamageMax += DamageBuff;
|
||||
|
||||
if (bc.Fame > 0)
|
||||
bc.Fame = (int)(bc.Fame * FameBuff);
|
||||
|
||||
if (bc.Fame > 32000)
|
||||
bc.Fame = 32000;
|
||||
|
||||
// TODO: Mana regeneration rate = Sqrt( buffedFame ) / 4
|
||||
|
||||
if (bc.Karma != 0)
|
||||
{
|
||||
bc.Karma = (int)(bc.Karma * KarmaBuff);
|
||||
|
||||
if (Math.Abs(bc.Karma) > 32000)
|
||||
bc.Karma = 32000 * Math.Sign(bc.Karma);
|
||||
}
|
||||
|
||||
new ParagonStamRegen(bc).Start();
|
||||
}
|
||||
|
||||
public static void UnConvert(BaseCreature bc)
|
||||
{
|
||||
if (!bc.IsParagon)
|
||||
return;
|
||||
|
||||
bc.Hue = 0;
|
||||
|
||||
if (bc.HitsMaxSeed >= 0)
|
||||
bc.HitsMaxSeed = (int)(bc.HitsMaxSeed / HitsBuff);
|
||||
|
||||
bc.RawStr = (int)(bc.RawStr / StrBuff);
|
||||
bc.RawInt = (int)(bc.RawInt / IntBuff);
|
||||
bc.RawDex = (int)(bc.RawDex / DexBuff);
|
||||
|
||||
bc.Hits = bc.HitsMax;
|
||||
bc.Mana = bc.ManaMax;
|
||||
bc.Stam = bc.StamMax;
|
||||
|
||||
for (int i = 0; i < bc.Skills.Length; i++)
|
||||
{
|
||||
Skill skill = bc.Skills[i];
|
||||
|
||||
if (skill.Base > 0.0)
|
||||
skill.Base /= SkillsBuff;
|
||||
}
|
||||
|
||||
bc.PassiveSpeed *= SpeedBuff;
|
||||
bc.ActiveSpeed *= SpeedBuff;
|
||||
bc.CurrentSpeed = bc.PassiveSpeed;
|
||||
|
||||
bc.DamageMin -= DamageBuff;
|
||||
bc.DamageMax -= DamageBuff;
|
||||
|
||||
if (bc.Fame > 0)
|
||||
bc.Fame = (int)(bc.Fame / FameBuff);
|
||||
if (bc.Karma != 0)
|
||||
bc.Karma = (int)(bc.Karma / KarmaBuff);
|
||||
}
|
||||
|
||||
public static bool CheckConvert(BaseCreature bc)
|
||||
{
|
||||
return CheckConvert(bc, bc.Location, bc.Map);
|
||||
}
|
||||
|
||||
public static bool CheckConvert(BaseCreature bc, Point3D location, Map m)
|
||||
{
|
||||
if (!Core.AOS)
|
||||
return false;
|
||||
|
||||
if (Array.IndexOf(Maps, m) == -1)
|
||||
return false;
|
||||
|
||||
if (bc is BaseChampion || bc is Harrower || bc is BaseVendor || bc is BaseEscortable || bc is Clone ||
|
||||
bc.IsParagon)
|
||||
return false;
|
||||
|
||||
int fame = bc.Fame;
|
||||
|
||||
if (fame > 32000)
|
||||
fame = 32000;
|
||||
|
||||
double chance = 1 / Math.Round(20.0 - fame / 3200);
|
||||
|
||||
return chance > Utility.RandomDouble();
|
||||
}
|
||||
|
||||
public static bool CheckArtifactChance(Mobile m, BaseCreature bc)
|
||||
{
|
||||
if (!Core.AOS)
|
||||
return false;
|
||||
|
||||
double fame = bc.Fame;
|
||||
|
||||
if (fame > 32000)
|
||||
fame = 32000;
|
||||
|
||||
double chance =
|
||||
1 / (Math.Max(10, 100 * (0.83 - Math.Round(Math.Log(Math.Round(fame / 6000, 3) + 0.001, 10), 3))) *
|
||||
(100 - Math.Sqrt(m.Luck)) / 100.0);
|
||||
|
||||
return chance > Utility.RandomDouble();
|
||||
}
|
||||
|
||||
public static void GiveArtifactTo(Mobile m)
|
||||
{
|
||||
Item item = (Item)Activator.CreateInstance(Artifacts[Utility.Random(Artifacts.Length)]);
|
||||
|
||||
if (m.AddToBackpack(item))
|
||||
m.SendMessage("As a reward for slaying the mighty paragon, an artifact has been placed in your backpack.");
|
||||
else
|
||||
m.SendMessage(
|
||||
"As your backpack is full, your reward for destroying the legendary paragon has been placed at your feet.");
|
||||
}
|
||||
|
||||
private class ParagonStamRegen : Timer
|
||||
{
|
||||
private BaseCreature m_Owner;
|
||||
|
||||
public ParagonStamRegen(Mobile m)
|
||||
: base(FastRegenRate, FastRegenRate)
|
||||
{
|
||||
Priority = TimerPriority.FiftyMS;
|
||||
|
||||
m_Owner = m as BaseCreature;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (!m_Owner.Deleted && m_Owner.IsParagon && m_Owner.Map != Map.Internal)
|
||||
{
|
||||
m_Owner.Stam++;
|
||||
|
||||
Delay = Interval = m_Owner.Stam < m_Owner.StamMax * .75 ? FastRegenRate : CPUSaverRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
166
Projects/Scripts/Mobiles/Special/Rikktor.cs
Normal file
166
Projects/Scripts/Mobiles/Special/Rikktor.cs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
using System;
|
||||
using Server.Engines.CannedEvil;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Rikktor : BaseChampion
|
||||
{
|
||||
[Constructible]
|
||||
public Rikktor() : base(AIType.AI_Melee)
|
||||
{
|
||||
Body = 172;
|
||||
|
||||
SetStr(701, 900);
|
||||
SetDex(201, 350);
|
||||
SetInt(51, 100);
|
||||
|
||||
SetHits(3000);
|
||||
SetStam(203, 650);
|
||||
|
||||
SetDamage(28, 55);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 25);
|
||||
SetDamageType(ResistanceType.Fire, 50);
|
||||
SetDamageType(ResistanceType.Energy, 25);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 80, 90);
|
||||
SetResistance(ResistanceType.Fire, 80, 90);
|
||||
SetResistance(ResistanceType.Cold, 30, 40);
|
||||
SetResistance(ResistanceType.Poison, 80, 90);
|
||||
SetResistance(ResistanceType.Energy, 80, 90);
|
||||
|
||||
SetSkill(SkillName.Anatomy, 100.0);
|
||||
SetSkill(SkillName.MagicResist, 140.2, 160.0);
|
||||
SetSkill(SkillName.Tactics, 100.0);
|
||||
|
||||
Fame = 22500;
|
||||
Karma = -22500;
|
||||
|
||||
VirtualArmor = 130;
|
||||
}
|
||||
|
||||
public Rikktor(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override ChampionSkullType SkullType => ChampionSkullType.Power;
|
||||
|
||||
public override Type[] UniqueList => new[] { typeof(CrownOfTalKeesh) };
|
||||
|
||||
public override Type[] SharedList => new[]
|
||||
{
|
||||
typeof(TheMostKnowledgePerson),
|
||||
typeof(BraveKnightOfTheBritannia),
|
||||
typeof(LieutenantOfTheBritannianRoyalGuard)
|
||||
};
|
||||
|
||||
public override Type[] DecorativeList => new[]
|
||||
{
|
||||
typeof(LavaTile),
|
||||
typeof(MonsterStatuette),
|
||||
typeof(MonsterStatuette)
|
||||
};
|
||||
|
||||
public override MonsterStatuetteType[] StatueTypes => new[]
|
||||
{
|
||||
MonsterStatuetteType.OphidianArchMage,
|
||||
MonsterStatuetteType.OphidianWarrior
|
||||
};
|
||||
|
||||
public override string DefaultName => "Rikktor";
|
||||
|
||||
public override Poison PoisonImmune => Poison.Lethal;
|
||||
public override ScaleType ScaleType => ScaleType.All;
|
||||
public override int Scales => 20;
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.UltraRich, 4);
|
||||
}
|
||||
|
||||
public override void OnGaveMeleeAttack(Mobile defender)
|
||||
{
|
||||
base.OnGaveMeleeAttack(defender);
|
||||
|
||||
if (0.2 >= Utility.RandomDouble())
|
||||
Earthquake();
|
||||
}
|
||||
|
||||
public void Earthquake()
|
||||
{
|
||||
Map map = Map;
|
||||
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
PlaySound(0x2F3);
|
||||
|
||||
IPooledEnumerable<Mobile> eable = GetMobilesInRange<Mobile>(8);
|
||||
|
||||
foreach (Mobile m in eable)
|
||||
{
|
||||
if (m == this || !(CanBeHarmful(m) || m.Player && m.Alive))
|
||||
continue;
|
||||
|
||||
if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team))
|
||||
continue;
|
||||
|
||||
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); // take hit
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
public override int GetAngerSound()
|
||||
{
|
||||
return Utility.Random(0x2CE, 2);
|
||||
}
|
||||
|
||||
public override int GetIdleSound()
|
||||
{
|
||||
return 0x2D2;
|
||||
}
|
||||
|
||||
public override int GetAttackSound()
|
||||
{
|
||||
return Utility.Random(0x2C7, 5);
|
||||
}
|
||||
|
||||
public override int GetHurtSound()
|
||||
{
|
||||
return 0x2D1;
|
||||
}
|
||||
|
||||
public override int GetDeathSound()
|
||||
{
|
||||
return 0x2CC;
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
143
Projects/Scripts/Mobiles/Special/Semidar.cs
Normal file
143
Projects/Scripts/Mobiles/Special/Semidar.cs
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
using System;
|
||||
using Server.Engines.CannedEvil;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Semidar : BaseChampion
|
||||
{
|
||||
[Constructible]
|
||||
public Semidar() : base(AIType.AI_Mage)
|
||||
{
|
||||
Body = 174;
|
||||
BaseSoundID = 0x4B0;
|
||||
|
||||
SetStr(502, 600);
|
||||
SetDex(102, 200);
|
||||
SetInt(601, 750);
|
||||
|
||||
SetHits(1500);
|
||||
SetStam(103, 250);
|
||||
|
||||
SetDamage(29, 35);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 75);
|
||||
SetDamageType(ResistanceType.Fire, 25);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 20, 30);
|
||||
SetResistance(ResistanceType.Fire, 50, 60);
|
||||
SetResistance(ResistanceType.Cold, 20, 30);
|
||||
SetResistance(ResistanceType.Poison, 20, 30);
|
||||
SetResistance(ResistanceType.Energy, 10, 20);
|
||||
|
||||
SetSkill(SkillName.EvalInt, 95.1, 100.0);
|
||||
SetSkill(SkillName.Magery, 90.1, 105.0);
|
||||
SetSkill(SkillName.Meditation, 95.1, 100.0);
|
||||
SetSkill(SkillName.MagicResist, 120.2, 140.0);
|
||||
SetSkill(SkillName.Tactics, 90.1, 105.0);
|
||||
SetSkill(SkillName.Wrestling, 90.1, 105.0);
|
||||
|
||||
Fame = 24000;
|
||||
Karma = -24000;
|
||||
|
||||
VirtualArmor = 20;
|
||||
}
|
||||
|
||||
public Semidar(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override ChampionSkullType SkullType => ChampionSkullType.Pain;
|
||||
|
||||
public override Type[] UniqueList => new[] { typeof(GladiatorsCollar) };
|
||||
|
||||
public override Type[] SharedList => new[]
|
||||
{ typeof(RoyalGuardSurvivalKnife), typeof(ANecromancerShroud), typeof(LieutenantOfTheBritannianRoyalGuard) };
|
||||
|
||||
public override Type[] DecorativeList => new[] { typeof(LavaTile), typeof(DemonSkull) };
|
||||
|
||||
public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { };
|
||||
|
||||
public override string DefaultName => "Semidar";
|
||||
|
||||
public override bool Unprovokable => true;
|
||||
public override Poison PoisonImmune => Poison.Lethal;
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.UltraRich, 4);
|
||||
AddLoot(LootPack.FilthyRich);
|
||||
}
|
||||
|
||||
public override void CheckReflect(Mobile caster, ref bool reflect)
|
||||
{
|
||||
if (caster.Body.IsMale)
|
||||
reflect = true; // Always reflect if caster isn't female
|
||||
}
|
||||
|
||||
public override void AlterDamageScalarFrom(Mobile caster, ref double scalar)
|
||||
{
|
||||
if (caster.Body.IsMale)
|
||||
scalar = 20; // Male bodies always reflect.. damage scaled 20x
|
||||
}
|
||||
|
||||
public void DrainLife()
|
||||
{
|
||||
if (Map == null)
|
||||
return;
|
||||
|
||||
IPooledEnumerable<Mobile> eable = GetMobilesInRange<Mobile>(2);
|
||||
|
||||
foreach (Mobile m in eable)
|
||||
{
|
||||
if (m == this || !(CanBeHarmful(m) || m.Player && m.Alive))
|
||||
continue;
|
||||
|
||||
if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team))
|
||||
continue;
|
||||
|
||||
DoHarmful(m);
|
||||
|
||||
m.FixedParticles(0x374A, 10, 15, 5013, 0x496, 0, EffectLayer.Waist);
|
||||
m.PlaySound(0x231);
|
||||
|
||||
m.SendMessage("You feel the life drain out of you!");
|
||||
|
||||
int toDrain = Utility.RandomMinMax(10, 40);
|
||||
|
||||
Hits += toDrain;
|
||||
m.Damage(toDrain, this);
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
public override void OnGaveMeleeAttack(Mobile defender)
|
||||
{
|
||||
base.OnGaveMeleeAttack(defender);
|
||||
|
||||
if (0.25 >= Utility.RandomDouble())
|
||||
DrainLife();
|
||||
}
|
||||
|
||||
public override void OnGotMeleeAttack(Mobile attacker)
|
||||
{
|
||||
base.OnGotMeleeAttack(attacker);
|
||||
|
||||
if (0.25 >= Utility.RandomDouble())
|
||||
DrainLife();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
185
Projects/Scripts/Mobiles/Special/Serado.cs
Normal file
185
Projects/Scripts/Mobiles/Special/Serado.cs
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
using System;
|
||||
using Server.Engines.CannedEvil;
|
||||
using Server.Engines.Plants;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Serado : BaseChampion
|
||||
{
|
||||
[Constructible]
|
||||
public Serado() : base(AIType.AI_Melee)
|
||||
{
|
||||
Title = "the awakened";
|
||||
|
||||
Body = 249;
|
||||
Hue = 0x96C;
|
||||
|
||||
SetStr(1000);
|
||||
SetDex(150);
|
||||
SetInt(300);
|
||||
|
||||
SetHits(9000);
|
||||
SetMana(300);
|
||||
|
||||
SetDamage(29, 35);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 70);
|
||||
SetDamageType(ResistanceType.Poison, 20);
|
||||
SetDamageType(ResistanceType.Energy, 10);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 30);
|
||||
SetResistance(ResistanceType.Fire, 60);
|
||||
SetResistance(ResistanceType.Cold, 60);
|
||||
SetResistance(ResistanceType.Poison, 90);
|
||||
SetResistance(ResistanceType.Energy, 50);
|
||||
|
||||
SetSkill(SkillName.MagicResist, 120.0);
|
||||
SetSkill(SkillName.Tactics, 120.0);
|
||||
SetSkill(SkillName.Wrestling, 70.0);
|
||||
SetSkill(SkillName.Poisoning, 150.0);
|
||||
|
||||
Fame = 22500;
|
||||
Karma = -22500;
|
||||
|
||||
PackItem(Seed.RandomBonsaiSeed());
|
||||
}
|
||||
|
||||
public Serado(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override ChampionSkullType SkullType => ChampionSkullType.Power;
|
||||
|
||||
public override Type[] UniqueList => new[] { typeof(Pacify) };
|
||||
|
||||
public override Type[] SharedList => new[]
|
||||
{
|
||||
typeof(BraveKnightOfTheBritannia),
|
||||
typeof(DetectiveBoots),
|
||||
typeof(EmbroideredOakLeafCloak),
|
||||
typeof(LieutenantOfTheBritannianRoyalGuard)
|
||||
};
|
||||
|
||||
public override Type[] DecorativeList => new[] { typeof(Futon), typeof(SwampTile) };
|
||||
|
||||
public override MonsterStatuetteType[] StatueTypes => new MonsterStatuetteType[] { };
|
||||
|
||||
public override string DefaultName => "Serado";
|
||||
|
||||
public override int TreasureMapLevel => 5;
|
||||
|
||||
public override Poison HitPoison => Poison.Lethal;
|
||||
public override Poison PoisonImmune => Poison.Lethal;
|
||||
public override double HitPoisonChance => 0.8;
|
||||
|
||||
public override int Feathers => 30;
|
||||
|
||||
public override bool ShowFameTitle => false;
|
||||
public override bool ClickTitle => false;
|
||||
|
||||
public override WeaponAbility GetWeaponAbility()
|
||||
{
|
||||
return WeaponAbility.DoubleStrike;
|
||||
}
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.UltraRich, 4);
|
||||
AddLoot(LootPack.FilthyRich);
|
||||
AddLoot(LootPack.Gems, 6);
|
||||
}
|
||||
|
||||
// TODO: Hit Lightning Area
|
||||
|
||||
public override void OnDamagedBySpell(Mobile attacker)
|
||||
{
|
||||
base.OnDamagedBySpell(attacker);
|
||||
|
||||
ScaleResistances();
|
||||
DoCounter(attacker);
|
||||
}
|
||||
|
||||
public override void OnGotMeleeAttack(Mobile attacker)
|
||||
{
|
||||
base.OnGotMeleeAttack(attacker);
|
||||
|
||||
ScaleResistances();
|
||||
DoCounter(attacker);
|
||||
}
|
||||
|
||||
private void ScaleResistances()
|
||||
{
|
||||
double hitsLost = (HitsMax - Hits) / (double)HitsMax;
|
||||
|
||||
SetResistance(ResistanceType.Physical, 30 + (int)(hitsLost * (95 - 30)));
|
||||
SetResistance(ResistanceType.Fire, 60 + (int)(hitsLost * (95 - 60)));
|
||||
SetResistance(ResistanceType.Cold, 60 + (int)(hitsLost * (95 - 60)));
|
||||
SetResistance(ResistanceType.Poison, 90 + (int)(hitsLost * (95 - 90)));
|
||||
SetResistance(ResistanceType.Energy, 50 + (int)(hitsLost * (95 - 50)));
|
||||
}
|
||||
|
||||
private void DoCounter(Mobile attacker)
|
||||
{
|
||||
if (Map == null)
|
||||
return;
|
||||
|
||||
if (!(0.2 > Utility.RandomDouble()))
|
||||
return;
|
||||
|
||||
Mobile target = null;
|
||||
|
||||
if (attacker is BaseCreature bcAttacker)
|
||||
{
|
||||
if (bcAttacker.BardProvoked)
|
||||
return;
|
||||
|
||||
target = bcAttacker.GetMaster();
|
||||
}
|
||||
|
||||
/* Counterattack with Hit Poison Area
|
||||
* 20-25 damage, unresistable
|
||||
* Lethal poison, 100% of the time
|
||||
* Particle effect: Type: "2" From: "0x4061A107" To: "0x0" ItemId: "0x36BD" ItemIdName: "explosion" FromLocation: "(296 615, 17)" ToLocation: "(296 615, 17)" Speed: "1" Duration: "10" FixedDirection: "True" Explode: "False" Hue: "0xA6" RenderMode: "0x0" Effect: "0x1F78" ExplodeEffect: "0x1" ExplodeSound: "0x0" Serial: "0x4061A107" Layer: "255" Unknown: "0x0"
|
||||
* Doesn't work on provoked monsters
|
||||
*/
|
||||
|
||||
if (target?.InRange(this, 25) != true)
|
||||
target = attacker;
|
||||
|
||||
Animate(10, 4, 1, true, false, 0);
|
||||
|
||||
IPooledEnumerable<Mobile> eable = target.GetMobilesInRange<Mobile>(8);
|
||||
|
||||
foreach (Mobile m in eable)
|
||||
{
|
||||
if (m == this || !(CanBeHarmful(m) || m.Player && m.Alive))
|
||||
continue;
|
||||
|
||||
if (!(m is BaseCreature bc) || !(bc.Controlled || bc.Summoned || bc.Team != Team))
|
||||
continue;
|
||||
|
||||
DoHarmful(m);
|
||||
|
||||
AOS.Damage(m, this, Utility.RandomMinMax(20, 25), true, 0, 0, 0, 100, 0);
|
||||
|
||||
m.FixedParticles(0x36BD, 1, 10, 0x1F78, 0xA6, 0, (EffectLayer)255);
|
||||
m.ApplyPoison(this, Poison.Lethal);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
47
Projects/Scripts/Mobiles/Special/ServantOfSemidar.cs
Normal file
47
Projects/Scripts/Mobiles/Special/ServantOfSemidar.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
namespace Server.Mobiles
|
||||
{
|
||||
public class ServantOfSemidar : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public ServantOfSemidar() : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
Body = 0x26;
|
||||
}
|
||||
|
||||
public ServantOfSemidar(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "a Servant of Semidar";
|
||||
|
||||
public override bool DisallowAllMoves => true;
|
||||
|
||||
public override bool InitialInnocent => true;
|
||||
|
||||
public override bool CanBeDamaged()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
|
||||
list.Add(1005494); // enslaved
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
114
Projects/Scripts/Mobiles/Special/Silvani.cs
Normal file
114
Projects/Scripts/Mobiles/Special/Silvani.cs
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
namespace Server.Mobiles
|
||||
{
|
||||
public class Silvani : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Silvani() : base(AIType.AI_Mage, FightMode.Evil, 18, 1, 0.1, 0.2)
|
||||
{
|
||||
Body = 176;
|
||||
BaseSoundID = 0x467;
|
||||
|
||||
SetStr(253, 400);
|
||||
SetDex(157, 850);
|
||||
SetInt(503, 800);
|
||||
|
||||
SetHits(600);
|
||||
|
||||
SetDamage(27, 38);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 75);
|
||||
SetDamageType(ResistanceType.Cold, 25);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 45, 55);
|
||||
SetResistance(ResistanceType.Fire, 30, 40);
|
||||
SetResistance(ResistanceType.Cold, 30, 40);
|
||||
SetResistance(ResistanceType.Poison, 40, 50);
|
||||
SetResistance(ResistanceType.Energy, 40, 50);
|
||||
|
||||
SetSkill(SkillName.EvalInt, 100.0);
|
||||
SetSkill(SkillName.Magery, 97.6, 107.5);
|
||||
SetSkill(SkillName.Meditation, 100.0);
|
||||
SetSkill(SkillName.MagicResist, 100.5, 150.0);
|
||||
SetSkill(SkillName.Tactics, 97.6, 100.0);
|
||||
SetSkill(SkillName.Wrestling, 97.6, 100.0);
|
||||
|
||||
Fame = 20000;
|
||||
Karma = 20000;
|
||||
|
||||
VirtualArmor = 50;
|
||||
}
|
||||
|
||||
public Silvani(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Silvani";
|
||||
|
||||
public override OppositionGroup OppositionGroup => OppositionGroup.FeyAndUndead;
|
||||
|
||||
public override bool CanFly => true;
|
||||
public override bool Unprovokable => true;
|
||||
public override Poison PoisonImmune => Poison.Regular;
|
||||
public override int TreasureMapLevel => 5;
|
||||
|
||||
public override void GenerateLoot()
|
||||
{
|
||||
AddLoot(LootPack.UltraRich, 2);
|
||||
}
|
||||
|
||||
public void SpawnPixies(Mobile target)
|
||||
{
|
||||
Map map = Map;
|
||||
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
int newPixies = Utility.RandomMinMax(3, 6);
|
||||
|
||||
for (int i = 0; i < newPixies; ++i)
|
||||
{
|
||||
Pixie pixie = new Pixie { Team = Team, FightMode = FightMode.Closest };
|
||||
|
||||
pixie.MoveToWorld(map.GetRandomNearbyLocation(Location), map);
|
||||
pixie.Combatant = target;
|
||||
}
|
||||
}
|
||||
|
||||
public override void AlterDamageScalarFrom(Mobile caster, ref double scalar)
|
||||
{
|
||||
if (0.1 >= Utility.RandomDouble())
|
||||
SpawnPixies(caster);
|
||||
}
|
||||
|
||||
public override void OnGaveMeleeAttack(Mobile defender)
|
||||
{
|
||||
base.OnGaveMeleeAttack(defender);
|
||||
|
||||
defender.Damage(Utility.Random(20, 10), this);
|
||||
defender.Stam -= Utility.Random(20, 10);
|
||||
defender.Mana -= Utility.Random(20, 10);
|
||||
}
|
||||
|
||||
public override void OnGotMeleeAttack(Mobile attacker)
|
||||
{
|
||||
base.OnGotMeleeAttack(attacker);
|
||||
|
||||
if (0.1 >= Utility.RandomDouble())
|
||||
SpawnPixies(attacker);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Projects/Scripts/Mobiles/Special/Wanderer.cs
Normal file
65
Projects/Scripts/Mobiles/Special/Wanderer.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Wanderer : Mobile
|
||||
{
|
||||
private Timer m_Timer;
|
||||
|
||||
[Constructible]
|
||||
public Wanderer()
|
||||
{
|
||||
Name = "Me";
|
||||
Body = 0x1;
|
||||
AccessLevel = AccessLevel.Counselor;
|
||||
|
||||
m_Timer = new InternalTimer(this);
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
public Wanderer(Serial serial) : base(serial)
|
||||
{
|
||||
m_Timer = new InternalTimer(this);
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
public override void OnDelete()
|
||||
{
|
||||
m_Timer.Stop();
|
||||
|
||||
base.OnDelete();
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private int m_Count;
|
||||
private Wanderer m_Owner;
|
||||
|
||||
public InternalTimer(Wanderer owner) : base(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.1))
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if ((m_Count++ & 0x3) == 0) m_Owner.Direction = (Direction)(Utility.Random(8) | 0x80);
|
||||
|
||||
m_Owner.Move(m_Owner.Direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue