#W# MLQuests: Escortable quests are now working. I just need to add more of them. Added moongate to Shiver Island.

This commit is contained in:
WarrentyExpired 2026-10-14 08:31:58 -04:00
parent ac47317723
commit b23e5fdd52
17 changed files with 167 additions and 127 deletions

View file

@ -104,7 +104,10 @@
"world.enableAutoRestart": "False", "world.enableAutoRestart": "False",
"world.savePath": "Saves", "world.savePath": "Saves",
"world.useMultithreadedSaves": "True", "world.useMultithreadedSaves": "True",
"opl.enable": "Core.AOS", "factions.enabled": "False",
"factions.enabled": "False" "vendor.isInvulnerable": "True",
"melee.enableInstaHit": "True",
"t2aCraftMenus": "False",
"opl.enable": "False"
} }
} }

View file

@ -18,6 +18,9 @@ LoomSouthAddon 0x1061
SpinningWheelEastAddon 0x1019 SpinningWheelEastAddon 0x1019
343 1275 0 343 1275 0
BountyBoard 0x1E5E
404 1283 5
# Cresthaven # Cresthaven
SpinningWheelEastAddOn 0x1019 SpinningWheelEastAddOn 0x1019
1571 1173 7 1571 1173 7
@ -32,6 +35,9 @@ SpinningWheelSouthAddon 0x1015
LoomEastAddon 0x1060 LoomEastAddon 0x1060
420 1888 5 420 1888 5
BountyBoard 0x1E5E
405 1876 5
# Coldbarrow # Coldbarrow
LoomSouthAddon 0x1061 LoomSouthAddon 0x1061
3371 2383 7 3371 2383 7
@ -39,9 +45,19 @@ LoomSouthAddon 0x1061
SpinningWheelSouthAddon 0x1015 SpinningWheelSouthAddon 0x1015
3373 2383 7 3373 2383 7
BountyBoard 0x1E5E
3383 2383 7
# Myrish # Myrish
LoomEastAddon 0x1060 LoomEastAddon 0x1060
1538 2919 7 1538 2919 7
SpinningWheelSouthAddon 0x1015 SpinningWheelSouthAddon 0x1015
1540 2915 7 1540 2915 7
BountyBoard 0x1E5E
1596 2901 7
# Fairwinds
BountyBoard 0x1E5E
2342 2787 5

View file

@ -70,6 +70,6 @@ DarkWoodDoor 1701 (Facing=WestCCW)
DarkWoodDoor 1701 (Facing=WestCCW) DarkWoodDoor 1701 (Facing=WestCCW)
3368 2391 7 3368 2391 7
# Hairstylist # Bounty House
DarkWoodDoor 1711 (Facing=NorthCW) DarkWoodDoor 1711 (Facing=NorthCW)
3385 2386 7 3385 2386 7

View file

@ -64,7 +64,7 @@ DarkWoodDoor 1701 (Facing=WestCCW)
DarkWoodDoor 1709 (Facing=SouthCCW) DarkWoodDoor 1709 (Facing=SouthCCW)
2337 2800 5 2337 2800 5
# Hairstyist # Bounty House
DarkWoodDoor 1701 (Facing=WestCCW) DarkWoodDoor 1701 (Facing=WestCCW)
2342 2790 5 2342 2790 5

View file

@ -86,7 +86,7 @@ DarkWoodDoor 1703 (Facing=EastCW)
StrongWoodDoor 1775 (Facing=NorthCW) StrongWoodDoor 1775 (Facing=NorthCW)
409 1296 5 409 1296 5
# Hairstylist # Bounty House
DarkWoodDoor 1711 (Facing=NorthCW) DarkWoodDoor 1711 (Facing=NorthCW)
409 1286 5 409 1286 5

View file

@ -29,3 +29,7 @@ CustomMoonGate 0xF6C
# Piece Island # Piece Island
CustomMoonGate 0xF6C CustomMoonGate 0xF6C
754 3458 0 754 3458 0
# Shiver Island
CustomMoonGate 0xF6C
3012 445 8

