diff --git a/Distribution/Configuration/modernuo.json b/Distribution/Configuration/modernuo.json index 0ee6e7a58..69a406d64 100644 --- a/Distribution/Configuration/modernuo.json +++ b/Distribution/Configuration/modernuo.json @@ -80,7 +80,7 @@ "pathfinding.recorder.enable": "False", "pathfinding.recorder.path": "/home/warrentyexpired/Projects/SovereignRealm/Server/Distribution/Data/Pathfinding/recordings/pathfinds.jsonl", "pingServer.enabled": "True", - "questSystem.enableMLQuests": "False", + "questSystem.enableMLQuests": "True", "serverListing.address": null, "serverListing.autoDetect": "True", "serverListing.serverName": "Sovereign Realm", diff --git a/Distribution/Data/MLQuests.cfg b/Distribution/Data/MLQuests.cfg index 76be8b793..4a322ffc3 100644 --- a/Distribution/Data/MLQuests.cfg +++ b/Distribution/Data/MLQuests.cfg @@ -1,307 +1,4 @@ -# Escorts -EscortToYew -EscortToVesper -EscortToTrinsic -EscortToSkaraBrae -EscortToSerpentsHold -EscortToNujelm -EscortToMoonglow -EscortToMinoc -EscortToMagincia -EscortToJhelom -EscortToCove -EscortToBritain -EscortToOcllo - -# Britannia -Aemaeth1 Aurelia -Aemaeth2 SkeletonOfSzandor -OddsAndEnds Patricus -EmbracingHumanity Iosep - -# Honest Beggar -HonestBeggar Evan -ReginasThanks Regina - -# Unfading Memories -UnfadingMemoriesPartOne Emilio -UnfadingMemoriesPartTwo Emilio -UnfadingMemoriesPartThree Thalia - -# A Ghost Of Covetous -AGhostOfCovetous Ben -SaveHisDad Frederic -AFathersGratitude Leon Andros - -# Heartwood -TheyreBreedingLikeRabbits Saril Tamm Yorus -TheyllEatAnything Saril Tamm Yorus -NoGoodFishStealing Saril Tamm Yorus -AHeroInTheMaking Saril Yorus -BullfightingSortOf Saril Tamm Yorus -AFineFeast Saril Tamm Yorus -ForcedMigration Saril Tamm Yorus -FilthyPests Saril Tamm -DeadManWalking Vilo Saril Tamm Cailla Tiana -KingOfBears Vilo Cailla -Specimens Vilo Clehin Salaenih Cailla Landy -Spirits Cailla -RollTheBones Vilo Cailla -ItsAGhastlyJob Vilo Cailla -Troglodytes Cailla Canir -UnholyKnights Vilo Cailla -AFeatherInYerCap Vilo Cailla -ATaleOfTail Vilo Cailla Drithen -ATrogAndHisDog Cailla Canir -Overpopulation Saril Tamm Yorus ElderAcob -WildBoarCull Saril Tamm Yorus ElderAcob -ItsElemental Caelas Alejaha -CircleOfLife Brinnae Aniel Ciala Mielan -DustToDust Aniel Ciala -CreepyCrawlies Clehin Aulan Landy -VoraciousPlants Aulan Salaenih -GibberJabber Aulan -AnimatedMonstrosity Aulan Salaenih -BirdsOfAFeather Aulan -Frightmares Aulan -MoltenReptiles Aulan -BloodyNuisance Aulan -BloodSuckers Aulan -TheAfterlife Brinnae -ForkedTongue Brinnae Saril Tamm Tiana Gorrow -ImpishDelights Brinnae -ThreeWishes Brinnae -EvilEye Brinnae -GargoylesWrath Brinnae -UndeadMages Brinnae -FriendlyNeighborhoodSpiderkiller Vilo Brinnae Cailla -MongbatMenace Clehin Brinnae Landy -StirringTheNest Brinnae -WarriorCaste Caelas Salaenih -BigWorms Caelas -OrcishElite Caelas -ThinningTheHerd Clehin Saril Tamm Landy Yorus -Squishy Salaenih -OrcSlaying LorekeeperOolua -ABigJob Salaenih -TrollingForTrolls Saril Tamm Tiana -ColdHearted Salaenih -ForkedTongues -ShakingThingsUp Salaenih -Arachnophobia Salaenih -MiniSwampThing Salaenih -ThePerilsOfFarming Vilo Tiana -IndustriousAsAnAntLion Vilo Tiana -UnholyConstruct Vilo Tiana Braen -AChillInTheAir Vilo Tiana -TheKingOfClothing Ahie Thallary -ThePuffyShirt Ahie Thallary -FromTheGaultierCollection Waelian Sleen Ahie Thallary -HauteCouture Ahie Thallary -TheSongOfTheWind Tholef Tillanil -BeerGoggles Tholef Tillanil -MessageInABottleQuest Tholef Tillanil -NecessitysMother Waelian Sleen -TickTock Waelian Sleen Danoel -ReptilianDentist Sleen Danoel -StopHarpingOnMe Waelian Sleen Anolly Cillitha Jusae Unoelil -TheFarEye Waelian Sleen Anolly Unoelil -LethalDarts Cillitha Jusae -ASimpleBow Cillitha Jusae -IngeniousArcheryPartOne Cillitha Jusae -IngeniousArcheryPartTwo Cillitha Jusae -IngeniousArcheryPartThree Cillitha Jusae -ScaleArmor Ahie Thallary Tallinin -CutsBothWays Lohn Olla -DragonProtection Lohn Olla -NothingFancy Anolly Lohn Olla Unoelil Danoel -TheBulwark Lohn Olla -ArchSupport Waelian Sleen Ciala Aniel -ParoxysmusSuccubi LorekeeperNillaen LorekeeperOolua -ParoxysmusMoloch LorekeeperNillaen LorekeeperOolua -ParoxysmusDaemons LorekeeperNillaen LorekeeperOolua -ParoxysmusArcaneDaemons LorekeeperNillaen LorekeeperOolua -CausticCombo LorekeeperNillaen LorekeeperOolua -PlagueLord LorekeeperNillaen LorekeeperOolua -GlassyFoe Ciala Aniel LorekeeperRyal LorekeeperRollarn -DaemonicPrism LorekeeperRyal LorekeeperRollarn -Hailstorm LorekeeperRyal LorekeeperRollarn -HowManyHeads LorekeeperRyal LorekeeperRollarn -DreadhornQuest LorekeeperCalendor LorekeeperOolua -NewLeadership ElderAcob -ExAssassins ElderAcob -ExtinguishingTheFlame ElderAcob -CrimeAndPunishment ElderAcob -DeathToTheNinja ElderAcob -AllThatGlittersIsNotGood LorekeeperSiarra ElderBrae - -# The Ancient World -TheAncientWorld LorekeeperBroolol -TheGoldenHorn LorekeeperBroolol -Bullish Braen -LostCivilization Braen - -# Warriors Of The Gemkeeper -WarriorsOfTheGemkeeper LorekeeperRollarn -CloseEnough LorekeeperRollarn -TakingTheBullByTheHorns Canir -EmissaryToTheMinotaur Canir - -# Sanctuary -BrokenShaft Beotham -BendingTheBow Beotham -ArmsRace Beotham -ImprovedCrossbows Beotham -BuildingTheBetterCrossbow Beotham -InstrumentOfWar Danoel -TheShield Danoel -MusicToMyEars Danoel -TheGlassEye Danoel -LazyHumans Danoel -InventiveTools Danoel -PixieDustToDust LorekeeperOolua -AnImpressivePlaid Tallinin -LeatherAndLace Danoel Tallinin -FeyHeadgear Tallinin -NewCloak Tallinin -ADishBestServedCold Tiana Koole -ArchEnemies Tiana -Vermin Tiana -ANiceShirt Tallinin -MougGuurMustDie Dallid -LeaderOfThePack Dallid -SayonaraSzavetra Dallid -TappingTheKeg Dallid -WaitingToBeFilled Dallid -BreezesSong Dallid -ProofOfTheDeed ElderOnallan Tiana -Marauders ElderOnallan Tiana Koole -TheBrainsOfTheOperation ElderOnallan Tiana -TheBrawn ElderOnallan Tiana -TheBiggerTheyAre ElderOnallan Tiana -TroubleOnTheWing Koole -BrotherlyLove LorekeeperRollarn -CommonBrigands Tiana Gorrow - -# Elven heritage -Seasons MaulTheBear -CaretakerOfTheLand Strongroot -WisdomOfTheSphynx Enigma -DefendingTheHerd Bravehorn -TheBalanceOfNature Huntsman -TheJoysOfLife Arielle - -# Human heritage -Ingenuity Sledge -HeaveHo Patricus -HumanInNeed -AllSeasonAdventurer Belulah - -# Ilshenar -Responsibility Lissbet -SomethingToWailAbout Jelrice -Runaways Jelrice -ViciousPredator Jelrice -GuileIrkAndSpite Yorus - -# New Haven -EscortToNHAlchemist -EscortToNHBard -EscortToNHWarrior -EscortToNHTailor -EscortToNHCarpenter -EscortToNHMapmaker -EscortToNHMage -EscortToNHInn -EscortToNHFarm -EscortToNHDocks -EscortToNHBowyer -EscortToNHBank - -# New Haven Training -SplitEnds Andric -IShotAnArrowIntoTheAir Kashiel -BakersDozen Asandos -AStitchInTime Clairesse -BatteredBucklers Gervis -MoreOrePlease Mugg -ComfortableSeating Lowel -ThePenIsMightier Lyle -AClockworkPuzzle Nibbet -DeliciousFishes Norton -FleeAndFatigue Sadrah -ChopChopOnTheDouble Hargrove - -# New Haven Skill Training -CleansingOldHaven Aelorn -TheRudimentsOfSelfDefense Dimethro -CrushingBonesAndTakingNames Churchill -SwiftAsAnArrow Robyn -EnGuarde Recaro -TheArtOfWar AldenArmstrong -TheWayOfTheBlade Jockles -ThouAndThineShield TylAriadne -DefyingTheArcane Alefian -StoppingTheWorld Gustar -ScribingArcaneKnowledge Jillian -TheMagesApprentice Kaelynna -ScholarlyTask Mithneral -TheRightToolForTheJob AmeliaYoungstone -KnowThineEnemy AndreasVesalius -BruisesBandagesAndBlood Avicenna -TheInnerWarrior SarsmeaSmythe -TheArtOfStealth Ryuichi -BecomingOneWithTheShadows Chiyo -WalkingSilently Jun -EyesOfARanger Walker -TheWayOfTheSamurai Hamato -TheAllureOfDarkMagic Mulcivikh -ChannelingTheSupernatural Morganna -TheDeluciansLostMine JacobWaltz -ItsHammerTime GeorgeHephaestus - -# Spellweaving -Patience Aeluva -NeedsOfTheManyHeartwood1 Aeluva -NeedsOfTheManyHeartwood2 Aeluva -MakingAContributionHeartwood Aeluva -UnnaturalCreations Aeluva - -Discipline Koole -NeedsOfTheManySanctuary Koole -MakingAContributionSanctuary Koole -SuppliesForSanctuary Koole -TheHumanBlight Koole - -FriendOfTheFey Synaeva -TokenOfFriendship Synaeva -Alliance Arielle - -FiendishFriends ElderBrae -CrackingTheWhipI ElderBrae -CrackingTheWhipII ElderBrae - -# ML dungeons -VilePoison Jamal -ARockAndAHardPlace Iosep -SympatheticMagic Iosep -AlreadyDead Iosep -Eureka Iosep -SubContracting Jamal -Momento Kia -CulinaryCrisis Emerillo -GoneNative MasterGnosos - -# Mistaken Identity -MistakenIdentity Aernya -YouScratchMyBack Gorrow -FoolingAernya Gorrow -NotQuiteThatEasy Aernya -ConvinceMe MasterGnosos -TuitionReimbursement MasterGnosos - -# Malas -PointyEars Gorrow Drithen Sledge - -# Lost items -LostAndFound BatteredBucket +IronForTheForge +DestardDrakeBounty +DungeonBountyBoard +DeceitSkeletalKnightBounty diff --git a/Projects/UOContent/Engines/ML Quests/Definitions/DungeonBountyBoard.cs b/Projects/UOContent/Engines/ML Quests/Definitions/DungeonBountyBoard.cs new file mode 100644 index 000000000..858f23447 --- /dev/null +++ b/Projects/UOContent/Engines/ML Quests/Definitions/DungeonBountyBoard.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using ModernUO.Serialization; +using Server.Engines.MLQuests; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions; + +// ========================================== +// 1. BOUNTY BOARD ITEM +// ========================================== +[SerializationGenerator(0, false)] +public partial class DungeonBountyBoard : Item, IQuestGiver +{ + // Implementation for IQuestGiver + public List MLQuests => MLQuestSystem.FindQuestList(GetType()); + + [Constructible] + public DungeonBountyBoard() : base(0x1E5E) // Bulletin board Graphic ID + { + Name = "Dungeon Bounty Board"; + Movable = false; + } + + public override void OnDoubleClick(Mobile from) + { + if (from is PlayerMobile pm) + { + if (from.InRange(GetWorldLocation(), 3)) + { + MLQuestSystem.OnDoubleClick(this, pm); + } + else + { + from.SendLocalizedMessage(500446); // That is too far away. + } + } + } +} + +// ========================================== +// 2. DESTARD BOUNTY: DRAKES +// ========================================== +public class DestardDrakeBounty : MLQuest +{ + public DestardDrakeBounty() + { + Activated = true; + Title = "Bounty: Destard Drakes"; + + Description = "Notice to all adventurers: Drake activity in the caverns of Destard has surged! Slay 10 Drakes to thin their numbers and keep the surrounding passes safe."; + RefusalMessage = "The bounty remains posted if you change your mind."; + InProgressMessage = "You haven't slain enough Drakes yet. Return once you've dispatched 10 of them in Destard."; + CompletionMessage = "Excellent work! The realm thanks you for your service. Here is your gold reward."; + CompletionNotice = CompletionNoticeShort; + + // Objective: Slay 10 Drakes + Objectives.Add(new KillObjective(10, new[] { typeof(Drake) }, "Drakes")); + + // Reward: 1,200 Gold + Rewards.Add(new ItemReward("1,200 Gold", typeof(Gold), 1200)); + } + + public override void Generate() + { + base.Generate(); + MLQuestSystem.Register(this, typeof(DungeonBountyBoard)); + } +} + +// ========================================== +// 3. DECEIT BOUNTY: SKELETAL KNIGHTS +// ========================================== +public class DeceitSkeletalKnightBounty : MLQuest +{ + public DeceitSkeletalKnightBounty() + { + Activated = true; + Title = "Bounty: Deceit Skeletal Knights"; + + Description = "Undead forces are amassing within the halls of Deceit. Slay 10 Skeletal Knights and report back to claim your reward."; + RefusalMessage = "The bounty remains posted on the board."; + InProgressMessage = "The skeletal knights still roam Deceit. Return when you have destroyed 10 of them."; + CompletionMessage = "The undead threat has been pushed back! Take your gold reward."; + CompletionNotice = CompletionNoticeShort; + + // Objective: Slay 10 Skeletal Knights + Objectives.Add(new KillObjective(10, new[] { typeof(SkeletalKnight) }, "Skeletal Knights")); + + // Reward: 1,500 Gold + Rewards.Add(new ItemReward("1,500 Gold", typeof(Gold), 1500)); + } + + public override void Generate() + { + base.Generate(); + MLQuestSystem.Register(this, typeof(DungeonBountyBoard)); + } +} diff --git a/Projects/UOContent/Engines/ML Quests/Definitions/IronForTheForge.cs b/Projects/UOContent/Engines/ML Quests/Definitions/IronForTheForge.cs new file mode 100644 index 000000000..6aa85ab79 --- /dev/null +++ b/Projects/UOContent/Engines/ML Quests/Definitions/IronForTheForge.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using ModernUO.Serialization; +using Server.Engines.MLQuests; +using Server.Engines.MLQuests.Objectives; +using Server.Engines.MLQuests.Rewards; +using Server.Items; +using Server.Mobiles; + +namespace Server.Engines.MLQuests.Definitions; + +public class IronForTheForge : MLQuest +{ + public IronForTheForge() + { + Activated = true; + Title = "Iron for the Forge"; + + Description = "Greetings traveler! The local guards have ordered a heavy shipment of armor, and my forge is running completely cold. Bring me 10 Iron Ingots so I can get back to work, and I will compensate you well."; + RefusalMessage = "I understand. Raw iron is heavy work, but come back if you change your mind."; + InProgressMessage = "Still looking for that iron? Mine it or buy it from a smithy, then bring 10 ingots back to me."; + CompletionMessage = "Ah, magnificent quality iron! This will keep the forge roaring today. Here is your pay as promised."; + CompletionNotice = CompletionNoticeShort; + + // Objective: Collect 10 Iron Ingots + Objectives.Add(new CollectObjective(10, typeof(IronIngot), "Iron Ingots")); + + // Reward: 500 Gold + Rewards.Add(new ItemReward("500 Gold", typeof(Gold), 500)); + } + + public override void Generate() + { + base.Generate(); + + // Registers this quest and links it to QuestBlacksmith + MLQuestSystem.Register(this, typeof(QuestBlacksmith)); + } +} + +[SerializationGenerator(0, false)] +public partial class QuestBlacksmith : BaseCreature, IQuestGiver +{ + // Implementation for IQuestGiver + public List MLQuests => MLQuestSystem.FindQuestList(GetType()); + + [Constructible] + public QuestBlacksmith() : base(AIType.AI_Vendor, FightMode.None, 2) + { + Title = "the Blacksmith"; + Race = Race.Human; + Body = 0x190; + Female = false; + Hue = Race.RandomSkinHue(); + + SetSpeed(0.5, 2.0); + InitStats(100, 100, 25); + + Utility.AssignRandomHair(this); + + AddItem(new Backpack()); + AddItem(new ShortPants(0x755)); + AddItem(new Shirt(Utility.RandomNeutralHue())); + AddItem(new FullApron(Utility.RandomNeutralHue())); + AddItem(new Boots()); + AddItem(new SmithHammer()); + } + + public override bool IsInvulnerable => true; + public override string DefaultName => "Gareth"; +} diff --git a/Projects/UOContent/Regions/Custom/GreetingDungeonRegion.cs b/Projects/UOContent/Regions/Custom/GreetingDungeonRegion.cs index e9a0dda1f..c956d0253 100644 --- a/Projects/UOContent/Regions/Custom/GreetingDungeonRegion.cs +++ b/Projects/UOContent/Regions/Custom/GreetingDungeonRegion.cs @@ -3,7 +3,7 @@ using Server.Mobiles; namespace Server.Regions { - public class GreetingDungeonRegion : DungeonRegion + public class GreetingDungeonRegion : NoTravelSpellsAllowedRegion { public GreetingDungeonRegion(string name, Map map, int priority, params Rectangle3D[] area) : base(name, map, priority, area)