From 0ddc044ba067a9baa6c73bc5e96fa4a1d8421e70 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:20:30 -0700 Subject: [PATCH] feat(throwing): add Raptor & StoneSlith and their SA artifact claws Port Raptor and StoneSlith from ServUO (stat-for-stat) so the throwing artifacts RaptorClaw and StoneSlithClaw finally have a real OSI drop source. Both creatures spawn automatically from the Raptor/StoneSlith entries that already exist in Distribution/Data/Spawns/post-uoml/termur/TerMur.json, and each drops its claw from OnDeath at the ServUO 0.5% rate (uncontrolled only). StoneSlith keeps its GraspingClaw monster ability; both use BleedAttack. Idiomatic ModernUO: default range perception (16) and fight range, derived GetSpeeds, [SerializationGenerator(0)] codegen, collection-expression arrays. Documented omissions vs ServUO (missing from ModernUO, flagged as TODO): Raptor's friend-spawn timer + 25% AncientPotteryFragments drop; StoneSlith's TailSwipe, DragonBlood, and SlithEye/TatteredAncientScroll/AncientPottery drops; plus HideType.Horned/Spined and PackInstinct.Ostard. Co-Authored-By: Joe Valentine Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Items/Weapons/Throwing/RaptorClaw.cs | 23 ++++++ .../Items/Weapons/Throwing/StoneSlithClaw.cs | 23 ++++++ .../Server.Items.RaptorClaw.v0.json | 4 + .../Server.Items.StoneSlithClaw.v0.json | 4 + .../Migrations/Server.Mobiles.Raptor.v0.json | 4 + .../Server.Mobiles.StoneSlith.v0.json | 4 + .../Mobiles/Monsters/Reptile/Raptor.cs | 75 +++++++++++++++++++ .../Mobiles/Monsters/Reptile/StoneSlith.cs | 72 ++++++++++++++++++ 8 files changed, 209 insertions(+) create mode 100644 Projects/UOContent/Items/Weapons/Throwing/RaptorClaw.cs create mode 100644 Projects/UOContent/Items/Weapons/Throwing/StoneSlithClaw.cs create mode 100644 Projects/UOContent/Migrations/Server.Items.RaptorClaw.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Items.StoneSlithClaw.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Mobiles.Raptor.v0.json create mode 100644 Projects/UOContent/Migrations/Server.Mobiles.StoneSlith.v0.json create mode 100644 Projects/UOContent/Mobiles/Monsters/Reptile/Raptor.cs create mode 100644 Projects/UOContent/Mobiles/Monsters/Reptile/StoneSlith.cs 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.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/Mobiles/Monsters/Reptile/Raptor.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/Raptor.cs new file mode 100644 index 000000000..07be49e4c --- /dev/null +++ b/Projects/UOContent/Mobiles/Monsters/Reptile/Raptor.cs @@ -0,0 +1,75 @@ +using ModernUO.Serialization; +using Server.Items; + +namespace Server.Mobiles; + +[SerializationGenerator(0)] +public partial class Raptor : BaseCreature +{ + [Constructible] + public Raptor() : base(AIType.AI_Melee, FightMode.Closest) + { + 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), PackInstinct.Ostard, and HideType.Horned (no ModernUO equivalent yet). + } + + 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 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/StoneSlith.cs b/Projects/UOContent/Mobiles/Monsters/Reptile/StoneSlith.cs new file mode 100644 index 000000000..be80df4b8 --- /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]; + + [Constructible] + public StoneSlith() : base(AIType.AI_Melee, FightMode.Closest) + { + 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 — SpecialAbility.TailSwipe (no ModernUO equivalent), + // DragonBlood carving, HideType.Spined, 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 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()); + } + } +}