View file

@ -92,7 +92,7 @@ DarkWoodDoor 1703 (Facing=EastCCW)
DarkWoodDoor 1703 (Facing=EastCCW) DarkWoodDoor 1703 (Facing=EastCCW)
1585 2901 27 1585 2901 27
# Hairstylist # Bounty House
DarkWoodDoor 1703 (Facing=EastCW) DarkWoodDoor 1703 (Facing=EastCW)
1599 2907 7 1599 2907 7

View file

@ -70,7 +70,7 @@ MediumWoodDoor 1717 (Facing=WestCCW)
MediumWoodDoor 1717 (Facing=WestCCW) MediumWoodDoor 1717 (Facing=WestCCW)
403 1895 5 403 1895 5
# Hairstylist # Bounty House
MediumWoodDoor 1727 (Facing=NorthCW) MediumWoodDoor 1727 (Facing=NorthCW)
410 1876 5 410 1876 5

View file

@ -1 +1,2 @@
IronForTheForge IronForTheForge
EscortToBastion

View file

@ -52,7 +52,7 @@
"spawnBounds": { "x1": 3380, "y1": 2385, "z1": -128, "x2": 3381, "y2": 2386, "z2": 128 }, "spawnBounds": { "x1": 3380, "y1": 2385, "z1": -128, "x2": 3381, "y2": 2386, "z2": 128 },
"walkingRange": 5, "walkingRange": 5,
"entries": [ "entries": [
{ "name": "hairstylist", "probability": 100, "maxCount": 1 } { "name": "bountyvendor", "probability": 100, "maxCount": 1 }
] ]
}, },
{ {

View file

@ -1,18 +1,32 @@
[ [
{ {
"$type": "RegionSpawner", "$type": "Spawner",
"guid": "7828a42b-6b29-4cda-87b5-88db80d9f506", "guid": "5f709ede-bf80-42ea-9c12-87bdb0186806",
"location": [1537, 954, 8], "location": [1536, 957, 8],
"map": "Veridia", "map": "Veridia",
"count": 8, "count": 3,
"minDelay": "00:05:00", "minDelay": "00:05:00",
"maxDelay": "00:10:00", "maxDelay": "00:10:00",
"region": "the End Point Dock", "homeRange": 6,
"walkingRange": 6,
"entries": [
{ "name": "rat", "probability": 100, "maxCount": 2 },
{ "name": "cat", "probability": 100, "maxCount": 1 }
]
},
{
"$type": "Spawner",
"guid": "2952bcb4-4a4e-4082-ae36-fc67b8c8b083",
"location": [1535, 942, 8],
"map": "Veridia",
"count": 3,
"minDelay": "00:05:00",
"maxDelay": "00:10:00",
"homeRange": 6,
"walkingRange": -1, "walkingRange": -1,
"entries": [ "entries": [
{ "name": "cat", "probability": 100, "maxCount": 2 },
{ "name": "rat", "probability": 100, "maxCount": 2 }, { "name": "rat", "probability": 100, "maxCount": 2 },
{ "name": "dog", "probability": 100, "maxCount": 1 } { "name": "cat", "probability": 100, "maxCount": 1 }
] ]
} }
] ]

View file

@ -0,0 +1,20 @@
namespace Server.Engines.MLQuests.Definitions
{
// Base class for escorts providing the AwardHumanInNeed option
public class BaseEscort : MLQuest
{
public BaseEscort() => CompletionNotice = CompletionNoticeShort;
public virtual bool AwardHumanInNeed => true;
public override void GetRewards(MLQuestInstance instance)
{
if (AwardHumanInNeed)
{
HumanInNeed.AwardTo(instance.Player);
}
base.GetRewards(instance);
}
}
}

View file

@ -0,0 +1,28 @@
using System;
using ModernUO.Serialization;
using Server.Engines.MLQuests.Objectives;
using Server.Engines.MLQuests.Rewards;
using Server.Items;
using Server.Mobiles;
namespace Server.Engines.MLQuests.Definitions;
// This is not a real quest, it is only used as a reference
public class HumanInNeed : MLQuest
{
public HumanInNeed()
{
Title = 1075011;
Description = 0;
RefusalMessage = 0;
InProgressMessage = 0;
}
public override bool RecordCompletion => true;
public static void AwardTo(PlayerMobile pm)
{
MLQuestSystem.GetOrCreateContext(pm).SetDoneQuest(MLQuestSystem.FindQuest(typeof(HumanInNeed)));
pm.SendLocalizedMessage(1074949, "", 0x2A);
}
}

View file

@ -0,0 +1,35 @@
using Server.Engines.MLQuests.Objectives;
using Server.Engines.MLQuests.Rewards;
using Server.Items;
namespace Server.Engines.MLQuests.Definitions
{
public class TownEscort : BaseEscort
{
// Escort reward
private static readonly BaseReward m_Reward = new ItemReward("Gold", typeof(Gold), 500);
public TownEscort(int title, int progress, int destination, string region)
{
Activated = true;
Title = title;
Description =
1072287;
RefusalMessage =
1072288;
InProgressMessage = progress;
Objectives.Add(new EscortObjective(new QuestArea(destination, region)));
Rewards.Add(m_Reward);
}
}
public class EscortToBastion : TownEscort
{
public EscortToBastion()
: base(1072275, 1072289, 1072227, "the town of Bastion")
{
}
}
}

View file

@ -2,7 +2,7 @@ using System;
using Server; using Server;
using Server.Gumps; using Server.Gumps;
using Server.Network; using Server.Network;
using Server.Items;
namespace Server.Gumps; namespace Server.Gumps;
public class CustomMoongateGump : Gump public class CustomMoongateGump : Gump
@ -20,11 +20,15 @@ public class CustomMoongateGump : Gump
new("Trails Moongate", new Point3D(3169, 2871, 0), Map.Trammel), new("Trails Moongate", new Point3D(3169, 2871, 0), Map.Trammel),
new("Coldbarrow Moongate", new Point3D(3285, 2331, 0), Map.Trammel), new("Coldbarrow Moongate", new Point3D(3285, 2331, 0), Map.Trammel),
new("Draco Island Moongate", new Point3D(3495, 3491, 2), Map.Trammel), new("Draco Island Moongate", new Point3D(3495, 3491, 2), Map.Trammel),
new("Piece Island Moongate", new Point3D(754, 3458, 0), Map.Trammel) new("Piece Island Moongate", new Point3D(754, 3458, 0), Map.Trammel),
new("Shiver Island Moongate", new Point3D(3012, 445, 8), Map.Trammel)
}; };
public CustomMoongateGump() : base(100, 100) private readonly CustomMoongate _gate;
public CustomMoongateGump(CustomMoongate gate) : base(100, 100)
{ {
_gate = gate;
Closable = true; Closable = true;
Disposable = true; Disposable = true;
Resizable = false; Resizable = false;
@ -32,10 +36,10 @@ public class CustomMoongateGump : Gump
AddPage(0); AddPage(0);
// Background and Alpha Region for a clean, modern look // Background and Alpha Region for a clean, modern look
AddBackground(0, 0, 250, 320, 9270); AddBackground(0, 0, 350, 370, 9270);
AddAlphaRegion(10, 10, 230, 300); AddAlphaRegion(10, 10, 330, 350);
AddHtml(0, 15, 250, 20, "<CENTER><BASEFONT COLOR=#FFFFFF>Select Destination</BASEFONT></CENTER>", false, false); AddHtml(0, 15, 350, 20, "<CENTER><BASEFONT COLOR=#FFFFFF>Select Destination</BASEFONT></CENTER>", false, false);
// Dynamically build the 8 buttons based on the array above // Dynamically build the 8 buttons based on the array above
int yOffset = 50; int yOffset = 50;
@ -62,6 +66,12 @@ public class CustomMoongateGump : Gump
if (buttonId == 0) if (buttonId == 0)
return; return;
if (_gate == null || _gate.Deleted || mobile.Map != _gate.Map || !mobile.InRange(_gate.GetWorldLocation(), 2))
{
mobile.SendMessage("You have moved too far away from the moongate.");
return;
}
// Subtract 1 from the ButtonID to get the actual array index (0 through 7) // Subtract 1 from the ButtonID to get the actual array index (0 through 7)
var index = buttonId - 1; var index = buttonId - 1;

View file

@ -56,7 +56,7 @@ public partial class CustomMoongate : Item
{ {
// Close any existing moongate gumps before opening a new one // Close any existing moongate gumps before opening a new one
pm.CloseGump<CustomMoongateGump>(); pm.CloseGump<CustomMoongateGump>();
pm.SendGump(new CustomMoongateGump()); pm.SendGump(new CustomMoongateGump(this));
} }
} }
} }

