feat(throwing): add Ter Mur reptiles (Raptor + slith family) and their SA claws (#2515)
Follow-up to the gargoyle Throwing work (#2510/#2512/#2514). Ports two Stygian Abyss creatures from ServUO so two of the throwing artifacts finally have a real OSI drop source instead of being `[add`-only. ## Changes - **`Raptor`** and **`StoneSlith`** — ported stat-for-stat from ServUO. They **spawn automatically**: `Distribution/Data/Spawns/post-uoml/termur/TerMur.json` already contained Raptor/StoneSlith spawner entries referencing these class names, so no spawn-file edits were needed. - **`RaptorClaw`** (Boomerang-based) and **`StoneSlithClaw`** (Cyclone-based) artifacts, dropped from each creature's `OnDeath` at ServUO's 0.5% rate (uncontrolled only). - StoneSlith retains its `GraspingClaw` monster ability; both use `BleedAttack`. ## ModernUO idioms Default range perception (16) / fight range, derived `GetSpeeds` (no `SetSpeed`), `[SerializationGenerator(0)]` codegen, collection-expression arrays. ## Documented omissions vs ServUO Flagged as TODO in-code — all are content missing from ModernUO, not silent drops: Raptor's friend-spawn timer + its 25% `AncientPotteryFragments` drop; StoneSlith's `TailSwipe`, `DragonBlood`, and `SlithEye`/`TatteredAncientScroll`/`AncientPotteryFragments` drops; plus `HideType.Horned/Spined` and `PackInstinct.Ostard` (no ModernUO equivalents yet). ## Not included The other three throwing artifacts (Storm Caller, Banshee's Call, Wind of Corruption) drop from renowned/boss creatures via a `BaseRenowned` artifact-list system that doesn't exist in ModernUO yet — a separate, larger effort. AbyssReaver stays with the (deferred) Into-the-Void quest. Verified: server builds clean; throwing suite 14/14.
This commit is contained in:
parent
9c376cb06c
commit
158e7f2e5f
16 changed files with 372 additions and 1 deletions
|
|
@ -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),
|
||||
|
|
|
|||
23
Projects/UOContent/Items/Weapons/Throwing/RaptorClaw.cs
Normal file
23
Projects/UOContent/Items/Weapons/Throwing/RaptorClaw.cs
Normal file
|
|
@ -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;
|
||||
}
|
||||
23
Projects/UOContent/Items/Weapons/Throwing/StoneSlithClaw.cs
Normal file
23
Projects/UOContent/Items/Weapons/Throwing/StoneSlithClaw.cs
Normal file
|
|
@ -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;
|
||||
}
|
||||
4
Projects/UOContent/Migrations/Server.Items.RaptorClaw.v0.json
generated
Normal file
4
Projects/UOContent/Migrations/Server.Items.RaptorClaw.v0.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Items.RaptorClaw"
|
||||
}
|
||||
4
Projects/UOContent/Migrations/Server.Items.StoneSlithClaw.v0.json
generated
Normal file
4
Projects/UOContent/Migrations/Server.Items.StoneSlithClaw.v0.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Items.StoneSlithClaw"
|
||||
}
|
||||
4
Projects/UOContent/Migrations/Server.Mobiles.Raptor.v0.json
generated
Normal file
4
Projects/UOContent/Migrations/Server.Mobiles.Raptor.v0.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Mobiles.Raptor"
|
||||
}
|
||||
4
Projects/UOContent/Migrations/Server.Mobiles.Slith.v0.json
generated
Normal file
4
Projects/UOContent/Migrations/Server.Mobiles.Slith.v0.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Mobiles.Slith"
|
||||
}
|
||||
4
Projects/UOContent/Migrations/Server.Mobiles.StoneSlith.v0.json
generated
Normal file
4
Projects/UOContent/Migrations/Server.Mobiles.StoneSlith.v0.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Mobiles.StoneSlith"
|
||||
}
|
||||
4
Projects/UOContent/Migrations/Server.Mobiles.ToxicSlith.v0.json
generated
Normal file
4
Projects/UOContent/Migrations/Server.Mobiles.ToxicSlith.v0.json
generated
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Mobiles.ToxicSlith"
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,5 +20,6 @@ public enum MonsterAbilityType
|
|||
FanningFire, // Fire debuff
|
||||
RuneCorruption,
|
||||
FanThrow,
|
||||
BloodBath
|
||||
BloodBath,
|
||||
TailSwipe
|
||||
}
|
||||
|
|
|
|||
35
Projects/UOContent/Mobiles/Abilities/TailSwipe.cs
Normal file
35
Projects/UOContent/Mobiles/Abilities/TailSwipe.cs
Normal file
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
76
Projects/UOContent/Mobiles/Monsters/Reptile/Raptor.cs
Normal file
76
Projects/UOContent/Mobiles/Monsters/Reptile/Raptor.cs
Normal file
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
56
Projects/UOContent/Mobiles/Monsters/Reptile/Slith.cs
Normal file
56
Projects/UOContent/Mobiles/Monsters/Reptile/Slith.cs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
72
Projects/UOContent/Mobiles/Monsters/Reptile/StoneSlith.cs
Normal file
72
Projects/UOContent/Mobiles/Monsters/Reptile/StoneSlith.cs
Normal file
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
56
Projects/UOContent/Mobiles/Monsters/Reptile/ToxicSlith.cs
Normal file
56
Projects/UOContent/Mobiles/Monsters/Reptile/ToxicSlith.cs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue