diff --git a/Projects/UOContent/Items/Weapons/SlayerGroup.cs b/Projects/UOContent/Items/Weapons/SlayerGroup.cs index b358431d0..87380978a 100644 --- a/Projects/UOContent/Items/Weapons/SlayerGroup.cs +++ b/Projects/UOContent/Items/Weapons/SlayerGroup.cs @@ -342,6 +342,7 @@ namespace Server.Items typeof(OphidianMage), typeof(OphidianMatriarch), typeof(OphidianWarrior), + typeof(Raptor), typeof(Reptalon), typeof(SeaSerpent), typeof(Serado), @@ -350,6 +351,9 @@ namespace Server.Items typeof(SilverSerpent), typeof(SkeletalDragon), typeof(Snake), + typeof(Slith), + typeof(StoneSlith), + typeof(ToxicSlith), typeof(SwampDragon), typeof(WhiteWyrm), typeof(Wyvern), diff --git a/Projects/UOContent/Items/Weapons/Throwing/RaptorClaw.cs b/Projects/UOContent/Items/Weapons/Throwing/RaptorClaw.cs new file mode 100644 index 000000000..9b3ed6a10 --- /dev/null +++ b/Projects/UOContent/Items/Weapons/Throwing/RaptorClaw.cs @@ -0,0 +1,23 @@ +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0)] +public partial class RaptorClaw : Boomerang +{ + [Constructible] + public RaptorClaw() + { + Hue = 53; + Attributes.AttackChance = 12; + Attributes.WeaponSpeed = 30; + Attributes.WeaponDamage = 35; + Slayer = SlayerName.Silver; + WeaponAttributes.HitLeechStam = 40; + } + + public override int LabelNumber => 1112394; // Raptor Claw + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; +} diff --git a/Projects/UOContent/Items/Weapons/Throwing/StoneSlithClaw.cs b/Projects/UOContent/Items/Weapons/Throwing/StoneSlithClaw.cs new file mode 100644 index 000000000..028253e0a --- /dev/null +++ b/Projects/UOContent/Items/Weapons/Throwing/StoneSlithClaw.cs @@ -0,0 +1,23 @@ +using ModernUO.Serialization; + +namespace Server.Items; + +[SerializationGenerator(0)] +public partial class StoneSlithClaw : Cyclone +{ + [Constructible] + public StoneSlithClaw() + { + Hue = 1150; + Attributes.WeaponSpeed = 25; + Attributes.WeaponDamage = 45; + Slayer = SlayerName.DaemonDismissal; + WeaponAttributes.HitHarm = 40; + WeaponAttributes.HitLowerDefend = 40; + } + + public override int LabelNumber => 1112393; // Stone Slith Claw + + public override int InitMinHits => 255; + public override int InitMaxHits => 255; +} diff --git a/Projects/UOContent/Migrations/Server.Items.RaptorClaw.v0.json b/Projects/UOContent/Migrations/Server.Items.RaptorClaw.v0.json new file mode 100644 index 000000000..8165371d4 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.RaptorClaw.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.RaptorClaw" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Items.StoneSlithClaw.v0.json b/Projects/UOContent/Migrations/Server.Items.StoneSlithClaw.v0.json new file mode 100644 index 000000000..f01d64da8 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Items.StoneSlithClaw.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Items.StoneSlithClaw" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Mobiles.Raptor.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.Raptor.v0.json new file mode 100644 index 000000000..4e2bcf4ab --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Mobiles.Raptor.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Mobiles.Raptor" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Mobiles.Slith.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.Slith.v0.json new file mode 100644 index 000000000..1254f919a --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Mobiles.Slith.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Mobiles.Slith" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Mobiles.StoneSlith.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.StoneSlith.v0.json new file mode 100644 index 000000000..58b5c4b1c --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Mobiles.StoneSlith.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Mobiles.StoneSlith" +} \ No newline at end of file diff --git a/Projects/UOContent/Migrations/Server.Mobiles.ToxicSlith.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.ToxicSlith.v0.json new file mode 100644 index 000000000..1184eca95 --- /dev/null +++ b/Projects/UOContent/Migrations/Server.Mobiles.ToxicSlith.v0.json @@ -0,0 +1,4 @@ +{ + "version": 0, + "type": "Server.Mobiles.ToxicSlith" +} \ No newline at end of file diff --git a/Projects/UOContent/Mobiles/Abilities/MonsterAbilities.cs b/Projects/UOContent/Mobiles/Abilities/MonsterAbilities.cs index 652bc5b05..0afdf05de 100644 --- a/Projects/UOContent/Mobiles/Abilities/MonsterAbilities.cs +++ b/Projects/UOContent/Mobiles/Abilities/MonsterAbilities.cs @@ -13,6 +13,7 @@ public static class MonsterAbilities // Resistance Debuffs public static GraspingClaw GraspingClaw => new(); + public static TailSwipe TailSwipe => new(); public static RuneCorruption RuneCorruption => new(); public static FanningFire FanningFire => new(0.05, -10, 35, 45); diff --git a/Projects/UOContent/Mobiles/Abilities/MonsterAbilityType.cs b/Projects/UOContent/Mobiles/Abilities/MonsterAbilityType.cs index 9f188243d..fe0fe46f4 100644 --- a/Projects/UOContent/Mobiles/Abilities/MonsterAbilityType.cs +++ b/Projects/UOContent/Mobiles/Abilities/MonsterAbilityType.cs @@ -20,5 +20,6 @@ public enum MonsterAbilityType FanningFire, // Fire debuff RuneCorruption, FanThrow, - BloodBath + BloodBath, + TailSwipe } diff --git a/Projects/UOContent/Mobiles/Abilities/TailSwipe.cs b/Projects/UOContent/Mobiles/Abilities/TailSwipe.cs new file mode 100644 index 000000000..9982355b2 --- /dev/null +++ b/Projects/UOContent/Mobiles/Abilities/TailSwipe.cs @@ -0,0 +1,35 @@ +using System; + +namespace Server.Mobiles; + +public class TailSwipe : MonsterAbilitySingleTarget +{ + public override MonsterAbilityType AbilityType => MonsterAbilityType.TailSwipe; + public override MonsterAbilityTrigger AbilityTrigger => MonsterAbilityTrigger.GiveMeleeDamage; + public override double ChanceToTrigger => 0.3; + + // ServUO's SpecialAbility base cooldown; TailSwipe does not override it. + public override TimeSpan MinTriggerCooldown => TimeSpan.FromSeconds(30); + public override TimeSpan MaxTriggerCooldown => TimeSpan.FromSeconds(30); + + protected override void OnTarget(MonsterAbilityTrigger trigger, BaseCreature source, Mobile defender) + { + source.DoHarmful(defender); + + defender.PlaySound(0x204); + defender.FixedEffect(0x376A, 6, 1); + + // OSI/Stratics reports roughly a 90% stun / 10% confuse split (ServUO's even 50/50 is incorrect). + if (Utility.RandomDouble() < 0.10) + { + defender.SendLocalizedMessage(1112555); // You're left confused as the creature's tail catches you right in the face! + defender.AddStatMod(new StatMod(StatType.Dex, "[TailSwipe] Dex", -20, TimeSpan.FromSeconds(5.0))); + defender.AddStatMod(new StatMod(StatType.Int, "[TailSwipe] Int", -20, TimeSpan.FromSeconds(5.0))); + } + else + { + defender.SendLocalizedMessage(1112554); // You're stunned as the creature's tail knocks the wind out of you. + defender.Paralyze(TimeSpan.FromSeconds(3.0)); + } + } +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Raptor.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Raptor.cs new file mode 100644 index 000000000..36c3088bb --- /dev/null +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Raptor.cs @@ -0,0 +1,76 @@ +using ModernUO.Serialization; +using Server.Items; + +namespace Server.Mobiles; + +[SerializationGenerator(0)] +public partial class Raptor : BaseCreature +{ + [Constructible] + public Raptor() : base(AIType.AI_Melee) + { + Body = 730; + + SetStr(404, 471); + SetDex(132, 155); + SetInt(105, 145); + + SetHits(343, 400); + + SetDamage(11, 17); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 45, 50); + SetResistance(ResistanceType.Fire, 50, 60); + SetResistance(ResistanceType.Cold, 40, 50); + SetResistance(ResistanceType.Poison, 20, 30); + SetResistance(ResistanceType.Energy, 30, 40); + + SetSkill(SkillName.MagicResist, 75.1, 90.0); + SetSkill(SkillName.Tactics, 75.1, 100.0); + SetSkill(SkillName.Wrestling, 70.1, 95.1); + + Fame = 7500; + Karma = -7500; + + Tamable = true; + MinTameSkill = 107.1; + ControlSlots = 2; + + // TODO(SA-creatures): ServUO Raptors summon up to 2 "friend" raptors on entering combat + // (InternalTimer/CheckFriends). Omitted pending a ModernUO timer/MonsterAbility adaptation. + // Also unported vs ServUO: the 25% AncientPotteryFragments corpse drop (item class not yet in ModernUO). + } + + public override string CorpseName => "a raptor corpse"; + public override string DefaultName => "a raptor"; + + public override int TreasureMapLevel => 3; + public override int Meat => 7; + public override int Hides => 11; + public override HideType HideType => HideType.Horned; + public override PackInstinct PackInstinct => PackInstinct.Ostard; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; + + public override int GetIdleSound() => 1573; + public override int GetAngerSound() => 1570; + public override int GetHurtSound() => 1572; + public override int GetDeathSound() => 1571; + + public override void GenerateLoot() + { + AddLoot(LootPack.Rich, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (!Controlled && Utility.RandomDouble() <= 0.005) + { + c.DropItem(new RaptorClaw()); + } + } +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/Slith.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Slith.cs new file mode 100644 index 000000000..90178101e --- /dev/null +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Slith.cs @@ -0,0 +1,56 @@ +using ModernUO.Serialization; + +namespace Server.Mobiles; + +[SerializationGenerator(0)] +public partial class Slith : BaseCreature +{ + // ServUO SpecialAbility.DragonBreath -> closest ModernUO monster ability. + private static readonly MonsterAbility[] _abilities = [MonsterAbilities.FireBreath]; + + [Constructible] + public Slith() : base(AIType.AI_Melee) + { + Body = 734; + + SetStr(129, 136); + SetDex(72, 75); + SetInt(12, 13); + + SetHits(84, 85); + + SetDamage(6, 24); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 35, 40); + SetResistance(ResistanceType.Fire, 35, 45); + SetResistance(ResistanceType.Poison, 25, 35); + SetResistance(ResistanceType.Energy, 25, 30); + + SetSkill(SkillName.MagicResist, 59.1, 63.5); + SetSkill(SkillName.Tactics, 74.6, 76.4); + SetSkill(SkillName.Wrestling, 62.0, 77.1); + + Tamable = true; + ControlSlots = 1; + MinTameSkill = 80.7; + + // TODO(SA-creatures): unported vs ServUO — DragonBlood carving and the minor drops + // SlithEye / AncientPotteryFragments / TatteredAncientScroll (item classes not yet in ModernUO). + } + + public override string CorpseName => "a slith corpse"; + public override string DefaultName => "a slith"; + + public override int TreasureMapLevel => 2; + public override int Meat => 6; + public override int Hides => 10; + + public override MonsterAbility[] GetMonsterAbilities() => _abilities; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + } +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/StoneSlith.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/StoneSlith.cs new file mode 100644 index 000000000..c7a3d7a45 --- /dev/null +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/StoneSlith.cs @@ -0,0 +1,72 @@ +using ModernUO.Serialization; +using Server.Items; + +namespace Server.Mobiles; + +[SerializationGenerator(0)] +public partial class StoneSlith : BaseCreature +{ + private static readonly MonsterAbility[] _abilities = [MonsterAbilities.GraspingClaw, MonsterAbilities.TailSwipe]; + + [Constructible] + public StoneSlith() : base(AIType.AI_Melee) + { + Body = 734; + + SetStr(250, 300); + SetDex(76, 90); + SetInt(34, 69); + + SetHits(154, 166); + SetStam(76, 90); + SetMana(34, 69); + + SetDamage(6, 24); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 50, 55); + SetResistance(ResistanceType.Fire, 20, 30); + SetResistance(ResistanceType.Cold, 10, 20); + SetResistance(ResistanceType.Poison, 30, 40); + SetResistance(ResistanceType.Energy, 30, 40); + + SetSkill(SkillName.MagicResist, 86.8, 95.1); + SetSkill(SkillName.Tactics, 82.6, 88.6); + SetSkill(SkillName.Wrestling, 75.8, 87.4); + SetSkill(SkillName.Anatomy, 0.0, 2.9); + + Tamable = true; + MinTameSkill = 65.1; + ControlSlots = 2; + + // TODO(SA-creatures): unported vs ServUO — DragonBlood carving, and the minor drops + // SlithEye / TatteredAncientScroll / AncientPotteryFragments (item classes not yet in ModernUO). + } + + public override string CorpseName => "a slith corpse"; + public override string DefaultName => "a stone slith"; + + public override int Meat => 1; + public override int Hides => 12; + public override HideType HideType => HideType.Spined; + + public override WeaponAbility GetWeaponAbility() => WeaponAbility.BleedAttack; + + public override MonsterAbility[] GetMonsterAbilities() => _abilities; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + } + + public override void OnDeath(Container c) + { + base.OnDeath(c); + + if (!Controlled && Utility.RandomDouble() <= 0.005) + { + c.DropItem(new StoneSlithClaw()); + } + } +} diff --git a/Projects/UOContent/Mobiles/Monsters/Reptile/ToxicSlith.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/ToxicSlith.cs new file mode 100644 index 000000000..fa33e4cb2 --- /dev/null +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/ToxicSlith.cs @@ -0,0 +1,56 @@ +using ModernUO.Serialization; + +namespace Server.Mobiles; + +[SerializationGenerator(0)] +public partial class ToxicSlith : BaseCreature +{ + // ServUO SpecialAbility.DragonBreath -> closest ModernUO monster ability. + private static readonly MonsterAbility[] _abilities = [MonsterAbilities.FireBreath]; + + [Constructible] + public ToxicSlith() : base(AIType.AI_Melee) + { + Body = 734; + Hue = 476; + + SetStr(223, 306); + SetDex(231, 258); + SetInt(30, 35); + + SetHits(197, 215); + SetStam(231, 258); + + SetDamage(6, 24); + + SetDamageType(ResistanceType.Physical, 100); + + SetResistance(ResistanceType.Physical, 35, 45); + SetResistance(ResistanceType.Fire, 0, 9); + SetResistance(ResistanceType.Cold, 5, 10); + SetResistance(ResistanceType.Poison, 100, 100); + SetResistance(ResistanceType.Energy, 5, 7); + + SetSkill(SkillName.MagicResist, 95.4, 98.3); + SetSkill(SkillName.Tactics, 85.5, 90.9); + SetSkill(SkillName.Wrestling, 90.4, 95.1); + SetSkill(SkillName.Poisoning, 90.0, 110.0); + + // TODO(SA-creatures): unported vs ServUO — DragonBlood carving and the minor drops + // ToxicVenomSac / SlithEye / AncientPotteryFragments / TatteredAncientScroll (not yet in ModernUO). + } + + public override string CorpseName => "a slith corpse"; + public override string DefaultName => "a toxic slith"; + + public override int Meat => 6; + public override int Hides => 11; + public override HideType HideType => HideType.Horned; + + public override MonsterAbility[] GetMonsterAbilities() => _abilities; + + public override void GenerateLoot() + { + AddLoot(LootPack.Average, 2); + } +}