fix: Removes scale speed by dex for monsters, fixes NPC movement/thinking speed (#1019)

* Removes scaled speed by dex for monsters
* Changes scaled speed by dex for pets (HS+ expansion) to be 400ms -> 100ms between 50 -> 200 dex
* Removes speed changes that were broken for various mobs
* Combines "Legacy" speed and renames the class to `NPCSpeeds`
* Creates speed "classes" (slow, medium, fast, very fast)
* Introduces a new overridable property `SpeedClass`. Register a new speed class using `NPCSpeeds.Register()` and then set the speed class to bulk/mass apply speeds.

Order of speed determination:
1. SpeedMod
2. SpeedClass property (not null)
3. SpeedClass entry in Data\npc-speeds.json for that type
4. "Fast" (200ms Active, 400ms Passive)
This commit is contained in:
Kamron Batman 2022-05-15 10:01:14 -07:00 committed by GitHub
parent 6ec84b3c01
commit eee8494558
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
74 changed files with 477 additions and 472 deletions

View file

@ -6,7 +6,7 @@ namespace Server.Mobiles
{
[Constructible]
public UnholySteed()
: base("a dark steed", 0x74, 0x3EA7, AIType.AI_Melee, FightMode.Aggressor, 10, 1)
: base("a dark steed", 0x74, 0x3EA7, AIType.AI_Melee, FightMode.Aggressor)
{
SetStr(496, 525);
SetDex(86, 105);

View file

@ -6,7 +6,7 @@ namespace Server.Mobiles
{
[Constructible]
public HolySteed()
: base("a silver steed", 0x75, 0x3EA8, AIType.AI_Melee, FightMode.Aggressor, 10, 1)
: base("a silver steed", 0x75, 0x3EA8, AIType.AI_Melee, FightMode.Aggressor)
{
SetStr(496, 525);
SetDex(86, 105);

View file

@ -10,7 +10,7 @@ namespace Server.Factions
[Constructible]
public FactionWarHorse(Faction faction = null)
: base("a war horse", 0xE2, 0x3EA0, AIType.AI_Melee, FightMode.Aggressor, 10, 1)
: base("a war horse", 0xE2, 0x3EA0, AIType.AI_Melee, FightMode.Aggressor)
{
BaseSoundID = 0xA8;

View file

@ -37,7 +37,6 @@ namespace Server.Factions
public BaseFactionGuard(string title) : base(AIType.AI_Melee)
{
SetSpeed(0.3, 1.0);
Orders = new Orders(this);
Title = title;

View file

@ -96,8 +96,7 @@ namespace Server.Engines.MLQuests.Definitions
public class Ben : BaseCreature
{
[Constructible]
public Ben()
: base(AIType.AI_Vendor, FightMode.None, 2)
public Ben() : base(AIType.AI_Vendor, FightMode.None, 2)
{
Title = "the Apprentice Necromancer";
Body = 0x190;

View file

@ -77,7 +77,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -122,7 +122,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -175,7 +175,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);

View file

@ -116,7 +116,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -169,7 +169,7 @@ namespace Server.Engines.MLQuests.Definitions
Hue = 0x83F2; // TODO: Random human hue? Why???
Body = 0x32;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
}

View file

@ -2012,7 +2012,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2079,7 +2079,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2147,7 +2147,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2213,7 +2213,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2280,7 +2280,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2346,7 +2346,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2410,7 +2410,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2482,7 +2482,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2546,7 +2546,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2624,7 +2624,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2684,7 +2684,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2748,7 +2748,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2810,7 +2810,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2887,7 +2887,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -2971,7 +2971,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3039,7 +3039,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3109,7 +3109,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3172,7 +3172,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3242,7 +3242,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3306,7 +3306,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3369,7 +3369,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3419,7 +3419,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3492,7 +3492,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3555,7 +3555,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3625,7 +3625,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3690,7 +3690,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3754,7 +3754,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3817,7 +3817,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3881,7 +3881,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3943,7 +3943,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -3988,7 +3988,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4046,7 +4046,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4090,7 +4090,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4139,7 +4139,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4185,7 +4185,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4231,7 +4231,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4275,7 +4275,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4319,7 +4319,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4364,7 +4364,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4415,7 +4415,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4459,7 +4459,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4512,7 +4512,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4569,7 +4569,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4621,7 +4621,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4686,7 +4686,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4742,7 +4742,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4797,7 +4797,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -4853,7 +4853,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);

View file

@ -283,7 +283,7 @@ namespace Server.Engines.MLQuests.Definitions
Body = 788;
BaseSoundID = 0x3EE;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
}
@ -622,7 +622,7 @@ namespace Server.Engines.MLQuests.Definitions
Body = 400;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
AddItem(new Tunic(Utility.RandomNeutralHue()));
@ -678,7 +678,7 @@ namespace Server.Engines.MLQuests.Definitions
Body = 400;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
AddItem(new FancyShirt(Utility.RandomNeutralHue()));
@ -722,7 +722,7 @@ namespace Server.Engines.MLQuests.Definitions
Body = 401;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);

View file

@ -63,7 +63,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -107,7 +107,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);

View file

@ -180,7 +180,7 @@ namespace Server.Engines.MLQuests.Definitions
Body = 400;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
var hairHue = 0x3B2 + Utility.Random(2);
@ -235,7 +235,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -286,7 +286,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);

View file

@ -35,7 +35,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
AddItem(new Backpack());

View file

@ -203,7 +203,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -250,7 +250,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
AddItem(new Backpack());
@ -308,7 +308,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = 0x83E8;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
HairItemID = 0x2049;

View file

@ -654,7 +654,7 @@ namespace Server.Engines.MLQuests.Definitions
FacialHairItemID = 0x204D;
FacialHairHue = 0x47D;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -719,7 +719,7 @@ namespace Server.Engines.MLQuests.Definitions
FacialHairItemID = 0x204D;
FacialHairHue = 0x455;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.EvalInt, 120.0);
@ -776,7 +776,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203C;
HairHue = 0x455;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -855,7 +855,7 @@ namespace Server.Engines.MLQuests.Definitions
HairHue = 0x47D;
Female = true;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -939,7 +939,7 @@ namespace Server.Engines.MLQuests.Definitions
FacialHairItemID = 0x204D;
FacialHairHue = 0x455;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -1021,7 +1021,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203B;
HairHue = 0x44E;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -1086,7 +1086,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203C;
HairHue = 0x8A7;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -1146,7 +1146,7 @@ namespace Server.Engines.MLQuests.Definitions
Hue = 0x8374;
HairItemID = 0;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -1228,7 +1228,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203D;
HairHue = 0x457;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.EvalInt, 120.0);
@ -1284,7 +1284,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203B;
HairHue = 0x455;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.EvalInt, 120.0);
@ -1367,7 +1367,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203D;
HairHue = 0x455;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.EvalInt, 120.0);
@ -1424,7 +1424,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203C;
HairHue = 0x47D;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.EvalInt, 120.0);
@ -1480,7 +1480,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203C;
HairHue = 0x455;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.EvalInt, 120.0);
@ -1542,7 +1542,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203D;
HairHue = 0x46C;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.ArmsLore, 120.0);
@ -1604,7 +1604,7 @@ namespace Server.Engines.MLQuests.Definitions
FacialHairItemID = 0x203E;
FacialHairHue = 0x477;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -1662,7 +1662,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203B;
HairHue = 0x477;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -1720,7 +1720,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203C;
HairHue = 0x456;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Anatomy, 120.0);
@ -1848,7 +1848,7 @@ namespace Server.Engines.MLQuests.Definitions
Title = "the Hiding Instructor";
Body = 0xF7;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Hiding, 120.0);
@ -1900,7 +1900,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203B;
HairHue = 0x455;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Hiding, 120.0);
@ -1962,7 +1962,7 @@ namespace Server.Engines.MLQuests.Definitions
FacialHairItemID = 0x204B;
FacialHairHue = 0x47D;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Hiding, 120.0);
@ -2100,7 +2100,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203D;
HairHue = 0x457;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Magery, 120.0);
@ -2180,7 +2180,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203C;
HairHue = 0x455;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.Magery, 120.0);
@ -2240,7 +2240,7 @@ namespace Server.Engines.MLQuests.Definitions
FacialHairItemID = 0x204D;
FacialHairHue = 0x44E;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.ArmsLore, 120.0);
@ -2301,7 +2301,7 @@ namespace Server.Engines.MLQuests.Definitions
HairItemID = 0x203B;
HairHue = 0x47B;
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
SetSkill(SkillName.ArmsLore, 120.0);