View file

@ -36,39 +36,27 @@ public partial class BaseEscortable : BaseCreature
// Used when: !MLQuestSystem.Enabled && !Core.ML // Used when: !MLQuestSystem.Enabled && !Core.ML
public static readonly string[] TownNames = public static readonly string[] TownNames =
[ [
"Cove", "Britain", "Jhelom", "the town of Bastion", "the town of Myrish", "the town of Fairwinds",
"Minoc", "Ocllo", "Trinsic", "the town of Stonehollow", "the town of Mireport", "the town of Cresthaven",
"Vesper", "Yew", "Skara Brae", "the town of Rivermouth", "the town of Teareek", "the town of Port Grim",
"Nujel'm", "Moonglow", "Magincia" "the town of Coldbarrow", "the town of Wharf's End", "the town of Landow"
]; ];
// ML list, pre-ML quest system // ML list, pre-ML quest system
// Used when: !MLQuestSystem.Enabled && Core.ML // Used when: !MLQuestSystem.Enabled && Core.ML
public static readonly string[] MlTownNames = public static readonly string[] MlTownNames =
[ [
"Cove", "Serpent's Hold", "Jhelom", "Nujel'm" "the town of Bastion", "the town of Myrish", "the town of Fairwinds",
"the town of Stonehollow", "the town of Mireport", "the town of Cresthaven",
"the town of Rivermouth", "the town of Teareek", "the town of Port Grim",
"the town of Coldbarrow", "the town of Wharf's End", "the town of Landow"
]; ];
// ML quest system general list // ML quest system general list
// Used when: MLQuestSystem.Enabled && !Region.IsPartOf( "Haven Island" ) // Used when: MLQuestSystem.Enabled && !Region.IsPartOf( "Haven Island" )
private static readonly Dictionary<Type, (int[], int)> _mlQuestTypes = new() private static readonly Dictionary<Type, (int[], int)> _mlQuestTypes = new()
{ {
/* { typeof(EscortToBastion), (Array.Empty<int>(), 0) }
{ typeof(EscortToYew), (Array.Empty<int>(), 0) },
{ typeof(EscortToVesper), (Array.Empty<int>(), 0) },
{ typeof(EscortToTrinsic), (Array.Empty<int>(), 0) },
{ typeof(EscortToSkaraBrae), (Array.Empty<int>(), 0) },
{ typeof(EscortToSerpentsHold), (Array.Empty<int>(), 0) },
{ typeof(EscortToNujelm), (Array.Empty<int>(), 0) },
{ typeof(EscortToMoonglow), (Array.Empty<int>(), 0) },
{ typeof(EscortToMinoc), (Array.Empty<int>(), 0) },
{ typeof(EscortToMagincia), (Array.Empty<int>(), 0) },
{ typeof(EscortToJhelom), (Array.Empty<int>(), 0) },
{ typeof(EscortToCove), (Array.Empty<int>(), 0) },
{ typeof(EscortToBritain), (Array.Empty<int>(), 0) }
// Ocllo was removed in pub 56
// { typeof(EscortToOcllo), (Array.Empty<int>(), 0) }
*/
}; };
// ML quest system New Haven list // ML quest system New Haven list
@ -77,86 +65,7 @@ public partial class BaseEscortable : BaseCreature
// that teach you where things are in a city instead of the randomly spawned ones. // that teach you where things are in a city instead of the randomly spawned ones.
private static readonly Dictionary<Type, (int[], int)> _mlQuestTypesNH = new() private static readonly Dictionary<Type, (int[], int)> _mlQuestTypesNH = new()
{ {
/* { typeof(EscortToBastion), ([1042803, 1042804, 1042805, 1042831], 1042818) },
// I am missing several components for my new potions, and I need to find the local alchemist.
// My daughter is sick , and I need medicine. Do you know the way to the local alchemist?
// I need some potions before I set out for a long journey. Can you take me to the alchemist in The Bottled Imp?
// I’m looking to go to the Alchemist's shop. Will you take me?
{ typeof(EscortToNHAlchemist), ([1042767, 1042768, 1042769, 1042824], 1042811) },
// I need new string for my lute, yet I do not know the way to the local music shop, could you take me?
// I was hoping to hire a bard for my birthday party. Can you take me to one?
// I fear my talent for music is less than my desire to learn, yet still I would like to try. Can you take me to the local music shop?
// I’m looking to go to the music center. Will you take me?
{ typeof(EscortToNHBard), ([1042770, 1042771, 1042772, 1042825], 1042812) },
// A family heirloom, our armoire, is falling apart. I need to see the local carpenter. Would you guide me to her?
// My goat has broken through our fence, and I need new boards. Can you direct me to the local wood worker?
// I need a hammer and nails. Never mind for what. Take me to the local carpenter or leave me be.
// I’m looking to go to the local woodworker. Will you take me?
{ typeof(EscortToNHCarpenter), ([1042773, 1042774, 1042775, 1042829], 1042816) },
//TODO: Add woodsman (camping, tracker, etc)
// 1042776 - I have a job for the local woodsman. I have lost my dog. Can you take me to see him?
// 1042777 - The tracker here is a good man. I know he will help me find my pet scorpion. Do you know the way to his house?
// 1042778 - I am hoping to learn something about camping. Can you take me to the local woodsman?
// 1042836 - I’m looking to go to the local woodsman's. Will you take me?
// 1042814 - Lead on! Payment will be made when we arrive at the weapon trainer's.
// Me spouse's cookin' is too good. I fear me belly is outgrowin' me clothes. I need to find the local seamstress. Can you take me to her?
// I want to learn how to sew. Can you take me to see the tailor?
// I need new clothes for a party, and I was wondering if you could take me to the tailor?
// I’m looking to go to the local tailor. Will you take me?
{ typeof(EscortToNHTailor), ([1042779, 1042780, 1042781, 1042828], 1042815) },
// I need to deposit some gold. You look like a trustworthy soul, so could you direct me to the local bank?
// A rich relative of mine said they deposited some gold in to my account. Would you be able to lead me to the bank?
// I have a debt I need to pay off at the bank. Do you know the way there?
// I’m looking to go to the city bank. Will you take me?
{ typeof(EscortToNHBank), ([1042782, 1042783, 1042784, 1042832], 1042819) },
// I wish to travel and see the world, but I fear I need martial skills. Would you direct me to the local weapons trainer?
// I need a sword to accompany me on a journey. Would escort me to the local fighter's union?
// I need someone to help me rid my home of mongbats. Please take me to the local swordfighter.
// I’m looking to go to the weapon trainer's. Will you take me?
{ typeof(EscortToNHWarrior), ([1042785, 1042786, 1042787, 1042827], 1042814) },
// My new house requires blessing, but I am not a mage and I have not the scroll. Would you take me to the local mages guild?
// I need a wizard. I can't say why. You'll take me to one, or won't you?
// You there. Take me to see a sorcerer so I can turn a friend back in to a human. He is currently a cat and keeps demanding milk.
// I’m looking to go to the magic shop. Will you take me?
{ typeof(EscortToNHMage), ([1042788, 1042789, 1042790, 1042833], 1042820) },
// Psst - I hate to admit it, but I am lost. Can you take me to a place where they sell maps?
// I am trying to confirm the location of dungeons around here. Would you take me to a map maker so I might buy supplies?
// Where am I? Who am I? Do you know me? Hmmm - on second thought, I think I best stick with where I am first. Do you know where I can get a map?
// I’m looking to go to the local Map maker's. Will you take me?
{ typeof(EscortToNHMapmaker), ([1042791, 1042792, 1042793, 1042835], 1042822) },
// I am in search of a loaf of fresh bread. Do you know where I might find some?
// I need to find some spices for my stew. The local chef might have some for me, can you take me to see him?
// I need something to eat. I am starving. Can you take me to the inn?
// I’m looking to go to the New Haven Inn. Will you take me?
{ typeof(EscortToNHInn), ([1042794, 1042795, 1042796, 1042834], 1042821) },
// Hey you! I need to find a farmer because all my plants keep dying. Please take me to one.
// Do you know where I might find a person who sells seeds for crops?
// I am hoping to swap soil stories with a local farmer, but I cannot find one. Can you take me to one?
// I’m looking to go to a local farm. Will you take me?
// { typeof(EscortToNHFarm), (new[] { 1042797, 1042798, 1042799, 1042830 }, 1042817) }, // Farm destination was remove
// Hey! I need to visit the local fisherman to ask about what kind of bait he is using. I keep pulling up sea serpents. Where is he?
// You know, I would really like some fish, but I do not know where a fisherman is. Do you?
// I have heard of a magical fish that grants wishes. I bet THAT fisherman knows where the fish is. Please take me to him.
// I’m looking to go to the fishing wharf. Will you take me?
{ typeof(EscortToNHDocks), ([1042800, 1042801, 1042802, 1042826], 1042813) },
// I need arrows to hunt rabbits for me rabbit stew. Can you take me to the local archer?
// I have a huge amount of feathers for the local Fletcher. Where might I find him?
// You there. Do you know the way to the local archer?
// I’m looking to go to the local archery range. Will you take me?
{ typeof(EscortToNHBowyer), ([1042803, 1042804, 1042805, 1042831], 1042818) },
*/
}; };
[SerializableField(0, setter: "private")] [SerializableField(0, setter: "private")]
@ -780,7 +689,7 @@ public partial class BaseEscortable : BaseCreature
public virtual string PickRandomDestination() public virtual string PickRandomDestination()
{ {
if (Map.Felucca.Regions.Count == 0 || Map == null || Map == Map.Internal || Location == Point3D.Zero) if (Map.Trammel.Regions.Count == 0 || Map == null || Map == Map.Internal || Location == Point3D.Zero)
{ {
return null; // Not yet fully initialized return null; // Not yet fully initialized
} }
@ -819,7 +728,7 @@ public partial class BaseEscortable : BaseCreature
return _destination; return _destination;
} }
if (Map.Felucca.Regions.Count > 0) if (Map.Trammel.Regions.Count > 0)
{ {
_destination = EDI.Find(_destinationString); _destination = EDI.Find(_destinationString);
@ -858,7 +767,7 @@ public class EscortDestinationInfo
public static void Initialize() public static void Initialize()
{ {
var list = Map.Felucca.Regions.Values; var list = Map.Trammel.Regions.Values;
if (list.Count == 0) if (list.Count == 0)
{ {
@ -869,7 +778,7 @@ public class EscortDestinationInfo
foreach (var r in list) foreach (var r in list)
{ {
if (r is DungeonRegion or TownRegion && r.Name != null) if (r.Name != null)
{ {
_table[r.Name] = new EDI(r.Name, r); _table[r.Name] = new EDI(r.Name, r);
} }