* Movie ignore mobiles to Mobile class * Allow necromancer familiars to ignore mobiles * ChampionSpawn should not quietly fail when creating new spawn * Fix client party crash bug: 2 people partied, the leader logs out, other client is hung * Fix spellbooks creating with magery/meditation only and creating magery multiple times * Fix BaseRunicTool.GetRandomSlayer() creating more undead slayers than intended * Do not allow players to dismount each other whilst mounted * Fix AOS onwards damage increase tooltip and wrong formula in AOS * Fix monsters killing other monster revenants + animate dead should not attack player pets + other animates * Fix fire steed having loot pack added twice * Fix oaks spawn not able to create Unicorns + Kirins via Activator.CreateInstace() due to constructor having name as parametr * Fix ignoreMobiles flag not propagated to client for non-players. * Fix harrower tents not leeching from players * Fix boats speedhacking around the map * Fix bless, agility etc. not renewing duration * Fix reveal always worked * Fix empty constructor for steeds so they don't throw now.
502 lines
18 KiB
C#
502 lines
18 KiB
C#
using System;
|
|
using Server.Mobiles;
|
|
|
|
namespace Server.Items
|
|
{
|
|
public class SlayerGroup
|
|
{
|
|
static SlayerGroup()
|
|
{
|
|
var humanoid = new SlayerGroup();
|
|
var undead = new SlayerGroup();
|
|
var elemental = new SlayerGroup();
|
|
var abyss = new SlayerGroup();
|
|
var arachnid = new SlayerGroup();
|
|
var reptilian = new SlayerGroup();
|
|
var fey = new SlayerGroup();
|
|
|
|
humanoid.Opposition = new[] { undead };
|
|
humanoid.FoundOn = new[] { typeof(BoneKnight), typeof(Lich), typeof(LichLord) };
|
|
humanoid.Super = new SlayerEntry(
|
|
SlayerName.Repond,
|
|
typeof(ArcticOgreLord),
|
|
typeof(Cyclops),
|
|
typeof(Ettin),
|
|
typeof(EvilMage),
|
|
typeof(EvilMageLord),
|
|
typeof(FrostTroll),
|
|
typeof(MeerCaptain),
|
|
typeof(MeerEternal),
|
|
typeof(MeerMage),
|
|
typeof(MeerWarrior),
|
|
typeof(Ogre),
|
|
typeof(OgreLord),
|
|
typeof(Orc),
|
|
typeof(OrcBomber),
|
|
typeof(OrcBrute),
|
|
typeof(OrcCaptain), /*typeof( OrcChopper ), typeof( OrcScout ),*/
|
|
typeof(OrcishLord),
|
|
typeof(OrcishMage),
|
|
typeof(Ratman),
|
|
typeof(RatmanArcher),
|
|
typeof(RatmanMage),
|
|
typeof(SavageRider),
|
|
typeof(SavageShaman),
|
|
typeof(Savage),
|
|
typeof(Titan),
|
|
typeof(Troglodyte),
|
|
typeof(Troll)
|
|
);
|
|
humanoid.Entries = new[]
|
|
{
|
|
new SlayerEntry(SlayerName.OgreTrashing, typeof(Ogre), typeof(OgreLord), typeof(ArcticOgreLord)),
|
|
new SlayerEntry(
|
|
SlayerName.OrcSlaying,
|
|
typeof(Orc),
|
|
typeof(OrcBomber),
|
|
typeof(OrcBrute),
|
|
typeof(OrcCaptain), /* typeof( OrcChopper ), typeof( OrcScout ),*/
|
|
typeof(OrcishLord),
|
|
typeof(OrcishMage)
|
|
),
|
|
new SlayerEntry(SlayerName.TrollSlaughter, typeof(Troll), typeof(FrostTroll))
|
|
};
|
|
|
|
undead.Opposition = new[] { humanoid };
|
|
undead.Super = new SlayerEntry(
|
|
SlayerName.Silver,
|
|
typeof(AncientLich),
|
|
typeof(Bogle),
|
|
typeof(BoneKnight),
|
|
typeof(BoneMagi), /* typeof( DarkGuardian ), */
|
|
typeof(DarknightCreeper),
|
|
typeof(FleshGolem),
|
|
typeof(Ghoul),
|
|
typeof(GoreFiend),
|
|
typeof(HellSteed),
|
|
typeof(LadyOfTheSnow),
|
|
typeof(Lich),
|
|
typeof(LichLord),
|
|
typeof(Mummy),
|
|
typeof(PestilentBandage),
|
|
typeof(Revenant),
|
|
typeof(RevenantLion),
|
|
typeof(RottingCorpse),
|
|
typeof(Shade),
|
|
typeof(ShadowKnight),
|
|
typeof(SkeletalKnight),
|
|
typeof(SkeletalMage),
|
|
typeof(SkeletalMount),
|
|
typeof(Skeleton),
|
|
typeof(Spectre),
|
|
typeof(Wraith),
|
|
typeof(Zombie)
|
|
);
|
|
undead.Entries = Array.Empty<SlayerEntry>();
|
|
|
|
fey.Opposition = new[] { abyss };
|
|
fey.Super = new SlayerEntry(
|
|
SlayerName.Fey,
|
|
typeof(Centaur),
|
|
typeof(CuSidhe),
|
|
typeof(EtherealWarrior),
|
|
typeof(Kirin),
|
|
typeof(LordOaks),
|
|
typeof(Pixie),
|
|
typeof(Silvani),
|
|
typeof(Treefellow),
|
|
typeof(Unicorn),
|
|
typeof(Wisp),
|
|
typeof(MLDryad),
|
|
typeof(Satyr)
|
|
);
|
|
fey.Entries = Array.Empty<SlayerEntry>();
|
|
|
|
elemental.Opposition = new[] { abyss };
|
|
elemental.FoundOn = new[] { typeof(Balron), typeof(Daemon) };
|
|
elemental.Super = new SlayerEntry(
|
|
SlayerName.ElementalBan,
|
|
typeof(AcidElemental),
|
|
typeof(AgapiteElemental),
|
|
typeof(AirElemental),
|
|
typeof(SummonedAirElemental),
|
|
typeof(BloodElemental),
|
|
typeof(BronzeElemental),
|
|
typeof(CopperElemental),
|
|
typeof(CrystalElemental),
|
|
typeof(DullCopperElemental),
|
|
typeof(EarthElemental),
|
|
typeof(SummonedEarthElemental),
|
|
typeof(Efreet),
|
|
typeof(FireElemental),
|
|
typeof(SummonedFireElemental),
|
|
typeof(GoldenElemental),
|
|
typeof(IceElemental),
|
|
typeof(KazeKemono),
|
|
typeof(PoisonElemental),
|
|
typeof(RaiJu),
|
|
typeof(SandVortex),
|
|
typeof(ShadowIronElemental),
|
|
typeof(SnowElemental),
|
|
typeof(ValoriteElemental),
|
|
typeof(VeriteElemental),
|
|
typeof(WaterElemental),
|
|
typeof(SummonedWaterElemental)
|
|
);
|
|
elemental.Entries = new[]
|
|
{
|
|
new SlayerEntry(SlayerName.BloodDrinking, typeof(BloodElemental)),
|
|
new SlayerEntry(
|
|
SlayerName.EarthShatter,
|
|
typeof(AgapiteElemental),
|
|
typeof(BronzeElemental),
|
|
typeof(CopperElemental),
|
|
typeof(DullCopperElemental),
|
|
typeof(EarthElemental),
|
|
typeof(SummonedEarthElemental),
|
|
typeof(GoldenElemental),
|
|
typeof(ShadowIronElemental),
|
|
typeof(ValoriteElemental),
|
|
typeof(VeriteElemental)
|
|
),
|
|
new SlayerEntry(SlayerName.ElementalHealth, typeof(PoisonElemental)),
|
|
new SlayerEntry(SlayerName.FlameDousing, typeof(FireElemental), typeof(SummonedFireElemental)),
|
|
new SlayerEntry(SlayerName.SummerWind, typeof(SnowElemental), typeof(IceElemental)),
|
|
new SlayerEntry(SlayerName.Vacuum, typeof(AirElemental), typeof(SummonedAirElemental)),
|
|
new SlayerEntry(SlayerName.WaterDissipation, typeof(WaterElemental), typeof(SummonedWaterElemental))
|
|
};
|
|
|
|
abyss.Opposition = new[] { elemental, fey };
|
|
abyss.FoundOn = new[] { typeof(BloodElemental) };
|
|
|
|
if (Core.AOS)
|
|
{
|
|
abyss.Super = new SlayerEntry(
|
|
SlayerName.Exorcism,
|
|
typeof(AbysmalHorror),
|
|
typeof(ArcaneDaemon),
|
|
typeof(Balron),
|
|
typeof(BoneDemon),
|
|
typeof(ChaosDaemon),
|
|
typeof(Daemon),
|
|
typeof(SummonedDaemon),
|
|
typeof(DemonKnight),
|
|
typeof(Devourer),
|
|
typeof(EnslavedGargoyle),
|
|
typeof(FanDancer),
|
|
typeof(FireGargoyle),
|
|
typeof(Gargoyle),
|
|
typeof(GargoyleDestroyer),
|
|
typeof(GargoyleEnforcer),
|
|
typeof(Gibberling),
|
|
typeof(HordeMinion),
|
|
typeof(IceFiend),
|
|
typeof(Imp),
|
|
typeof(Impaler),
|
|
typeof(Moloch),
|
|
typeof(Oni),
|
|
typeof(Ravager),
|
|
typeof(Semidar),
|
|
typeof(StoneGargoyle),
|
|
typeof(Succubus),
|
|
typeof(TsukiWolf)
|
|
);
|
|
|
|
abyss.Entries = new[]
|
|
{
|
|
// Daemon Dismissal & Balron Damnation have been removed and moved up to super slayer on OSI.
|
|
new SlayerEntry(
|
|
SlayerName.GargoylesFoe,
|
|
typeof(EnslavedGargoyle),
|
|
typeof(FireGargoyle),
|
|
typeof(Gargoyle),
|
|
typeof(GargoyleDestroyer),
|
|
typeof(GargoyleEnforcer),
|
|
typeof(StoneGargoyle)
|
|
)
|
|
};
|
|
}
|
|
else
|
|
{
|
|
abyss.Super = new SlayerEntry(
|
|
SlayerName.Exorcism,
|
|
typeof(AbysmalHorror),
|
|
typeof(Balron),
|
|
typeof(BoneDemon),
|
|
typeof(ChaosDaemon),
|
|
typeof(Daemon),
|
|
typeof(SummonedDaemon),
|
|
typeof(DemonKnight),
|
|
typeof(Devourer),
|
|
typeof(Gargoyle),
|
|
typeof(FireGargoyle),
|
|
typeof(Gibberling),
|
|
typeof(HordeMinion),
|
|
typeof(IceFiend),
|
|
typeof(Imp),
|
|
typeof(Impaler),
|
|
typeof(Ravager),
|
|
typeof(StoneGargoyle),
|
|
typeof(ArcaneDaemon),
|
|
typeof(EnslavedGargoyle),
|
|
typeof(GargoyleDestroyer),
|
|
typeof(GargoyleEnforcer),
|
|
typeof(Moloch)
|
|
);
|
|
|
|
abyss.Entries = new[]
|
|
{
|
|
new SlayerEntry(
|
|
SlayerName.DaemonDismissal,
|
|
typeof(AbysmalHorror),
|
|
typeof(Balron),
|
|
typeof(BoneDemon),
|
|
typeof(ChaosDaemon),
|
|
typeof(Daemon),
|
|
typeof(SummonedDaemon),
|
|
typeof(DemonKnight),
|
|
typeof(Devourer),
|
|
typeof(Gibberling),
|
|
typeof(HordeMinion),
|
|
typeof(IceFiend),
|
|
typeof(Imp),
|
|
typeof(Impaler),
|
|
typeof(Ravager),
|
|
typeof(ArcaneDaemon),
|
|
typeof(Moloch)
|
|
),
|
|
new SlayerEntry(
|
|
SlayerName.GargoylesFoe,
|
|
typeof(FireGargoyle),
|
|
typeof(Gargoyle),
|
|
typeof(StoneGargoyle),
|
|
typeof(EnslavedGargoyle),
|
|
typeof(GargoyleDestroyer),
|
|
typeof(GargoyleEnforcer)
|
|
),
|
|
new SlayerEntry(SlayerName.BalronDamnation, typeof(Balron))
|
|
};
|
|
}
|
|
|
|
arachnid.Opposition = new[] { reptilian };
|
|
arachnid.FoundOn = new[]
|
|
{
|
|
typeof(AncientWyrm), typeof(GreaterDragon), typeof(Dragon), typeof(OphidianMatriarch), typeof(ShadowWyrm)
|
|
};
|
|
arachnid.Super = new SlayerEntry(
|
|
SlayerName.ArachnidDoom,
|
|
typeof(DreadSpider),
|
|
typeof(FrostSpider),
|
|
typeof(GiantBlackWidow),
|
|
typeof(GiantSpider),
|
|
typeof(Mephitis),
|
|
typeof(Scorpion),
|
|
typeof(TerathanAvenger),
|
|
typeof(TerathanDrone),
|
|
typeof(TerathanMatriarch),
|
|
typeof(TerathanWarrior)
|
|
);
|
|
arachnid.Entries = new[]
|
|
{
|
|
new SlayerEntry(SlayerName.ScorpionsBane, typeof(Scorpion)),
|
|
new SlayerEntry(
|
|
SlayerName.SpidersDeath,
|
|
typeof(DreadSpider),
|
|
typeof(FrostSpider),
|
|
typeof(GiantBlackWidow),
|
|
typeof(GiantSpider),
|
|
typeof(Mephitis)
|
|
),
|
|
new SlayerEntry(
|
|
SlayerName.Terathan,
|
|
typeof(TerathanAvenger),
|
|
typeof(TerathanDrone),
|
|
typeof(TerathanMatriarch),
|
|
typeof(TerathanWarrior)
|
|
)
|
|
};
|
|
|
|
reptilian.Opposition = new[] { arachnid };
|
|
reptilian.FoundOn = new[] { typeof(TerathanAvenger), typeof(TerathanMatriarch) };
|
|
reptilian.Super = new SlayerEntry(
|
|
SlayerName.ReptilianDeath,
|
|
typeof(AncientWyrm),
|
|
typeof(DeepSeaSerpent),
|
|
typeof(GreaterDragon),
|
|
typeof(Dragon),
|
|
typeof(Drake),
|
|
typeof(GiantIceWorm),
|
|
typeof(IceSerpent),
|
|
typeof(GiantSerpent),
|
|
typeof(Hiryu),
|
|
typeof(IceSnake),
|
|
typeof(JukaLord),
|
|
typeof(JukaMage),
|
|
typeof(JukaWarrior),
|
|
typeof(LavaSerpent),
|
|
typeof(LavaSnake),
|
|
typeof(LesserHiryu),
|
|
typeof(Lizardman),
|
|
typeof(OphidianArchmage),
|
|
typeof(OphidianKnight),
|
|
typeof(OphidianMage),
|
|
typeof(OphidianMatriarch),
|
|
typeof(OphidianWarrior),
|
|
typeof(Reptalon),
|
|
typeof(SeaSerpent),
|
|
typeof(Serado),
|
|
typeof(SerpentineDragon),
|
|
typeof(ShadowWyrm),
|
|
typeof(SilverSerpent),
|
|
typeof(SkeletalDragon),
|
|
typeof(Snake),
|
|
typeof(SwampDragon),
|
|
typeof(WhiteWyrm),
|
|
typeof(Wyvern),
|
|
typeof(Yamandon)
|
|
);
|
|
reptilian.Entries = new[]
|
|
{
|
|
new SlayerEntry(
|
|
SlayerName.DragonSlaying,
|
|
typeof(AncientWyrm),
|
|
typeof(GreaterDragon),
|
|
typeof(Dragon),
|
|
typeof(Drake),
|
|
typeof(Hiryu),
|
|
typeof(LesserHiryu),
|
|
typeof(Reptalon),
|
|
typeof(SerpentineDragon),
|
|
typeof(ShadowWyrm),
|
|
typeof(SkeletalDragon),
|
|
typeof(SwampDragon),
|
|
typeof(WhiteWyrm),
|
|
typeof(Wyvern)
|
|
),
|
|
new SlayerEntry(SlayerName.LizardmanSlaughter, typeof(Lizardman)),
|
|
new SlayerEntry(
|
|
SlayerName.Ophidian,
|
|
typeof(OphidianArchmage),
|
|
typeof(OphidianKnight),
|
|
typeof(OphidianMage),
|
|
typeof(OphidianMatriarch),
|
|
typeof(OphidianWarrior)
|
|
),
|
|
new SlayerEntry(
|
|
SlayerName.SnakesBane,
|
|
typeof(DeepSeaSerpent),
|
|
typeof(GiantIceWorm),
|
|
typeof(GiantSerpent),
|
|
typeof(IceSerpent),
|
|
typeof(IceSnake),
|
|
typeof(LavaSerpent),
|
|
typeof(LavaSnake),
|
|
typeof(SeaSerpent),
|
|
typeof(Serado),
|
|
typeof(SilverSerpent),
|
|
typeof(Snake),
|
|
typeof(Yamandon)
|
|
)
|
|
};
|
|
|
|
Groups = new[]
|
|
{
|
|
humanoid,
|
|
elemental,
|
|
abyss,
|
|
arachnid,
|
|
reptilian,
|
|
// Skip undead for minor slayers
|
|
undead,
|
|
// Skip fey for random slayer
|
|
fey
|
|
};
|
|
|
|
TotalEntries = CompileEntries(Groups);
|
|
}
|
|
|
|
public static SlayerEntry[] TotalEntries { get; }
|
|
|
|
public static SlayerGroup[] Groups { get; }
|
|
|
|
public SlayerGroup[] Opposition { get; set; }
|
|
|
|
public SlayerEntry Super { get; set; }
|
|
|
|
public SlayerEntry[] Entries { get; set; }
|
|
|
|
public Type[] FoundOn { get; set; }
|
|
|
|
public static SlayerEntry GetEntryByName(SlayerName name)
|
|
{
|
|
var v = (int)name;
|
|
|
|
if (v >= 0 && v < TotalEntries.Length)
|
|
{
|
|
return TotalEntries[v];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public static SlayerName GetLootSlayerType(Type type)
|
|
{
|
|
for (var i = 0; i < Groups.Length; ++i)
|
|
{
|
|
var group = Groups[i];
|
|
var foundOn = group.FoundOn;
|
|
|
|
var inGroup = false;
|
|
|
|
for (var j = 0; foundOn != null && !inGroup && j < foundOn.Length; ++j)
|
|
{
|
|
inGroup = foundOn[j] == type;
|
|
}
|
|
|
|
if (inGroup)
|
|
{
|
|
var index = Utility.Random(1 + group.Entries.Length);
|
|
|
|
return index == 0 ? group.Super.Name : group.Entries[index - 1].Name;
|
|
}
|
|
}
|
|
|
|
return SlayerName.Silver;
|
|
}
|
|
|
|
private static SlayerEntry[] CompileEntries(SlayerGroup[] groups)
|
|
{
|
|
var entries = new SlayerEntry[28];
|
|
|
|
for (var i = 0; i < groups.Length; ++i)
|
|
{
|
|
var g = groups[i];
|
|
|
|
g.Super.Group = g;
|
|
|
|
entries[(int)g.Super.Name] = g.Super;
|
|
|
|
for (var j = 0; j < g.Entries.Length; ++j)
|
|
{
|
|
g.Entries[j].Group = g;
|
|
entries[(int)g.Entries[j].Name] = g.Entries[j];
|
|
}
|
|
}
|
|
|
|
return entries;
|
|
}
|
|
|
|
public bool OppositionSuperSlays(Mobile m)
|
|
{
|
|
for (var i = 0; i < Opposition.Length; i++)
|
|
{
|
|
if (Opposition[i].Super.Slays(m))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
}
|