View file

@ -270,7 +270,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -349,7 +349,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -412,7 +412,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -473,7 +473,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -530,7 +530,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -599,7 +599,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -653,7 +653,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -712,7 +712,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -769,7 +769,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -815,7 +815,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -874,7 +874,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = true;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);
@ -935,7 +935,7 @@ namespace Server.Engines.MLQuests.Definitions
Female = false;
Hue = Race.RandomSkinHue();
SetSpeed(0.5, 2);
SetSpeed(0.5, 2.0);
InitStats(100, 100, 25);
Utility.AssignRandomHair(this);

View file

@ -13,7 +13,6 @@ namespace Server.Engines.Quests.Necro
{
m_Necromancer = necromancer;
SetSpeed(0.3, 1.0);
InitStats(45, 30, 5);
Title = "the Paladin";

View file

@ -8,7 +8,6 @@ namespace Server.Engines.Quests.Ninja
[Constructible]
public Henchman() : base(AIType.AI_Melee, FightMode.Aggressor)
{
SetSpeed(0.3, 1.0);
InitStats(45, 30, 5);
Hue = Race.Human.RandomSkinHue();

View file

@ -11,7 +11,6 @@ namespace Server.Engines.Quests.Samurai
Body = 3;
BaseSoundID = 471;
SetSpeed(0.3, 1.0);
SetStr(20, 40);
SetDex(40, 60);
SetInt(15, 25);

View file

@ -11,7 +11,6 @@ namespace Server.Engines.Quests.Samurai
BaseSoundID = 422;
Hue = 0x66A;
SetSpeed(0.3, 1.0);
SetStr(91, 115);
SetDex(61, 80);
SetInt(86, 105);

View file

@ -11,7 +11,6 @@ namespace Server.Engines.Quests.Samurai
Hue = Utility.RandomAnimalHue();
BaseSoundID = 0x69;
SetSpeed(0.3, 1.0);
SetStr(9);
SetDex(35);
SetInt(5);

View file

@ -10,7 +10,6 @@ namespace Server.Engines.Quests.Samurai
Body = 103;
BaseSoundID = 362;
SetSpeed(0.3, 1.0);
SetStr(6000, 6020);
SetDex(0);
SetInt(850, 870);

View file

@ -12,7 +12,6 @@ namespace Server.Engines.Quests.Samurai
Hue = Utility.RandomAnimalHue();
SetSpeed(0.3, 1.0);
SetStr(10, 20);
SetDex(45, 65);
SetInt(10, 15);

View file

@ -8,7 +8,6 @@ namespace Server.Engines.Quests.Samurai
[Constructible]
public YoungNinja() : base(AIType.AI_Melee, FightMode.Aggressor)
{
SetSpeed(0.3, 1.0);
InitStats(45, 30, 5);
SetHits(20, 30);

View file

@ -8,7 +8,6 @@ namespace Server.Engines.Quests.Samurai
[Constructible]
public YoungRonin() : base(AIType.AI_Melee, FightMode.Aggressor)
{
SetSpeed(0.3, 1.0);
InitStats(45, 30, 5);
SetHits(10, 20);

View file

@ -11,7 +11,6 @@ namespace Server.Engines.Quests.Haven
[Constructible]
public MilitiaFighter() : base(AIType.AI_Melee)
{
SetSpeed(0.3, 1.0);
InitStats(40, 30, 5);
Title = "the Militia Fighter";

View file

@ -278,7 +278,6 @@ namespace Server.Engines.Events
public NaughtyTwin(Mobile from) : base(AIType.AI_Melee, FightMode.None)
{
SetSpeed(0.3, 1.0);
if (TrickOrTreat.CheckMobile(from))
{
Body = from.Body;

View file

@ -166,7 +166,6 @@ namespace Server.Engines.Events
Body = 0x93;
BaseSoundID = 0x1c3;
SetSpeed(0.3, 1.0);
SetStr(500);
SetDex(500);
SetInt(500);

View file

@ -11,7 +11,6 @@ namespace Server.Mobiles
public BaseTalismanSummon() : base(AIType.AI_Melee, FightMode.None)
{
SetSpeed(0.3, 1.0);
// TODO: Stats/skills
}

View file

@ -7,6 +7,7 @@ using Server.Engines.Spawners;
using Server.Factions;
using Server.Gumps;
using Server.Items;
using Server.Logging;
using Server.Network;
using Server.Spells;
using Server.Spells.Spellweaving;
@ -1091,7 +1092,7 @@ namespace Server.Mobiles
m_Mobile.ControlMaster.RevealingAction();
m_Mobile.CurrentSpeed = m_Mobile.PassiveSpeed;
m_Mobile.PlaySound(m_Mobile.GetIdleSound());
m_Mobile.Warmode = true;
m_Mobile.Warmode = false;
m_Mobile.Combatant = null;
break;
}
@ -1110,8 +1111,7 @@ namespace Server.Mobiles
m_Mobile.PlaySound(m_Mobile.GetIdleSound());
m_Mobile.Warmode = true;
m_Mobile.Combatant = null;
var petname = $"{m_Mobile.Name}";
m_Mobile.ControlMaster.SendLocalizedMessage(1049671, petname); // ~1_PETNAME~ is now guarding you.
m_Mobile.ControlMaster.SendLocalizedMessage(1049671, m_Mobile.Name); // ~1_PETNAME~ is now guarding you.
break;
}
@ -1368,10 +1368,6 @@ namespace Server.Mobiles
{
m_Mobile.CurrentSpeed = 0.1;
}
else if (m_Mobile.CurrentSpeed == m_Mobile.ActiveSpeed && m_Mobile.ControlTarget == m_Mobile.ControlMaster)
{
m_Mobile.CurrentSpeed = Math.Max(SpeedInfo.MinDelay, m_Mobile.CurrentSpeed * 0.5);
}
}
}
}
@ -1923,19 +1919,31 @@ namespace Server.Mobiles
public double TransformMoveDelay(double delay)
{
// Non-monsters in PVP combat (like pets) are penalized
if (!m_Mobile.IsMonster && m_Mobile.InActivePVPCombat() && delay <= SpeedInfo.MaxDelay)
// Monster is passive
if (m_Mobile is { Controlled: false, Summoned: false } && Math.Abs(delay - m_Mobile.PassiveSpeed) < 0.0001)
{
delay += 0.4;
delay *= 3;
}
if (!m_Mobile.IsDeadPet && (m_Mobile.ReduceSpeedWithDamage || m_Mobile.IsSubdued))
{
double offset = m_Mobile.StamMax <= 0 ? 1.0 : Math.Max(0, m_Mobile.Stam) / (double)m_Mobile.StamMax;
int stats, statsMax;
if (Core.HS)
{
stats = m_Mobile.Stam;
statsMax = m_Mobile.StamMax;
}
else
{
stats = m_Mobile.Hits;
statsMax = m_Mobile.HitsMax;
}
var offset = statsMax <= 0 ? 1.0 : Math.Max(0, stats) / (double)statsMax;
if (offset < 1.0)
{
delay += delay * (1.0 - offset);
delay += m_Mobile.PassiveSpeed * (1.0 - offset);
}
}
@ -1969,7 +1977,6 @@ namespace Server.Mobiles
m_Mobile.Direction = d;
var delay = (int)(TransformMoveDelay(m_Mobile.CurrentSpeed) * 1000);
NextMove += delay;
if (Core.TickCount - NextMove > 0)
@ -2708,7 +2715,7 @@ namespace Server.Mobiles
*/
public virtual void OnCurrentSpeedChanged()
{
m_Timer.Interval = TimeSpan.FromSeconds(Math.Max(0.0, m_Mobile.CurrentSpeed));
m_Timer.Interval = TimeSpan.FromSeconds(Math.Max(0.008, m_Mobile.CurrentSpeed));
}
private class InternalEntry : ContextMenuEntry

View file

@ -1,77 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json.Serialization;
using Server.Json;
using Server.Logging;
namespace Server;
public class LegacySpeedInfo
{
private static readonly ILogger logger = LogFactory.GetLogger(typeof(LegacySpeedInfo));
private const string _tablePath = "Data/npc-speeds.json";
private static Dictionary<Type, LegacySpeedEntry> m_Table;
public static bool Enabled { get; private set; }
public static bool GetSpeeds(Type type, out double activeSpeed, out double passiveSpeed)
{
if (!(Enabled && m_Table.TryGetValue(type, out var sp)))
{
activeSpeed = 0;
passiveSpeed = 0;
return false;
}
activeSpeed = sp.ActiveSpeed;
passiveSpeed = sp.PassiveSpeed;
return true;
}
public static void Configure()
{
Enabled = ServerConfiguration.GetSetting("movement.delay.useLegacySpeeds", !Core.HS);
if (!Enabled)
{
return;
}
var path = Path.Combine(Core.BaseDirectory, _tablePath);
if (!File.Exists(path))
{
logger.Warning($"Cannot find {path}. Disabling legacy speed system.");
Enabled = false;
return;
}
var speeds = JsonConfig.Deserialize<LegacySpeedEntry[]>(path);
m_Table = new Dictionary<Type, LegacySpeedEntry>();
for (var i = 0; i < speeds.Length; ++i)
{
var info = speeds[i];
foreach (var type in info.Types)
{
m_Table[type] = info;
}
}
}
public record LegacySpeedEntry
{
[JsonPropertyName("active")]
public double ActiveSpeed { get; init; }
[JsonPropertyName("passive")]
public double PassiveSpeed { get; init; }
[JsonPropertyName("types")]
public HashSet<Type> Types { get; init; }
}
}

View file

@ -1,49 +0,0 @@
using System;
using Server.Mobiles;
namespace Server;
public static class SpeedInfo
{
public static double MinDelay { get; private set; }
public static double MaxDelay { get; private set; }
public static double MinMonsterDelay { get; private set; }
public static double MaxMonsterDelay { get; private set; }
// Determines the maximum dex for delay by dex
public static int MaxDex { get; private set; }
public static int MaxMonsterDex { get; private set; }
public static void Configure()
{
// Default speed determined by dex (0 -> 190) for non-monster NPCs including pets
MinDelay = ServerConfiguration.GetOrUpdateSetting("movement.delay.npcMinDelay", 0.1);
MaxDelay = ServerConfiguration.GetOrUpdateSetting("movement.delay.npcMaxDelay", 0.5);
MaxDex = ServerConfiguration.GetOrUpdateSetting("movement.delay.maxDex", 190);
// Default speed determined by dex (0 -> 150) for monsters
MinMonsterDelay = ServerConfiguration.GetOrUpdateSetting("movement.delay.monsterMinDelay", 0.4);
MaxMonsterDelay = ServerConfiguration.GetOrUpdateSetting("movement.delay.monsterMaxDelay", 0.8);
MaxMonsterDex = ServerConfiguration.GetOrUpdateSetting("movement.delay.monsterMaxDex", 150);
}
public static void GetSpeeds(BaseCreature bc, out double activeSpeed, out double passiveSpeed)
{
// Legacy is used if it is enabled, and the type is in the table
if (LegacySpeedInfo.GetSpeeds(bc.GetType(), out activeSpeed, out passiveSpeed))
{
return;
}
var isMonster = bc.IsMonster;
var maxDex = isMonster ? MaxMonsterDex : MaxDex;
var dex = Math.Clamp(bc.Dex, 25, maxDex);
double min = isMonster ? MinMonsterDelay : MinDelay;
double max = isMonster ? MaxMonsterDelay : MaxDelay;
activeSpeed = Math.Max(max - (max - min) * ((double)dex / maxDex), min);
passiveSpeed = activeSpeed * 2;
}
}

View file

@ -14,7 +14,26 @@ namespace Server.Mobiles
{
BaseSoundID = Core.AOS ? 0xA8 : 0x16A;
SetStr(496, 525);
// Publish 97
if (Core.TOL)
{
if (Utility.RandomDouble() < 0.3)
{
SetStr(296, 315);
ControlSlots = 2;
}
else
{
SetStr(496, 525);
ControlSlots = 3;
}
}
else
{
SetStr(496, 525);
ControlSlots = 2;
}
SetDex(86, 105);
SetInt(86, 125);
@ -44,7 +63,6 @@ namespace Server.Mobiles
VirtualArmor = 60;
Tamable = true;
ControlSlots = 2;
MinTameSkill = 95.1;
switch (Utility.Random(3))

View file

@ -5,7 +5,6 @@ namespace Server.Mobiles
[Constructible]
public SeaHorse(string name = "a sea horse") : base(name, 0x90, 0x3EB3, AIType.AI_Animal, FightMode.Aggressor)
{
SetSpeed(0.4, 0.8);
InitStats(Utility.Random(50, 30), Utility.Random(50, 30), 10);
Skills.MagicResist.Base = 25.0 + Utility.RandomDouble() * 5.0;
Skills.Wrestling.Base = 35.0 + Utility.RandomDouble() * 10.0;

View file

@ -5,8 +5,6 @@ namespace Server.Mobiles
[Constructible]
public SilverSteed(string name = "a silver steed") : base(name, 0x75, 0x3EA8, AIType.AI_Animal, FightMode.Aggressor)
{
SetSpeed(0.55, 1.1);
InitStats(Utility.Random(50, 30), Utility.Random(50, 30), 10);
Skills.MagicResist.Base = 25.0 + Utility.RandomDouble() * 5.0;
Skills.Wrestling.Base = 35.0 + Utility.RandomDouble() * 10.0;

View file

@ -5,7 +5,6 @@ namespace Server.Mobiles
[Constructible]
public SkeletalMount(string name = null) : base(name, 793, 0x3EBB, AIType.AI_Animal, FightMode.Aggressor)
{
SetSpeed(0.55, 1.1);
SetStr(91, 100);
SetDex(46, 55);
SetInt(46, 60);

View file

@ -338,12 +338,7 @@ namespace Server.Mobiles
FightMode = mode;
if (LegacySpeedInfo.Enabled && LegacySpeedInfo.GetSpeeds(GetType(), out var activeSpeed, out var passiveSpeed))
{
ActiveSpeed = activeSpeed;
PassiveSpeed = passiveSpeed;
CurrentSpeed = passiveSpeed;
}
ResetSpeeds();
m_Team = 0;
@ -879,6 +874,8 @@ namespace Server.Mobiles
public virtual bool ReturnsToHome =>
SeeksHome && Home != Point3D.Zero && !m_ReturnQueued && !Controlled && !Summoned;
public virtual bool ScaleSpeedByDex => NPCSpeeds.ScaleSpeedByDex && !IsMonster;
// used for deleting untamed creatures [in houses]
[CommandProperty(AccessLevel.GameMaster)]
public bool RemoveIfUntamed { get; set; }
@ -1363,7 +1360,8 @@ namespace Server.Mobiles
public override void OnRawDexChange(int oldValue)
{
if (oldValue != RawDex && ActiveSpeed <= 0 && PassiveSpeed <= 0)
// This only really happens for pets or when a GM modifies a mob.
if (oldValue != RawDex && ScaleSpeedByDex)
{
ResetSpeeds();
}
@ -1627,23 +1625,35 @@ namespace Server.Mobiles
switch (sc)
{
case ScaleType.Red:
corpse.AddCarvedItem(new RedScales(scales), from);
break;
{
corpse.AddCarvedItem(new RedScales(scales), from);
break;
}
case ScaleType.Yellow:
corpse.AddCarvedItem(new YellowScales(scales), from);
break;
{
corpse.AddCarvedItem(new YellowScales(scales), from);
break;
}
case ScaleType.Black:
corpse.AddCarvedItem(new BlackScales(scales), from);
break;
{
corpse.AddCarvedItem(new BlackScales(scales), from);
break;
}
case ScaleType.Green:
corpse.AddCarvedItem(new GreenScales(scales), from);
break;
{
corpse.AddCarvedItem(new GreenScales(scales), from);
break;
}
case ScaleType.White:
corpse.AddCarvedItem(new WhiteScales(scales), from);
break;
{
corpse.AddCarvedItem(new WhiteScales(scales), from);
break;
}
case ScaleType.Blue:
corpse.AddCarvedItem(new BlueScales(scales), from);
break;
{
corpse.AddCarvedItem(new BlueScales(scales), from);
break;
}
case ScaleType.All:
{
corpse.AddCarvedItem(new RedScales(scales), from);
@ -2567,18 +2577,23 @@ namespace Server.Mobiles
return false; // not idling, but don't want to enter idle state
}
m_IdleReleaseTime = Core.Now + TimeSpan.FromSeconds(Utility.RandomMinMax(15, 25));
var idleSeconds = Utility.RandomMinMax(NPCSpeeds.MinIdleSeconds, NPCSpeeds.MaxIdleSeconds);
m_IdleReleaseTime = Core.Now + TimeSpan.FromSeconds(idleSeconds);
if (Body.IsHuman)
{
switch (Utility.Random(2))
{
case 0:
CheckedAnimate(5, 5, 1, true, true, 1);
break;
{
CheckedAnimate(5, 5, 1, true, true, 1);
break;
}
case 1:
CheckedAnimate(6, 5, 1, true, false, 1);
break;
{
CheckedAnimate(6, 5, 1, true, false, 1);
break;
}
}
}
else if (Body.IsAnimal)
@ -2586,14 +2601,20 @@ namespace Server.Mobiles
switch (Utility.Random(3))
{
case 0:
CheckedAnimate(3, 3, 1, true, false, 1);
break;
{
CheckedAnimate(3, 3, 1, true, false, 1);
break;
}
case 1:
CheckedAnimate(9, 5, 1, true, false, 1);
break;
{
CheckedAnimate(9, 5, 1, true, false, 1);
break;
}
case 2:
CheckedAnimate(10, 5, 1, true, false, 1);
break;
{
CheckedAnimate(10, 5, 1, true, false, 1);
break;
}
}
}
else if (Body.IsMonster)
@ -2601,11 +2622,15 @@ namespace Server.Mobiles
switch (Utility.Random(2))
{
case 0:
CheckedAnimate(17, 5, 1, true, false, 1);
break;
{
CheckedAnimate(17, 5, 1, true, false, 1);
break;
}
case 1:
CheckedAnimate(18, 5, 1, true, false, 1);
break;
{
CheckedAnimate(18, 5, 1, true, false, 1);
break;
}
}
}
@ -2862,17 +2887,25 @@ namespace Server.Mobiles
switch (Utility.Random(4))
{
case 0:
PackItem(new CocoaButter());
break;
{
PackItem(new CocoaButter());
break;
}
case 1:
PackItem(new CocoaLiquor());
break;
{
PackItem(new CocoaLiquor());
break;
}
case 2:
PackItem(new SackOfSugar());
break;
{
PackItem(new SackOfSugar());
break;
}
case 3:
PackItem(new Vanilla());
break;
{
PackItem(new Vanilla());
break;
}
}
}
}
@ -3323,11 +3356,6 @@ namespace Server.Mobiles
Controlled = false;
ControlTarget = null;
ControlOrder = OrderType.None;
Guild = null;
ResetSpeeds();
Delta(MobileDelta.Noto);
}
else
{
@ -3351,19 +3379,20 @@ namespace Server.Mobiles
Controlled = true;
ControlTarget = null;
ControlOrder = OrderType.Come;
Guild = null;
if (m_DeleteTimer != null)
{
m_DeleteTimer.Stop();
m_DeleteTimer = null;
}
ResetSpeeds(true);
Delta(MobileDelta.Noto);
}
Guild = null;
ResetSpeeds();
Delta(MobileDelta.Noto);
InvalidateProperties();
return true;
@ -3953,20 +3982,30 @@ namespace Server.Mobiles
switch (Utility.Random(5))
{
case 0:
physDamage += BreathChaosDamage;
break;
{
physDamage += BreathChaosDamage;
break;
}
case 1:
fireDamage += BreathChaosDamage;
break;
{
fireDamage += BreathChaosDamage;
break;
}
case 2:
coldDamage += BreathChaosDamage;
break;
{
coldDamage += BreathChaosDamage;
break;
}
case 3:
poisDamage += BreathChaosDamage;
break;
{
poisDamage += BreathChaosDamage;
break;
}
case 4:
nrgyDamage += BreathChaosDamage;
break;
{
nrgyDamage += BreathChaosDamage;
break;
}
}
}
@ -4620,20 +4659,30 @@ namespace Server.Mobiles
switch (type)
{
case ResistanceType.Physical:
PhysicalDamage = val;
break;
{
PhysicalDamage = val;
break;
}
case ResistanceType.Fire:
FireDamage = val;
break;
{
FireDamage = val;
break;
}
case ResistanceType.Cold:
ColdDamage = val;
break;
{
ColdDamage = val;
break;
}
case ResistanceType.Poison:
PoisonDamage = val;
break;
{
PoisonDamage = val;
break;
}
case ResistanceType.Energy:
EnergyDamage = val;
break;
{
EnergyDamage = val;
break;
}
}
}
@ -4647,20 +4696,30 @@ namespace Server.Mobiles
switch (type)
{
case ResistanceType.Physical:
m_PhysicalResistance = val;
break;
{
m_PhysicalResistance = val;
break;
}
case ResistanceType.Fire:
m_FireResistance = val;
break;
{
m_FireResistance = val;
break;
}
case ResistanceType.Cold:
m_ColdResistance = val;
break;
{
m_ColdResistance = val;
break;
}
case ResistanceType.Poison:
m_PoisonResistance = val;
break;
{
m_PoisonResistance = val;
break;
}
case ResistanceType.Energy:
m_EnergyResistance = val;
break;
{
m_EnergyResistance = val;
break;
}
}
UpdateResistances();
@ -4794,9 +4853,17 @@ namespace Server.Mobiles
}
}
public virtual void ResetSpeeds(bool currentUseActive = false)
// If this needs to be serialized, recommend creating a hash or registry id. Don't serialize strings.
public virtual string SpeedClass => null;
public virtual void GetSpeeds(out double activeSpeed, out double passiveSpeed)
{
SpeedInfo.GetSpeeds(this, out var activeSpeed, out var passiveSpeed);
NPCSpeeds.GetSpeeds(this, out activeSpeed, out passiveSpeed);
}
public void ResetSpeeds(bool currentUseActive = false)
{
GetSpeeds(out var activeSpeed, out var passiveSpeed);
ActiveSpeed = activeSpeed;
PassiveSpeed = passiveSpeed;

View file

@ -10,7 +10,7 @@ namespace Server.Mobiles
public BaseFamiliar() : base(AIType.AI_Melee)
{
SetSpeed(0.1, 0.1);
SetSpeed(0.1, 0.11);
}
public BaseFamiliar(Serial serial) : base(serial)

View file

@ -19,8 +19,6 @@ namespace Server.Mobiles
m_Target = target;
m_ExpireTime = Core.Now + duration;
SetSpeed(0.25, 0.55);
SetStr(200);
SetDex(150);
SetInt(150);

View file

@ -19,8 +19,6 @@ namespace Server.Mobiles
m_Target = target;
m_ExpireTime = Core.Now + TimeSpan.FromMinutes(10.0);
SetSpeed(0.25, 0.55);
SetStr(401, 500);
SetDex(296, 315);
SetInt(101, 200);

View file

@ -10,7 +10,7 @@ namespace Server.Mobiles
Body = 0x190;
Hue = Race.Human.RandomSkinHue();
SetSpeed(0.25, 1.0);
SetSpeed(0.15, 0.4);
SetStr(176, 225);
SetDex(81, 95);

View file

@ -10,7 +10,7 @@ namespace Server.Mobiles
Body = 0x190;
Hue = Race.Human.RandomSkinHue();
SetSpeed(0.25, 1.0);
SetSpeed(0.15, 0.4);
SetStr(276, 350);
SetDex(66, 90);

View file

@ -5,7 +5,7 @@ namespace Server.Mobiles
public class CuSidhe : BaseMount
{
[Constructible]
public CuSidhe(string name = null) : base(name, 277, 0x3E91, AIType.AI_Animal, FightMode.Aggressor, 10, 1)
public CuSidhe(string name = null) : base(name, 277, 0x3E91, AIType.AI_Animal, FightMode.Aggressor)
{
var chance = Utility.RandomDouble() * 23301;

View file

@ -19,7 +19,6 @@ namespace Server.Mobiles
{
Body = 0x117;
SetSpeed(0.3, 1.0);
SetStr(41, 48);
SetDex(55);
SetInt(75);

View file

@ -8,7 +8,6 @@ namespace Server.Mobiles
Body = 212;
BaseSoundID = 0xA3;
SetSpeed(0.3, 1.0);
SetStr(1251, 1550);
SetDex(801, 1050);
SetInt(151, 400);

View file

@ -7,7 +7,6 @@ namespace Server.Mobiles
{
Body = 0x116;
SetSpeed(0.3, 1.0);
SetStr(44, 50);
SetDex(35);
SetInt(5);

View file

@ -8,14 +8,13 @@ namespace Server.Mobiles
Body = 0x3CA;
Hue = 0x453;
SetSpeed(0.25, 5);
SetStr(102, 115);
SetDex(101, 115);
SetInt(203, 215);
SetHits(61, 69);
SetSpeed(0.25, 2.5);
SetDamage(4, 40);
SetDamageType(ResistanceType.Physical, 100);

View file

@ -11,8 +11,6 @@ namespace Server.Mobiles
Hue = 0x8FD;
SetSpeed(0.1, 0.6);
SetStr(255, 847);
SetDex(145, 428);
SetInt(26, 380);

View file

@ -9,8 +9,6 @@ namespace Server.Mobiles
{
BaseSoundID = 0x16A;
SetSpeed(0.25, 0.55);
SetStr(1001, 1025);
SetDex(152, 164);
SetInt(251, 289);

View file

@ -11,7 +11,6 @@ public class BladeSpirits : BaseCreature
{
Body = 574;
SetSpeed(0.5, 1.2);
SetStr(150);
SetDex(150);
SetInt(100);

View file

@ -18,8 +18,6 @@ namespace Server.Mobiles
Hue = 2101;
}
SetSpeed(0.9, 1.5);
SetStr((int)(251 * scalar), (int)(350 * scalar));
SetDex((int)(76 * scalar), (int)(100 * scalar));
SetInt((int)(101 * scalar), (int)(150 * scalar));

View file

@ -16,7 +16,7 @@ namespace Server.Mobiles
SetHits(251, 350);
SetStr(126, 225);
SetDex(81, 95);
SetDex(175, 275);
SetInt(151, 165);
SetDamage(12, 20);

View file

@ -7,10 +7,11 @@ namespace Server.Mobiles
public class FireBeetle : BaseMount
{
[Constructible]
public FireBeetle() : base("a fire beetle", 0xA9, 0x3E95, AIType.AI_Melee, FightMode.Closest, 10, 1)
public FireBeetle() : base("a fire beetle", 0xA9, 0x3E95, AIType.AI_Melee)
{
SetStam(100);
SetStr(300);
SetDex(100);
SetDex(65, 100);
SetInt(500);
SetHits(200);

View file

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json.Serialization;
using Server.Json;
namespace Server.Mobiles;
public static class NPCSpeeds
{
private const string _tablePath = "Data/npc-speeds.json";
private static Dictionary<Type, SpeedClassEntry> _speedsByType = new();
private static Dictionary<string, SpeedClassEntry> _speedsByName = new();
// Enabled for pets on HS+
public static bool ScaleSpeedByDex { get; private set; }
public static double MinDelay { get; private set; }
public static double MaxDelay { get; private set; }
public static int MinDex { get; private set; }
public static int MaxDex { get; private set; }
// Time period to lock NPCs into idling
public static int MinIdleSeconds { get; private set; }
public static int MaxIdleSeconds { get; private set; }
public static void GetSpeeds(BaseCreature bc, out double activeSpeed, out double passiveSpeed)
{
// Used for scaling pet's speed by dex in HS+
if (bc.ScaleSpeedByDex)
{
var maxDex = MaxDex;
double min = MinDelay;
double max = MaxDelay;
var dex = Math.Clamp(bc.Dex, MinDex, maxDex);
activeSpeed = Math.Max(max - (max - min) * ((double)dex / maxDex), min);
passiveSpeed = activeSpeed * 2;
return;
}
if (bc.SpeedClass != null && _speedsByName.TryGetValue(bc.SpeedClass, out var sp) ||
_speedsByType.TryGetValue(bc.GetType(), out sp))
{
activeSpeed = sp.ActiveSpeed;
passiveSpeed = sp.PassiveSpeed;
return;
}
// "Fast"
activeSpeed = 0.2;
passiveSpeed = 0.4;
}
public static void RegisterSpeed(SpeedClassEntry entry)
{
_speedsByName[entry.Name] = entry;
foreach (var type in entry.Types)
{
_speedsByType[type] = entry;
}
}
public static void Configure()
{
ScaleSpeedByDex = ServerConfiguration.GetSetting("movement.delay.scaleSpeedByDex", Core.HS);
MinDelay = ServerConfiguration.GetSetting("movement.delay.npcMinDelay", 0.1);
MaxDelay = ServerConfiguration.GetSetting("movement.delay.npcMaxDelay", 0.4);
MaxDex = ServerConfiguration.GetSetting("movement.delay.npcMinDex", 50);
MaxDex = ServerConfiguration.GetSetting("movement.delay.npcMaxDex", 200);
MinIdleSeconds = ServerConfiguration.GetSetting("movement.delay.npcMinIdle", 15);
MaxIdleSeconds = ServerConfiguration.GetSetting("movement.delay.npcMaxIdle", 25);
var path = Path.Combine(Core.BaseDirectory, _tablePath);
if (!File.Exists(path))
{
return;
}
var speeds = JsonConfig.Deserialize<SpeedClassEntry[]>(path);
for (var i = 0; i < speeds.Length; i++)
{
RegisterSpeed(speeds[i]);
}
}
public record SpeedClassEntry
{
[JsonPropertyName("name")]
public string Name { get; init; }
[JsonPropertyName("active")]
public double ActiveSpeed { get; init; }
[JsonPropertyName("passive")]
public double PassiveSpeed { get; init; }
[JsonPropertyName("types")]
public HashSet<Type> Types { get; init; }
}
}

View file

@ -9,7 +9,6 @@ namespace Server.Mobiles
{
public BaseChampion(AIType aiType, FightMode mode = FightMode.Closest) : base(aiType, mode, 18)
{
SetSpeed(0.25, 0.55);
}
public BaseChampion(Serial serial) : base(serial)

View file

@ -7,12 +7,11 @@ namespace Server.Mobiles
{
public BaseShieldGuard() : base(AIType.AI_Melee, FightMode.Aggressor, 14)
{
SetSpeed(0.5, 2.0);
InitStats(1000, 1000, 1000);
Title = "the guard";
SetSpeed(0.5, 2.0);
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())

View file

@ -12,8 +12,6 @@ namespace Server.Mobiles
Body = 173;
BaseSoundID = 0x183;
SetSpeed(0.1, 0.6);
SetStr(505, 1000);
SetDex(102, 300);
SetInt(402, 600);

View file

@ -12,8 +12,6 @@ namespace Server.Mobiles
Body = 174;
BaseSoundID = 0x4B0;
SetSpeed(0.1, 0.6);
SetStr(502, 600);
SetDex(102, 200);
SetInt(601, 750);

View file

@ -8,8 +8,6 @@ namespace Server.Mobiles
Body = 176;
BaseSoundID = 0x467;
SetSpeed(0.25, 0.55);
SetStr(253, 400);
SetDex(157, 850);
SetInt(503, 800);

View file

@ -7,11 +7,10 @@ namespace Server.Mobiles
[Constructible]
public Actor() : base(AIType.AI_Animal, FightMode.None)
{
SetSpeed(0.6, 1.2);
InitStats(31, 41, 51);
SetSpeed(0.2, 0.4);
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())

View file

@ -7,11 +7,10 @@ namespace Server.Mobiles
[Constructible]
public Artist() : base(AIType.AI_Animal, FightMode.None)
{
SetSpeed(0.6, 1.2);
InitStats(31, 41, 51);
SetSkill(SkillName.Healing, 36, 68);
SetSpeed(0.2, 0.4);
SpeechHue = Utility.RandomDyedHue();
Title = "the artist";
Hue = Race.Human.RandomSkinHue();

View file

@ -94,13 +94,13 @@ namespace Server.Mobiles
[Constructible]
public BaseEscortable() : base(AIType.AI_Melee, FightMode.Aggressor, 22)
{
SetSpeed(0.3, 1.0);
InitBody();
InitOutfit();
Fame = 200;
Karma = 4000;
SetSpeed(0.2, 1.0);
}
public BaseEscortable(Serial serial)

View file

@ -7,15 +7,13 @@ namespace Server.Mobiles
[Constructible]
public Gypsy() : base(AIType.AI_Animal, FightMode.None)
{
SetSpeed(0.6, 1.2);
InitStats(31, 41, 51);
SpeechHue = Utility.RandomDyedHue();
SetSkill(SkillName.Cooking, 65, 88);
SetSkill(SkillName.Snooping, 65, 88);
SetSkill(SkillName.Stealing, 65, 88);
SetSpeed(0.2, 0.4);
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())

View file

@ -7,11 +7,10 @@ namespace Server.Mobiles
[Constructible]
public HarborMaster() : base(AIType.AI_Animal, FightMode.None)
{
SetSpeed(0.6, 1.2);
InitStats(31, 41, 51);
SetSkill(SkillName.Mining, 36, 68);
SetSpeed(0.2, 0.4);
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
Blessed = true;

View file

@ -8,7 +8,6 @@ namespace Server.Mobiles
public Ninja() : base(AIType.AI_Melee, FightMode.Aggressor)
{
Title = "the ninja";
InitStats(100, 100, 25);
SetSkill(SkillName.Fencing, 64.0, 80.0);
@ -18,8 +17,8 @@ namespace Server.Mobiles
SetSkill(SkillName.Tactics, 64.0, 85.0);
SetSkill(SkillName.Swords, 64.0, 85.0);
SetSpeed(0.2, 0.4);
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())

View file

@ -16,8 +16,8 @@ namespace Server.Mobiles
SetSkill(SkillName.Parry, 64.0, 80.0);
SetSkill(SkillName.Swords, 64.0, 85.0);
SetSpeed(0.2, 0.4);
SpeechHue = Utility.RandomDyedHue();
Hue = Race.Human.RandomSkinHue();
if (Female = Utility.RandomBool())

View file

@ -7,9 +7,9 @@ namespace Server.Mobiles
[Constructible]
public Sculptor() : base(AIType.AI_Animal, FightMode.None)
{
SetSpeed(0.6, 1.2);
InitStats(31, 41, 51);
SetSpeed(0.2, 0.4);
SpeechHue = Utility.RandomDyedHue();
Title = "the sculptor";
Hue = Race.Human.RandomSkinHue();

View file

@ -26,15 +26,7 @@ namespace Server.Mobiles
public override bool ClickTitle => false; // Do not display 'the seeker of adventure' when single-clicking
public override string[] GetPossibleDestinations()
{
if (Core.ML)
{
return m_MLDestinations;
}
return m_Dungeons;
}
public override string[] GetPossibleDestinations() => Core.ML ? m_MLDestinations : m_Dungeons;
private static int GetRandomHue()
{

View file

@ -54,12 +54,11 @@ namespace Server.Mobiles
public BaseVendor(string title = null) : base(AIType.AI_Vendor, FightMode.None, 2)
{
SetSpeed(0.5, 2);
LoadSBInfo();
Title = title;
InitBody();
InitOutfit();
SetSpeed(0.5, 2.0);
// these packs MUST exist, or the client will crash when the packets are sent
Container pack = new Backpack { Layer = Layer.ShopBuy, Movable = false, Visible = false };

View file

@ -486,16 +486,13 @@ namespace Server.SkillHandlers
if (m_Creature is GreaterDragon)
{
ScaleSkills(m_Creature, 0.72, 0.90); // 72% of original skills trainable to 90%
m_Creature.Skills.Magery.Base =
m_Creature.Skills.Magery
.Cap; // Greater dragons have a 90% cap reduction and 90% skill reduction on magery
// Greater dragons have a 90% cap reduction and 90% skill reduction on magery
m_Creature.Skills.Magery.Base = m_Creature.Skills.Magery.Cap;
}
else if (m_Paralyzed)
{
ScaleSkills(
m_Creature,
0.86
); // 86% of original skills if they were paralyzed during the taming
// 86% of original skills if they were paralyzed during the taming
ScaleSkills(m_Creature, 0.86);
}
else
{

View file

@ -130,7 +130,6 @@ namespace Server.Mobiles
public Clone(Mobile caster) : base(AIType.AI_Melee, FightMode.None)
{
SetSpeed(0.3, 1.0);
m_Caster = caster;
Body = caster.Body;

View file

@ -9,7 +9,6 @@ namespace Server.Mobiles
Body = 128;
BaseSoundID = 0x467;
SetSpeed(0.3, 1.0);
SetStr(20);
SetDex(150);
SetInt(125);

View file

@ -8,7 +8,6 @@ namespace Server.Mobiles
Body = 74;
BaseSoundID = 422;
SetSpeed(0.3, 1.0);
SetStr(55);
SetDex(40);
SetInt(60);

View file

@ -10,7 +10,6 @@ namespace Server.Mobiles
Body = 0x33;
Hue = 0x4001;
SetSpeed(0.3, 1.0);
SetStr(150);
SetDex(150);
SetInt(100);