Reorganizes Project (#41)
This commit is contained in:
parent
08bf44af9a
commit
3614a66aee
3499 changed files with 79 additions and 55 deletions
|
|
@ -0,0 +1,289 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Quests
|
||||
|
||||
public class AGhostOfCovetous : MLQuest
|
||||
{
|
||||
public AGhostOfCovetous()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1075287; // A Ghost of Covetous
|
||||
Description =
|
||||
1075286; // What? Oh, you startled me! Sorry, I'm a little jumpy. My master Griswolt learned that a ghost has recently taken up residence in the Covetous dungeon. He sent me to capture it, but I . . . well, it terrified me, to be perfectly honest. If you think yourself courageous enough, I'll give you my Spirit Bottle, and you can try to capture it yourself. I'm certain my master would reward you richly for such service.
|
||||
RefusalMessage =
|
||||
1075288; // That's okay, I'm sure someone with more courage than either of us will come along eventually.
|
||||
InProgressMessage = 1075290; // You'll find that ghost in the mountain pass above the Covetous dungeon.
|
||||
CompletionMessage =
|
||||
1075291; // (As you try to use the Spirit Bottle, the ghost snatches it out of your hand and smashes it on the rocks) Please, don't be frightened. I need your help!
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(SpiritBottle), 1, "Spirit Bottle", typeof(Frederic)));
|
||||
|
||||
Rewards.Add(new DummyReward(
|
||||
1075284)); // Return the filled Spirit Bottle to Griswolt the Master Necromancer to receive a reward.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(SaveHisDad);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Ben"), new Point3D(2467, 402, 15), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Ben"), new Point3D(2467, 402, 15), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
public class SaveHisDad : MLQuest
|
||||
{
|
||||
public SaveHisDad()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1075337; // Save His Dad
|
||||
Description =
|
||||
1075338; // My father, Andros, is a smith in Minoc. Last week his forge overturned and he was splashed by molten steel. He was horribly burned, and we feared he would die. An alchemist in Vesper promised to make a bandage that could heal him, but he needed the silk of a dread spider. I came here to get some, but I was careless, and succumbed to their poison. Please, won<6F>t you help my father?
|
||||
RefusalMessage = 1075340; // Oh . . . that<61>s your decision . . . OooOoooOOoo . . .
|
||||
InProgressMessage =
|
||||
1075341; // Thank you! Deliver it to Leon the Alchemist in Vesper. The silk crumbles easily, and much time has already passed since I died. Please! Hurry!
|
||||
CompletionMessage =
|
||||
1075342; // How may I help thee? You have the silk of a dread spider? Of course I can make you a bandage, but what happened to Frederic?
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new TimedDeliverObjective(TimeSpan.FromSeconds(600), typeof(DreadSpiderSilk), 1,
|
||||
"Dread Spider Silk", typeof(Leon)));
|
||||
|
||||
Rewards.Add(new DummyReward(
|
||||
1075339)); // Hurry! You must get the silk to Leon the Alchemist quickly, or it will crumble and become useless!
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(AFathersGratitude);
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 0, "Frederic"), new Point3D(2415, 887, 0), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 0, "Frederic"), new Point3D(2415, 887, 0), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
public class AFathersGratitude : MLQuest
|
||||
{
|
||||
public AFathersGratitude()
|
||||
{
|
||||
Activated = true;
|
||||
OneTimeOnly = true;
|
||||
Title = 1075343; // A Father<65>s Gratitude
|
||||
Description =
|
||||
1075344; // That is simply terrible. First Andros, and now his son. Well, let<65>s make sure Frederic<69>s sacrifice wasn<73>t in vain. Will you take the bandages to his father? You can probably deliver them faster than I can, can<61>t you?
|
||||
RefusalMessage =
|
||||
1075346; // Well I<>m sorry to hear you say that. Without your help, I don<6F>t know if I can get these to Andros quickly enough to help him.
|
||||
InProgressMessage =
|
||||
1075347; // I don<6F>t know how much longer Andros will survive. You<6F>d better get this to him as quick as you can. Every second counts!
|
||||
CompletionMessage =
|
||||
1075348; // Sorry, I<>m not accepting commissions at the moment. What? You have the bandage I need from Leon? Thank you so much! But why didn<64>t my son bring this to me himself? . . . Oh, no! You can't be serious! *sag* My Freddie, my son! Thank you for carrying out his last wish. Here -- I made this for my son, to give to him when he became a journeyman. I want you to have it.
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(AlchemistsBandage), 1, "Alchemist's Bandage", typeof(Andros)));
|
||||
|
||||
Rewards.Add(new ItemReward(1075345, typeof(AndrosGratitude))); // Andros<6F> Gratitude
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Leon"), new Point3D(2918, 851, 0), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Leon"), new Point3D(2918, 851, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Andros"), new Point3D(2531, 581, 0), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Andros"), new Point3D(2531, 581, 0), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
public class Ben : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Ben()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Apprentice Necromancer";
|
||||
BodyValue = 0x190;
|
||||
Hue = 0x83FD;
|
||||
HairItemID = 0x2048;
|
||||
HairHue = 0x463;
|
||||
FacialHairItemID = 0x204C;
|
||||
FacialHairHue = 0x463;
|
||||
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Shoes(0x901));
|
||||
AddItem(new LongPants(0x1BB));
|
||||
AddItem(new FancyShirt(0x756));
|
||||
}
|
||||
|
||||
public Ben(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Ben";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("The Ghost of Frederic Smithson")]
|
||||
public class Frederic : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Frederic()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
BodyValue = 0x1A;
|
||||
Hue = 0x455;
|
||||
Frozen = true;
|
||||
|
||||
InitStats(100, 100, 25);
|
||||
}
|
||||
|
||||
public Frederic(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "The Ghost of Frederic Smithson";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Leon : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Leon()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Alchemist";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x190;
|
||||
Female = false;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Shoes(0x901));
|
||||
AddItem(new Robe(0x657));
|
||||
}
|
||||
|
||||
public Leon(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Leon";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Andros : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Andros()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Blacksmith";
|
||||
BodyValue = 0x190;
|
||||
Hue = 0x8409;
|
||||
FacialHairItemID = 0x2041;
|
||||
FacialHairHue = 0x45E;
|
||||
HairItemID = 0x2049;
|
||||
HairHue = 0x45E;
|
||||
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Boots(0x901));
|
||||
AddItem(new FancyShirt(0x60B));
|
||||
AddItem(new LongPants(0x1BB));
|
||||
AddItem(new FullApron(0x901));
|
||||
AddItem(new SmithHammer());
|
||||
}
|
||||
|
||||
public Andros(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Andros";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
21
Projects/Scripts/Engines/MLQuests/Definitions/BaseEscort.cs
Normal file
21
Projects/Scripts/Engines/MLQuests/Definitions/BaseEscort.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
230
Projects/Scripts/Engines/MLQuests/Definitions/Bedlam.cs
Normal file
230
Projects/Scripts/Engines/MLQuests/Definitions/Bedlam.cs
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Quests
|
||||
|
||||
public class Momento : MLQuest
|
||||
{
|
||||
public Momento()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074750; // Momento!
|
||||
Description =
|
||||
1074751; // I was going to march right out there and get it myself, but no ... Master Gnosos won't let me. But you see, that bridle means so much to me. A momento of happier, less-dead ... well undead horseback riding. Could you fetch it for me? I think my horse, formerly known as 'Resolve', may still be wearing it.
|
||||
RefusalMessage = 1074752; // Hrmph.
|
||||
InProgressMessage =
|
||||
1074753; // The bridle would be hard to miss on him now ... since he's skeletal. Please do what you need to do to retrieve it for me.
|
||||
CompletionMessage = 1074754; // I'd know that jingling sound anywhere! You have recovered my bridle. Thank you.
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(ResolvesBridle), "Resolve's Bridle"));
|
||||
|
||||
Rewards.Add(ItemReward.LargeBagOfTreasure);
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Kia"), new Point3D(87, 1640, 0), Map.Malas);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Nythalia"), new Point3D(91, 1639, 0), Map.Malas);
|
||||
}
|
||||
}
|
||||
|
||||
public class CulinaryCrisis : MLQuest
|
||||
{
|
||||
public CulinaryCrisis()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074755; // Culinary Crisis
|
||||
Description =
|
||||
1074756; // You have NO idea how impossible this is. Simply intolerable! How can one expect an artiste' like me to create masterpieces of culinary delight without the best, fresh ingredients? Ever since this whositwhatsit started this uproar, my thrice-daily produce deliveries have ended. I can't survive another hour without produce!
|
||||
RefusalMessage = 1074757; // You have no artistry in your soul.
|
||||
InProgressMessage = 1074758; // I must have fresh produce and cheese at once!
|
||||
CompletionMessage =
|
||||
1074759; // Those dates look bruised! Oh no, and you fetched a soft cheese. *deep pained sigh* Well, even I can only do so much with inferior ingredients. BAM!
|
||||
|
||||
Objectives.Add(new CollectObjective(20, typeof(Dates), 1025927)); // bunch of dates
|
||||
Objectives.Add(new CollectObjective(5, typeof(CheeseWheel), 1022430)); // wheel of cheese
|
||||
|
||||
Rewards.Add(ItemReward.BagOfTreasure);
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Emerillo"), new Point3D(90, 1639, 0), Map.Malas);
|
||||
}
|
||||
}
|
||||
|
||||
public class GoneNative : MLQuest
|
||||
{
|
||||
public GoneNative()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074855; // Gone Native
|
||||
Description =
|
||||
1074856; // Pathetic really. I must say, a senior instructor going native -- forgetting about his students and peers and engaging in such disgraceful behavior! I'm speaking, of course, of Theophilus. Master Theophilus to you. He may have gone native but he still holds a Mastery Degree from Bedlam College! But, well, that's neither here nor there. I need you to take care of my colleague. Convince him of the error of his ways. He may resist. In fact, assume he will and kill him. We'll get him resurrected and be ready to cure his folly. What do you say?
|
||||
RefusalMessage =
|
||||
1074857; // I understand. A Master of Bedlam, even one entirely off his rocker, is too much for you to handle.
|
||||
InProgressMessage =
|
||||
1074858; // You had better get going. Master Theophilus isn't likely to kill himself just to save me this embarrassment.
|
||||
CompletionMessage =
|
||||
1074859; // You look a bit worse for wear! He put up a good fight did he? Hah! That's the spirit … a Master of Bedlam is a match for most.
|
||||
|
||||
Objectives.Add(new KillObjective(1, new[] { typeof(MasterTheophilus) }, "Master Theophilus"));
|
||||
|
||||
Rewards.Add(ItemReward.LargeBagOfTreasure);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
[QuesterName("Kia (Bedlam)")]
|
||||
public class Kia : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Kia()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the student";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x191;
|
||||
Female = true;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Sandals(0x709));
|
||||
AddItem(new Robe(0x497));
|
||||
}
|
||||
|
||||
public Kia(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Kia";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Emerillo (Bedlam)")]
|
||||
public class Emerillo : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Emerillo()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the cook";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x190;
|
||||
Female = false;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Sandals(Utility.RandomNeutralHue()));
|
||||
AddItem(new ShortPants(Utility.RandomPinkHue()));
|
||||
AddItem(new Shirt());
|
||||
AddItem(new HalfApron(0x8FD));
|
||||
}
|
||||
|
||||
public Emerillo(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Emerillo";
|
||||
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, 1074222); // Could I trouble you for some assistance?
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Nythalia : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Nythalia()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the student";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x191;
|
||||
Female = true;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Shoes(Utility.RandomNeutralHue()));
|
||||
AddItem(new Robe(Utility.RandomBool() ? 0x497 : 0x498));
|
||||
}
|
||||
|
||||
public Nythalia(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Mythalia";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
287
Projects/Scripts/Engines/MLQuests/Definitions/BlightedGrove.cs
Normal file
287
Projects/Scripts/Engines/MLQuests/Definitions/BlightedGrove.cs
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Quests
|
||||
|
||||
public class VilePoison : MLQuest
|
||||
{
|
||||
public VilePoison()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074950; // Vile Poison
|
||||
Description =
|
||||
1074956; // Heya! I'm sure glad to see you. Listen I'm in a bit of a bind here. I'm supposed to be gathering poisoned water at the base of that corrupted tree there, but I can't get in under the roots to get a good sample. The branches and brush are so tainted that they can't be cut, burned or even magically passed. It's put my work at a real standstill. If you help me out, I'll help you get in there too. Whadda ya say?
|
||||
RefusalMessage = 1074964; // Okay. If you change your mind, I'll probably still be stuck here trying to get in.
|
||||
InProgressMessage = 1074968; // My friend, Iosep, is a weaponsmith in Jhelom. If anyone can help us, he can!
|
||||
CompletionMessage =
|
||||
1074991; // Greetings. What have you there? Ah, a sample from a poisonous tree, you say? My friend Jamal sent you? Well, let me see that then, and we'll get to work.
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(TaintedTreeSample), 1, "tainted tree sample", typeof(Iosep)));
|
||||
|
||||
Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(ARockAndAHardPlace);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jamal"), new Point3D(559, 1651, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Jamal"), new Point3D(559, 1651, 0), Map.Trammel);
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 2, "Iosep"), new Point3D(1354, 3754, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 2, "Iosep"), new Point3D(1354, 3754, 0), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
public class ARockAndAHardPlace : MLQuest
|
||||
{
|
||||
public ARockAndAHardPlace()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074951; // A Rock and a Hard Place
|
||||
Description =
|
||||
1074957; // This is some nasty stuff, that's for certain. I don't even want to think about what sort of blight caused this venomous reaction from that old tree. Let's get to work … we'll need to try something really hard but still workable as our base material. Nothing's harder than stone and diamond. Let's try them first.
|
||||
RefusalMessage = 1074965; // Sure, no problem. I thought you were interested in figuring this out.
|
||||
InProgressMessage =
|
||||
1074969; // If you're a miner, you should have no trouble getting that stuff. If not, you can probably buy some samples from a miner?
|
||||
CompletionMessage =
|
||||
1074992; // Have you got the granite and diamonds? Great, let me see them and we'll see what effect this venom has upon them.
|
||||
|
||||
// Any type of granite works
|
||||
Objectives.Add(new CollectObjective(4, typeof(BaseGranite), 1026009)); // rock
|
||||
Objectives.Add(new CollectObjective(2, typeof(BlueDiamond), 1032696)); // Blue Diamond
|
||||
|
||||
Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(SympatheticMagic);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class SympatheticMagic : MLQuest
|
||||
{
|
||||
public SympatheticMagic()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074952; // Sympathetic Magic
|
||||
Description =
|
||||
1074958; // Hmm, I've never even heard of something that can damage diamond like that. I guess we'll have to go with plan B. Let's try something similar. Sometimes there's a natural immunity to be found when you use a substance that's like the one you're trying to cut. A sort of "sympathetic" thing. Y'know?
|
||||
RefusalMessage = 1074965; // Sure, no problem. I thought you were interested in figuring this out.
|
||||
InProgressMessage = 1074970; // I think a lumberjack can help supply bark.
|
||||
CompletionMessage = 1074993; // You're back with the bark already? Terrific! I bet this will do the trick.
|
||||
|
||||
Objectives.Add(new CollectObjective(10, typeof(BarkFragment), 1032687)); // Bark Fragment
|
||||
|
||||
Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(AlreadyDead);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class AlreadyDead : MLQuest
|
||||
{
|
||||
public AlreadyDead()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074953; // Already Dead
|
||||
Description =
|
||||
1074959; // Amazing! The bark was reduced to ash in seconds. Whatever this taint is, it plays havok with living things. And of course, it took the edge off both diamonds and granite even faster. What we need is something workable but dead; something that can hold an edge without melting. See what you can come up with, please.
|
||||
RefusalMessage = 1074965; // Sure, no problem. I thought you were interested in figuring this out.
|
||||
InProgressMessage =
|
||||
1074971; // I'm thinking we need something fairly brittle or it won't hold an edge. And, it can't be alive, of course.
|
||||
CompletionMessage = 1074994; // Great thought! Bone might just do the trick.
|
||||
|
||||
Objectives.Add(new InternalObjective());
|
||||
|
||||
Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(Eureka);
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
private class InternalObjective : CollectObjective
|
||||
{
|
||||
public InternalObjective()
|
||||
: base(10, typeof(Bone), 1074963) // (10) workable samples
|
||||
{
|
||||
}
|
||||
|
||||
public override bool ShowDetailed => false;
|
||||
}
|
||||
}
|
||||
|
||||
public class Eureka : MLQuest
|
||||
{
|
||||
public Eureka()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074954; // Eureka!
|
||||
Description =
|
||||
1074960; // We're in business! I've put together the instructions for chopping sort of sword, in the style of one of those new-fangled elven machetes. Take those back to Jamal for me, if you would.
|
||||
RefusalMessage = 1074966; // Well, okay. I guess I thought you'd want to see this through.
|
||||
InProgressMessage =
|
||||
1074972; // I'm sure Jamal is eager to get this information. He's probably still hanging around near that big old blighted tree.
|
||||
CompletionMessage = 1074995; // Heya! You're back. Was Iosep able to help? Let me see what he's sent.
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(SealedNotesForJamal), 1, "sealed note for Jamal", typeof(Jamal)));
|
||||
|
||||
Rewards.Add(new DummyReward(1074962)); // A step closer to entering Blighted Grove.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(SubContracting);
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
PlayerMobile pm = instance.Player;
|
||||
|
||||
if (!pm.HasRecipe(32))
|
||||
{
|
||||
// The ability is awarded regardless of blacksmithy skill
|
||||
pm.AcquireRecipe(32);
|
||||
|
||||
if (pm.Skills.Blacksmith.Base < 45.0) // TODO: Verify threshold
|
||||
pm.SendLocalizedMessage(
|
||||
1075005); // You observe carefully but you can't grasp the complexities of smithing a bone handled machete.
|
||||
else
|
||||
pm.SendLocalizedMessage(1075006); // You have learned how to smith a bone handled machete!
|
||||
}
|
||||
|
||||
base.GetRewards(instance);
|
||||
}
|
||||
}
|
||||
|
||||
public class SubContracting : MLQuest
|
||||
{
|
||||
public SubContracting()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074955; // Sub Contracting
|
||||
Description =
|
||||
1074961; // Wonderful! Now we can both get in there! Let me show you these instructions for making this machete. If you're not skilled in smithing, I'm not sure how much sense it will make though. Listen, if you're heading in there anyway … maybe you'd do me one more favor? I'm ah ... buried in work out here ... so if you'd go in and get me a few water samples, I'd be obliged.
|
||||
RefusalMessage = 1074967; // Oh. Right, I guess you're really ... ah ... busy too.
|
||||
InProgressMessage =
|
||||
1074973; // Once you're inside, look for places where the water has twisted and warped the natural creatures.
|
||||
CompletionMessage =
|
||||
1074996; // I hear sloshing ... that must mean you've got my water samples. Whew, I'm so glad you braved the dangers in there ... I mean, I would have but I'm so busy out here. Here's your reward!
|
||||
|
||||
Objectives.Add(new CollectObjective(3, typeof(SamplesOfCorruptedWater),
|
||||
"samples of corrupted water")); // On OSI the label is "#1074999"
|
||||
// TODO: "Return to" should say "Jamal (near Blighted Grove)"
|
||||
// Maybe every quest NPC has directions as a property?
|
||||
|
||||
Rewards.Add(ItemReward.LargeBagOfTreasure);
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
[QuesterName("Jamal (near Blighted Grove)")]
|
||||
public class Jamal : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Jamal()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.2, 0.4)
|
||||
{
|
||||
Title = "the Fisherman";
|
||||
Body = 400;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
Utility.AssignRandomFacialHair(this, HairHue);
|
||||
|
||||
AddItem(new Shirt(0x1BB));
|
||||
AddItem(new ShortPants(Utility.RandomNeutralHue()));
|
||||
AddItem(new ThighBoots(Utility.RandomAnimalHue()));
|
||||
AddItem(new Backpack());
|
||||
}
|
||||
|
||||
public Jamal(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Jamal";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Iosep (Jhelom)")]
|
||||
public class Iosep : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Iosep()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.2, 0.4)
|
||||
{
|
||||
Title = "the Exporter";
|
||||
Body = 400;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
AddItem(new FancyShirt(Utility.RandomBlueHue()));
|
||||
AddItem(new LongPants(0x1BB));
|
||||
AddItem(new Shoes(Utility.RandomNeutralHue()));
|
||||
AddItem(new Backpack());
|
||||
}
|
||||
|
||||
public Iosep(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Iosep";
|
||||
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, Utility.RandomList(
|
||||
1074209, // Hey, could you help me out with something?
|
||||
1074215 // Don’t test my patience you sniveling worm!
|
||||
));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
204
Projects/Scripts/Engines/MLQuests/Definitions/Britannia.cs
Normal file
204
Projects/Scripts/Engines/MLQuests/Definitions/Britannia.cs
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Quests
|
||||
|
||||
public class Aemaeth1 : MLQuest
|
||||
{
|
||||
public Aemaeth1()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1075321; // Aemaeth
|
||||
Description =
|
||||
1075322; // My father died in an accident some months ago. My mother refused to accept his death. We had a little money set by, and she took it to a necromancer, who promised to restore my father to life. Well, he revived my father, all right, the cheat! Now my father is a walking corpse, a travesty . . . a monster. My mother is beside herself -- she won't eat, she can't sleep. I prayed at the shrine of Spirituality for guidance, and I must have fallen asleep. When I awoke, there was this basin of clear water. I cannot leave my mother, for I fear what she might do to herself. Could you take this to the graveyard, and give it to what is left of my father?
|
||||
RefusalMessage =
|
||||
1075324; // Oh! Alright then. I hope someone comes along soon who can help me, or I dont know what will become of us.
|
||||
InProgressMessage =
|
||||
1075325; // My father - or what remains of him - can be found in the graveyard northwest of the city.
|
||||
CompletionMessage = 1075326; // What is this you give me? A basin of water?
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(BasinOfCrystalClearWater), 1, "Basin of Crystal Clear Water",
|
||||
typeof(SkeletonOfSzandor)));
|
||||
|
||||
Rewards.Add(new DummyReward(1075323)); // Aurelia's gratitude.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(Aemaeth2);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aurelia"), new Point3D(1459, 3795, 0), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aurelia"), new Point3D(1459, 3795, 0), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
public class Aemaeth2 : MLQuest
|
||||
{
|
||||
public Aemaeth2()
|
||||
{
|
||||
Activated = true;
|
||||
OneTimeOnly = true;
|
||||
Title = 1075327; // Aemaeth
|
||||
Description =
|
||||
1075328; // You tell me it is time to leave this flesh. I did not understand until now. I thought: I can see my wife and my daughter, I can speak. Is this not life? But now, as I regard my reflection, I see what I have become. This only a mockery of life. Thank you for having the courage to show me the truth. For the love I bear my wife and daughter, I know now that I must pass beyond the veil. Will you return this basin to Aurelia? She will know by this that I am at rest.
|
||||
RefusalMessage =
|
||||
1075330; // You wont take this back to my daughter? Please, I cannot leave until she knows I am at peace.
|
||||
InProgressMessage = 1075331; // My daughter will be at my home, on the east side of the city.
|
||||
CompletionMessage =
|
||||
1075332; // Thank goodness! Now we can honor my father for the great man he was while he lived, rather than the horror he became.
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(BasinOfCrystalClearWater), 1, "Basin of Crystal Clear Water",
|
||||
typeof(Aurelia)));
|
||||
|
||||
Rewards.Add(new ItemReward(1075304, typeof(MirrorOfPurification))); // Mirror of Purification
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 2, "SkeletonOfSzandor"), new Point3D(1277, 3731, 0), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 2, "SkeletonOfSzandor"), new Point3D(1277, 3731, 0), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
public class OddsAndEnds : MLQuest
|
||||
{
|
||||
public OddsAndEnds()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074354; // Odds and Ends
|
||||
Description =
|
||||
1074677; // I've always been fascinated by primitive cultures -- especially the artifacts. I'm a collector, you see. I'm working on building my troglodyte display and I'm saddened to say that I'm short on examples of religion and superstition amongst the creatures. If you come across any primitive fetishes, I'd be happy to trade you something interesting for them.
|
||||
RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me.
|
||||
InProgressMessage =
|
||||
1074678; // I don't really want to know where you get the primitive fetishes, as I can't support the destruction of their lifestyle and culture. That would be wrong.
|
||||
CompletionMessage = 1074679; // Bravo! These fetishes are just what I needed. You've earned this reward.
|
||||
|
||||
Objectives.Add(new CollectObjective(12, typeof(PrimitiveFetish), "Primitive Fetishes"));
|
||||
|
||||
Rewards.Add(ItemReward.BagOfTreasure);
|
||||
}
|
||||
}
|
||||
|
||||
public class EmbracingHumanity : MLQuest
|
||||
{
|
||||
public EmbracingHumanity()
|
||||
{
|
||||
Activated = true;
|
||||
OneTimeOnly = true; // OSI has no limit or delay, VERY exploitable
|
||||
Title = 1074349; // Embracing Humanity
|
||||
Description =
|
||||
1074357; // Well, I don't mind saying it -- I'm flabbergasted! Absolutely astonished. I just heard that some elves want to convert themselves to humans through some magical process. My cousin Nedrick does whatever needs doing. I guess you could check it out for yourself if you're curious. Anyway, I wonder if you'll bring my cousin, Drithen, this here treat my wife baked up for him special.
|
||||
RefusalMessage = 1074459; // That's okay, I'll find someone else to make the delivery.
|
||||
InProgressMessage = 1074460; // If I knew where my cousin was, I'd make the delivery myself.
|
||||
CompletionMessage = 1074461; // Oh, hello there. What do you have for me?
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(SpecialTreatForDrithen), 1, "treat for Drithen", typeof(Drithen)));
|
||||
|
||||
Rewards.Add(ItemReward.BagOfTreasure);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
public class Aurelia : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Aurelia()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Architect's Daughter";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x191;
|
||||
Female = true;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Sandals(Utility.RandomPinkHue()));
|
||||
|
||||
if (Utility.RandomBool())
|
||||
AddItem(new Kilt(Utility.RandomPinkHue()));
|
||||
else
|
||||
AddItem(new Skirt(Utility.RandomPinkHue()));
|
||||
|
||||
AddItem(new FancyShirt(Utility.RandomRedHue()));
|
||||
}
|
||||
|
||||
public Aurelia(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Aurelia";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Szandor")]
|
||||
public class SkeletonOfSzandor : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public SkeletonOfSzandor()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Late Architect";
|
||||
Hue = 0x83F2; // TODO: Random human hue? Why???
|
||||
Body = 0x32;
|
||||
InitStats(100, 100, 25);
|
||||
}
|
||||
|
||||
public SkeletonOfSzandor(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Skeleton of Szandor";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
4680
Projects/Scripts/Engines/MLQuests/Definitions/Heartwood.cs
Normal file
4680
Projects/Scripts/Engines/MLQuests/Definitions/Heartwood.cs
Normal file
File diff suppressed because it is too large
Load diff
833
Projects/Scripts/Engines/MLQuests/Definitions/Heritage.cs
Normal file
833
Projects/Scripts/Engines/MLQuests/Definitions/Heritage.cs
Normal file
|
|
@ -0,0 +1,833 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Human To Elf Quests
|
||||
|
||||
public class Seasons : MLQuest
|
||||
{
|
||||
public Seasons()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072782; // Seasons
|
||||
Description =
|
||||
1072802; // *rumbling growl* *sniff* ... not-smell ... seek-fight ... not-smell ... fear-stench ... *rumble* ... cold-soon-time comes ... hungry ... eat-fish ... sleep-soon-time ... *deep fang-filled yawn* ... much-fish.
|
||||
RefusalMessage = 1072810; // *yawn* ... cold-soon-time ... *growl*
|
||||
InProgressMessage = 1072811; // *sniff* *sniff* ... not-much-fish ... hungry ... *grumble*
|
||||
CompletionMessage = 1074174; // *sniff* fish! much-fish!
|
||||
|
||||
Objectives.Add(new CollectObjective(20, typeof(RawFishSteak), 1022426)); // raw fish steak
|
||||
|
||||
Rewards.Add(new DummyReward(1072803)); // The boon of Maul.
|
||||
}
|
||||
|
||||
public override bool RecordCompletion => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.Player.SendLocalizedMessage(1074940, "",
|
||||
0x2A); // You have gained the boon of Maul! Your understanding of the seasons grows. You are one step closer to claiming your elven heritage.
|
||||
instance.ClaimRewards(); // skip gump
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Darius"), new Point3D(4310, 954, 10), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Darius"), new Point3D(4310, 954, 10), Map.Trammel);
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "MaulTheBear"), new Point3D(1730, 257, 16), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "MaulTheBear"), new Point3D(1730, 257, 16), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
public class CaretakerOfTheLand : MLQuest
|
||||
{
|
||||
public CaretakerOfTheLand()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072783; // Caretaker of the Land
|
||||
Description =
|
||||
1072812; // Hrrrrr. Hurrrr. Huuuman. *creaking branches* Suuun on baaark, roooooots diiig deeeeeep, wiiind caaaresses leeeaves … Hrrrrr. Saaap of Sooosaria feeeeeeds us. Hrrrrr. Huuuman leeearn. Caaaretaker of plaaants … teeend … prooove.<br>
|
||||
RefusalMessage = 1072813; // Hrrrrr. Hrrrrr. Huuuman.
|
||||
InProgressMessage =
|
||||
1072814; // Hrrrr. Hrrrr. Roooooots neeeeeed saaap of Sooosaria. Hrrrrr. Roooooots tiiingle neeeaaar Yeeew. Seeeaaarch. Hrrrr!
|
||||
CompletionMessage = 1074175; // Thiiirsty. Hurrr. Hurrr.
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(SapOfSosaria), "sap of sosaria"));
|
||||
|
||||
Rewards.Add(new DummyReward(1072804)); // The boon of Strongroot.
|
||||
}
|
||||
|
||||
public override bool RecordCompletion => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.Player.SendLocalizedMessage(1074941, "",
|
||||
0x2A); // You have gained the boon of Strongroot! You have been approved by one whose roots touch the bones of Sosaria. You are one step closer to claiming your elven heritage.
|
||||
instance.ClaimRewards(); // skip gump
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Strongroot"), new Point3D(597, 1744, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Strongroot"), new Point3D(597, 1744, 0), Map.Trammel);
|
||||
|
||||
PutSpawner(new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(2), 0, 12, "SapOfSosaria"),
|
||||
new Point3D(757, 1004, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromMinutes(2), 0, 12, "SapOfSosaria"),
|
||||
new Point3D(757, 1004, 0), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
public class WisdomOfTheSphynx : MLQuest
|
||||
{
|
||||
public WisdomOfTheSphynx()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072784; // Wisdom of the Sphynx
|
||||
Description =
|
||||
1072822; // I greet thee human and divine my boon thou seek. Convey hence the object of my riddle and I shall reward thee with thy desire.<br><br>Three lives have I.<br>Gentle enough to soothe the skin,<br>Light enough to caress the sky,<br>Hard enough to crack rocks<br>What am I?
|
||||
RefusalMessage = 1072823; // As thou wish, human.
|
||||
InProgressMessage =
|
||||
1072824; // I give thee a hint then human. The answer to my riddle must be held carefully or it cannot be contained at all. Bring this elusive item to me in a suitable container.
|
||||
CompletionMessage = 1074176; // Ah, thus it ends.
|
||||
|
||||
Objectives.Add(new InternalObjective());
|
||||
|
||||
Rewards.Add(new DummyReward(1072805)); // The boon of Enigma.
|
||||
}
|
||||
|
||||
public override bool RecordCompletion => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.Player.SendLocalizedMessage(1074945, "",
|
||||
0x2A); // You have gained the boon of Enigma! You are wise enough to know how little you know. You are one step closer to claiming your elven heritage.
|
||||
instance.ClaimRewards(); // skip gump
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Enigma"), new Point3D(1828, 961, 7), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Enigma"), new Point3D(1828, 961, 7), Map.Trammel);
|
||||
}
|
||||
|
||||
private class InternalObjective : CollectObjective
|
||||
{
|
||||
public InternalObjective()
|
||||
: base(1, typeof(Pitcher), 1074869) // The answer to the riddle.
|
||||
{
|
||||
}
|
||||
|
||||
public override bool ShowDetailed => false;
|
||||
|
||||
public override bool CheckItem(Item item)
|
||||
{
|
||||
return item is Pitcher pitcher && pitcher.Content == BeverageType.Water && pitcher.Quantity > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DefendingTheHerd : MLQuest
|
||||
{
|
||||
public DefendingTheHerd()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072785; // Defending the Herd
|
||||
Description =
|
||||
1072825; // *snort* ... guard-mates ... guard-herd *hoof stomp* ... defend-with-hoof-and-horn ... thirsty-drink. *proud head-toss*
|
||||
RefusalMessage = 1072826; // *snort*
|
||||
InProgressMessage = 1072827; // *impatient hoof stomp* ... thirsty herd ... water scent.
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(
|
||||
new EscortObjective(new QuestArea(1074779, "Bravehorn's drinking pool"))); // Bravehorn's drinking pool
|
||||
|
||||
Rewards.Add(new DummyReward(1072806)); // The boon of Bravehorn.
|
||||
}
|
||||
|
||||
public override bool RecordCompletion => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.Player.SendLocalizedMessage(1074942, "",
|
||||
0x2A); // You have gained the boon of Bravehorn! You have glimpsed the nobility of those that sacrifice themselves for their people. You are one step closer to claiming your elven heritage.
|
||||
instance.ClaimRewards(); // skip gump
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(90), 0, 5, "Bravehorn"),
|
||||
new Point3D(1193, 2467, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(90), 0, 5, "Bravehorn"),
|
||||
new Point3D(1193, 2467, 0), Map.Trammel);
|
||||
|
||||
PutSpawner(new Spawner(5, TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(30), 0, 8, "BravehornsMate"),
|
||||
new Point3D(1192, 2467, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(5, TimeSpan.FromSeconds(20), TimeSpan.FromSeconds(30), 0, 8, "BravehornsMate"),
|
||||
new Point3D(1192, 2467, 0), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
public class TheBalanceOfNature : MLQuest
|
||||
{
|
||||
public TheBalanceOfNature()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072786; // The Balance of Nature
|
||||
Description =
|
||||
1072829; // Ho, there human. Why do you seek out the Huntsman? The hunter serves the land by culling both predators and prey. The hunter maintains the essential balance of life and does not kill for sport or glory. If you seek my favor, human, then demonstrate you are capable of the duty. Cull the wolves nearby.
|
||||
RefusalMessage = 1072830; // Then begone. I have no time to waste on you, human.
|
||||
InProgressMessage = 1072831; // The timber wolves are easily tracked, human.
|
||||
|
||||
Objectives.Add(new KillObjective(15, new[] { typeof(TimberWolf) }, "timber wolves",
|
||||
new QuestArea(1074833, "Huntsman's Forest"))); // Huntsman's Forest
|
||||
|
||||
Rewards.Add(new DummyReward(1072807)); // The boon of the Huntsman.
|
||||
}
|
||||
|
||||
public override bool RecordCompletion => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.Player.SendLocalizedMessage(1074943, "",
|
||||
0x2A); // You have gained the boon of the Huntsman! You have been given a taste of the bittersweet duty of those who guard the balance. You are one step closer to claiming your elven heritage.
|
||||
instance.ClaimRewards(); // skip gump
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Huntsman"), new Point3D(1676, 593, 16), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Huntsman"), new Point3D(1676, 593, 16), Map.Trammel);
|
||||
|
||||
PutSpawner(new Spawner(5, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15), 0, 10, "TimberWolf"),
|
||||
new Point3D(1671, 592, 16), Map.Felucca);
|
||||
PutSpawner(new Spawner(5, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15), 0, 10, "TimberWolf"),
|
||||
new Point3D(1671, 592, 16), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
public class TheJoysOfLife : MLQuest
|
||||
{
|
||||
public TheJoysOfLife()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072787; // The Joys of Life
|
||||
Description =
|
||||
1072832; // *giggle* So serious, so grim! *tickle* Enjoy life! Have fun! Laugh! Be merry! *giggle* Find three of my baubles ... *giggle* I hid them! *giggles hysterically* Hid them! La la la! Bring them quickly! They are magical and will hide themselves again if you are too slow.
|
||||
RefusalMessage = 1072833; // *giggle* Too serious. Too thinky!
|
||||
InProgressMessage = 1072834; // Magical baubles hidden, find them as you're bidden! *giggle*
|
||||
CompletionMessage = 1074177; // *giggle* So pretty!
|
||||
|
||||
Objectives.Add(new CollectObjective(3, typeof(ABauble), "arielle's baubles"));
|
||||
|
||||
Rewards.Add(new DummyReward(1072809)); // The boon of Arielle.
|
||||
}
|
||||
|
||||
public override bool RecordCompletion => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.Player.SendLocalizedMessage(1074944, "",
|
||||
0x2A); // You have gained the boon of Arielle! You have been taught the importance of laughter and light spirits. You are one step closer to claiming your elven heritage.
|
||||
instance.ClaimRewards(); // skip gump
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Arielle"), new Point3D(1560, 1182, -27), Map.Ilshenar);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Arielle"), new Point3D(3366, 292, 9),
|
||||
Map.Felucca); // Felucca spawn for reds
|
||||
|
||||
PutSpawner(new Spawner(6, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(30), 0, 20, "ABauble"),
|
||||
new Point3D(1585, 1212, -13), Map.Ilshenar);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Human To Elf Mobiles
|
||||
|
||||
[QuesterName("Maul")]
|
||||
public class MaulTheBear : GrizzlyBear
|
||||
{
|
||||
[Constructible]
|
||||
public MaulTheBear()
|
||||
{
|
||||
AI = AIType.AI_Vendor;
|
||||
FightMode = FightMode.None;
|
||||
Tamable = false;
|
||||
}
|
||||
|
||||
public MaulTheBear(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Maul";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Strongroot : Treefellow
|
||||
{
|
||||
[Constructible]
|
||||
public Strongroot()
|
||||
{
|
||||
AI = AIType.AI_Vendor;
|
||||
FightMode = FightMode.None;
|
||||
}
|
||||
|
||||
public Strongroot(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Strongroot";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Enigma : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Enigma()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
BodyValue = 788;
|
||||
BaseSoundID = 0x3EE;
|
||||
|
||||
InitStats(100, 100, 25);
|
||||
}
|
||||
|
||||
public Enigma(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Enigma";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Bravehorn : BaseEscortable
|
||||
{
|
||||
[Constructible]
|
||||
public Bravehorn()
|
||||
{
|
||||
}
|
||||
|
||||
public Bravehorn(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool StaticMLQuester => true;
|
||||
public override bool InitialInnocent => true;
|
||||
public override string DefaultName => "Bravehorn";
|
||||
|
||||
public override void InitBody()
|
||||
{
|
||||
Body = 0xEA;
|
||||
|
||||
SetStr(41, 71);
|
||||
SetDex(47, 77);
|
||||
SetInt(27, 57);
|
||||
|
||||
SetHits(27, 41);
|
||||
SetMana(0);
|
||||
|
||||
SetDamage(5, 9);
|
||||
|
||||
SetDamageType(ResistanceType.Physical, 100);
|
||||
|
||||
SetResistance(ResistanceType.Physical, 20, 25);
|
||||
SetResistance(ResistanceType.Cold, 5, 10);
|
||||
|
||||
SetSkill(SkillName.MagicResist, 26.8, 44.5);
|
||||
SetSkill(SkillName.Tactics, 29.8, 47.5);
|
||||
SetSkill(SkillName.Wrestling, 29.8, 47.5);
|
||||
|
||||
Fame = 300;
|
||||
Karma = 0;
|
||||
|
||||
VirtualArmor = 24;
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
}
|
||||
|
||||
public override int GetAttackSound()
|
||||
{
|
||||
return 0x82;
|
||||
}
|
||||
|
||||
public override int GetHurtSound()
|
||||
{
|
||||
return 0x83;
|
||||
}
|
||||
|
||||
public override int GetDeathSound()
|
||||
{
|
||||
return 0x84;
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class BravehornsMate : Hind
|
||||
{
|
||||
[Constructible]
|
||||
public BravehornsMate()
|
||||
{
|
||||
Tamable = false;
|
||||
}
|
||||
|
||||
public BravehornsMate(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "bravehorn's mate";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Huntsman : Centaur
|
||||
{
|
||||
[Constructible]
|
||||
public Huntsman()
|
||||
{
|
||||
AI = AIType.AI_Vendor;
|
||||
FightMode = FightMode.None;
|
||||
}
|
||||
|
||||
public Huntsman(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Huntsman";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Arielle : Pixie
|
||||
{
|
||||
[Constructible]
|
||||
public Arielle()
|
||||
{
|
||||
AI = AIType.AI_Vendor;
|
||||
FightMode = FightMode.None;
|
||||
}
|
||||
|
||||
public Arielle(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Arielle";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Elf To Human Quests
|
||||
|
||||
public class Ingenuity : MLQuest
|
||||
{
|
||||
public Ingenuity()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074350; // Ingenuity
|
||||
Description =
|
||||
1074462; // The best thing about my job is that I do a little bit of everything, every day. It's what we're good at really. Just picking up something and making it do something else. Listen, I'm really low on parts. Are you interested in fetching me some supplies?
|
||||
RefusalMessage = 1074508; // Okay. Best of luck with your other endeavors.
|
||||
InProgressMessage =
|
||||
1074509; // Lord overseers are the best source I know for power crystals of the type I need. Iron golems too, can have them but they're harder to find.
|
||||
CompletionMessage =
|
||||
1074510; // Do you have those power crystals? I'm ready to put the finishing touches on my latest experiment.
|
||||
CompletionNotice = CompletionNoticeShortReturn;
|
||||
|
||||
Objectives.Add(new CollectObjective(10, typeof(PowerCrystal), "Power Crystals"));
|
||||
|
||||
Rewards.Add(new DummyReward(1074875)); // Another step closer to becoming human.
|
||||
}
|
||||
|
||||
public override bool RecordCompletion => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.Player.SendLocalizedMessage(1074946, "",
|
||||
0x2A); // You have demonstrated your ingenuity! Humans are jacks of all trades and know a little about a lot of things. You are one step closer to achieving humanity.
|
||||
instance.ClaimRewards(); // skip gump
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Nedrick"), new Point3D(2958, 3466, 15), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Nedrick"), new Point3D(2958, 3466, 15), Map.Trammel);
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sledge"), new Point3D(2673, 2129, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Sledge"), new Point3D(2673, 2129, 0), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
public class HeaveHo : MLQuest
|
||||
{
|
||||
public HeaveHo()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074351; // Heave Ho!
|
||||
Description =
|
||||
1074519; // Ho there! There's nothing quite like a day's honest labor to make you appreciate being alive. Hey, maybe you'd like to help out with this project? These crates need to be delivered to Sledge. The only thing is -- it's a bit of a rush job and if you don't make it in time, he won't take them. Can I trust you to help out?
|
||||
RefusalMessage = 1074521; // Oh yah, if you're too busy, no problem.
|
||||
InProgressMessage =
|
||||
1074522; // Sledge can be found in Buc's Den. Better hurry, he won't take those crates if you take too long with them.
|
||||
CompletionMessage = 1074523; // Hey, if you have cargo for me, you can start unloading over here.
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new TimedDeliverObjective(TimeSpan.FromHours(1), typeof(CrateForSledge), 5, "Crates for Sledge",
|
||||
typeof(Sledge)));
|
||||
|
||||
Rewards.Add(new DummyReward(1074875)); // Another step closer to becoming human.
|
||||
}
|
||||
|
||||
public override bool RecordCompletion => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.Player.SendLocalizedMessage(1074948, "",
|
||||
0x2A); // You have demonstrated your physical strength! Humans can carry vast loads without complaint. You are one step closer to achieving humanity.
|
||||
instance.ClaimRewards(); // skip gump
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Patricus"), new Point3D(3007, 823, -2), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Patricus"), new Point3D(3007, 823, -2), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
// This is not a real quest, it is only used as a reference
|
||||
public class HumanInNeed : MLQuest
|
||||
{
|
||||
public HumanInNeed()
|
||||
{
|
||||
Title = 1075011; // A quest that asks you to defend a human in need.
|
||||
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); // You have demonstrated your compassion! Your kind actions have been noted.
|
||||
}
|
||||
}
|
||||
|
||||
public class AllSeasonAdventurer : MLQuest
|
||||
{
|
||||
public AllSeasonAdventurer()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074353; // All Season Adventurer
|
||||
Description =
|
||||
1074527; // It's all about hardship, suffering, struggle and pain. Without challenges, you've got nothing to test yourself against -- and that's what life is all about. Self improvement! Honing your body and mind! Overcoming obstacles ... You'll see what I mean if you take on my challenge.
|
||||
RefusalMessage = 1074528; // My way of life isn't for everyone, that's true enough.
|
||||
InProgressMessage = 1074529; // You're not making much progress in the honing-mind-and-body department, are you?
|
||||
CompletionNotice = CompletionNoticeShortReturn;
|
||||
|
||||
Objectives.Add(new KillObjective(5, new[] { typeof(Efreet) }, "efreets",
|
||||
new QuestArea(1074808, "Fire"))); // Fire
|
||||
Objectives.Add(new KillObjective(5, new[] { typeof(IceFiend) }, "ice fiends",
|
||||
new QuestArea(1074809, "Ice"))); // Ice
|
||||
|
||||
Rewards.Add(new DummyReward(1074875)); // Another step closer to becoming human.
|
||||
}
|
||||
|
||||
public override bool RecordCompletion => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.Player.SendLocalizedMessage(1074947, "",
|
||||
0x2A); // You have demonstrated your toughness! Humans are able to endure unimaginable hardships in pursuit of their goals. You are one step closer to achieving humanity.
|
||||
instance.ClaimRewards(); // skip gump
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Belulah"), new Point3D(3782, 1266, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Belulah"), new Point3D(3782, 1266, 0), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Elf To Human Mobiles
|
||||
|
||||
[QuesterName("Sledge (Buc's Den)")]
|
||||
public class Sledge : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Sledge()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Versatile";
|
||||
Body = 400;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
AddItem(new Tunic(Utility.RandomNeutralHue()));
|
||||
AddItem(new LongPants(Utility.RandomBlueHue()));
|
||||
AddItem(new Cloak(Utility.RandomBrightHue()));
|
||||
AddItem(new ElvenBoots(Utility.RandomNeutralHue()));
|
||||
AddItem(new Backpack());
|
||||
}
|
||||
|
||||
public Sledge(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Sledge";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, Utility.RandomList(
|
||||
1074188, // Weakling! You are not up to the task I have.
|
||||
1074195 // You there, in the stupid hat! Come here.
|
||||
));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Patricus (Vesper)")]
|
||||
public class Patricus : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Patricus()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Trader";
|
||||
Body = 400;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
AddItem(new FancyShirt(Utility.RandomNeutralHue()));
|
||||
AddItem(new LongPants(Utility.RandomBrightHue()));
|
||||
AddItem(new Cloak(0x1BB));
|
||||
AddItem(new Shoes(Utility.RandomNeutralHue()));
|
||||
AddItem(new Backpack());
|
||||
}
|
||||
|
||||
public Patricus(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Patricus";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Belulah (Nujel'm)")] // On OSI it's "Belulah (Nu'Jelm)" (incorrect spelling)
|
||||
public class Belulah : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Belulah()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the scorned";
|
||||
Female = true;
|
||||
Body = 401;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new FancyShirt(Utility.RandomBlueHue()));
|
||||
AddItem(new LongPants(Utility.RandomNondyedHue()));
|
||||
AddItem(new Boots());
|
||||
}
|
||||
|
||||
public Belulah(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Belulah";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
/*
|
||||
* 1074205 - Oh great adventurer, would you please assist a weak soul in need of aid?
|
||||
* 1074206 - Excuse me please traveler, might I have a little of your time?
|
||||
*/
|
||||
MLQuestSystem.Tell(this, pm, Utility.Random(1074205, 2));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
164
Projects/Scripts/Engines/MLQuests/Definitions/HonestBeggar.cs
Normal file
164
Projects/Scripts/Engines/MLQuests/Definitions/HonestBeggar.cs
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Quests
|
||||
|
||||
public class HonestBeggar : MLQuest
|
||||
{
|
||||
public HonestBeggar()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1075392; // Honest Beggar
|
||||
Description =
|
||||
1075393; // Beg pardon, sir. I mean, madam. Uh, can I ask a favor of you? I found this jeweled ring. Most people would sell it and keep the money, but not me. I ain't never stole nothing, and I ain't about to start. I tried to take it over to Brit castle, figgerin' it must belong to some highborn lady, but the guards threw me out. You look like they might let you pass. Will you take the ring over there and see if you can find the owner?
|
||||
RefusalMessage = 1075395; // I see. Too good to help an honest beggar like me, eh?
|
||||
InProgressMessage =
|
||||
1075396; // A jewel like this must be worth a lot, so it must belong to some noble or another. I would show it around the castle. Someone<6E>s bound to recognize it.
|
||||
CompletionMessage =
|
||||
1075397; // Didst thou find my ring? I thank thee very much! It is an old ring, and a gift from my husband. I was most distraught when I realized it was missing.
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(ReginasRing), 1, "Regina's Ring", typeof(Regina)));
|
||||
|
||||
Rewards.Add(new DummyReward(1075394)); // Find the ring<6E>s owner.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(ReginasThanks);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 4, "Evan"), new Point3D(1486, 1706, 0), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 4, "Evan"), new Point3D(1486, 1706, 0), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
public class ReginasThanks : MLQuest
|
||||
{
|
||||
public ReginasThanks()
|
||||
{
|
||||
Activated = true;
|
||||
OneTimeOnly = true;
|
||||
Title = 1075398; // Regina<6E>s Thanks
|
||||
Description =
|
||||
1075399; // What<61>s that you say? It was a humble beggar that found my ring? Such honesty must be rewarded. Here, take this packet and return it to him, and I will be in your debt.
|
||||
RefusalMessage = 1075401; // Hmph. Very well. What did you say his name was?
|
||||
InProgressMessage = 1075402; // Take the packet and return it to the beggar who found my ring.
|
||||
CompletionMessage =
|
||||
1075403; // What? For me? Let me see . . . these sapphire earrings are for you, it says. Oh, she wants to offer me a job! This is the most wonderful thing that ever happened to me!
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(ReginasLetter), 1, "Regina's Letter", typeof(Evan)));
|
||||
|
||||
Rewards.Add(new ItemReward(1075400, typeof(TransparentHeart))); // Transparent Heart
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 0, "Regina"), new Point3D(1362, 1622, 50), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Regina"), new Point3D(1422, 1621, 20), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
public class Evan : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Evan()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Beggar";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x190;
|
||||
Female = false;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Doublet());
|
||||
AddItem(new ShortPants(0x755));
|
||||
}
|
||||
|
||||
public Evan(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Evan";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Regina : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Regina()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Noble";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x191;
|
||||
Female = true;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new GildedDress());
|
||||
AddItem(new Boots());
|
||||
}
|
||||
|
||||
public Regina(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Regina";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
347
Projects/Scripts/Engines/MLQuests/Definitions/Ilshenar.cs
Normal file
347
Projects/Scripts/Engines/MLQuests/Definitions/Ilshenar.cs
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
public class Responsibility : BaseEscort
|
||||
{
|
||||
public Responsibility()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074352; // Responsibility
|
||||
Description =
|
||||
1074524; // Oh! I just don't know what to do. My mother is away and my father told me not to talk to strangers ... *worried frown* But my grandfather has sent word that he has been hurt and needs me to tend his wounds. He has a small farm southeast of here. Would you ... could you ... escort me there safely?
|
||||
RefusalMessage = 1074525; // I hope my grandfather will be alright.
|
||||
InProgressMessage =
|
||||
1074526; // Grandfather's farm is a ways west of the Shrine of Spirituality. So, we're not quite there yet. Thank you again for keeping me safe.
|
||||
|
||||
Objectives.Add(new EscortObjective(new QuestArea(1074781, "Sheep Farm"))); // Sheep Farm
|
||||
|
||||
Rewards.Add(ItemReward.BagOfTrinkets);
|
||||
}
|
||||
|
||||
// OSI sends this instead, but it doesn't make sense for an escortable
|
||||
//public override void OnComplete( MLQuestInstance instance )
|
||||
//{
|
||||
// instance.Player.SendLocalizedMessage( 1073775, "", 0x23 ); // Your quest is complete. Return for your reward.
|
||||
//}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30), 0, 5, "Lissbet"),
|
||||
new Point3D(1568, 1040, -7), Map.Ilshenar);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 8, "GrandpaCharley"), new Point3D(1322, 1331, -14), Map.Ilshenar);
|
||||
PutSpawner(new Spawner(1, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30), 0, 3, "Sheep"),
|
||||
new Point3D(1308, 1324, -14), Map.Ilshenar);
|
||||
}
|
||||
}
|
||||
|
||||
public class SomethingToWailAbout : MLQuest
|
||||
{
|
||||
public SomethingToWailAbout()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1073071; // Something to Wail About
|
||||
Description =
|
||||
1073561; // Can you hear them? The never-ending howling? The incessant wailing? These banshees, they never cease! Never! They haunt my nights. Please, I beg you -- will you silence them? I would be ever so grateful.
|
||||
RefusalMessage = 1073580; // I hope you'll reconsider. Until then, farwell.
|
||||
InProgressMessage = 1073581; // Until you kill 12 Wailing Banshees, there will be no peace.
|
||||
|
||||
Objectives.Add(new KillObjective(12, new[] { typeof(WailingBanshee) }, "wailing banshees"));
|
||||
|
||||
Rewards.Add(ItemReward.BagOfTreasure);
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 4, "Jelrice"), new Point3D(1176, 1196, -25), Map.Ilshenar);
|
||||
}
|
||||
}
|
||||
|
||||
public class Runaways : MLQuest
|
||||
{
|
||||
public Runaways()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072993; // Runaways!
|
||||
Description =
|
||||
1073026; // You've got to help me out! Those wild ostards have been causing absolute havok around here. Kill them off before they destroy my land. There are around twelve of them.
|
||||
RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me.
|
||||
InProgressMessage = 1072271; // You're not quite done yet. Get back to work!
|
||||
|
||||
Objectives.Add(new KillObjective(12, new[] { typeof(FrenziedOstard) }, "frenzied ostards"));
|
||||
|
||||
Rewards.Add(ItemReward.BagOfTrinkets);
|
||||
}
|
||||
}
|
||||
|
||||
public class ViciousPredator : MLQuest
|
||||
{
|
||||
public ViciousPredator()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072994; // Vicious Predator
|
||||
Description =
|
||||
1073028; // You've got to help me out! Those dire wolves have been causing absolute havok around here. Kill them off before they destroy my land. They run around in a pack of around ten.
|
||||
RefusalMessage = 1072270; // Well, okay. But if you decide you are up for it after all, c'mon back and see me.
|
||||
InProgressMessage = 1072271; // You're not quite done yet. Get back to work!
|
||||
|
||||
Objectives.Add(new KillObjective(10, new[] { typeof(DireWolf) }, "dire wolves"));
|
||||
|
||||
Rewards.Add(ItemReward.BagOfTrinkets);
|
||||
}
|
||||
}
|
||||
|
||||
public class GuileIrkAndSpite : MLQuest
|
||||
{
|
||||
public GuileIrkAndSpite()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074739; // Guile, Irk and Spite
|
||||
Description =
|
||||
1074740; // You know them, don't you. The three? They look like you, you'll see. They looked like me, I remember, they looked like, well, you'll see. The three. They'll drive you mad too, if you let them. They are trouble, and they need to be slain. Seek them out.
|
||||
RefusalMessage =
|
||||
1074745; // You just don't understand the gravity of the situation. If you did, you'd agree to my task.
|
||||
InProgressMessage =
|
||||
1074746; // Perhaps I was unclear. You'll know them when you see them, because you'll see you, and you, and you. Hurry now.
|
||||
CompletionMessage =
|
||||
1074747; // Are you one of THEM? Ahhhh! Oh, wait, if you were them, then you'd be me. So you're -- you. Good job!
|
||||
|
||||
Objectives.Add(new KillObjective(1, new[] { typeof(Guile) }, "Guile"));
|
||||
Objectives.Add(new KillObjective(1, new[] { typeof(Irk) }, "Irk"));
|
||||
Objectives.Add(new KillObjective(1, new[] { typeof(Spite) }, "Spite"));
|
||||
|
||||
Rewards.Add(ItemReward.Strongbox);
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "Yorus"), new Point3D(1389, 423, -24), Map.Ilshenar);
|
||||
}
|
||||
}
|
||||
|
||||
public class Lissbet : BaseEscortable
|
||||
{
|
||||
[Constructible]
|
||||
public Lissbet()
|
||||
{
|
||||
}
|
||||
|
||||
public Lissbet(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool StaticMLQuester => true;
|
||||
public override bool InitialInnocent => true;
|
||||
public override string DefaultName => "Lissbet";
|
||||
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, Utility.RandomList(
|
||||
1074204, // Greetings seeker. I have an urgent matter for you, if you are willing.
|
||||
1074222 // Could I trouble you for some assistance?
|
||||
));
|
||||
}
|
||||
|
||||
public override void InitBody()
|
||||
{
|
||||
SetStr(40, 50);
|
||||
SetDex(70, 80);
|
||||
SetInt(80, 90);
|
||||
|
||||
Hue = Race.Human.RandomSkinHue();
|
||||
Female = true;
|
||||
Body = 401;
|
||||
|
||||
Title = "the flower girl";
|
||||
|
||||
HairItemID = 0x203D;
|
||||
HairHue = 0x1BB;
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
AddItem(new Kilt(Utility.RandomYellowHue()));
|
||||
AddItem(new FancyShirt(Utility.RandomYellowHue()));
|
||||
AddItem(new Sandals());
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class GrandpaCharley : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public GrandpaCharley()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the farmer";
|
||||
Body = 400;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
int hairHue = 0x3B2 + Utility.Random(2);
|
||||
Utility.AssignRandomHair(this, hairHue);
|
||||
|
||||
FacialHairItemID = 0x203E; // Long Beard
|
||||
FacialHairHue = hairHue;
|
||||
|
||||
SetSkill(SkillName.ItemID, 80, 90);
|
||||
|
||||
AddItem(new WideBrimHat(Utility.RandomNondyedHue()));
|
||||
AddItem(new FancyShirt(Utility.RandomNondyedHue()));
|
||||
AddItem(new LongPants(Utility.RandomNondyedHue()));
|
||||
AddItem(new Sandals(Utility.RandomNeutralHue()));
|
||||
AddItem(new ShepherdsCrook());
|
||||
AddItem(new Backpack());
|
||||
}
|
||||
|
||||
public GrandpaCharley(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Grandpa Charley";
|
||||
public override bool CanTeach => true;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Jelrice (Ilshenar)")]
|
||||
public class Jelrice : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Jelrice()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the trader";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x191;
|
||||
Female = true;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Shoes(Utility.RandomNeutralHue()));
|
||||
AddItem(new Skirt(Utility.RandomBlueHue()));
|
||||
AddItem(new FancyShirt(Utility.RandomRedHue()));
|
||||
}
|
||||
|
||||
public Jelrice(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Jelrice";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, 1074221); // Greetings! I have a small task for you good traveler.
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Yorus (Ilshenar)")]
|
||||
public class Yorus : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Yorus()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the tinker";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x190;
|
||||
Female = false;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Shoes(Utility.RandomNeutralHue()));
|
||||
AddItem(new LongPants(Utility.RandomBlueHue()));
|
||||
AddItem(new FancyShirt(Utility.RandomOrangeHue()));
|
||||
AddItem(new Cloak(Utility.RandomBrightHue()));
|
||||
}
|
||||
|
||||
public Yorus(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Yorus";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, 1074218); // Hey! I want to talk to you, now.
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
71
Projects/Scripts/Engines/MLQuests/Definitions/LostItems.cs
Normal file
71
Projects/Scripts/Engines/MLQuests/Definitions/LostItems.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Items;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
// TODO: Assassination Contract, Evidence, Lost in Transit, Last Words
|
||||
|
||||
#region Quests
|
||||
|
||||
public class LostAndFound : MLQuest
|
||||
{
|
||||
public LostAndFound()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072370; // Lost and Found
|
||||
Description =
|
||||
1072589; // The battered, old bucket is inscribed with barely legible writing that indicates it belongs to someone named "Dallid". Maybe they'd pay for its return?
|
||||
RefusalMessage =
|
||||
1072590; // You're right, who cares if Dallid might pay for his battered old bucket back. This way you can carry it around with you!
|
||||
InProgressMessage = 1072591; // Whoever this "Dallid" might be, he's probably looking for his bucket.
|
||||
CompletionMessage =
|
||||
1074580; // Is that my bucket? I had to ditch my favorite bucket when a group of ratmen jumped me!
|
||||
|
||||
Objectives.Add(new TimedDeliverObjective(TimeSpan.FromSeconds(600), typeof(BatteredBucket), 1, "battered bucket",
|
||||
typeof(Dallid), false));
|
||||
|
||||
Rewards.Add(ItemReward.BagOfTrinkets);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Items
|
||||
|
||||
public class BatteredBucket : TransientQuestGiverItem
|
||||
{
|
||||
[Constructible]
|
||||
public BatteredBucket()
|
||||
: base(0x2004, TimeSpan.FromMinutes(10))
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public BatteredBucket(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
// Original label, doesn't fit the expiration message well
|
||||
//public override int LabelNumber => 1073129; // A battered bucket.
|
||||
|
||||
public override string DefaultName => "battered bucket";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
93
Projects/Scripts/Engines/MLQuests/Definitions/Malas.cs
Normal file
93
Projects/Scripts/Engines/MLQuests/Definitions/Malas.cs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Quests
|
||||
|
||||
public class PointyEars : MLQuest
|
||||
{
|
||||
public PointyEars()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074640; // Pointy Ears
|
||||
Description =
|
||||
1074641; // I've heard ... there's some that will pay a good bounty for pointed ears, much like we used to pay for each wolf skin. I've got nothing personal against these elves. It's just business. You want in on this? I'm not fussy who I work with.
|
||||
RefusalMessage = 1074642; // Suit yourself.
|
||||
InProgressMessage = 1074643; // I can't pay a bounty if you don't bring bag the ears.
|
||||
CompletionMessage = 1074644; // Here to collect on a bounty?
|
||||
|
||||
Objectives.Add(new CollectObjective(20, typeof(SeveredElfEars), 1032590)); // severed elf ears
|
||||
|
||||
Rewards.Add(ItemReward.BagOfTrinkets);
|
||||
}
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 4, "Drithen"), new Point3D(1983, 1364, -80), Map.Malas);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
[QuesterName("Drithen (Umbra)")]
|
||||
public class Drithen : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Drithen()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Fierce";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x190;
|
||||
Female = false;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new ElvenBoots(Utility.RandomNeutralHue()));
|
||||
AddItem(new LongPants(Utility.RandomBlueHue()));
|
||||
AddItem(new Tunic(Utility.RandomNeutralHue()));
|
||||
AddItem(new Cloak(Utility.RandomBrightHue()));
|
||||
|
||||
SetSkill(SkillName.Focus, 60.0, 80.0);
|
||||
}
|
||||
|
||||
public Drithen(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override bool CanTeach => true;
|
||||
public override string DefaultName => "Drithen";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, 1074188); // Weakling! You are not up to the task I have.
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,356 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Items;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Quests
|
||||
|
||||
public class MistakenIdentity : MLQuest
|
||||
{
|
||||
public MistakenIdentity()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074573; // Mistaken Identity
|
||||
Description =
|
||||
1074574; // What do you want? Wonderful, another whining request for a refund on tuition. You know, experiences like that are invaluable ... and infrequent. Having the opportunity to test yourself under such realistic situations isn't something the college offers all students. Fine. Fine. You'll need to submit a refund request form in triplicate before I can return your 1,000,000 gold tuition. You'll need to get some signatures and a few other odds and ends.
|
||||
RefusalMessage = 1074606; // If you're not willing to follow the proper process then go away.
|
||||
InProgressMessage = 1074605; // You're not getting a refund without the proper forms and signatures.
|
||||
CompletionMessage = 1074607; // Oh blast! Not another of those forms. I'm so sick of this endless paperwork.
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(TuitionReimbursementForm), 1, "Tuition Reimbursement Form",
|
||||
typeof(Gorrow)));
|
||||
|
||||
Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(YouScratchMyBack);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 4, "Aernya"), new Point3D(2095, 1380, -90), Map.Malas);
|
||||
}
|
||||
}
|
||||
|
||||
public class YouScratchMyBack : MLQuest
|
||||
{
|
||||
public YouScratchMyBack()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074608; // You Scratch My Back
|
||||
Description =
|
||||
1074609; // Heh. Heheheh. Good one. You're not a Bedlam student and you're definitely not eligible for a tuition refund. Heheheh. That old witch Aernya doesn't see as well as she used to you know. Otherwise, she would have ... hmmm, wait a minute. I sense a certain 'opportunity' here. I'll sign your forms in return for a little help with a project of my own. What do you say?
|
||||
RefusalMessage = 1074615; // Hehehe. Your choice.
|
||||
InProgressMessage =
|
||||
1074616; // I'm something of a gourmet, you see. It's tough getting some of the ingredients, though. Bring me back some pixie legs, unicorn ribs and ki-rin brains and I'll sign your form.
|
||||
CompletionMessage =
|
||||
1074617; // Oh excellent, you're back. I'll get the oven going. That thing about pixie legs, you see, is that they burn and dry out if you're not really careful. Taste just like chicken too!
|
||||
CompletionNotice = CompletionNoticeShortReturn;
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(UnicornRibs), "Unicorn Ribs"));
|
||||
Objectives.Add(new CollectObjective(2, typeof(KirinBrains), "Ki-Rin Brains"));
|
||||
Objectives.Add(new CollectObjective(5, typeof(PixieLeg), "Pixie Leg"));
|
||||
|
||||
Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(FoolingAernya);
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 4, "Gorrow"), new Point3D(993, 512, -50), Map.Malas);
|
||||
}
|
||||
}
|
||||
|
||||
public class FoolingAernya : MLQuest
|
||||
{
|
||||
public FoolingAernya()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074618; // Fooling Aernya
|
||||
Description =
|
||||
1074619; // Now that I've signed your papers you'd better get back to that witch Aernya. Mmmm mmm smell those ribs!
|
||||
RefusalMessage = 1074620; // Giving up on your scheme eh? Suit yourself.
|
||||
InProgressMessage =
|
||||
1074621; // You better hurry back to Mistress Aernya with that signed form. The college only has so much money and with enough claims you may find yourself unable to get your tuition refunded. *wink*
|
||||
CompletionMessage = 1074622; // What? Hrmph. Gorrow signed your form did he? Let me see that. *squint*
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(SignedTuitionReimbursementForm), 1,
|
||||
"Signed Tuition Reimbursement Form", typeof(Aernya)));
|
||||
|
||||
Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(NotQuiteThatEasy);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class NotQuiteThatEasy : MLQuest
|
||||
{
|
||||
public NotQuiteThatEasy()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074623; // Not Quite That Easy
|
||||
Description =
|
||||
1074624; // I wouldn't be too smug just yet, whiner. You still need Master Gnosos' signature before I can cut your refund. Last I heard, he's coordinating the recovery of the portions of the college that are currently overrun. *nasty smile* Off with you.
|
||||
RefusalMessage = 1074626; // Coward.
|
||||
InProgressMessage = 1074627; // What are you waiting for? The iron maiden is still the portal to Bedlam.
|
||||
CompletionMessage =
|
||||
1074628; // Made it through did you? Did you happen to see Red Death out there? Big horse, skeletal ... burning eyes? No? What's this? Forms? FORMS? I'm up to my eyebrows in ravenous out-of-control undead and you want a signature?
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(SignedTuitionReimbursementForm), 1,
|
||||
"Signed Tuition Reimbursement Form", typeof(MasterGnosos)));
|
||||
|
||||
Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(ConvinceMe);
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutDeco(new BedlamTeleporter(), new Point3D(2067, 1371, -75), Map.Malas);
|
||||
}
|
||||
|
||||
public override void OnAccepted(MLQuestInstance instance)
|
||||
{
|
||||
instance.PlayerContext.BedlamAccess = true; // Permanent access
|
||||
}
|
||||
}
|
||||
|
||||
public class ConvinceMe : MLQuest
|
||||
{
|
||||
public ConvinceMe()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074629; // Convince Me
|
||||
Description =
|
||||
1074630; // I'm not signing any forms until the situation here is under control. So, you can either help out or you can forget getting your tuition refund. Which will it be? Help control the shambling dead?
|
||||
RefusalMessage = 1074631; // No signature for you.
|
||||
InProgressMessage =
|
||||
1074632; // No signature for you until you kill off some of the shambling dead out there and destroy that blasted horse.
|
||||
CompletionMessage = 1074633; // Pulled it off huh? Well then you've earned this signature!
|
||||
CompletionNotice = CompletionNoticeShortReturn;
|
||||
|
||||
QuestArea bedlam = new QuestArea(1074835, "Bedlam"); // Bedlam
|
||||
|
||||
Objectives.Add(new KillObjective(1, new[] { typeof(RedDeath) }, "Red Death", bedlam));
|
||||
Objectives.Add(new KillObjective(10, new[] { typeof(GoreFiend) }, "gore fiends", bedlam));
|
||||
Objectives.Add(new KillObjective(8, new[] { typeof(RottingCorpse) }, "rotting corpses", bedlam));
|
||||
|
||||
Rewards.Add(new DummyReward(1074634)); // Tuition Reimbursement
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(TuitionReimbursement);
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "MasterGnosos"), new Point3D(87, 1639, 0), Map.Malas);
|
||||
}
|
||||
}
|
||||
|
||||
public class TuitionReimbursement : MLQuest
|
||||
{
|
||||
public TuitionReimbursement()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074634; // Tuition Reimbursement
|
||||
Description =
|
||||
1074635; // Well, there you are. I've added my signature to that of Gorrow, so you should be set to return to Mistress Aernya and get your tuition refunded.
|
||||
RefusalMessage =
|
||||
1074636; // Great! If you're going to stick around here, I know we have more tasks for you to perform.
|
||||
InProgressMessage =
|
||||
1074637; // Just head out the main gates there and you'll find yourself embracing the iron maiden in the Bloodletter's Guild.
|
||||
CompletionMessage =
|
||||
1074638; // *disinterested stare* What? Oh, you've gotten your form filled in. How nice. *glare* And I'd hoped you'd drop this charade before I was forced to rub your nose in it. *nasty smile* You're not even a student and as such, you're not eligible for a refund -- you've never paid tuition. For your services, Master Gnosos has recommended you receive pay. So here. Now go away.
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(CompletedTuitionReimbursementForm), 1,
|
||||
"Completed Tuition Reimbursement Form", typeof(Aernya)));
|
||||
|
||||
Rewards.Add(ItemReward.Strongbox);
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
[QuesterName("Aernya (Umbra)")]
|
||||
public class Aernya : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Aernya()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Mistress of Admissions";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x191;
|
||||
Female = true;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Sandals(Utility.RandomNeutralHue()));
|
||||
AddItem(new Skirt(Utility.RandomBool() ? 0x1 : 0x0));
|
||||
AddItem(new Cloak(Utility.RandomBrightHue()));
|
||||
AddItem(new FancyShirt(Utility.RandomBool() ? 0x3B2 : 0x3B3));
|
||||
}
|
||||
|
||||
public Aernya(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Aernya";
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Gorrow (Luna)")]
|
||||
public class Gorrow : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Gorrow()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Mayor";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x190;
|
||||
Female = false;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Shoes(0x1BB));
|
||||
AddItem(new Tunic(Utility.RandomNeutralHue()));
|
||||
AddItem(new LongPants(0x901));
|
||||
AddItem(new Cloak(Utility.RandomRedHue()));
|
||||
}
|
||||
|
||||
public Gorrow(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override string DefaultName => "Gorrow";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, Utility.RandomList(
|
||||
1074200, // Thank goodness you are here, there<72>s no time to lose.
|
||||
1074203 // Hello friend. I realize you are busy but if you would be willing to render me a service I can assure you that you will be judiciously renumerated.
|
||||
));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Master Gnosos (Bedlam)")]
|
||||
public class MasterGnosos : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public MasterGnosos()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the necromancer";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x190;
|
||||
Female = false;
|
||||
Hue = 0x83E8;
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
HairItemID = 0x2049;
|
||||
FacialHairItemID = 0x204B;
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Shoes(0x485));
|
||||
AddItem(new Robe(0x497));
|
||||
|
||||
SetSkill(SkillName.EvalInt, 60.0, 80.0);
|
||||
SetSkill(SkillName.Inscribe, 60.0, 80.0);
|
||||
SetSkill(SkillName.MagicResist, 60.0, 80.0);
|
||||
SetSkill(SkillName.SpiritSpeak, 60.0, 80.0);
|
||||
SetSkill(SkillName.Meditation, 60.0, 80.0);
|
||||
SetSkill(SkillName.Necromancy, 60.0, 80.0);
|
||||
}
|
||||
|
||||
public MasterGnosos(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override bool CanTeach => true;
|
||||
public override string DefaultName => "Master Gnosos";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, 1074186); // Come here, I have a task.
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
125
Projects/Scripts/Engines/MLQuests/Definitions/NewHaven.cs
Normal file
125
Projects/Scripts/Engines/MLQuests/Definitions/NewHaven.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
public class NewHavenEscort : BaseEscort
|
||||
{
|
||||
// Escort reward
|
||||
private static readonly BaseReward m_Reward = new ItemReward("Gold", typeof(Gold), 500);
|
||||
|
||||
public NewHavenEscort(int title, int description, int progress, int destination, string region)
|
||||
{
|
||||
Activated = true;
|
||||
Title = title;
|
||||
Description = description;
|
||||
RefusalMessage =
|
||||
1072288; // I wish you would reconsider my offer. I'll be waiting right here for someone brave enough to assist me.
|
||||
InProgressMessage = progress;
|
||||
|
||||
Objectives.Add(new EscortObjective(new QuestArea(destination, region)));
|
||||
|
||||
Rewards.Add(m_Reward);
|
||||
}
|
||||
|
||||
// New Haven escorts do not count for 'helping a human in need'
|
||||
public override bool AwardHumanInNeed => false;
|
||||
}
|
||||
|
||||
public class EscortToNHAlchemist : NewHavenEscort
|
||||
{
|
||||
public EscortToNHAlchemist()
|
||||
: base(1072314, 1042769, 1072326, 1073864, "the New Haven Alchemist")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHBard : NewHavenEscort
|
||||
{
|
||||
public EscortToNHBard()
|
||||
: base(1072315, 1042772, 1072327, 1073865, "the New Haven Bard")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHWarrior : NewHavenEscort
|
||||
{
|
||||
public EscortToNHWarrior()
|
||||
: base(1072316, 1042787, 1072328, 1073866, "the New Haven Warrior")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHTailor : NewHavenEscort
|
||||
{
|
||||
public EscortToNHTailor()
|
||||
: base(1072317, 1042781, 1072329, 1073867, "the New Haven Tailor")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHCarpenter : NewHavenEscort
|
||||
{
|
||||
public EscortToNHCarpenter()
|
||||
: base(1072318, 1042775, 1072330, 1073868, "the New Haven Carpenter")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHMapmaker : NewHavenEscort
|
||||
{
|
||||
public EscortToNHMapmaker()
|
||||
: base(1072319, 1042793, 1072331, 1073869, "the New Haven Mapmaker")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHMage : NewHavenEscort
|
||||
{
|
||||
public EscortToNHMage()
|
||||
: base(1072320, 1042790, 1072332, 1073870, "the New Haven Mage")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHInn : NewHavenEscort
|
||||
{
|
||||
public EscortToNHInn()
|
||||
: base(1072321, 1042796, 1072333, 1073871, "the New Haven Inn")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHFarm : NewHavenEscort
|
||||
{
|
||||
public EscortToNHFarm()
|
||||
: base(1072322, 1042799, 1072334, 1073872, "the New Haven Farm")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHDocks : NewHavenEscort
|
||||
{
|
||||
public EscortToNHDocks()
|
||||
: base(1072323, 1042802, 1072335, 1073873, "the New Haven Docks")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHBowyer : NewHavenEscort
|
||||
{
|
||||
public EscortToNHBowyer()
|
||||
: base(1072324, 1042805, 1072336, 1073874, "the New Haven Bowyer")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNHBank : NewHavenEscort
|
||||
{
|
||||
public EscortToNHBank()
|
||||
: base(1072325, 1042784, 1072337, 1073875, "the New Haven Bank")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
1039
Projects/Scripts/Engines/MLQuests/Definitions/NewHavenTraining.cs
Normal file
1039
Projects/Scripts/Engines/MLQuests/Definitions/NewHavenTraining.cs
Normal file
File diff suppressed because it is too large
Load diff
1314
Projects/Scripts/Engines/MLQuests/Definitions/Sanctuary.cs
Normal file
1314
Projects/Scripts/Engines/MLQuests/Definitions/Sanctuary.cs
Normal file
File diff suppressed because it is too large
Load diff
727
Projects/Scripts/Engines/MLQuests/Definitions/Spellweaving.cs
Normal file
727
Projects/Scripts/Engines/MLQuests/Definitions/Spellweaving.cs
Normal file
|
|
@ -0,0 +1,727 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
public static class Spellweaving
|
||||
{
|
||||
public static void AwardTo(PlayerMobile pm)
|
||||
{
|
||||
if (pm == null)
|
||||
return;
|
||||
|
||||
MLQuestContext context = MLQuestSystem.GetOrCreateContext(pm);
|
||||
|
||||
if (!context.Spellweaving)
|
||||
{
|
||||
context.Spellweaving = true;
|
||||
|
||||
Effects.SendLocationParticles(EffectItem.Create(pm.Location, pm.Map, EffectItem.DefaultDuration), 0, 0, 0, 0,
|
||||
0, 5060, 0);
|
||||
Effects.PlaySound(pm.Location, pm.Map, 0x243);
|
||||
|
||||
Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(pm.X - 6, pm.Y - 6, pm.Z + 15), pm.Map), pm,
|
||||
0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100);
|
||||
Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(pm.X - 4, pm.Y - 6, pm.Z + 15), pm.Map), pm,
|
||||
0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100);
|
||||
Effects.SendMovingParticles(new Entity(Serial.Zero, new Point3D(pm.X - 6, pm.Y - 4, pm.Z + 15), pm.Map), pm,
|
||||
0x36D4, 7, 0, false, true, 0x497, 0, 9502, 1, 0, (EffectLayer)255, 0x100);
|
||||
|
||||
Effects.SendTargetParticles(pm, 0x375A, 35, 90, 0x00, 0x00, 9502, (EffectLayer)255, 0x100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Patience
|
||||
|
||||
public class Patience : MLQuest
|
||||
{
|
||||
public Patience()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072753; // Patience
|
||||
Description =
|
||||
1072762; // Learning to weave spells and control the forces of nature requires sacrifice, discipline, focus, and an unwavering dedication to Sosaria herself. We do not teach the unworthy. They do not comprehend the lessons nor the dedication required. If you would walk the path of the Arcanist, then you must do as I require without hesitation or question. Your first task is to gather miniature mushrooms ... 20 of them from the branches of our mighty home. I give you one hour to complete the task.
|
||||
RefusalMessage = 1072767; // *nods* Not everyone has the temperment to undertake the way of the Arcanist.
|
||||
InProgressMessage =
|
||||
1072774; // The mushrooms I seek can be found growing here in The Heartwood. Seek them out and gather them. You are running out of time.
|
||||
CompletionMessage = 1074166; // Have you gathered the mushrooms?
|
||||
|
||||
Objectives.Add(new TimedCollectObjective(TimeSpan.FromHours(1), 20, typeof(MiniatureMushroom),
|
||||
"miniature mushrooms"));
|
||||
|
||||
Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(NeedsOfTheManyHeartwood1);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Aeluva"), new Point3D(7064, 349, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Aeluva"), new Point3D(7064, 349, 0), Map.Trammel);
|
||||
|
||||
// Split up to prevent stacking on the spawner
|
||||
PutSpawner(new Spawner(20, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 30, "MiniatureMushroom"),
|
||||
new Point3D(7015, 366, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(20, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 30, "MiniatureMushroom"),
|
||||
new Point3D(7015, 366, 0), Map.Trammel);
|
||||
|
||||
PutSpawner(new Spawner(5, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"),
|
||||
new Point3D(7081, 373, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(5, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"),
|
||||
new Point3D(7081, 373, 0), Map.Trammel);
|
||||
|
||||
PutSpawner(new Spawner(15, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"),
|
||||
new Point3D(7052, 414, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(15, TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), 0, 20, "MiniatureMushroom"),
|
||||
new Point3D(7052, 414, 0), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
public class NeedsOfTheManyHeartwood1 : MLQuest
|
||||
{
|
||||
public NeedsOfTheManyHeartwood1()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072797; // Needs of the Many - The Heartwood
|
||||
Description =
|
||||
1072763; // The way of the Arcanist involves cooperation with others and a strong commitment to the community of your people. We have run low on the cotton we use to pack wounds and our people have need. Bring 10 bales of cotton to me.
|
||||
RefusalMessage = 1072768; // You endanger your progress along the path with your unwillingness.
|
||||
InProgressMessage = 1072775; // I care not where you acquire the cotton, merely that you provide it.
|
||||
CompletionMessage = 1074110; // Well, where are the cotton bales?
|
||||
|
||||
Objectives.Add(new CollectObjective(10, typeof(Cotton), 1023577)); // bale of cotton
|
||||
|
||||
Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(NeedsOfTheManyHeartwood2);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class NeedsOfTheManyHeartwood2 : MLQuest
|
||||
{
|
||||
public NeedsOfTheManyHeartwood2()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072797; // Needs of the Many - The Heartwood
|
||||
Description = 1072764; // We must look to the defense of our people! Bring boards for new arrows.
|
||||
RefusalMessage =
|
||||
1072769; // The people have need of these items. You are proving yourself inadequate to the demands of a member of this community.
|
||||
InProgressMessage = 1072776; // The requirements are simple -- 250 boards.
|
||||
CompletionMessage = 1074152; // Well, where are the boards?
|
||||
|
||||
Objectives.Add(new CollectObjective(250, typeof(Board), 1027127)); // board
|
||||
|
||||
Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(MakingAContributionHeartwood);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class MakingAContributionHeartwood : MLQuest
|
||||
{
|
||||
public MakingAContributionHeartwood()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072798; // Making a Contribution - The Heartwood
|
||||
Description =
|
||||
1072765; // With health and defense assured, we need look to the need of the community for food and drink. We will feast on fish steaks, sweets, and wine. You will supply the ingredients, the cooks will prepare the meal. As a Arcanist relies upon others to build focus and lend their power to her workings, the community needs the effort of all to survive.
|
||||
RefusalMessage = 1072770; // Do not falter now. You have begun to show promise.
|
||||
InProgressMessage = 1072777; // Where are the items you've been tasked to supply for the feast?
|
||||
CompletionMessage = 1074158; // Ah good, you're back. We're eager for the feast.
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(SackFlour), 1024153)); // sack of flour
|
||||
Objectives.Add(new CollectObjective(10, typeof(JarHoney), 1022540)); // jar of honey
|
||||
Objectives.Add(new CollectObjective(20, typeof(FishSteak), 1022427)); // fish steak
|
||||
|
||||
Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(UnnaturalCreations);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class UnnaturalCreations : MLQuest
|
||||
{
|
||||
public UnnaturalCreations()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072758; // Unnatural Creations
|
||||
Description =
|
||||
1072780; // You have proven your desire to contribute to the community and serve the people. Now you must demonstrate your willingness to defend Sosaria from the greatest blight that plagues her. Unnatural creatures, brought to a sort of perverted life, despoil our fair world. Destroy them -- 5 Exodus Overseers and 2 Exodus Minions.
|
||||
RefusalMessage =
|
||||
1072771; // You must serve Sosaria with all your heart and strength. Your unwillingness does not reflect favorably upon you.
|
||||
InProgressMessage = 1072779; // Every moment you procrastinate, these unnatural creatures damage Sosaria.
|
||||
CompletionMessage = 1074167; // Well done! Well done, indeed. You are worthy to become an arcanist!
|
||||
|
||||
Objectives.Add(new KillObjective(5, new[] { typeof(ExodusOverseer) }, "Exodus Overseers"));
|
||||
Objectives.Add(new KillObjective(2, new[] { typeof(ExodusMinion) }, "Exodus Minions"));
|
||||
|
||||
Rewards.Add(new ItemReward(1031601, typeof(ArcaneCircleScroll))); // Arcane Circle
|
||||
Rewards.Add(new ItemReward(1031600, typeof(SpellweavingBook))); // Spellweaving Spellbook
|
||||
Rewards.Add(new ItemReward(1031602, typeof(GiftOfRenewalScroll))); // Gift of Renewal
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
Spellweaving.AwardTo(instance.Player);
|
||||
base.GetRewards(instance);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Discipline
|
||||
|
||||
public class Discipline : MLQuest
|
||||
{
|
||||
public Discipline()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072752; // Discipline
|
||||
Description =
|
||||
1072761; // Learning to weave spells and control the forces of nature requires sacrifice, discipline, focus, and an unwavering dedication to Sosaria herself. We do not teach the unworthy. They do not comprehend the lessons nor the dedication required. If you would walk the path of the Arcanist, then you must do as I require without hesitation or question. Your first task is to rid our home of rats ... 50 of them in the next hour.
|
||||
RefusalMessage = 1072767; // *nods* Not everyone has the temperament to undertake the way of the Arcanist.
|
||||
InProgressMessage = 1072773; // You waste my time. The task is simple. Kill 50 rats in an hour.
|
||||
// No completion message
|
||||
|
||||
Objectives.Add(new TimedKillObjective(TimeSpan.FromHours(1), 50, new[] { typeof(Rat) }, "rats",
|
||||
new QuestArea(1074807, "Sanctuary"))); // Sanctuary
|
||||
|
||||
Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(NeedsOfTheManySanctuary);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 0, "Koole"), new Point3D(6257, 110, -10), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 0, "Koole"), new Point3D(6257, 110, -10), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
public class NeedsOfTheManySanctuary : MLQuest
|
||||
{
|
||||
public NeedsOfTheManySanctuary()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072754; // Needs of the Many - Sanctuary
|
||||
Description =
|
||||
1072763; // The way of the Arcanist involves cooperation with others and a strong commitment to the community of your people. We have run low on the cotton we use to pack wounds and our people have need. Bring 10 bales of cotton to me.
|
||||
RefusalMessage = 1072768; // You endanger your progress along the path with your unwillingness.
|
||||
InProgressMessage = 1072775; // I care not where you acquire the cotton, merely that you provide it.
|
||||
CompletionMessage = 1074110; // Well, where are the cotton bales?
|
||||
|
||||
Objectives.Add(new CollectObjective(10, typeof(Cotton), 1023577)); // bale of cotton
|
||||
|
||||
Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(MakingAContributionSanctuary);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class MakingAContributionSanctuary : MLQuest
|
||||
{
|
||||
public MakingAContributionSanctuary()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072755; // Making a Contribution - Sanctuary
|
||||
Description = 1072764; // We must look to the defense of our people! Bring boards for new arrows.
|
||||
RefusalMessage =
|
||||
1072769; // The people have need of these items. You are proving yourself inadequate to the demands of a member of this community.
|
||||
InProgressMessage = 1072776; // The requirements are simple -- 250 boards.
|
||||
CompletionMessage = 1074152; // Well, where are the boards?
|
||||
|
||||
Objectives.Add(new CollectObjective(250, typeof(Board), 1027127)); // board
|
||||
|
||||
Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(SuppliesForSanctuary);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class SuppliesForSanctuary : MLQuest
|
||||
{
|
||||
public SuppliesForSanctuary()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072756; // Supplies for Sanctuary
|
||||
Description =
|
||||
1072765; // With health and defense assured, we need look to the need of the community for food and drink. We will feast on fish steaks, sweets, and wine. You will supply the ingredients, the cooks will prepare the meal. As a Arcanist relies upon others to build focus and lend their power to her workings, the community needs the effort of all to survive.
|
||||
RefusalMessage = 1072770; // Do not falter now. You have begun to show promise.
|
||||
InProgressMessage = 1072777; // Where are the items you've been tasked to supply for the feast?
|
||||
CompletionMessage = 1074158; // Ah good, you're back. We're eager for the feast.
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(SackFlour), 1024153)); // sack of flour
|
||||
Objectives.Add(new CollectObjective(10, typeof(JarHoney), 1022540)); // jar of honey
|
||||
Objectives.Add(new CollectObjective(20, typeof(FishSteak), 1022427)); // fish steak
|
||||
|
||||
Rewards.Add(new DummyReward(1074872)); // The opportunity to learn the ways of the Arcanist.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(TheHumanBlight);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class TheHumanBlight : MLQuest
|
||||
{
|
||||
public TheHumanBlight()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1072757; // The Human Blight
|
||||
Description =
|
||||
1072766; // You have proven your desire to contribute to the community and serve the people. Now you must demonstrate your willingness to defend Sosaria from the greatest blight that plagues her. The human vermin that have spread as a disease, despoiling the land are the greatest blight we face. Kill humans and return to me the proof of your actions. Bring me 30 human ears.
|
||||
RefusalMessage =
|
||||
1072771; // You must serve Sosaria with all your heart and strength. Your unwillingness does not reflect favorably upon you.
|
||||
InProgressMessage = 1072778; // Why do you delay? The human blight must be averted.
|
||||
CompletionMessage = 1074160; // I will take the ears you have collected now. Hand them here.
|
||||
|
||||
Objectives.Add(new CollectObjective(30, typeof(SeveredHumanEars), 1032591)); // severed human ears
|
||||
|
||||
Rewards.Add(new ItemReward(1031601, typeof(ArcaneCircleScroll))); // Arcane Circle
|
||||
Rewards.Add(new ItemReward(1031600, typeof(SpellweavingBook))); // Spellweaving Spellbook
|
||||
Rewards.Add(new ItemReward(1031602, typeof(GiftOfRenewalScroll))); // Gift of Renewal
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
Spellweaving.AwardTo(instance.Player);
|
||||
base.GetRewards(instance);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Friend of the Fey
|
||||
|
||||
public class FriendOfTheFey : MLQuest
|
||||
{
|
||||
public FriendOfTheFey()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074284; // Friend of the Fey
|
||||
Description =
|
||||
1074286; // The children of Sosaria understand the dedication and committment of an arcanist -- and will, from time to time offer their friendship. If you would forge such a bond, first seek out a goodwill offering to present. Pixies enjoy sweets and pretty things.
|
||||
RefusalMessage = 1074288; // There's always time to make new friends.
|
||||
InProgressMessage = 1074290; // I think honey and some sparkly beads would please a pixie.
|
||||
CompletionMessage = 1074292; // What have we here? Oh yes, gifts for a pixie.
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(Beads), 1024235)); // beads
|
||||
Objectives.Add(new CollectObjective(1, typeof(JarHoney), 1022540)); // jar of honey
|
||||
|
||||
Rewards.Add(new DummyReward(
|
||||
1074874)); // The opportunity to prove yourself worthy of learning to Summon Fey. (Sufficient spellweaving skill is required to cast the spell)
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(TokenOfFriendship);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Synaeva"), new Point3D(7064, 350, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Synaeva"), new Point3D(7064, 350, 0), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
public class TokenOfFriendship : MLQuest
|
||||
{
|
||||
public TokenOfFriendship()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074293; // Token of Friendship
|
||||
Description =
|
||||
1074297; // I've wrapped your gift suitably to present to a pixie of discriminating taste. Seek out Arielle and give her your offering.
|
||||
RefusalMessage = 1074310; // I'll hold onto this gift in case you change your mind.
|
||||
InProgressMessage =
|
||||
1074315; // Arielle wanders quite a bit, so I'm not sure exactly where to find her. I'm sure she's going to love your gift.
|
||||
CompletionMessage = 1074319; // *giggle* Oooh! For me?
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(GiftForArielle), 1, "gift for Arielle", typeof(Arielle)));
|
||||
|
||||
Rewards.Add(new DummyReward(
|
||||
1074874)); // The opportunity to prove yourself worthy of learning to Summon Fey. (Sufficient spellweaving skill is required to cast the spell)
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(Alliance);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class Alliance : MLQuest
|
||||
{
|
||||
public Alliance()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074294; // Alliance
|
||||
Description = 1074298; // *giggle* Mean reapers make pixies unhappy. *light-hearted giggle* You could fix them!
|
||||
RefusalMessage = 1074311; // *giggle* Okies!
|
||||
InProgressMessage = 1074316; // Mean reapers are all around trees! *giggle* You fix them up, please.
|
||||
CompletionNotice = CompletionNoticeShortReturn;
|
||||
|
||||
Objectives.Add(new KillObjective(20, new[] { typeof(Reaper) }, "reapers"));
|
||||
|
||||
Rewards.Add(new ItemReward(1031607, typeof(SummonFeyScroll))); // Summon Fey
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.PlayerContext.SummonFey = true;
|
||||
instance.Player.SendLocalizedMessage(1074320, "",
|
||||
0x2A); // *giggle* Mean reapers got fixed! Pixie friend now! *giggle* When mean thingies bother you, a brave pixie will help.
|
||||
|
||||
base.GetRewards(instance);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fiendish Friends
|
||||
|
||||
public class FiendishFriends : MLQuest
|
||||
{
|
||||
public FiendishFriends()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074283; // Fiendish Friends
|
||||
Description =
|
||||
1074285; // It is true that a skilled arcanist can summon and dominate an imp to serve at their pleasure. To do such at thing though, you must master the miserable little fiends utterly by demonstrating your superiority. Rough them up some -- kill a few. That will do the trick.
|
||||
RefusalMessage = 1074287; // You're probably right. They're not worth the effort.
|
||||
InProgressMessage = 1074289; // Surely you're not having difficulties swatting down those annoying pests?
|
||||
// TODO: Verify
|
||||
CompletionMessage = 1074291; // Hah! You showed them!
|
||||
|
||||
Objectives.Add(new KillObjective(50, new[] { typeof(Imp) }, "imps"));
|
||||
|
||||
Rewards.Add(new DummyReward(
|
||||
1074873)); // The opportunity to prove yourself worthy of learning to Summon Fiends. (Sufficient spellweaving skill is required to cast the spell)
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(CrackingTheWhipI);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderBrae"), new Point3D(6266, 124, 0), Map.Felucca);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 0, "ElderBrae"), new Point3D(6266, 124, 0), Map.Trammel);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Verify
|
||||
public class CrackingTheWhipI : MLQuest
|
||||
{
|
||||
public CrackingTheWhipI()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074295; // Cracking the Whip
|
||||
Description =
|
||||
1074300; // Now that you've shown those mini pests your might, you should collect suitable implements to use to train your summoned pet. I suggest a stout whip.
|
||||
RefusalMessage = 1074313; // Heh. Changed your mind, eh?
|
||||
InProgressMessage =
|
||||
1074317; // Well, hurry up. If you don't get a whip how do you expect to control the little devil?
|
||||
CompletionMessage = 1074321; // That's a well-made whip. No imp will ignore the sting of that lash.
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(StoutWhip), "Stout Whip"));
|
||||
|
||||
Rewards.Add(new DummyReward(
|
||||
1074873)); // The opportunity to prove yourself worthy of learning to Summon Fiends. (Sufficient spellweaving skill is required to cast the spell)
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(CrackingTheWhipII);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
// TODO: Verify
|
||||
public class CrackingTheWhipII : MLQuest
|
||||
{
|
||||
public CrackingTheWhipII()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074295; // Cracking the Whip
|
||||
Description =
|
||||
1074302; // Now you just need to make the little buggers fear you -- if you can slay an arcane daemon, you'll earn their subservience.
|
||||
RefusalMessage = 1074314; // If you're not up for it, so be it.
|
||||
InProgressMessage = 1074318; // You need to vanquish an arcane daemon before the imps will fear you properly.
|
||||
|
||||
Objectives.Add(new KillObjective(1, new[] { typeof(ArcaneDaemon) }, 1029733)); // arcane demon
|
||||
|
||||
Rewards.Add(new ItemReward(1031608, typeof(SummonFiendScroll))); // Summon Fiend
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.PlayerContext.SummonFiend = true;
|
||||
instance.Player.SendLocalizedMessage(1074322, "",
|
||||
0x2A); // You've demonstrated your strength, got a means of control, and taught the imps to fear you. You're ready now to summon them.
|
||||
|
||||
base.GetRewards(instance);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
[QuesterName("Aeluva (The Heartwood)")]
|
||||
public class Aeluva : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Aeluva()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0)
|
||||
{
|
||||
Title = "the arcanist";
|
||||
Race = Race.Elf;
|
||||
Female = true;
|
||||
Body = 606;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
SetSkill(SkillName.Meditation, 60.0, 80.0);
|
||||
SetSkill(SkillName.Focus, 60.0, 80.0);
|
||||
|
||||
AddItem(new ElvenShirt());
|
||||
AddItem(new Kilt(Utility.RandomNondyedHue())); // Note: OSI hue = 0x1516, typo?
|
||||
AddItem(new ElvenBoots());
|
||||
AddItem(new Circlet());
|
||||
}
|
||||
|
||||
public Aeluva(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override bool CanTeach => true;
|
||||
public override string DefaultName => "Aeluva";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
/*
|
||||
* 1074206 - Excuse me please traveler, might I have a little of your time?
|
||||
* 1074207 - Good day to you friend! Allow me to offer you a fabulous opportunity! Thrills and adventure await!
|
||||
*/
|
||||
MLQuestSystem.Tell(this, pm, Utility.Random(1074206, 2));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Koole (Sanctuary)")]
|
||||
public class Koole : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Koole()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0)
|
||||
{
|
||||
Title = "the arcanist";
|
||||
Race = Race.Elf;
|
||||
Body = 605;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
SetSkill(SkillName.Meditation, 60.0, 80.0);
|
||||
SetSkill(SkillName.Focus, 60.0, 80.0);
|
||||
|
||||
Item item;
|
||||
|
||||
item = new LeafChest();
|
||||
item.Hue = 443;
|
||||
AddItem(item);
|
||||
|
||||
item = new LeafArms();
|
||||
item.Hue = 443;
|
||||
AddItem(item);
|
||||
|
||||
AddItem(new LeafTonlet());
|
||||
AddItem(new ThighBoots(Utility.RandomAnimalHue()));
|
||||
AddItem(new RoyalCirclet());
|
||||
}
|
||||
|
||||
public Koole(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override bool CanTeach => true;
|
||||
public override string DefaultName => "Koole";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, Utility.RandomList(
|
||||
1074186, // Come here, I have a task.
|
||||
1074218 // Hey! I want to talk to you, now.
|
||||
));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Synaeva (The Heartwood)")]
|
||||
public class Synaeva : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Synaeva()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0)
|
||||
{
|
||||
Title = "the arcanist";
|
||||
Race = Race.Elf;
|
||||
Female = true;
|
||||
Body = 606;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
SetSkill(SkillName.Meditation, 60.0, 80.0);
|
||||
SetSkill(SkillName.Focus, 60.0, 80.0);
|
||||
|
||||
Item item = new RavenHelm();
|
||||
item.Hue = Utility.RandomGreenHue();
|
||||
AddItem(item);
|
||||
|
||||
AddItem(new FemaleLeafChest());
|
||||
AddItem(new LeafArms());
|
||||
AddItem(new LeafTonlet());
|
||||
AddItem(new ElvenBoots());
|
||||
AddItem(new WildStaff());
|
||||
}
|
||||
|
||||
public Synaeva(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override bool CanTeach => true;
|
||||
public override string DefaultName => "Synaeva";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, 1074223); // Have you done it yet? Oh, I haven’t told you, have I?
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Elder Brae (Sanctuary)")]
|
||||
public class ElderBrae : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public ElderBrae()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2.0)
|
||||
{
|
||||
Title = "the wise";
|
||||
Race = Race.Elf;
|
||||
Female = true;
|
||||
Body = 606;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
SetSkill(SkillName.Meditation, 60.0, 80.0);
|
||||
SetSkill(SkillName.Focus, 60.0, 80.0);
|
||||
|
||||
AddItem(new GemmedCirclet());
|
||||
AddItem(new FemaleElvenRobe(Utility.RandomBrightHue()));
|
||||
AddItem(new ElvenBoots(Utility.RandomAnimalHue()));
|
||||
}
|
||||
|
||||
public ElderBrae(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override bool CanTeach => true;
|
||||
public override string DefaultName => "Elder Brae";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, Utility.RandomList(
|
||||
1074215, // Don’t test my patience you sniveling worm!
|
||||
1074218 // Hey! I want to talk to you, now.
|
||||
));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
166
Projects/Scripts/Engines/MLQuests/Definitions/TheAncientWorld.cs
Normal file
166
Projects/Scripts/Engines/MLQuests/Definitions/TheAncientWorld.cs
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Quests
|
||||
|
||||
public class TheAncientWorld : MLQuest
|
||||
{
|
||||
public TheAncientWorld()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074534; // The Ancient World
|
||||
Description =
|
||||
1074535; // The lore of my people mentions Mondain many times. In one tale, it is revealed that he created and enslaved a race -- a sort of man bull, known as a 'minotaur'. The tales speak of mighty warriors who charged with blood-soaked horns into the heat of battle. But, alas, the fate of the bull-men is unknown after the rupture. Will you seek information about their civilization?
|
||||
RefusalMessage = 1074538; // I am disappointed, but I respect your decision.
|
||||
InProgressMessage =
|
||||
1074539; // A traveler has told me that worshippers of Mondain still exist and wander the land. Perhaps their lore speaks of whether the bull-men survived. I do not think they share their secrets gladly. You may need to be 'persuasive'.
|
||||
CompletionMessage = 1074542; // What have you found?
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(FragmentOfAMap), "fragment of a map"));
|
||||
|
||||
Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(TheGoldenHorn);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperBroolol"), new Point3D(7011, 375, 0), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 5, "LorekeeperBroolol"), new Point3D(7011, 375, 0), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
public class TheGoldenHorn : MLQuest
|
||||
{
|
||||
public TheGoldenHorn()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074543; // The Golden Horn
|
||||
Description =
|
||||
1074545; // Ah ha! You see here ... and over here ... The map fragment places the city of the bull-men, Labyrinth, on that piece of Sosaria that was thrown into the sky. Hmmm, I would have you go there and find any artifacts that remain that help tell the story. But, legend speaks of a mighty barrier to prevent invasion of the city. Take this map to Braen and explain the problem. Perhaps he can devise a solution.
|
||||
RefusalMessage = 1074538; // I am disappointed, but I respect your decision.
|
||||
InProgressMessage = 1074547; // Braen is nearby, run and speak with him.
|
||||
CompletionMessage = 1074549; // Yes? What do you want? I'm very busy.
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(FragmentOfAMapDelivery), 1, "fragment of a map", typeof(Braen)));
|
||||
|
||||
Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(Bullish);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class Bullish : MLQuest
|
||||
{
|
||||
public Bullish()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074550; // Bullish
|
||||
Description =
|
||||
1074552; // Oh, I see. I will need some materials to infuse you with the essence of a bull-man, so you can fool their defenses. The most similar beast to the original Baratarian bull that the minotaur were bred from is undoubtedly the mighty Gaman, native to the Lands of the Feudal Lords. I need horns, in great quantity to undertake this magic.
|
||||
RefusalMessage = 1074554; // Oh come now, don't be afraid. The magic won't harm you.
|
||||
InProgressMessage =
|
||||
1074555; // I cannot grant you the ability to pass through the bull-men's defenses without the gaman horns.
|
||||
CompletionMessage =
|
||||
1074556; // You've returned at last! Give me just a moment to examine what you've brought and I can perform the magic that will allow you enter the Labyrinth.
|
||||
|
||||
Objectives.Add(new CollectObjective(20, typeof(GamanHorns), "gaman horns"));
|
||||
|
||||
Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(LostCivilization);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class LostCivilization : MLQuest
|
||||
{
|
||||
public LostCivilization()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074823; // Lost Civilization
|
||||
Description =
|
||||
1074825; // *whew* It is done! The fierce essence of the bull has been infused into your aura. You are able now to breach the ancient defenses of the city. Go forth and seek the minotaur -- and then return with wonderous tales and evidence of your visit to the Labyrinth.
|
||||
RefusalMessage =
|
||||
1074827; // As you wish. I can't understand why you'd pass up such a remarkable opportunity. Think of the adventures you would have.
|
||||
InProgressMessage =
|
||||
1074828; // You won't reach the minotaur city by loitering around here! What are you waiting for? You need to get to Malas and find the access point for the island. You'll be renowned for your discovery!
|
||||
CompletionMessage =
|
||||
1074829; // Oh! You've returned at last! I can't wait to hear the tales ... but first, let me see those artifacts. You've certainly earned this reward.
|
||||
|
||||
Objectives.Add(new CollectObjective(3, typeof(MinotaurArtifact), "minotaur artifacts"));
|
||||
|
||||
Rewards.Add(ItemReward.Strongbox);
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
[QuesterName("Broolol (The Heartwood)")]
|
||||
public class LorekeeperBroolol : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public LorekeeperBroolol()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the keeper of tradition";
|
||||
Race = Race.Elf;
|
||||
BodyValue = 0x25E;
|
||||
Female = true;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
SetSkill(SkillName.Meditation, 60.0, 80.0);
|
||||
SetSkill(SkillName.Focus, 60.0, 80.0);
|
||||
|
||||
AddItem(new ElvenBoots(0x70D));
|
||||
AddItem(new FemaleElvenRobe(0x3A));
|
||||
AddItem(new WildStaff());
|
||||
}
|
||||
|
||||
public LorekeeperBroolol(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
public override bool CanTeach => true;
|
||||
public override string DefaultName => "Lorekeeper Broolol";
|
||||
public override bool CanShout => true;
|
||||
|
||||
public override void Shout(PlayerMobile pm)
|
||||
{
|
||||
MLQuestSystem.Tell(this, pm, 1074200); // Thank goodness you are here, there<72>s no time to lose.
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
131
Projects/Scripts/Engines/MLQuests/Definitions/TownEscorts.cs
Normal file
131
Projects/Scripts/Engines/MLQuests/Definitions/TownEscorts.cs
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
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; // I seek a worthy escort. I can offer some small pay to any able bodied adventurer who can assist me. It is imperative that I reach my destination.
|
||||
RefusalMessage =
|
||||
1072288; // I wish you would reconsider my offer. I'll be waiting right here for someone brave enough to assist me.
|
||||
InProgressMessage = progress;
|
||||
|
||||
Objectives.Add(new EscortObjective(new QuestArea(destination, region)));
|
||||
|
||||
Rewards.Add(m_Reward);
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToYew : TownEscort
|
||||
{
|
||||
public EscortToYew()
|
||||
: base(1072275, 1072289, 1072227, "Yew")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToVesper : TownEscort
|
||||
{
|
||||
public EscortToVesper()
|
||||
: base(1072276, 1072290, 1072229, "Vesper")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToTrinsic : TownEscort
|
||||
{
|
||||
public EscortToTrinsic()
|
||||
: base(1072277, 1072291, 1072236, "Trinsic")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToSkaraBrae : TownEscort
|
||||
{
|
||||
public EscortToSkaraBrae()
|
||||
: base(1072278, 1072292, 1072235, "Skara Brae")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToSerpentsHold : TownEscort
|
||||
{
|
||||
public EscortToSerpentsHold()
|
||||
: base(1072279, 1072293, 1072238, "Serpent's Hold")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToNujelm : TownEscort
|
||||
{
|
||||
public EscortToNujelm()
|
||||
: base(1072280, 1072294, 1072237, "Nujel'm")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToMoonglow : TownEscort
|
||||
{
|
||||
public EscortToMoonglow()
|
||||
: base(1072281, 1072295, 1072232, "Moonglow")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToMinoc : TownEscort
|
||||
{
|
||||
public EscortToMinoc()
|
||||
: base(1072282, 1072296, 1072228, "Minoc")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToMagincia : TownEscort
|
||||
{
|
||||
public EscortToMagincia()
|
||||
: base(1072283, 1072297, 1072233, "Magincia")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToJhelom : TownEscort
|
||||
{
|
||||
public EscortToJhelom()
|
||||
: base(1072284, 1072298, 1072239, "Jhelom")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToCove : TownEscort
|
||||
{
|
||||
public EscortToCove()
|
||||
: base(1072285, 1072299, 1072230, "Cove")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToBritain : TownEscort
|
||||
{
|
||||
public EscortToBritain()
|
||||
: base(1072286, 1072300, 1072231, "Britain")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class EscortToOcllo : TownEscort
|
||||
{
|
||||
public EscortToOcllo()
|
||||
: base(1072312, 1072313, 1072234, "Ocllo")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
#region Quests
|
||||
|
||||
public class UnfadingMemoriesPartOne : MLQuest
|
||||
{
|
||||
public UnfadingMemoriesPartOne()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1075355; // Unfading Memories
|
||||
Description =
|
||||
1075356; // Aargh! It<49>s just not right! It doesn<73>t capture the unique color of her hair at all! If only I had some Prismatic Amber. That would be perfect. They used to mine it in Malas, but alas, those veins ran dry some time ago. I hear it may have been found in the Prism of Light. Oh, if only there were a bold adventurer within earshot who would go to the Prism of Light and retrieve some for me!
|
||||
RefusalMessage = 1075358; // Is there no one who can help a humble artist pursue his Muse?
|
||||
InProgressMessage =
|
||||
1075359; // You can find Prismatic Amber in the Prism of Light, located just north of the city of Nujel'm.
|
||||
CompletionMessage =
|
||||
1075360; // I knew it! See, it<69>s just the color I needed! Look how it brings out the highlights of her wheaten tresses!
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(PrismaticAmber), "Prismatic Amber"));
|
||||
|
||||
Rewards.Add(new DummyReward(
|
||||
1075357)); // The joy of contributing to a noble artistic effort, however paltry the end product.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(UnfadingMemoriesPartTwo);
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Emilio"), new Point3D(1447, 1664, 10), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Emilio"), new Point3D(1447, 1664, 10), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
public class UnfadingMemoriesPartTwo : MLQuest
|
||||
{
|
||||
public UnfadingMemoriesPartTwo()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1075367; // Unfading Memories
|
||||
Description =
|
||||
1075368; // Finished! With the pigment I was able to create from the Prismatic Amber you brought me, I was able to complete my humble work. I should explain. Once, I loved a noble lady of gentleness and refinement, who possessed such beauty that I have found myself unable to love another to this day. But it was from afar that I admired her, for it is not for one so lowly as I to pay court to the likes of her. You have heard of the fair Thalia, Lady of Nujel'm? No? Well, she was my Muse, my inspiration, and when I heard she was to be married, I lost whatever pitiful talent I possessed. I felt I must compose a portrait of her, my masterpiece, or I would never be able to paint again. You, my friend, have helped me complete my work. Now I ask another favor of you. Will you take it to her as a wedding gift? She will probably reject it, but I must make the offer.
|
||||
RefusalMessage =
|
||||
1075370; // Alright then, you have already helped me more than I deserved. I shall find someone else to undertake this task.
|
||||
InProgressMessage =
|
||||
1075371; // The wedding is taking place in the palace in Nujel'm. You will likely find her there.
|
||||
CompletionMessage =
|
||||
1075372; // I<>m sorry, I<>m getting ready to be married. I don<6F>t have time to . . . what<61>s that you say?
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(PortraitOfTheBride), 1, "Portrait of the Bride", typeof(Thalia)));
|
||||
|
||||
Rewards.Add(new DummyReward(1075369)); // The Artist<73>s gratitude.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(UnfadingMemoriesPartThree);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class UnfadingMemoriesPartThree : MLQuest
|
||||
{
|
||||
public UnfadingMemoriesPartThree()
|
||||
{
|
||||
Activated = true;
|
||||
OneTimeOnly = true;
|
||||
Title = 1075373; // Unfading Memories
|
||||
Description =
|
||||
1075374; // Emilio painted this? It is absolutely wonderful! I used to love looking at his paintings, but I don<6F>t remember him creating anything like this before. Would you be so kind as to carry a letter to him? Fate may have it that I am to marry another, yet I am compelled to reveal to him that his love was not entirely unrequited.
|
||||
RefusalMessage = 1075376; // Very well, then. If you will excuse me, I need to get ready.
|
||||
InProgressMessage =
|
||||
1075377; // Take the letter back to the Artist<73>s Guild in Britain, if you would do me this kindness.
|
||||
CompletionMessage =
|
||||
1075378; // She said what? She thinks what of me? I . . . I can<61>t believe it! All this time, I never knew how she truly felt. Thank you, my friend. I believe now I will be able to paint once again. Here, take this bleach. I was going to use it to destroy all of my works. Perhaps you can find a better use for it now.
|
||||
CompletionNotice = CompletionNoticeShort;
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(BridesLetter), 1, "Bride's Letter", typeof(Emilio)));
|
||||
|
||||
Rewards.Add(new ItemReward(1075375, typeof(Bleach))); // Bleach
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
|
||||
public override void Generate()
|
||||
{
|
||||
base.Generate();
|
||||
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Thalia"), new Point3D(3675, 1322, 20), Map.Trammel);
|
||||
PutSpawner(new Spawner(1, 5, 10, 0, 3, "Thalia"), new Point3D(3675, 1322, 20), Map.Felucca);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mobiles
|
||||
|
||||
[QuesterName("Emilio (Britain)")] // OSI's description is "Artist", not very helpful
|
||||
public class Emilio : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Emilio()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Tortured Artist";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x190;
|
||||
Female = false;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Sandals(0x72B));
|
||||
AddItem(new LongPants(0x525));
|
||||
AddItem(new FancyShirt(0x53F));
|
||||
AddItem(new FloppyHat(0x58C));
|
||||
AddItem(new BodySash(0x1C));
|
||||
}
|
||||
|
||||
public Emilio(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Emilio";
|
||||
public override bool IsInvulnerable => true;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[QuesterName("Thalia (Nujel'm)")] // OSI's description is "Bride", not very helpful
|
||||
public class Thalia : BaseCreature
|
||||
{
|
||||
[Constructible]
|
||||
public Thalia()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
Title = "the Bride";
|
||||
Race = Race.Human;
|
||||
BodyValue = 0x191;
|
||||
Female = true;
|
||||
Hue = Race.RandomSkinHue();
|
||||
InitStats(100, 100, 25);
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
AddItem(new Backpack());
|
||||
AddItem(new Sandals(0x8FD));
|
||||
AddItem(new FancyDress(0x8FD));
|
||||
}
|
||||
|
||||
public Thalia(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Thalia";
|
||||
public override bool IsInvulnerable => true;
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Engines.MLQuests.Definitions
|
||||
{
|
||||
public class WarriorsOfTheGemkeeper : MLQuest
|
||||
{
|
||||
public WarriorsOfTheGemkeeper()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074536; // Warriors of the Gemkeeper
|
||||
Description =
|
||||
1074537; // Here we honor the Gemkeeper's Apprentice and seek to aid her efforts against the humans responsible for the death of her teacher - and the destruction of the elven way of life. Our tales speak of a fierce race of servants of the Gemkeeper, the men-bulls whose battle-skill was renowned. It is desireable to discover the fate of these noble creatures after the Rupture. Will you seek information?
|
||||
RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then.
|
||||
InProgressMessage =
|
||||
1074540; // I care not how you get the information. Kill as many humans as you must ... but find the fate of the minotaurs. Perhaps another of the Gemkeeper's servants has the knowledge we seek.
|
||||
CompletionMessage = 1074542; // What have you found?
|
||||
|
||||
Objectives.Add(new CollectObjective(1, typeof(FragmentOfAMap), "fragment of a map"));
|
||||
|
||||
Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(CloseEnough);
|
||||
}
|
||||
|
||||
public class CloseEnough : MLQuest
|
||||
{
|
||||
public CloseEnough()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074544; // Close Enough
|
||||
Description =
|
||||
1074546; // Ah ha! You see here ... and over here ... The map fragment places the city of the bull-men, Labyrinth, on that piece of Sosaria that was thrown into the sky. Hmmm, I would have you go there and seek out these warriors to see if they might join our cause. But, legend speaks of a mighty barrier to prevent invasion of the city. Take this map to Canir and explain the problem. Perhaps she can devise a solution.
|
||||
RefusalMessage = 1074063; // Fine then, I'm shall find another to run my errands then.
|
||||
InProgressMessage = 1074548; // Canir is nearby, run and speak with her.
|
||||
CompletionMessage = 1074549; // Yes? What do you want? I'm very busy.
|
||||
|
||||
Objectives.Add(new DeliverObjective(typeof(FragmentOfAMapDelivery), 1, "fragment of a map", typeof(Canir)));
|
||||
|
||||
Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(TakingTheBullByTheHorns);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class TakingTheBullByTheHorns : MLQuest
|
||||
{
|
||||
public TakingTheBullByTheHorns()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074551; // Taking the Bull by the Horns
|
||||
Description =
|
||||
1074553; // Interesting. I believe I have a way. I will need some materials to infuse you with the essence of a bull-man, so you can fool their defenses. The most similar beast to the original Baratarian bull that the minotaur were bred from is undoubtedly the mighty Gaman, native to the Lands of the Feudal Lords. I need horns, in great quantity to undertake this magic.
|
||||
RefusalMessage = 1074554; // Oh come now, don't be afraid. The magic won't harm you.
|
||||
InProgressMessage =
|
||||
1074555; // I cannot grant you the ability to pass through the bull-men's defenses without the gaman horns.
|
||||
CompletionMessage =
|
||||
1074556; // You've returned at last! Give me just a moment to examine what you've brought and I can perform the magic that will allow you enter the Labyrinth.
|
||||
|
||||
Objectives.Add(new CollectObjective(20, typeof(GamanHorns), "gaman horns"));
|
||||
|
||||
Rewards.Add(new DummyReward(1074876)); // Knowledge of the legendary minotaur.
|
||||
}
|
||||
|
||||
public override Type NextQuest => typeof(EmissaryToTheMinotaur);
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
|
||||
public class EmissaryToTheMinotaur : MLQuest
|
||||
{
|
||||
public EmissaryToTheMinotaur()
|
||||
{
|
||||
Activated = true;
|
||||
Title = 1074824; // Emissary to the Minotaur
|
||||
Description =
|
||||
1074825; // *whew* It is done! The fierce essence of the bull has been infused into your aura. You are able now to breach the ancient defenses of the city. Go forth and seek the minotaur -- and then return with wonderous tales and evidence of your visit to the Labyrinth.
|
||||
RefusalMessage =
|
||||
1074827; // As you wish. I can't understand why you'd pass up such a remarkable opportunity. Think of the adventures you would have.
|
||||
InProgressMessage =
|
||||
1074828; // You won't reach the minotaur city by loitering around here! What are you waiting for? You need to get to Malas and find the access point for the island. You'll be renowned for your discovery!
|
||||
CompletionMessage =
|
||||
1074829; // Oh! You've returned at last! I can't wait to hear the tales ... but first, let me see those artifacts. You've certainly earned this reward.
|
||||
|
||||
Objectives.Add(new CollectObjective(3, typeof(MinotaurArtifact), "minotaur artifacts"));
|
||||
|
||||
Rewards.Add(ItemReward.Strongbox);
|
||||
}
|
||||
|
||||
public override bool IsChainTriggered => true;
|
||||
}
|
||||
}
|
||||
291
Projects/Scripts/Engines/MLQuests/Gumps/BaseQuestGump.cs
Normal file
291
Projects/Scripts/Engines/MLQuests/Gumps/BaseQuestGump.cs
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
using System.Collections.Generic;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public enum ButtonPosition : byte
|
||||
{
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
public enum ButtonGraphic : ushort
|
||||
{
|
||||
Invalid,
|
||||
Accept = 0x2EE0,
|
||||
Clear = 0x2EE3,
|
||||
Close = 0x2EE6,
|
||||
Continue = 0x2EE9,
|
||||
Okay = 0x2EEC,
|
||||
Previous = 0x2EEF,
|
||||
Refuse = 0x2EF2,
|
||||
Resign = 0x2EF5
|
||||
}
|
||||
|
||||
public abstract class BaseQuestGump : Gump
|
||||
{
|
||||
private struct ButtonInfo
|
||||
{
|
||||
public ButtonPosition Position{ get; }
|
||||
|
||||
public ButtonGraphic Graphic{ get; }
|
||||
|
||||
public int ButtonID{ get; }
|
||||
|
||||
public ButtonInfo(ButtonPosition position, ButtonGraphic graphic, int buttonID)
|
||||
{
|
||||
Position = position;
|
||||
Graphic = graphic;
|
||||
ButtonID = buttonID;
|
||||
}
|
||||
}
|
||||
|
||||
private int m_Page;
|
||||
private int m_MaxPages;
|
||||
private int m_Label;
|
||||
private string m_Title;
|
||||
private List<ButtonInfo> m_Buttons;
|
||||
|
||||
#if false
|
||||
// OSI clone, inefficient layout
|
||||
public BaseQuestGump( int label ) : base( 75, 25 )
|
||||
{
|
||||
m_Page = 0;
|
||||
m_MaxPages = 0;
|
||||
m_Label = label;
|
||||
m_Title = null;
|
||||
m_Buttons = new List<ButtonInfo>( 2 );
|
||||
}
|
||||
|
||||
public void BuildPage()
|
||||
{
|
||||
AddPage( ++m_Page );
|
||||
|
||||
Closable = false;
|
||||
AddImageTiled( 50, 20, 400, 460, 0x1404 );
|
||||
AddImageTiled( 50, 29, 30, 450, 0x28DC );
|
||||
AddImageTiled( 34, 140, 17, 339, 0x242F );
|
||||
AddImage( 48, 135, 0x28AB );
|
||||
AddImage( -16, 285, 0x28A2 );
|
||||
AddImage( 0, 10, 0x28B5 );
|
||||
AddImage( 25, 0, 0x28B4 );
|
||||
AddImageTiled( 83, 15, 350, 15, 0x280A );
|
||||
AddImage( 34, 479, 0x2842 );
|
||||
AddImage( 442, 479, 0x2840 );
|
||||
AddImageTiled( 51, 479, 392, 17, 0x2775 );
|
||||
AddImageTiled( 415, 29, 44, 450, 0xA2D );
|
||||
AddImageTiled( 415, 29, 30, 450, 0x28DC );
|
||||
AddLabel( 100, 50, 0x481, "" );
|
||||
AddImage( 370, 50, 0x589 );
|
||||
AddImage( 379, 60, 0x15A9 );
|
||||
AddImage( 425, 0, 0x28C9 );
|
||||
AddImage( 90, 33, 0x232D );
|
||||
AddHtmlLocalized( 130, 45, 270, 16, m_Label, 0xFFFFFF, false, false );
|
||||
AddImageTiled( 130, 65, 175, 1, 0x238D );
|
||||
|
||||
if ( m_Page > 1 )
|
||||
AddButton( 130, 430, (int)ButtonGraphic.Previous, (int)ButtonGraphic.Previous + 2, 0, GumpButtonType.Page, m_Page - 1 );
|
||||
|
||||
if ( m_Page < m_MaxPages )
|
||||
AddButton( 275, 430, (int)ButtonGraphic.Continue, (int)ButtonGraphic.Continue + 2, 0, GumpButtonType.Page, m_Page + 1 );
|
||||
|
||||
foreach ( ButtonInfo button in m_Buttons )
|
||||
AddButton( button.Position == ButtonPosition.Left ? 95 : 313, 455, (int)button.Graphic, (int)button.Graphic + 2, button.ButtonID, );
|
||||
|
||||
if ( m_Title != null )
|
||||
AddHtmlLocalized( 130, 68, 220, 48, 1114513, m_Title, 0x2710, false, false ); // <DIV ALIGN=CENTER>~1_TOKEN~</DIV>
|
||||
}
|
||||
#else
|
||||
// RunUO optimized version
|
||||
public BaseQuestGump(int label)
|
||||
: base(75, 25)
|
||||
{
|
||||
m_Page = 0;
|
||||
m_MaxPages = 0;
|
||||
m_Label = label;
|
||||
m_Title = null;
|
||||
m_Buttons = new List<ButtonInfo>(2);
|
||||
|
||||
Closable = false;
|
||||
|
||||
AddPage(0);
|
||||
|
||||
AddImageTiled(50, 20, 400, 460, 0x1404);
|
||||
AddImageTiled(50, 29, 30, 450, 0x28DC);
|
||||
AddImageTiled(34, 140, 17, 339, 0x242F);
|
||||
AddImage(48, 135, 0x28AB);
|
||||
AddImage(-16, 285, 0x28A2);
|
||||
AddImage(0, 10, 0x28B5);
|
||||
AddImage(25, 0, 0x28B4);
|
||||
AddImageTiled(83, 15, 350, 15, 0x280A);
|
||||
AddImage(34, 479, 0x2842);
|
||||
AddImage(442, 479, 0x2840);
|
||||
AddImageTiled(51, 479, 392, 17, 0x2775);
|
||||
AddImageTiled(415, 29, 44, 450, 0xA2D);
|
||||
AddImageTiled(415, 29, 30, 450, 0x28DC);
|
||||
//AddLabel( 100, 50, 0x481, "" );
|
||||
AddImage(370, 50, 0x589);
|
||||
AddImage(379, 60, 0x15A9);
|
||||
AddImage(425, 0, 0x28C9);
|
||||
AddImage(90, 33, 0x232D);
|
||||
AddHtmlLocalized(130, 45, 270, 16, label, 0xFFFFFF);
|
||||
AddImageTiled(130, 65, 175, 1, 0x238D);
|
||||
}
|
||||
|
||||
public void BuildPage()
|
||||
{
|
||||
AddPage(++m_Page);
|
||||
|
||||
if (m_Page > 1)
|
||||
AddButton(130, 430, (int)ButtonGraphic.Previous, (int)ButtonGraphic.Previous + 2, 0, GumpButtonType.Page,
|
||||
m_Page - 1);
|
||||
|
||||
if (m_Page < m_MaxPages)
|
||||
AddButton(275, 430, (int)ButtonGraphic.Continue, (int)ButtonGraphic.Continue + 2, 0, GumpButtonType.Page,
|
||||
m_Page + 1);
|
||||
|
||||
foreach (ButtonInfo button in m_Buttons)
|
||||
AddButton(button.Position == ButtonPosition.Left ? 95 : 313, 455, (int)button.Graphic,
|
||||
(int)button.Graphic + 2, button.ButtonID);
|
||||
|
||||
if (m_Title != null)
|
||||
AddHtmlLocalized(130, 68, 220, 48, 1114513, m_Title, 0x2710); // <DIV ALIGN=CENTER>~1_TOKEN~</DIV>
|
||||
}
|
||||
#endif
|
||||
|
||||
public void SetPageCount(int maxPages)
|
||||
{
|
||||
m_MaxPages = maxPages;
|
||||
}
|
||||
|
||||
public void SetTitle(TextDefinition def)
|
||||
{
|
||||
if (def.Number > 0)
|
||||
m_Title = $"#{def.Number}"; // OSI does "@@#{0}" instead, why? KR client related?
|
||||
else
|
||||
m_Title = def.String;
|
||||
}
|
||||
|
||||
public void RegisterButton(ButtonPosition position, ButtonGraphic graphic, int buttonID)
|
||||
{
|
||||
m_Buttons.Add(new ButtonInfo(position, graphic, buttonID));
|
||||
}
|
||||
|
||||
#region Elaborate Formatting Shortcuts
|
||||
|
||||
public void AddDescription(MLQuest quest)
|
||||
{
|
||||
AddHtmlLocalized(98, 140, 312, 16, quest.IsChainTriggered || quest.NextQuest != null ? 1075024 : 1072202, 0x2710); // Description [(quest chain)]
|
||||
TextDefinition.AddHtmlText(this, 98, 156, 312, 240, quest.Description, false, true, 0x15F90, 0xBDE784);
|
||||
}
|
||||
|
||||
public void AddObjectives(MLQuest quest)
|
||||
{
|
||||
AddHtmlLocalized(98, 140, 312, 16, 1049073, 0x2710); // Objective:
|
||||
AddHtmlLocalized(98, 156, 312, 16, quest.ObjectiveType == ObjectiveType.All ? 1072208 : 1072209, 0x2710); // All of the following / Only one of the following
|
||||
|
||||
int y = 172;
|
||||
|
||||
foreach (BaseObjective objective in quest.Objectives)
|
||||
{
|
||||
objective.WriteToGump(this, ref y);
|
||||
|
||||
if (objective.IsTimed)
|
||||
{
|
||||
if (objective is CollectObjective)
|
||||
y -= 16;
|
||||
|
||||
BaseObjectiveInstance.WriteTimeRemaining(this, ref y, objective.Duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddObjectivesProgress(MLQuestInstance instance)
|
||||
{
|
||||
MLQuest quest = instance.Quest;
|
||||
|
||||
AddHtmlLocalized(98, 140, 312, 16, 1049073, 0x2710); // Objective:
|
||||
AddHtmlLocalized(98, 156, 312, 16, quest.ObjectiveType == ObjectiveType.All ? 1072208 : 1072209, 0x2710); // All of the following / Only one of the following
|
||||
|
||||
int y = 172;
|
||||
|
||||
foreach (BaseObjectiveInstance objInstance in instance.Objectives)
|
||||
objInstance.WriteToGump(this, ref y);
|
||||
}
|
||||
|
||||
public void AddRewardsPage(MLQuest quest) // For the quest log/offer gumps
|
||||
{
|
||||
AddHtmlLocalized(98, 140, 312, 16, 1072201, 0x2710); // Reward
|
||||
|
||||
int y = 162;
|
||||
|
||||
if (quest.Rewards.Count > 1)
|
||||
{
|
||||
// TODO: Is this what this is for? Does "Only one of the following" occur?
|
||||
AddHtmlLocalized(98, 156, 312, 16, 1072208, 0x2710); // All of the following
|
||||
y += 16;
|
||||
}
|
||||
|
||||
AddRewards(quest, 105, y, 16);
|
||||
}
|
||||
|
||||
public void AddRewards(MLQuest quest) // For the claim rewards gump
|
||||
{
|
||||
int y = 146;
|
||||
|
||||
if (quest.Rewards.Count > 1)
|
||||
{
|
||||
// TODO: Is this what this is for? Does "Only one of the following" occur?
|
||||
AddHtmlLocalized(100, 140, 312, 16, 1072208, 0x2710); // All of the following
|
||||
y += 16;
|
||||
}
|
||||
|
||||
AddRewards(quest, 107, y, 26);
|
||||
}
|
||||
|
||||
public void AddRewards(MLQuest quest, int x, int y, int spacing)
|
||||
{
|
||||
int xReward = x + 28;
|
||||
|
||||
foreach (BaseReward reward in quest.Rewards)
|
||||
{
|
||||
AddImage(x, y + 1, 0x4B9);
|
||||
reward.WriteToGump(this, xReward, ref y);
|
||||
y += spacing;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddConversation(TextDefinition text)
|
||||
{
|
||||
TextDefinition.AddHtmlText(this, 98, 140, 312, 180, text, false, true, 0x15F90, 0xBDE784);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/* OSI gump IDs:
|
||||
* 800 - QuestOfferGump
|
||||
* 801 - QuestCancelConfirmGump
|
||||
* 802 - ?? (gets closed by Toggle Quest Item)
|
||||
* 803 - QuestRewardGump
|
||||
* 804 - ?? (gets closed by Toggle Quest Item)
|
||||
* 805 - QuestLogGump
|
||||
* 806 - QuestConversationGump (refuse / in progress)
|
||||
* 807 - ?? (gets closed by Toggle Quest Item and most quest gumps)
|
||||
* 808 - InfoNPCGump
|
||||
* 809 - QuestLogDetailedGump
|
||||
* 810 - QuestReportBackGump
|
||||
*/
|
||||
public static void CloseOtherGumps(PlayerMobile pm)
|
||||
{
|
||||
pm.CloseGump<InfoNPCGump>();
|
||||
pm.CloseGump<QuestRewardGump>();
|
||||
pm.CloseGump<QuestConversationGump>();
|
||||
pm.CloseGump<QuestReportBackGump>();
|
||||
//pm.CloseGump( typeof( UnknownGump807 ) );
|
||||
pm.CloseGump<QuestCancelConfirmGump>();
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Projects/Scripts/Engines/MLQuests/Gumps/InfoNPCGump.cs
Normal file
17
Projects/Scripts/Engines/MLQuests/Gumps/InfoNPCGump.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public class InfoNPCGump : BaseQuestGump
|
||||
{
|
||||
public InfoNPCGump(TextDefinition title, TextDefinition message)
|
||||
: base(1060668) // INFORMATION
|
||||
{
|
||||
RegisterButton(ButtonPosition.Left, ButtonGraphic.Close, 3);
|
||||
|
||||
SetPageCount(1);
|
||||
|
||||
BuildPage();
|
||||
TextDefinition.AddHtmlText(this, 160, 108, 250, 16, title, false, false, 0x2710, 0x4AC684);
|
||||
TextDefinition.AddHtmlText(this, 98, 156, 312, 180, message, false, true, 0x15F90, 0xBDE784);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public class QuestCancelConfirmGump : Gump
|
||||
{
|
||||
private bool m_CloseGumps;
|
||||
private MLQuestInstance m_Instance;
|
||||
|
||||
public QuestCancelConfirmGump(MLQuestInstance instance, bool closeGumps = true)
|
||||
: base(120, 50)
|
||||
{
|
||||
m_Instance = instance;
|
||||
m_CloseGumps = closeGumps;
|
||||
|
||||
if (closeGumps)
|
||||
BaseQuestGump.CloseOtherGumps(instance.Player);
|
||||
|
||||
AddPage(0);
|
||||
|
||||
Closable = false;
|
||||
|
||||
AddImageTiled(0, 0, 348, 262, 0xA8E);
|
||||
AddAlphaRegion(0, 0, 348, 262);
|
||||
|
||||
AddImage(0, 15, 0x27A8);
|
||||
AddImageTiled(0, 30, 17, 200, 0x27A7);
|
||||
AddImage(0, 230, 0x27AA);
|
||||
|
||||
AddImage(15, 0, 0x280C);
|
||||
AddImageTiled(30, 0, 300, 17, 0x280A);
|
||||
AddImage(315, 0, 0x280E);
|
||||
|
||||
AddImage(15, 244, 0x280C);
|
||||
AddImageTiled(30, 244, 300, 17, 0x280A);
|
||||
AddImage(315, 244, 0x280E);
|
||||
|
||||
AddImage(330, 15, 0x27A8);
|
||||
AddImageTiled(330, 30, 17, 200, 0x27A7);
|
||||
AddImage(330, 230, 0x27AA);
|
||||
|
||||
AddImage(333, 2, 0x2716);
|
||||
AddImage(333, 248, 0x2716);
|
||||
AddImage(2, 248, 0x2716);
|
||||
AddImage(2, 2, 0x2716);
|
||||
|
||||
AddHtmlLocalized(25, 22, 200, 20, 1049000, 0x7D00); // Confirm Quest Cancellation
|
||||
AddImage(25, 40, 0xBBF);
|
||||
|
||||
/*
|
||||
* This quest will give you valuable information, skills
|
||||
* and equipment that will help you advance in the
|
||||
* game at a quicker pace.<BR>
|
||||
* <BR>
|
||||
* Are you certain you wish to cancel at this time?
|
||||
*/
|
||||
AddHtmlLocalized(25, 55, 300, 120, 1060836, 0xFFFFFF);
|
||||
|
||||
MLQuest quest = instance.Quest;
|
||||
|
||||
if (quest.IsChainTriggered || quest.NextQuest != null)
|
||||
{
|
||||
AddRadio(25, 145, 0x25F8, 0x25FB, false, 2);
|
||||
AddHtmlLocalized(60, 150, 280, 20, 1075023, 0xFFFFFF); // Yes, I want to quit this entire chain!
|
||||
}
|
||||
|
||||
AddRadio(25, 180, 0x25F8, 0x25FB, true, 1);
|
||||
AddHtmlLocalized(60, 185, 280, 20, 1049005, 0xFFFFFF); // Yes, I really want to quit this quest!
|
||||
|
||||
AddRadio(25, 215, 0x25F8, 0x25FB, false, 0);
|
||||
AddHtmlLocalized(60, 220, 280, 20, 1049006, 0xFFFFFF); // No, I don't want to quit.
|
||||
|
||||
AddButton(265, 220, 0xF7, 0xF8, 7);
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (m_Instance.Removed)
|
||||
return;
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 7: // Okay
|
||||
{
|
||||
if (info.IsSwitched(2))
|
||||
m_Instance.Cancel(true);
|
||||
else if (info.IsSwitched(1))
|
||||
m_Instance.Cancel(false);
|
||||
|
||||
sender.Mobile.SendGump(new QuestLogGump(m_Instance.Player, m_CloseGumps));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public class QuestConversationGump : BaseQuestGump
|
||||
{
|
||||
public QuestConversationGump(MLQuest quest, PlayerMobile pm, TextDefinition text)
|
||||
: base(3006156) // Quest Conversation
|
||||
{
|
||||
CloseOtherGumps(pm);
|
||||
|
||||
SetTitle(quest.Title);
|
||||
RegisterButton(ButtonPosition.Right, ButtonGraphic.Close, 3);
|
||||
|
||||
SetPageCount(1);
|
||||
|
||||
BuildPage();
|
||||
AddConversation(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public class QuestLogDetailedGump : BaseQuestGump
|
||||
{
|
||||
private bool m_CloseGumps;
|
||||
private MLQuestInstance m_Instance;
|
||||
|
||||
public QuestLogDetailedGump(MLQuestInstance instance, bool closeGumps = true)
|
||||
: base(1046026) // Quest Log
|
||||
{
|
||||
m_Instance = instance;
|
||||
m_CloseGumps = closeGumps;
|
||||
|
||||
PlayerMobile pm = instance.Player;
|
||||
MLQuest quest = instance.Quest;
|
||||
|
||||
if (closeGumps)
|
||||
{
|
||||
CloseOtherGumps(pm);
|
||||
pm.CloseGump<QuestLogDetailedGump>();
|
||||
}
|
||||
|
||||
SetTitle(quest.Title);
|
||||
RegisterButton(ButtonPosition.Left, ButtonGraphic.Resign, 1);
|
||||
RegisterButton(ButtonPosition.Right, ButtonGraphic.Okay, 2);
|
||||
|
||||
SetPageCount(3);
|
||||
|
||||
BuildPage();
|
||||
AddDescription(quest);
|
||||
|
||||
if (instance.Failed) // only displayed on the first page
|
||||
AddHtmlLocalized(160, 80, 250, 16, 500039, 0x3C00); // Failed!
|
||||
|
||||
BuildPage();
|
||||
AddObjectivesProgress(instance);
|
||||
|
||||
BuildPage();
|
||||
AddRewardsPage(quest);
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (m_Instance.Removed)
|
||||
return;
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Resign
|
||||
{
|
||||
// TODO: Custom reward loss protection? OSI doesn't have this
|
||||
//if ( m_Instance.ClaimReward )
|
||||
// pm.SendMessage( "You cannot cancel a quest with rewards pending." );
|
||||
//else
|
||||
|
||||
sender.Mobile.SendGump(new QuestCancelConfirmGump(m_Instance, m_CloseGumps));
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Okay
|
||||
{
|
||||
sender.Mobile.SendGump(new QuestLogGump(m_Instance.Player, m_CloseGumps));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Projects/Scripts/Engines/MLQuests/Gumps/QuestLogGump.cs
Normal file
77
Projects/Scripts/Engines/MLQuests/Gumps/QuestLogGump.cs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
using System.Collections.Generic;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public class QuestLogGump : BaseQuestGump
|
||||
{
|
||||
private bool m_CloseGumps;
|
||||
private PlayerMobile m_Owner;
|
||||
|
||||
public QuestLogGump(PlayerMobile pm, bool closeGumps = true)
|
||||
: base(1046026) // Quest Log
|
||||
{
|
||||
m_Owner = pm;
|
||||
m_CloseGumps = closeGumps;
|
||||
|
||||
if (closeGumps)
|
||||
{
|
||||
pm.CloseGump<QuestLogGump>();
|
||||
pm.CloseGump<QuestLogDetailedGump>();
|
||||
}
|
||||
|
||||
RegisterButton(ButtonPosition.Right, ButtonGraphic.Okay, 3);
|
||||
|
||||
SetPageCount(1);
|
||||
|
||||
BuildPage();
|
||||
|
||||
int numberColor, stringColor;
|
||||
|
||||
MLQuestContext context = MLQuestSystem.GetContext(pm);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
List<MLQuestInstance> instances = context.QuestInstances;
|
||||
|
||||
for (int i = 0; i < instances.Count; ++i)
|
||||
{
|
||||
if (instances[i].Failed)
|
||||
{
|
||||
numberColor = 0x3C00;
|
||||
stringColor = 0x7B0000;
|
||||
}
|
||||
else
|
||||
{
|
||||
numberColor = stringColor = 0xFFFFFF;
|
||||
}
|
||||
|
||||
TextDefinition.AddHtmlText(this, 98, 140 + 21 * i, 270, 21, instances[i].Quest.Title, false, false,
|
||||
numberColor, stringColor);
|
||||
AddButton(368, 140 + 21 * i, 0x26B0, 0x26B1, 6 + i, GumpButtonType.Reply, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (info.ButtonID < 6)
|
||||
return;
|
||||
|
||||
MLQuestContext context = MLQuestSystem.GetContext(m_Owner);
|
||||
|
||||
if (context == null)
|
||||
return;
|
||||
|
||||
List<MLQuestInstance> instances = context.QuestInstances;
|
||||
int index = info.ButtonID - 6;
|
||||
|
||||
if (index >= instances.Count)
|
||||
return;
|
||||
|
||||
sender.Mobile.SendGump(new QuestLogDetailedGump(instances[index], m_CloseGumps));
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Projects/Scripts/Engines/MLQuests/Gumps/QuestOfferGump.cs
Normal file
57
Projects/Scripts/Engines/MLQuests/Gumps/QuestOfferGump.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public class QuestOfferGump : BaseQuestGump
|
||||
{
|
||||
private MLQuest m_Quest;
|
||||
private IQuestGiver m_Quester;
|
||||
|
||||
public QuestOfferGump(MLQuest quest, IQuestGiver quester, PlayerMobile pm)
|
||||
: base(1049010) // Quest Offer
|
||||
{
|
||||
m_Quest = quest;
|
||||
m_Quester = quester;
|
||||
|
||||
CloseOtherGumps(pm);
|
||||
pm.CloseGump<QuestOfferGump>();
|
||||
|
||||
SetTitle(quest.Title);
|
||||
RegisterButton(ButtonPosition.Left, ButtonGraphic.Accept, 1);
|
||||
RegisterButton(ButtonPosition.Right, ButtonGraphic.Refuse, 2);
|
||||
|
||||
SetPageCount(3);
|
||||
|
||||
BuildPage();
|
||||
AddDescription(quest);
|
||||
|
||||
BuildPage();
|
||||
AddObjectives(quest);
|
||||
|
||||
BuildPage();
|
||||
AddRewardsPage(quest);
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (!(sender.Mobile is PlayerMobile pm))
|
||||
return;
|
||||
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 1: // Accept
|
||||
{
|
||||
m_Quest.OnAccept(m_Quester, pm);
|
||||
break;
|
||||
}
|
||||
case 2: // Refuse
|
||||
{
|
||||
m_Quest.OnRefuse(m_Quester, pm);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public class QuestReportBackGump : BaseQuestGump
|
||||
{
|
||||
private MLQuestInstance m_Instance;
|
||||
|
||||
public QuestReportBackGump(MLQuestInstance instance)
|
||||
: base(3006156) // Quest Conversation
|
||||
{
|
||||
m_Instance = instance;
|
||||
|
||||
MLQuest quest = instance.Quest;
|
||||
PlayerMobile pm = instance.Player;
|
||||
|
||||
// TODO: Check close sequence
|
||||
CloseOtherGumps(pm);
|
||||
|
||||
SetTitle(quest.Title);
|
||||
RegisterButton(ButtonPosition.Left, ButtonGraphic.Continue, 4);
|
||||
RegisterButton(ButtonPosition.Right, ButtonGraphic.Close, 3);
|
||||
|
||||
SetPageCount(1);
|
||||
|
||||
BuildPage();
|
||||
AddConversation(quest.CompletionMessage);
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (info.ButtonID == 4)
|
||||
m_Instance.ContinueReportBack(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Projects/Scripts/Engines/MLQuests/Gumps/QuestRewardGump.cs
Normal file
36
Projects/Scripts/Engines/MLQuests/Gumps/QuestRewardGump.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public class QuestRewardGump : BaseQuestGump
|
||||
{
|
||||
private MLQuestInstance m_Instance;
|
||||
|
||||
public QuestRewardGump(MLQuestInstance instance)
|
||||
: base(1072201) // Reward
|
||||
{
|
||||
m_Instance = instance;
|
||||
|
||||
MLQuest quest = instance.Quest;
|
||||
PlayerMobile pm = instance.Player;
|
||||
|
||||
CloseOtherGumps(pm);
|
||||
|
||||
SetTitle(quest.Title);
|
||||
RegisterButton(ButtonPosition.Left, ButtonGraphic.Accept, 1);
|
||||
|
||||
SetPageCount(1);
|
||||
|
||||
BuildPage();
|
||||
AddRewards(quest);
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
if (info.ButtonID == 1)
|
||||
m_Instance.ClaimRewards();
|
||||
}
|
||||
}
|
||||
}
|
||||
340
Projects/Scripts/Engines/MLQuests/Gumps/RaceChangeGump.cs
Normal file
340
Projects/Scripts/Engines/MLQuests/Gumps/RaceChangeGump.cs
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Spells.Fifth;
|
||||
using Server.Spells.Ninjitsu;
|
||||
using Server.Spells.Seventh;
|
||||
|
||||
namespace Server.Engines.MLQuests.Gumps
|
||||
{
|
||||
public interface IRaceChanger
|
||||
{
|
||||
bool CheckComplete(PlayerMobile from);
|
||||
void ConsumeNeeded(PlayerMobile from);
|
||||
void OnCancel(PlayerMobile from);
|
||||
}
|
||||
|
||||
public class RaceChangeConfirmGump : Gump
|
||||
{
|
||||
private static Dictionary<NetState, RaceChangeState> m_Pending;
|
||||
private PlayerMobile m_From;
|
||||
|
||||
private IRaceChanger m_Owner;
|
||||
private Race m_Race;
|
||||
|
||||
public RaceChangeConfirmGump(IRaceChanger owner, PlayerMobile from, Race targetRace)
|
||||
: base(50, 50)
|
||||
{
|
||||
from.CloseGump<RaceChangeConfirmGump>();
|
||||
|
||||
m_Owner = owner;
|
||||
m_From = from;
|
||||
m_Race = targetRace;
|
||||
|
||||
AddPage(0);
|
||||
AddBackground(0, 0, 240, 135, 0x2422);
|
||||
|
||||
if (targetRace == Race.Human)
|
||||
AddHtmlLocalized(15, 15, 210, 75, 1073643, 0); // Are you sure you wish to embrace your humanity?
|
||||
else if (targetRace == Race.Elf)
|
||||
AddHtmlLocalized(15, 15, 210, 75, 1073642, 0); // Are you sure you want to follow the elven ways?
|
||||
else
|
||||
AddHtml(15, 15, 210, 75, $"Are you sure you want to change your race to {targetRace.Name}?");
|
||||
|
||||
AddButton(160, 95, 0xF7, 0xF8, 1);
|
||||
AddButton(90, 95, 0xF2, 0xF1, 0);
|
||||
}
|
||||
|
||||
public override void OnResponse(NetState sender, RelayInfo info)
|
||||
{
|
||||
switch (info.ButtonID)
|
||||
{
|
||||
case 0: // Cancel
|
||||
{
|
||||
m_Owner?.OnCancel(m_From);
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: // Okay
|
||||
{
|
||||
if (m_Owner == null || m_Owner.CheckComplete(m_From))
|
||||
Offer(m_Owner, m_From, m_Race);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
m_Pending = new Dictionary<NetState, RaceChangeState>();
|
||||
|
||||
PacketHandlers.RegisterExtended(0x2A, true, RaceChangeReply);
|
||||
}
|
||||
|
||||
public static bool IsPending(NetState state)
|
||||
{
|
||||
return state != null && m_Pending.ContainsKey(state);
|
||||
}
|
||||
|
||||
private static void Offer(IRaceChanger owner, PlayerMobile from, Race targetRace)
|
||||
{
|
||||
NetState ns = from.NetState;
|
||||
|
||||
if (ns == null || !CanChange(from, targetRace))
|
||||
return;
|
||||
|
||||
CloseCurrent(ns);
|
||||
|
||||
m_Pending[ns] = new RaceChangeState(owner, ns, targetRace);
|
||||
ns.Send(new RaceChanger(from.Female, targetRace));
|
||||
}
|
||||
|
||||
private static void CloseCurrent(NetState ns)
|
||||
{
|
||||
if (m_Pending.TryGetValue(ns, out RaceChangeState state))
|
||||
{
|
||||
state.m_Timeout.Stop();
|
||||
m_Pending.Remove(ns);
|
||||
}
|
||||
|
||||
ns.Send(CloseRaceChanger.Instance);
|
||||
}
|
||||
|
||||
private static void Timeout(NetState ns)
|
||||
{
|
||||
if (IsPending(ns))
|
||||
{
|
||||
m_Pending.Remove(ns);
|
||||
ns.Send(CloseRaceChanger.Instance);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsWearingEquipment(Mobile from)
|
||||
{
|
||||
foreach (Item item in from.Items)
|
||||
switch (item.Layer)
|
||||
{
|
||||
case Layer.Hair:
|
||||
case Layer.FacialHair:
|
||||
case Layer.Backpack:
|
||||
case Layer.Mount:
|
||||
case Layer.Bank:
|
||||
{
|
||||
continue; // ignore
|
||||
}
|
||||
default:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool CanChange(PlayerMobile from, Race targetRace)
|
||||
{
|
||||
if (from.Deleted)
|
||||
return false;
|
||||
|
||||
if (from.Race == targetRace)
|
||||
from.SendLocalizedMessage(1111918); // You are already that race.
|
||||
else if (!MondainsLegacy.CheckML(from, false))
|
||||
from.SendLocalizedMessage(1073651); // You must have Mondain's Legacy before proceeding...
|
||||
else if (!from.Alive)
|
||||
from.SendLocalizedMessage(1073646); // Only the living may proceed...
|
||||
else if (from.Mounted)
|
||||
from.SendLocalizedMessage(1073647); // You may not continue while mounted...
|
||||
else if (!from.CanBeginAction<PolymorphSpell>() || DisguiseTimers.IsDisguised(from) ||
|
||||
AnimalForm.UnderTransformation(from) || !from.CanBeginAction<IncognitoSpell>() ||
|
||||
from.IsBodyMod) // TODO: Does this cover everything?
|
||||
from.SendLocalizedMessage(1073648); // You may only proceed while in your original state...
|
||||
else if (from.Spell != null && from.Spell.IsCasting)
|
||||
from.SendLocalizedMessage(1073649); // One may not proceed while embracing magic...
|
||||
else if (from.Poisoned)
|
||||
from.SendLocalizedMessage(1073652); // You must be healthy to proceed...
|
||||
else if (IsWearingEquipment(from))
|
||||
from.SendLocalizedMessage(1073650); // To proceed you must be unburdened by equipment...
|
||||
else
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void RaceChangeReply(NetState state, PacketReader pvSrc)
|
||||
{
|
||||
if (!m_Pending.TryGetValue(state, out RaceChangeState raceChangeState))
|
||||
return;
|
||||
|
||||
CloseCurrent(state);
|
||||
|
||||
if (!(state.Mobile is PlayerMobile pm))
|
||||
return;
|
||||
|
||||
IRaceChanger owner = raceChangeState.m_Owner;
|
||||
Race targetRace = raceChangeState.m_TargetRace;
|
||||
|
||||
if (pvSrc.Length == 5)
|
||||
{
|
||||
owner?.OnCancel(pm);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CanChange(pm, targetRace) || owner?.CheckComplete(pm) == false)
|
||||
return;
|
||||
|
||||
int hue = pvSrc.ReadUInt16();
|
||||
int hairItemId = pvSrc.ReadUInt16();
|
||||
int hairHue = pvSrc.ReadUInt16();
|
||||
int facialHairItemId = pvSrc.ReadUInt16();
|
||||
int facialHairHue = pvSrc.ReadUInt16();
|
||||
|
||||
pm.Race = targetRace;
|
||||
pm.Hue = targetRace.ClipSkinHue(hue) | 0x8000;
|
||||
|
||||
if (targetRace.ValidateHair(pm, hairItemId))
|
||||
{
|
||||
pm.HairItemID = hairItemId;
|
||||
pm.HairHue = targetRace.ClipHairHue(hairHue);
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.HairItemID = 0;
|
||||
}
|
||||
|
||||
if (targetRace.ValidateFacialHair(pm, facialHairItemId))
|
||||
{
|
||||
pm.FacialHairItemID = facialHairItemId;
|
||||
pm.FacialHairHue = targetRace.ClipHairHue(facialHairHue);
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.FacialHairItemID = 0;
|
||||
}
|
||||
|
||||
if (targetRace == Race.Human)
|
||||
pm.SendLocalizedMessage(1073654); // You are now fully human.
|
||||
else if (targetRace == Race.Elf)
|
||||
pm.SendLocalizedMessage(1073653); // You are now fully initiated into the Elven culture.
|
||||
else
|
||||
pm.SendMessage("You have fully changed your race to {0}.", targetRace.Name);
|
||||
|
||||
owner?.ConsumeNeeded(pm);
|
||||
}
|
||||
|
||||
private class RaceChangeState
|
||||
{
|
||||
private static readonly TimeSpan m_TimeoutDelay = TimeSpan.FromMinutes(1);
|
||||
|
||||
public IRaceChanger m_Owner;
|
||||
public Race m_TargetRace;
|
||||
public Timer m_Timeout;
|
||||
|
||||
public RaceChangeState(IRaceChanger owner, NetState ns, Race targetRace)
|
||||
{
|
||||
m_Owner = owner;
|
||||
m_TargetRace = targetRace;
|
||||
m_Timeout = Timer.DelayCall(m_TimeoutDelay, Timeout, ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RaceChanger : Packet
|
||||
{
|
||||
public RaceChanger(bool female, Race targetRace)
|
||||
: base(0xBF)
|
||||
{
|
||||
EnsureCapacity(7);
|
||||
|
||||
m_Stream.Write((short)0x2A);
|
||||
m_Stream.Write((byte)(female ? 1 : 0));
|
||||
m_Stream.Write((byte)(targetRace.RaceID + 1));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class CloseRaceChanger : Packet
|
||||
{
|
||||
public static readonly Packet Instance = SetStatic(new CloseRaceChanger());
|
||||
|
||||
private CloseRaceChanger()
|
||||
: base(0xBF)
|
||||
{
|
||||
EnsureCapacity(7);
|
||||
|
||||
m_Stream.Write((short)0x2A);
|
||||
m_Stream.Write((byte)0);
|
||||
m_Stream.Write((byte)0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
#region For testing
|
||||
|
||||
public class RaceChangeDeed : Item, IRaceChanger
|
||||
{
|
||||
[Constructible]
|
||||
public RaceChangeDeed()
|
||||
: base(0x14F0)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public RaceChangeDeed(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "a race change deed";
|
||||
|
||||
public bool CheckComplete(PlayerMobile pm)
|
||||
{
|
||||
if (Deleted)
|
||||
return false;
|
||||
|
||||
if (!IsChildOf(pm.Backpack))
|
||||
{
|
||||
pm.SendLocalizedMessage(1042001); // That must be in your pack for you to use it.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ConsumeNeeded(PlayerMobile pm)
|
||||
{
|
||||
Consume();
|
||||
}
|
||||
|
||||
public void OnCancel(PlayerMobile pm)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (!(from is PlayerMobile pm))
|
||||
return;
|
||||
|
||||
if (CheckComplete(pm))
|
||||
pm.SendGump(new RaceChangeConfirmGump(this, pm, pm.Race == Race.Human ? Race.Elf : Race.Human));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
15
Projects/Scripts/Engines/MLQuests/IQuestGiver.cs
Normal file
15
Projects/Scripts/Engines/MLQuests/IQuestGiver.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Engines.MLQuests
|
||||
{
|
||||
public interface IQuestGiver
|
||||
{
|
||||
List<MLQuest> MLQuests{ get; }
|
||||
|
||||
Serial Serial{ get; }
|
||||
bool Deleted{ get; }
|
||||
|
||||
Type GetType();
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/ABauble.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/ABauble.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class ABauble : Item
|
||||
{
|
||||
[Constructible]
|
||||
public ABauble() : base(0x23B)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public ABauble(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1073137; // A bauble
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class APersonalLetterAddressedToAhie : TransientItem
|
||||
{
|
||||
[Constructible]
|
||||
public APersonalLetterAddressedToAhie() : base(0x14ED, TimeSpan.FromMinutes(30))
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public APersonalLetterAddressedToAhie(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1073128; // A personal letter addressed to: Ahie
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Projects/Scripts/Engines/MLQuests/Items/AlchemistsBandage.cs
Normal file
40
Projects/Scripts/Engines/MLQuests/Items/AlchemistsBandage.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class AlchemistsBandage : Item
|
||||
{
|
||||
[Constructible]
|
||||
public AlchemistsBandage() : base(0xE21)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0x482;
|
||||
}
|
||||
|
||||
public AlchemistsBandage(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075452; // Alchemist's Bandage
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/AnOldNecklace.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/AnOldNecklace.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class AnOldNecklace : Necklace
|
||||
{
|
||||
[Constructible]
|
||||
public AnOldNecklace()
|
||||
{
|
||||
Hue = 0x222;
|
||||
}
|
||||
|
||||
public AnOldNecklace(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075525; // an old necklace
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/AnOldRing.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/AnOldRing.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class AnOldRing : GoldRing
|
||||
{
|
||||
[Constructible]
|
||||
public AnOldRing()
|
||||
{
|
||||
Hue = 0x222;
|
||||
}
|
||||
|
||||
public AnOldRing(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075524; // an old ring
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/AndricSatchel.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/AndricSatchel.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class AndricSatchel : Backpack
|
||||
{
|
||||
[Constructible]
|
||||
public AndricSatchel()
|
||||
{
|
||||
Hue = Utility.RandomBrightHue();
|
||||
DropItem(new Feather(10));
|
||||
DropItem(new FletcherTools());
|
||||
}
|
||||
|
||||
public AndricSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/AndrosGratitude.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/AndrosGratitude.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class AndrosGratitude : SmithHammer
|
||||
{
|
||||
[Constructible]
|
||||
public AndrosGratitude() : base(10)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public AndrosGratitude(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075345; // Andros Gratitude
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/AsandosSatchel.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/AsandosSatchel.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class AsandosSatchel : Backpack
|
||||
{
|
||||
[Constructible]
|
||||
public AsandosSatchel()
|
||||
{
|
||||
Hue = Utility.RandomBrightHue();
|
||||
DropItem(new SackFlour());
|
||||
DropItem(new Skillet());
|
||||
}
|
||||
|
||||
public AsandosSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class BasinOfCrystalClearWater : Item
|
||||
{
|
||||
[Constructible]
|
||||
public BasinOfCrystalClearWater() : base(0x1008)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public BasinOfCrystalClearWater(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075303; // Basin of Crystal-Clear Water
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Projects/Scripts/Engines/MLQuests/Items/BedlamTeleporter.cs
Normal file
57
Projects/Scripts/Engines/MLQuests/Items/BedlamTeleporter.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Items
|
||||
{
|
||||
public class BedlamTeleporter : Item
|
||||
{
|
||||
private static readonly Point3D PointDest = new Point3D(120, 1682, 0);
|
||||
private static readonly Map MapDest = Map.Malas;
|
||||
|
||||
public BedlamTeleporter()
|
||||
: base(0x124D)
|
||||
{
|
||||
Movable = false;
|
||||
}
|
||||
|
||||
public BedlamTeleporter(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074161; // Access to Bedlam by invitation only
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (!from.InRange(GetWorldLocation(), 2))
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
|
||||
return;
|
||||
}
|
||||
|
||||
if (from is PlayerMobile mobile && MLQuestSystem.GetContext(mobile)?.BedlamAccess == true)
|
||||
{
|
||||
BaseCreature.TeleportPets(mobile, PointDest, MapDest);
|
||||
mobile.MoveToWorld(PointDest, MapDest);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1074276); // You press and push on the iron maiden, but nothing happens.
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/Bleach.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/Bleach.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class Bleach : PigmentsOfTokuno
|
||||
{
|
||||
[Constructible]
|
||||
public Bleach()
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public Bleach(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075375; // Bleach
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Projects/Scripts/Engines/MLQuests/Items/BridesLetter.cs
Normal file
39
Projects/Scripts/Engines/MLQuests/Items/BridesLetter.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class BridesLetter : Item
|
||||
{
|
||||
[Constructible]
|
||||
public BridesLetter() : base(0x14ED)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public BridesLetter(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075301; // Bride's Letter
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class CompletedTuitionReimbursementForm : Item
|
||||
{
|
||||
[Constructible]
|
||||
public CompletedTuitionReimbursementForm() : base(0x14F0)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public CompletedTuitionReimbursementForm(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074625; // Completed Tuition Reimbursement Form
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
227
Projects/Scripts/Engines/MLQuests/Items/CraftmansSatchel.cs
Normal file
227
Projects/Scripts/Engines/MLQuests/Items/CraftmansSatchel.cs
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
using System;
|
||||
using Server.Engines.Craft;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Engines.MLQuests.Items
|
||||
{
|
||||
public abstract class BaseCraftmansSatchel : Backpack
|
||||
{
|
||||
protected static readonly Type[] m_TalismanType = { typeof(RandomTalisman) };
|
||||
|
||||
public BaseCraftmansSatchel()
|
||||
{
|
||||
Hue = Utility.RandomBrightHue();
|
||||
}
|
||||
|
||||
public BaseCraftmansSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
protected void AddBaseLoot(params Type[][] lootSets)
|
||||
{
|
||||
Item loot = Loot.Construct(lootSets[Utility.Random(lootSets.Length)]);
|
||||
|
||||
if (loot == null)
|
||||
return;
|
||||
|
||||
RewardBag.Enhance(loot);
|
||||
DropItem(loot);
|
||||
}
|
||||
|
||||
protected void AddRecipe(CraftSystem system)
|
||||
{
|
||||
// TODO: change craftable artifact recipes to a rarer drop
|
||||
int recipeID = system.RandomRecipe();
|
||||
|
||||
if (recipeID != -1)
|
||||
DropItem(new RecipeScroll(recipeID));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class TailorSatchel : BaseCraftmansSatchel
|
||||
{
|
||||
[Constructible]
|
||||
public TailorSatchel()
|
||||
{
|
||||
AddBaseLoot(Loot.MLArmorTypes, Loot.JewelryTypes, m_TalismanType);
|
||||
|
||||
if (Utility.RandomDouble() < 0.50)
|
||||
AddRecipe(DefTailoring.CraftSystem);
|
||||
}
|
||||
|
||||
public TailorSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class BlacksmithSatchel : BaseCraftmansSatchel
|
||||
{
|
||||
[Constructible]
|
||||
public BlacksmithSatchel()
|
||||
{
|
||||
AddBaseLoot(Loot.MLWeaponTypes, Loot.JewelryTypes, m_TalismanType);
|
||||
|
||||
if (Utility.RandomDouble() < 0.50)
|
||||
AddRecipe(DefBlacksmithy.CraftSystem);
|
||||
}
|
||||
|
||||
public BlacksmithSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class TinkerSatchel : BaseCraftmansSatchel
|
||||
{
|
||||
[Constructible]
|
||||
public TinkerSatchel()
|
||||
{
|
||||
AddBaseLoot(Loot.MLArmorTypes, Loot.MLWeaponTypes, Loot.MLRangedWeaponTypes, Loot.JewelryTypes, m_TalismanType);
|
||||
|
||||
if (Utility.RandomDouble() < 0.50)
|
||||
switch (Utility.Random(6))
|
||||
{
|
||||
case 0:
|
||||
AddRecipe(DefInscription.CraftSystem);
|
||||
break;
|
||||
case 1:
|
||||
AddRecipe(DefAlchemy.CraftSystem);
|
||||
break;
|
||||
// TODO
|
||||
//case 2: AddNonArtifactRecipe( DefTailoring.CraftSystem ); break;
|
||||
//case 3: AddNonArtifactRecipe( DefBlacksmithy.CraftSystem ); break;
|
||||
//case 4: AddNonArtifactRecipe( DefCarpentry.CraftSystem ); break;
|
||||
//case 5: AddNonArtifactRecipe( DefBowFletching.CraftSystem ); break;
|
||||
}
|
||||
}
|
||||
|
||||
public TinkerSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class FletchingSatchel : BaseCraftmansSatchel
|
||||
{
|
||||
[Constructible]
|
||||
public FletchingSatchel()
|
||||
{
|
||||
AddBaseLoot(Loot.MLRangedWeaponTypes, Loot.JewelryTypes, m_TalismanType);
|
||||
|
||||
if (Utility.RandomDouble() < 0.50)
|
||||
AddRecipe(DefBowFletching.CraftSystem);
|
||||
|
||||
// TODO: runic fletching kit
|
||||
}
|
||||
|
||||
public FletchingSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class CarpentrySatchel : BaseCraftmansSatchel
|
||||
{
|
||||
[Constructible]
|
||||
public CarpentrySatchel()
|
||||
{
|
||||
AddBaseLoot(Loot.MLArmorTypes, Loot.MLWeaponTypes, Loot.MLRangedWeaponTypes, Loot.JewelryTypes, m_TalismanType);
|
||||
|
||||
if (Utility.RandomDouble() < 0.50)
|
||||
AddRecipe(DefCarpentry.CraftSystem);
|
||||
|
||||
// TODO: Add runic dovetail saw
|
||||
}
|
||||
|
||||
public CarpentrySatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Projects/Scripts/Engines/MLQuests/Items/CrateForSledge.cs
Normal file
41
Projects/Scripts/Engines/MLQuests/Items/CrateForSledge.cs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class CrateForSledge : TransientItem
|
||||
{
|
||||
[Constructible]
|
||||
public CrateForSledge() : base(0x1FFF, TimeSpan.FromHours(1))
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public CrateForSledge(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074520; // Crate for Sledge
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Projects/Scripts/Engines/MLQuests/Items/DreadSpiderSilk.cs
Normal file
40
Projects/Scripts/Engines/MLQuests/Items/DreadSpiderSilk.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class DreadSpiderSilk : Item
|
||||
{
|
||||
[Constructible]
|
||||
public DreadSpiderSilk() : base(0xDF8)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0x481;
|
||||
}
|
||||
|
||||
public DreadSpiderSilk(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075319; // Dread Spider Silk
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/FragmentOfAMap.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/FragmentOfAMap.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class FragmentOfAMap : Item
|
||||
{
|
||||
[Constructible]
|
||||
public FragmentOfAMap() : base(0x14ED)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public FragmentOfAMap(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074533; // Fragment of a Map
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class FragmentOfAMapDelivery : Item
|
||||
{
|
||||
[Constructible]
|
||||
public FragmentOfAMapDelivery() : base(0x14ED)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public FragmentOfAMapDelivery(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074533; // Fragment of a Map
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class FriendOfTheLibraryToken : Item
|
||||
{
|
||||
[Constructible]
|
||||
public FriendOfTheLibraryToken() : base(0x2F58)
|
||||
{
|
||||
Layer = Layer.Talisman;
|
||||
Hue = 0x28A;
|
||||
}
|
||||
|
||||
public FriendOfTheLibraryToken(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1073136; // Friend of the Library Token (allows donations to be made)
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class FriendsOfTheLibraryApplication : Item
|
||||
{
|
||||
[Constructible]
|
||||
public FriendsOfTheLibraryApplication() : base(0xEC0)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public FriendsOfTheLibraryApplication(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1073131; // Friends of the Library Application
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Projects/Scripts/Engines/MLQuests/Items/GamanHorns.cs
Normal file
34
Projects/Scripts/Engines/MLQuests/Items/GamanHorns.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class GamanHorns : Item
|
||||
{
|
||||
[Constructible]
|
||||
public GamanHorns(int amount = 1) : base(0x1084)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Stackable = true;
|
||||
Amount = amount;
|
||||
Hue = 0x395;
|
||||
}
|
||||
|
||||
public GamanHorns(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074557; // Gaman Horns
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/GervisSatchel.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/GervisSatchel.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class GervisSatchel : Backpack
|
||||
{
|
||||
[Constructible]
|
||||
public GervisSatchel()
|
||||
{
|
||||
Hue = Utility.RandomBrightHue();
|
||||
DropItem(new IronIngot(10));
|
||||
DropItem(new SmithHammer());
|
||||
}
|
||||
|
||||
public GervisSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Projects/Scripts/Engines/MLQuests/Items/GiftForArielle.cs
Normal file
40
Projects/Scripts/Engines/MLQuests/Items/GiftForArielle.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class GiftForArielle : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public GiftForArielle() : base(0x1882)
|
||||
{
|
||||
Hue = 0x2C4;
|
||||
}
|
||||
|
||||
public GiftForArielle(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074356; // gift for arielle
|
||||
public override int DefaultGumpID => 0x41;
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/HargroveSatchel.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/HargroveSatchel.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class HargroveSatchel : Backpack
|
||||
{
|
||||
[Constructible]
|
||||
public HargroveSatchel()
|
||||
{
|
||||
Hue = Utility.RandomBrightHue();
|
||||
DropItem(new Gold(15));
|
||||
DropItem(new Hatchet());
|
||||
}
|
||||
|
||||
public HargroveSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/KirinBrains.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/KirinBrains.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class KirinBrains : Item
|
||||
{
|
||||
[Constructible]
|
||||
public KirinBrains() : base(0x1CF0)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0xD7;
|
||||
}
|
||||
|
||||
public KirinBrains(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074612; // Ki-Rin Brains
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/LowelSatchel.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/LowelSatchel.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class LowelSatchel : Backpack
|
||||
{
|
||||
[Constructible]
|
||||
public LowelSatchel()
|
||||
{
|
||||
Hue = Utility.RandomBrightHue();
|
||||
DropItem(new Board(10));
|
||||
DropItem(new DovetailSaw());
|
||||
}
|
||||
|
||||
public LowelSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/MiniatureMushroom.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/MiniatureMushroom.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class MiniatureMushroom : Food
|
||||
{
|
||||
[Constructible]
|
||||
public MiniatureMushroom() : base(0xD16)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public MiniatureMushroom(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1073138; // Miniature mushroom
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class MirrorOfPurification : Item
|
||||
{
|
||||
[Constructible]
|
||||
public MirrorOfPurification() : base(0x1008)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0x530;
|
||||
}
|
||||
|
||||
public MirrorOfPurification(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075304; // Mirror of Purification
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/MuggSatchel.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/MuggSatchel.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class MuggSatchel : Backpack
|
||||
{
|
||||
[Constructible]
|
||||
public MuggSatchel()
|
||||
{
|
||||
Hue = Utility.RandomBrightHue();
|
||||
DropItem(new Pickaxe());
|
||||
DropItem(new Pickaxe());
|
||||
}
|
||||
|
||||
public MuggSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Projects/Scripts/Engines/MLQuests/Items/NibbetSatchel.cs
Normal file
65
Projects/Scripts/Engines/MLQuests/Items/NibbetSatchel.cs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class NibbetSatchel : Backpack
|
||||
{
|
||||
[Constructible]
|
||||
public NibbetSatchel()
|
||||
{
|
||||
Hue = Utility.RandomBrightHue();
|
||||
DropItem(new TinkerTools());
|
||||
|
||||
switch (Utility.Random(10))
|
||||
{
|
||||
case 0:
|
||||
DropItem(new Springs(3));
|
||||
break;
|
||||
case 1:
|
||||
DropItem(new Axle(3));
|
||||
break;
|
||||
case 2:
|
||||
DropItem(new Hinge(3));
|
||||
break;
|
||||
case 3:
|
||||
DropItem(new Key());
|
||||
break;
|
||||
case 4:
|
||||
DropItem(new Scissors());
|
||||
break;
|
||||
case 5:
|
||||
DropItem(new BarrelTap(3));
|
||||
break;
|
||||
case 6:
|
||||
DropItem(new BarrelHoops());
|
||||
break;
|
||||
case 7:
|
||||
DropItem(new Gears(3));
|
||||
break;
|
||||
case 8:
|
||||
DropItem(new Lockpick(3));
|
||||
break;
|
||||
case 9:
|
||||
DropItem(new ClockFrame(3));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public NibbetSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class NotarizedApplication : Item
|
||||
{
|
||||
[Constructible]
|
||||
public NotarizedApplication() : base(0x14EF)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public NotarizedApplication(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1073135; // Notarized Application
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class OfficialSealingWax : Item
|
||||
{
|
||||
[Constructible]
|
||||
public OfficialSealingWax() : base(0x1426)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0x84;
|
||||
}
|
||||
|
||||
public OfficialSealingWax(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1072744; // Official Sealing Wax
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class PeppercornFishsteak : FishSteak
|
||||
{
|
||||
[Constructible]
|
||||
public PeppercornFishsteak()
|
||||
{
|
||||
Hue = 0x222;
|
||||
}
|
||||
|
||||
public PeppercornFishsteak(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075557; // peppercorn fishsteak
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/PixieLeg.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/PixieLeg.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class PixieLeg : ChickenLeg
|
||||
{
|
||||
[Constructible]
|
||||
public PixieLeg(int amount = 1) : base(amount)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0x1C2;
|
||||
}
|
||||
|
||||
public PixieLeg(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074613; // Pixie Leg
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class PortraitOfTheBride : Item
|
||||
{
|
||||
[Constructible]
|
||||
public PortraitOfTheBride() : base(0xE9F)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public PortraitOfTheBride(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075300; // Portrait of the Bride
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
73
Projects/Scripts/Engines/MLQuests/Items/PrismaticAmber.cs
Normal file
73
Projects/Scripts/Engines/MLQuests/Items/PrismaticAmber.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class PrismaticAmber : Amber
|
||||
{
|
||||
[Constructible]
|
||||
public PrismaticAmber()
|
||||
{
|
||||
}
|
||||
|
||||
public PrismaticAmber(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075299; // Prismatic Amber
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
|
||||
list.Add(1075269); // Destroyed when dropped
|
||||
}
|
||||
|
||||
public override bool DropToWorld(Mobile from, Point3D p)
|
||||
{
|
||||
bool ret = base.DropToWorld(from, p);
|
||||
|
||||
if (ret)
|
||||
DestroyItem(from);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override bool DropToMobile(Mobile from, Mobile target, Point3D p)
|
||||
{
|
||||
bool ret = base.DropToMobile(from, target, p);
|
||||
|
||||
if (ret)
|
||||
DestroyItem(from);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override bool DropToItem(Mobile from, Item target, Point3D p)
|
||||
{
|
||||
bool ret = base.DropToItem(from, target, p);
|
||||
|
||||
if (ret && Parent != from.Backpack)
|
||||
DestroyItem(from);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public virtual void DestroyItem(Mobile from)
|
||||
{
|
||||
from.SendLocalizedMessage(500424); // You destroyed the item.
|
||||
Delete();
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
71
Projects/Scripts/Engines/MLQuests/Items/PrismaticCrystal.cs
Normal file
71
Projects/Scripts/Engines/MLQuests/Items/PrismaticCrystal.cs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
using Server.Engines.MLQuests;
|
||||
using Server.Engines.MLQuests.Definitions;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class PrismaticCrystal : Item
|
||||
{
|
||||
[Constructible]
|
||||
public PrismaticCrystal() : base(0x2DA)
|
||||
{
|
||||
Movable = false;
|
||||
Hue = 0x32;
|
||||
}
|
||||
|
||||
public PrismaticCrystal(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074269; // prismatic crystal
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (!(from is PlayerMobile pm) || pm.Backpack == null)
|
||||
return;
|
||||
|
||||
if (pm.InRange(GetWorldLocation(), 2))
|
||||
{
|
||||
if (MLQuestSystem.GetContext(pm)?.IsDoingQuest(typeof(UnfadingMemoriesPartOne)) == true &&
|
||||
pm.Backpack.FindItemByType<PrismaticAmber>(false) == null)
|
||||
{
|
||||
Item amber = new PrismaticAmber();
|
||||
|
||||
if (pm.PlaceInBackpack(amber))
|
||||
{
|
||||
MLQuestSystem.MarkQuestItem(pm, amber);
|
||||
Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.SendLocalizedMessage(502385); // Your pack cannot hold this item.
|
||||
amber.Delete();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.SendLocalizedMessage(1075464); // You already have as many of those as you need.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
140
Projects/Scripts/Engines/MLQuests/Items/QuestGiverItem.cs
Normal file
140
Projects/Scripts/Engines/MLQuests/Items/QuestGiverItem.cs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Items
|
||||
{
|
||||
public abstract class QuestGiverItem : Item, IQuestGiver
|
||||
{
|
||||
private List<MLQuest> m_MLQuests;
|
||||
|
||||
public QuestGiverItem(int itemId)
|
||||
: base(itemId)
|
||||
{
|
||||
}
|
||||
|
||||
public QuestGiverItem(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public bool CanGiveMLQuest => MLQuests.Count != 0;
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public List<MLQuest> MLQuests => m_MLQuests ??
|
||||
(m_MLQuests = MLQuestSystem.FindQuestList(GetType()) ?? MLQuestSystem.EmptyList);
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
|
||||
AddQuestItemProperty(list);
|
||||
|
||||
if (CanGiveMLQuest)
|
||||
list.Add(1072269); // Quest Giver
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (!from.InRange(GetWorldLocation(), 2))
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
|
||||
else if (!IsChildOf(from.Backpack))
|
||||
from.SendLocalizedMessage(1042593); // That is not in your backpack.
|
||||
else if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile)
|
||||
MLQuestSystem.OnDoubleClick(this, mobile);
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
|
||||
if (MLQuestSystem.Enabled)
|
||||
MLQuestSystem.HandleDeletion(this);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class TransientQuestGiverItem : TransientItem, IQuestGiver
|
||||
{
|
||||
private List<MLQuest> m_MLQuests;
|
||||
|
||||
public TransientQuestGiverItem(int itemId, TimeSpan lifeSpan)
|
||||
: base(itemId, lifeSpan)
|
||||
{
|
||||
}
|
||||
|
||||
public TransientQuestGiverItem(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public bool CanGiveMLQuest => MLQuests.Count != 0;
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public List<MLQuest> MLQuests => m_MLQuests ??
|
||||
(m_MLQuests = MLQuestSystem.FindQuestList(GetType()) ?? MLQuestSystem.EmptyList);
|
||||
|
||||
public override void HandleInvalidTransfer(Mobile from)
|
||||
{
|
||||
}
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
|
||||
AddQuestItemProperty(list);
|
||||
|
||||
if (CanGiveMLQuest)
|
||||
list.Add(1072269); // Quest Giver
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (!from.InRange(GetWorldLocation(), 2))
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
|
||||
else if (!IsChildOf(from.Backpack))
|
||||
from.SendLocalizedMessage(1042593); // That is not in your backpack.
|
||||
else if (MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile mobile)
|
||||
MLQuestSystem.OnDoubleClick(this, mobile);
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
base.OnAfterDelete();
|
||||
|
||||
if (MLQuestSystem.Enabled)
|
||||
MLQuestSystem.HandleDeletion(this);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Projects/Scripts/Engines/MLQuests/Items/RedLeatherBook.cs
Normal file
30
Projects/Scripts/Engines/MLQuests/Items/RedLeatherBook.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class RedLeatherBook : BlueBook
|
||||
{
|
||||
[Constructible]
|
||||
public RedLeatherBook()
|
||||
{
|
||||
Hue = 0x485;
|
||||
}
|
||||
|
||||
public RedLeatherBook(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Projects/Scripts/Engines/MLQuests/Items/ReginasLetter.cs
Normal file
39
Projects/Scripts/Engines/MLQuests/Items/ReginasLetter.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class ReginasLetter : Item
|
||||
{
|
||||
[Constructible]
|
||||
public ReginasLetter() : base(0x14ED)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public ReginasLetter(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075306; // Regina's Letter
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Projects/Scripts/Engines/MLQuests/Items/ReginasRing.cs
Normal file
39
Projects/Scripts/Engines/MLQuests/Items/ReginasRing.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class ReginasRing : SilverRing
|
||||
{
|
||||
[Constructible]
|
||||
public ReginasRing()
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public ReginasRing(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075305; // Regina's Ring
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
203
Projects/Scripts/Engines/MLQuests/Items/RewardBags.cs
Normal file
203
Projects/Scripts/Engines/MLQuests/Items/RewardBags.cs
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
using Server.Items;
|
||||
|
||||
namespace Server.Engines.MLQuests.Items
|
||||
{
|
||||
public static class RewardBag
|
||||
{
|
||||
public static void Fill(Container c, int itemCount, double talismanChance)
|
||||
{
|
||||
c.Hue = Utility.RandomNondyedHue();
|
||||
|
||||
int done = 0;
|
||||
|
||||
if (Utility.RandomDouble() < talismanChance)
|
||||
{
|
||||
c.DropItem(new RandomTalisman());
|
||||
++done;
|
||||
}
|
||||
|
||||
for (; done < itemCount; ++done)
|
||||
{
|
||||
Item loot = null;
|
||||
|
||||
switch (Utility.Random(5))
|
||||
{
|
||||
case 0:
|
||||
loot = Loot.RandomWeapon(false, true);
|
||||
break;
|
||||
case 1:
|
||||
loot = Loot.RandomArmor(false, true);
|
||||
break;
|
||||
case 2:
|
||||
loot = Loot.RandomRangedWeapon(false, true);
|
||||
break;
|
||||
case 3:
|
||||
loot = Loot.RandomJewelry();
|
||||
break;
|
||||
case 4:
|
||||
loot = Loot.RandomHat(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (loot == null)
|
||||
continue;
|
||||
|
||||
Enhance(loot);
|
||||
c.DropItem(loot);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Enhance(Item loot)
|
||||
{
|
||||
if (loot is BaseWeapon weapon)
|
||||
{
|
||||
BaseRunicTool.ApplyAttributesTo(weapon, Utility.RandomMinMax(1, 5), 10, 80);
|
||||
return;
|
||||
}
|
||||
|
||||
if (loot is BaseArmor armor) BaseRunicTool.ApplyAttributesTo(armor, Utility.RandomMinMax(1, 5), 10, 80);
|
||||
|
||||
if (loot is BaseJewel jewel) BaseRunicTool.ApplyAttributesTo(jewel, Utility.RandomMinMax(1, 5), 10, 80);
|
||||
}
|
||||
}
|
||||
|
||||
public class SmallBagOfTrinkets : Bag
|
||||
{
|
||||
[Constructible]
|
||||
public SmallBagOfTrinkets()
|
||||
{
|
||||
RewardBag.Fill(this, 1, 0.0);
|
||||
}
|
||||
|
||||
public SmallBagOfTrinkets(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class BagOfTrinkets : Bag
|
||||
{
|
||||
[Constructible]
|
||||
public BagOfTrinkets()
|
||||
{
|
||||
RewardBag.Fill(this, 2, 0.05);
|
||||
}
|
||||
|
||||
public BagOfTrinkets(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class BagOfTreasure : Bag
|
||||
{
|
||||
[Constructible]
|
||||
public BagOfTreasure()
|
||||
{
|
||||
RewardBag.Fill(this, 3, 0.20);
|
||||
}
|
||||
|
||||
public BagOfTreasure(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class LargeBagOfTreasure : Bag
|
||||
{
|
||||
[Constructible]
|
||||
public LargeBagOfTreasure()
|
||||
{
|
||||
RewardBag.Fill(this, 4, 0.50);
|
||||
}
|
||||
|
||||
public LargeBagOfTreasure(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class RewardStrongbox : WoodenBox
|
||||
{
|
||||
[Constructible]
|
||||
public RewardStrongbox()
|
||||
{
|
||||
RewardBag.Fill(this, 5, 1.0);
|
||||
}
|
||||
|
||||
public RewardStrongbox(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/SadrahSatchel.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/SadrahSatchel.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class SadrahSatchel : Backpack
|
||||
{
|
||||
[Constructible]
|
||||
public SadrahSatchel()
|
||||
{
|
||||
Hue = Utility.RandomBrightHue();
|
||||
DropItem(new Bloodmoss(10));
|
||||
DropItem(new MortarPestle());
|
||||
}
|
||||
|
||||
public SadrahSatchel(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Projects/Scripts/Engines/MLQuests/Items/SapOfSosaria.cs
Normal file
33
Projects/Scripts/Engines/MLQuests/Items/SapOfSosaria.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class SapOfSosaria : Item
|
||||
{
|
||||
[Constructible]
|
||||
public SapOfSosaria(int amount = 1) : base(0x1848)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Stackable = true;
|
||||
Amount = amount;
|
||||
}
|
||||
|
||||
public SapOfSosaria(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074178; // Sap of Sosaria
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class SealedNotesForJamal : Item
|
||||
{
|
||||
[Constructible]
|
||||
public SealedNotesForJamal() : base(0xEF9)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public SealedNotesForJamal(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074998; // Sealed Notes For Jamal
|
||||
public override double DefaultWeight => 1.0;
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class SealingWaxOrderAddressedToPetrus : Item
|
||||
{
|
||||
[Constructible]
|
||||
public SealingWaxOrderAddressedToPetrus() : base(0xEBF)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public SealingWaxOrderAddressedToPetrus(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1073132; // Sealing Wax Order addressed to Petrus
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/SeveredElfEars.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/SeveredElfEars.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
[Flippable(0x312D, 0x312E)]
|
||||
public class SeveredElfEars : Item
|
||||
{
|
||||
[Constructible]
|
||||
public SeveredElfEars(int amount = 1) : base(Utility.RandomList(0x312D, 0x312E))
|
||||
{
|
||||
Stackable = true;
|
||||
Amount = amount;
|
||||
}
|
||||
|
||||
public SeveredElfEars(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/SeveredHumanEars.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/SeveredHumanEars.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
[Flippable(0x312F, 0x3130)]
|
||||
public class SeveredHumanEars : Item
|
||||
{
|
||||
[Constructible]
|
||||
public SeveredHumanEars(int amount = 1) : base(Utility.RandomList(0x312F, 0x3130))
|
||||
{
|
||||
Stackable = true;
|
||||
Amount = amount;
|
||||
}
|
||||
|
||||
public SeveredHumanEars(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class SignedTuitionReimbursementForm : Item
|
||||
{
|
||||
[Constructible]
|
||||
public SignedTuitionReimbursementForm() : base(0x14F0)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public SignedTuitionReimbursementForm(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074614; // Signed Tuition Reimbursement Form
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class SpecialTreatForDrithen : Item
|
||||
{
|
||||
[Constructible]
|
||||
public SpecialTreatForDrithen() : base(0x21B)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0x489;
|
||||
}
|
||||
|
||||
public SpecialTreatForDrithen(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074517; // Special Treat for Drithen
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Projects/Scripts/Engines/MLQuests/Items/SpeckledPoisonSac.cs
Normal file
33
Projects/Scripts/Engines/MLQuests/Items/SpeckledPoisonSac.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class SpeckledPoisonSac : TransientItem
|
||||
{
|
||||
[Constructible]
|
||||
public SpeckledPoisonSac() : base(0x23A, TimeSpan.FromHours(1))
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public SpeckledPoisonSac(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1073133; // Speckled Poison Sac
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
39
Projects/Scripts/Engines/MLQuests/Items/SpiritBottle.cs
Normal file
39
Projects/Scripts/Engines/MLQuests/Items/SpiritBottle.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class SpiritBottle : Item
|
||||
{
|
||||
[Constructible]
|
||||
public SpiritBottle() : base(0xEFB)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public SpiritBottle(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075283; // Spirit bottle
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Projects/Scripts/Engines/MLQuests/Items/StoutWhip.cs
Normal file
31
Projects/Scripts/Engines/MLQuests/Items/StoutWhip.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class StoutWhip : Item
|
||||
{
|
||||
[Constructible]
|
||||
public StoutWhip() : base(0x166F)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public StoutWhip(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074812; // Stout Whip
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Projects/Scripts/Engines/MLQuests/Items/TaintedTreeSample.cs
Normal file
40
Projects/Scripts/Engines/MLQuests/Items/TaintedTreeSample.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class TaintedTreeSample : Item // On OSI the base class is Kindling, and it's ignitable...
|
||||
{
|
||||
[Constructible]
|
||||
public TaintedTreeSample() : base(0xDE2)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0x9D;
|
||||
}
|
||||
|
||||
public TaintedTreeSample(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074997; // Tainted Tree Sample
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
194
Projects/Scripts/Engines/MLQuests/Items/Teleporters.cs
Normal file
194
Projects/Scripts/Engines/MLQuests/Items/Teleporters.cs
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Items
|
||||
{
|
||||
public class MLQuestTeleporter : Teleporter
|
||||
{
|
||||
private Type m_QuestType;
|
||||
|
||||
[Constructible]
|
||||
public MLQuestTeleporter()
|
||||
: this(Point3D.Zero)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public MLQuestTeleporter(
|
||||
Point3D pointDest, Map mapDest = null, Type questType = null, TextDefinition message = null)
|
||||
: base(pointDest, mapDest)
|
||||
{
|
||||
m_QuestType = questType;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public MLQuestTeleporter(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Type QuestType
|
||||
{
|
||||
get => m_QuestType;
|
||||
set
|
||||
{
|
||||
m_QuestType = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public TextDefinition Message{ get; set; }
|
||||
|
||||
public override bool CanTeleport(Mobile m)
|
||||
{
|
||||
if (!base.CanTeleport(m))
|
||||
return false;
|
||||
|
||||
if (m_QuestType == null)
|
||||
return true;
|
||||
if (!(m is PlayerMobile pm))
|
||||
return false;
|
||||
|
||||
MLQuestContext context = MLQuestSystem.GetContext(pm);
|
||||
|
||||
if (context?.IsDoingQuest(m_QuestType) == true || context?.HasDoneQuest(m_QuestType) == true)
|
||||
return true;
|
||||
|
||||
TextDefinition.SendMessageTo(m, Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void GetProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.GetProperties(list);
|
||||
|
||||
if (m_QuestType != null)
|
||||
list.Add($"Required quest: {m_QuestType.Name}");
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_QuestType != null ? m_QuestType.FullName : null);
|
||||
TextDefinition.Serialize(writer, Message);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
string typeName = reader.ReadString();
|
||||
|
||||
if (typeName != null)
|
||||
m_QuestType = ScriptCompiler.FindTypeByFullName(typeName, false);
|
||||
|
||||
Message = TextDefinition.Deserialize(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public interface ITicket
|
||||
{
|
||||
void OnTicketUsed(Mobile from);
|
||||
}
|
||||
|
||||
public class TicketTeleporter : Teleporter
|
||||
{
|
||||
private Type m_TicketType;
|
||||
|
||||
[Constructible]
|
||||
public TicketTeleporter()
|
||||
: this(Point3D.Zero)
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public TicketTeleporter(
|
||||
Point3D pointDest, Map mapDest = null, Type ticketType = null, TextDefinition message = null)
|
||||
: base(pointDest, mapDest)
|
||||
{
|
||||
m_TicketType = ticketType;
|
||||
Message = message;
|
||||
}
|
||||
|
||||
public TicketTeleporter(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Type TicketType
|
||||
{
|
||||
get => m_TicketType;
|
||||
set
|
||||
{
|
||||
m_TicketType = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public TextDefinition Message{ get; set; }
|
||||
|
||||
public override bool CanTeleport(Mobile m)
|
||||
{
|
||||
if (!base.CanTeleport(m))
|
||||
return false;
|
||||
|
||||
if (m_TicketType == null)
|
||||
return true;
|
||||
|
||||
Container pack = m.Backpack;
|
||||
Item ticket = pack?.FindItemByType(m_TicketType, false) ?? m.Items.Find(item => m_TicketType.IsInstanceOfType(item));
|
||||
|
||||
if (ticket == null)
|
||||
{
|
||||
TextDefinition.SendMessageTo(m, Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
(ticket as ITicket)?.OnTicketUsed(m);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void GetProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.GetProperties(list);
|
||||
|
||||
if (m_TicketType != null)
|
||||
list.Add($"Required ticket: {m_TicketType.Name}");
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_TicketType != null ? m_TicketType.FullName : null);
|
||||
TextDefinition.Serialize(writer, Message);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
string typeName = reader.ReadString();
|
||||
|
||||
if (typeName != null)
|
||||
m_TicketType = ScriptCompiler.FindTypeByFullName(typeName, false);
|
||||
|
||||
Message = TextDefinition.Deserialize(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Projects/Scripts/Engines/MLQuests/Items/TransparentHeart.cs
Normal file
32
Projects/Scripts/Engines/MLQuests/Items/TransparentHeart.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class TransparentHeart : GoldEarrings
|
||||
{
|
||||
[Constructible]
|
||||
public TransparentHeart()
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0x4AB;
|
||||
}
|
||||
|
||||
public TransparentHeart(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1075400; // Transparent Heart
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class TuitionReimbursementForm : Item
|
||||
{
|
||||
[Constructible]
|
||||
public TuitionReimbursementForm() : base(0xE3A)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
}
|
||||
|
||||
public TuitionReimbursementForm(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074610; // Tuition Reimbursement Form (in triplicate)
|
||||
|
||||
public override bool Nontransferable => true;
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
AddQuestItemProperty(list);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Projects/Scripts/Engines/MLQuests/Items/UnicornRibs.cs
Normal file
34
Projects/Scripts/Engines/MLQuests/Items/UnicornRibs.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
public class UnicornRibs : Item
|
||||
{
|
||||
[Constructible]
|
||||
public UnicornRibs(int amount = 1) : base(0x9F1)
|
||||
{
|
||||
LootType = LootType.Blessed;
|
||||
Hue = 0x14B;
|
||||
Stackable = true;
|
||||
Amount = amount;
|
||||
}
|
||||
|
||||
public UnicornRibs(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1074611; // Unicorn Ribs
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // Version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
273
Projects/Scripts/Engines/MLQuests/MLQuest.cs
Normal file
273
Projects/Scripts/Engines/MLQuests/MLQuest.cs
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Engines.MLQuests.Gumps;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests
|
||||
{
|
||||
public enum ObjectiveType
|
||||
{
|
||||
All,
|
||||
Any
|
||||
}
|
||||
|
||||
public class MLQuest
|
||||
{
|
||||
public static readonly TextDefinition
|
||||
CompletionNoticeDefault =
|
||||
new TextDefinition(1072273); // You've completed a quest! Don't forget to collect your reward.
|
||||
|
||||
public static readonly TextDefinition CompletionNoticeShort = new TextDefinition(1046258); // Your quest is complete.
|
||||
|
||||
public static readonly TextDefinition
|
||||
CompletionNoticeShortReturn = new TextDefinition(1073775); // Your quest is complete. Return for your reward.
|
||||
|
||||
public static readonly TextDefinition
|
||||
CompletionNoticeCraft = new TextDefinition(1073967); // You obtained what you seek, now receive your reward.
|
||||
|
||||
public MLQuest()
|
||||
{
|
||||
Activated = false;
|
||||
Objectives = new List<BaseObjective>();
|
||||
ObjectiveType = ObjectiveType.All;
|
||||
Rewards = new List<BaseReward>();
|
||||
CompletionNotice = CompletionNoticeDefault;
|
||||
|
||||
Instances = new List<MLQuestInstance>();
|
||||
|
||||
SaveEnabled = true;
|
||||
}
|
||||
|
||||
public bool Deserialized{ get; set; }
|
||||
|
||||
public bool SaveEnabled{ get; set; }
|
||||
|
||||
// TODO: Flags? (Deserialized, SaveEnabled, Activated)
|
||||
|
||||
public bool Activated{ get; set; }
|
||||
|
||||
public List<BaseObjective> Objectives{ get; set; }
|
||||
|
||||
public ObjectiveType ObjectiveType{ get; set; }
|
||||
|
||||
public List<BaseReward> Rewards{ get; set; }
|
||||
|
||||
public List<MLQuestInstance> Instances{ get; set; }
|
||||
|
||||
public bool OneTimeOnly{ get; set; }
|
||||
|
||||
public bool HasRestartDelay{ get; set; }
|
||||
|
||||
public bool IsEscort => HasObjective<EscortObjective>();
|
||||
|
||||
public bool IsSkillTrainer => HasObjective<GainSkillObjective>();
|
||||
|
||||
public bool RequiresCollection => HasObjective<CollectObjective>() || HasObjective<DeliverObjective>();
|
||||
|
||||
public virtual bool RecordCompletion => OneTimeOnly || HasRestartDelay;
|
||||
|
||||
public virtual bool IsChainTriggered => false;
|
||||
public virtual Type NextQuest => null;
|
||||
|
||||
public TextDefinition Title{ get; set; }
|
||||
|
||||
public TextDefinition Description{ get; set; }
|
||||
|
||||
public TextDefinition RefusalMessage{ get; set; }
|
||||
|
||||
public TextDefinition InProgressMessage{ get; set; }
|
||||
|
||||
public TextDefinition CompletionMessage{ get; set; }
|
||||
|
||||
public TextDefinition CompletionNotice{ get; set; }
|
||||
|
||||
public virtual int Version => 0;
|
||||
|
||||
public bool HasObjective<T>() where T : BaseObjective
|
||||
{
|
||||
foreach (BaseObjective obj in Objectives)
|
||||
if (obj is T)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void Generate()
|
||||
{
|
||||
if (MLQuestSystem.Debug)
|
||||
Console.WriteLine("INFO: Generating quest: {0}", GetType());
|
||||
}
|
||||
|
||||
public MLQuestInstance CreateInstance(IQuestGiver quester, PlayerMobile pm)
|
||||
{
|
||||
return new MLQuestInstance(this, quester, pm);
|
||||
}
|
||||
|
||||
public bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message)
|
||||
{
|
||||
return CanOffer(quester, pm, MLQuestSystem.GetContext(pm), message);
|
||||
}
|
||||
|
||||
public virtual bool CanOffer(IQuestGiver quester, PlayerMobile pm, MLQuestContext context, bool message)
|
||||
{
|
||||
if (!Activated || quester.Deleted)
|
||||
return false;
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
if (context.IsFull)
|
||||
{
|
||||
if (message)
|
||||
MLQuestSystem.Tell(quester, pm, 1080107); // I'm sorry, I have nothing for you at this time.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MLQuest checkQuest = this;
|
||||
|
||||
while (checkQuest != null)
|
||||
{
|
||||
if (context.HasDoneQuest(checkQuest, out DateTime nextAvailable))
|
||||
{
|
||||
if (checkQuest.OneTimeOnly)
|
||||
{
|
||||
if (message)
|
||||
MLQuestSystem.Tell(quester, pm, 1075454); // I cannot offer you the quest again.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nextAvailable > DateTime.UtcNow)
|
||||
{
|
||||
if (message)
|
||||
MLQuestSystem.Tell(quester, pm,
|
||||
1075575); // I'm sorry, but I don't have anything else for you right now. Could you check back with me in a few minutes?
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkQuest.NextQuest == null)
|
||||
break;
|
||||
|
||||
checkQuest = MLQuestSystem.FindQuest(checkQuest.NextQuest);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (BaseObjective obj in Objectives)
|
||||
if (!obj.CanOffer(quester, pm, message))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void SendOffer(IQuestGiver quester, PlayerMobile pm)
|
||||
{
|
||||
pm.SendGump(new QuestOfferGump(this, quester, pm));
|
||||
}
|
||||
|
||||
public virtual void OnAccept(IQuestGiver quester, PlayerMobile pm)
|
||||
{
|
||||
if (!CanOffer(quester, pm, true))
|
||||
return;
|
||||
|
||||
MLQuestInstance instance = CreateInstance(quester, pm);
|
||||
|
||||
pm.SendLocalizedMessage(1049019); // You have accepted the Quest.
|
||||
pm.SendSound(0x2E7); // private sound
|
||||
|
||||
OnAccepted(instance);
|
||||
|
||||
foreach (BaseObjectiveInstance obj in instance.Objectives)
|
||||
obj.OnQuestAccepted();
|
||||
}
|
||||
|
||||
public virtual void OnAccepted(MLQuestInstance instance)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnRefuse(IQuestGiver quester, PlayerMobile pm)
|
||||
{
|
||||
pm.SendGump(new QuestConversationGump(this, pm, RefusalMessage));
|
||||
}
|
||||
|
||||
public virtual void GetRewards(MLQuestInstance instance)
|
||||
{
|
||||
instance.SendRewardGump();
|
||||
}
|
||||
|
||||
public virtual void OnRewardClaimed(MLQuestInstance instance)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnCancel(MLQuestInstance instance)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnQuesterDeleted(MLQuestInstance instance)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnPlayerDeath(MLQuestInstance instance)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual TimeSpan GetRestartDelay()
|
||||
{
|
||||
return TimeSpan.FromSeconds(Utility.Random(1, 5) * 30);
|
||||
}
|
||||
|
||||
public static void Serialize(GenericWriter writer, MLQuest quest)
|
||||
{
|
||||
MLQuestSystem.WriteQuestRef(writer, quest);
|
||||
writer.Write(quest.Version);
|
||||
}
|
||||
|
||||
public static void Deserialize(GenericReader reader, int version)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.ReadQuestRef(reader);
|
||||
int oldVersion = reader.ReadInt();
|
||||
|
||||
if (quest == null)
|
||||
return; // not saved or no longer exists
|
||||
|
||||
quest.Refresh(oldVersion);
|
||||
quest.Deserialized = true;
|
||||
}
|
||||
|
||||
public virtual void Refresh(int oldVersion)
|
||||
{
|
||||
}
|
||||
|
||||
#region Generation Methods
|
||||
|
||||
public void PutSpawner(Spawner s, Point3D loc, Map map)
|
||||
{
|
||||
string name = $"MLQS-{GetType().Name}";
|
||||
|
||||
IEnumerable<Item> toDelete = map.GetItemsInRange(loc, 0).Where(item => item is Spawner && item.Name == name);
|
||||
|
||||
foreach (Item item in toDelete)
|
||||
item.Delete();
|
||||
|
||||
s.Name = name;
|
||||
s.MoveToWorld(loc, map);
|
||||
}
|
||||
|
||||
public void PutDeco(Item deco, Point3D loc, Map map)
|
||||
{
|
||||
// Auto cleanup on regeneration
|
||||
IEnumerable<Item> toDelete = map.GetItemsInRange(loc, 0).Where(item => item.ItemID == deco.ItemID && item.Z == loc.Z);
|
||||
|
||||
foreach (Item item in toDelete)
|
||||
item.Delete();
|
||||
|
||||
deco.MoveToWorld(loc, map);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
275
Projects/Scripts/Engines/MLQuests/MLQuestContext.cs
Normal file
275
Projects/Scripts/Engines/MLQuests/MLQuestContext.cs
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests
|
||||
{
|
||||
[Flags]
|
||||
public enum MLQuestFlag
|
||||
{
|
||||
None = 0x00,
|
||||
Spellweaving = 0x01,
|
||||
SummonFey = 0x02,
|
||||
SummonFiend = 0x04,
|
||||
BedlamAccess = 0x08
|
||||
}
|
||||
|
||||
[PropertyObject]
|
||||
public class MLQuestContext
|
||||
{
|
||||
private List<MLDoneQuestInfo> m_DoneQuests;
|
||||
private MLQuestFlag m_Flags;
|
||||
|
||||
public MLQuestContext(PlayerMobile owner)
|
||||
{
|
||||
Owner = owner;
|
||||
QuestInstances = new List<MLQuestInstance>();
|
||||
m_DoneQuests = new List<MLDoneQuestInfo>();
|
||||
ChainOffers = new List<MLQuest>();
|
||||
m_Flags = MLQuestFlag.None;
|
||||
}
|
||||
|
||||
public MLQuestContext(GenericReader reader, int version)
|
||||
{
|
||||
Owner = reader.ReadMobile<PlayerMobile>();
|
||||
QuestInstances = new List<MLQuestInstance>();
|
||||
m_DoneQuests = new List<MLDoneQuestInfo>();
|
||||
ChainOffers = new List<MLQuest>();
|
||||
|
||||
int instances = reader.ReadInt();
|
||||
|
||||
for (int i = 0; i < instances; ++i)
|
||||
{
|
||||
MLQuestInstance instance = MLQuestInstance.Deserialize(reader, version, Owner);
|
||||
|
||||
if (instance != null)
|
||||
QuestInstances.Add(instance);
|
||||
}
|
||||
|
||||
int doneQuests = reader.ReadInt();
|
||||
|
||||
for (int i = 0; i < doneQuests; ++i)
|
||||
{
|
||||
MLDoneQuestInfo info = MLDoneQuestInfo.Deserialize(reader, version);
|
||||
|
||||
if (info != null)
|
||||
m_DoneQuests.Add(info);
|
||||
}
|
||||
|
||||
int chainOffers = reader.ReadInt();
|
||||
|
||||
for (int i = 0; i < chainOffers; ++i)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.ReadQuestRef(reader);
|
||||
|
||||
if (quest?.IsChainTriggered == true)
|
||||
ChainOffers.Add(quest);
|
||||
}
|
||||
|
||||
m_Flags = (MLQuestFlag)reader.ReadEncodedInt();
|
||||
}
|
||||
|
||||
public PlayerMobile Owner{ get; }
|
||||
|
||||
public List<MLQuestInstance> QuestInstances{ get; }
|
||||
|
||||
public List<MLQuest> ChainOffers{ get; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool IsFull => QuestInstances.Count >= MLQuestSystem.MaxConcurrentQuests;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool Spellweaving
|
||||
{
|
||||
get => GetFlag(MLQuestFlag.Spellweaving);
|
||||
set => SetFlag(MLQuestFlag.Spellweaving, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool SummonFey
|
||||
{
|
||||
get => GetFlag(MLQuestFlag.SummonFey);
|
||||
set => SetFlag(MLQuestFlag.SummonFey, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool SummonFiend
|
||||
{
|
||||
get => GetFlag(MLQuestFlag.SummonFiend);
|
||||
set => SetFlag(MLQuestFlag.SummonFiend, value);
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool BedlamAccess
|
||||
{
|
||||
get => GetFlag(MLQuestFlag.BedlamAccess);
|
||||
set => SetFlag(MLQuestFlag.BedlamAccess, value);
|
||||
}
|
||||
|
||||
public bool HasDoneQuest(Type questType)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.FindQuest(questType);
|
||||
|
||||
return quest != null && HasDoneQuest(quest);
|
||||
}
|
||||
|
||||
public bool HasDoneQuest(MLQuest quest)
|
||||
{
|
||||
foreach (MLDoneQuestInfo info in m_DoneQuests)
|
||||
if (info.m_Quest == quest)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool HasDoneQuest(MLQuest quest, out DateTime nextAvailable)
|
||||
{
|
||||
nextAvailable = DateTime.MinValue;
|
||||
|
||||
foreach (MLDoneQuestInfo info in m_DoneQuests)
|
||||
if (info.m_Quest == quest)
|
||||
{
|
||||
nextAvailable = info.m_NextAvailable;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SetDoneQuest(MLQuest quest)
|
||||
{
|
||||
SetDoneQuest(quest, DateTime.MinValue);
|
||||
}
|
||||
|
||||
public void SetDoneQuest(MLQuest quest, DateTime nextAvailable)
|
||||
{
|
||||
foreach (MLDoneQuestInfo info in m_DoneQuests)
|
||||
if (info.m_Quest == quest)
|
||||
{
|
||||
info.m_NextAvailable = nextAvailable;
|
||||
return;
|
||||
}
|
||||
|
||||
m_DoneQuests.Add(new MLDoneQuestInfo(quest, nextAvailable));
|
||||
}
|
||||
|
||||
public void RemoveDoneQuest(MLQuest quest)
|
||||
{
|
||||
for (int i = m_DoneQuests.Count - 1; i >= 0; --i)
|
||||
{
|
||||
MLDoneQuestInfo info = m_DoneQuests[i];
|
||||
|
||||
if (info.m_Quest == quest)
|
||||
m_DoneQuests.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleDeath()
|
||||
{
|
||||
for (int i = QuestInstances.Count - 1; i >= 0; --i)
|
||||
QuestInstances[i].OnPlayerDeath();
|
||||
}
|
||||
|
||||
public void HandleDeletion()
|
||||
{
|
||||
for (int i = QuestInstances.Count - 1; i >= 0; --i)
|
||||
QuestInstances[i].Remove();
|
||||
}
|
||||
|
||||
public MLQuestInstance FindInstance(Type questType)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.FindQuest(questType);
|
||||
|
||||
if (quest == null)
|
||||
return null;
|
||||
|
||||
return FindInstance(quest);
|
||||
}
|
||||
|
||||
public MLQuestInstance FindInstance(MLQuest quest)
|
||||
{
|
||||
foreach (MLQuestInstance instance in QuestInstances)
|
||||
if (instance.Quest == quest)
|
||||
return instance;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool IsDoingQuest(Type questType)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.FindQuest(questType);
|
||||
|
||||
return quest != null && IsDoingQuest(quest);
|
||||
}
|
||||
|
||||
public bool IsDoingQuest(MLQuest quest)
|
||||
{
|
||||
return FindInstance(quest) != null;
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
// Version info is written in MLQuestPersistence.Serialize
|
||||
|
||||
writer.WriteMobile(Owner);
|
||||
writer.Write(QuestInstances.Count);
|
||||
|
||||
foreach (MLQuestInstance instance in QuestInstances)
|
||||
instance.Serialize(writer);
|
||||
|
||||
writer.Write(m_DoneQuests.Count);
|
||||
|
||||
foreach (MLDoneQuestInfo info in m_DoneQuests)
|
||||
info.Serialize(writer);
|
||||
|
||||
writer.Write(ChainOffers.Count);
|
||||
|
||||
foreach (MLQuest quest in ChainOffers)
|
||||
MLQuestSystem.WriteQuestRef(writer, quest);
|
||||
|
||||
writer.WriteEncodedInt((int)m_Flags);
|
||||
}
|
||||
|
||||
public bool GetFlag(MLQuestFlag flag)
|
||||
{
|
||||
return (m_Flags & flag) != 0;
|
||||
}
|
||||
|
||||
public void SetFlag(MLQuestFlag flag, bool value)
|
||||
{
|
||||
if (value)
|
||||
m_Flags |= flag;
|
||||
else
|
||||
m_Flags &= ~flag;
|
||||
}
|
||||
|
||||
private class MLDoneQuestInfo
|
||||
{
|
||||
public DateTime m_NextAvailable;
|
||||
public MLQuest m_Quest;
|
||||
|
||||
public MLDoneQuestInfo(MLQuest quest, DateTime nextAvailable)
|
||||
{
|
||||
m_Quest = quest;
|
||||
m_NextAvailable = nextAvailable;
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
MLQuestSystem.WriteQuestRef(writer, m_Quest);
|
||||
writer.Write(m_NextAvailable);
|
||||
}
|
||||
|
||||
public static MLDoneQuestInfo Deserialize(GenericReader reader, int version)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.ReadQuestRef(reader);
|
||||
DateTime nextAvailable = reader.ReadDateTime();
|
||||
|
||||
if (quest == null || !quest.RecordCompletion)
|
||||
return null; // forget about this record
|
||||
|
||||
return new MLDoneQuestInfo(quest, nextAvailable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
484
Projects/Scripts/Engines/MLQuests/MLQuestEntry.cs
Normal file
484
Projects/Scripts/Engines/MLQuests/MLQuestEntry.cs
Normal file
|
|
@ -0,0 +1,484 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Engines.MLQuests.Gumps;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Engines.MLQuests.Rewards;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests
|
||||
{
|
||||
[Flags]
|
||||
public enum MLQuestInstanceFlags : byte
|
||||
{
|
||||
None = 0x00,
|
||||
ClaimReward = 0x01,
|
||||
Removed = 0x02,
|
||||
Failed = 0x04
|
||||
}
|
||||
|
||||
public class MLQuestInstance
|
||||
{
|
||||
private MLQuestInstanceFlags m_Flags;
|
||||
private IQuestGiver m_Quester;
|
||||
|
||||
private Timer m_Timer;
|
||||
|
||||
public MLQuestInstance(MLQuest quest, IQuestGiver quester, PlayerMobile player)
|
||||
{
|
||||
Quest = quest;
|
||||
|
||||
m_Quester = quester;
|
||||
QuesterType = quester?.GetType();
|
||||
Player = player;
|
||||
|
||||
Accepted = DateTime.UtcNow;
|
||||
m_Flags = MLQuestInstanceFlags.None;
|
||||
|
||||
Objectives = new BaseObjectiveInstance[quest.Objectives.Count];
|
||||
|
||||
BaseObjectiveInstance obj;
|
||||
bool timed = false;
|
||||
|
||||
for (int i = 0; i < quest.Objectives.Count; ++i)
|
||||
{
|
||||
Objectives[i] = obj = quest.Objectives[i].CreateInstance(this);
|
||||
|
||||
if (obj.IsTimed)
|
||||
timed = true;
|
||||
}
|
||||
|
||||
Register();
|
||||
|
||||
if (timed)
|
||||
m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), Slice);
|
||||
}
|
||||
|
||||
public MLQuest Quest{ get; set; }
|
||||
|
||||
public IQuestGiver Quester
|
||||
{
|
||||
get => m_Quester;
|
||||
set
|
||||
{
|
||||
m_Quester = value;
|
||||
QuesterType = value?.GetType();
|
||||
}
|
||||
}
|
||||
|
||||
public Type QuesterType{ get; private set; }
|
||||
|
||||
public PlayerMobile Player{ get; set; }
|
||||
|
||||
public MLQuestContext PlayerContext => MLQuestSystem.GetOrCreateContext(Player);
|
||||
|
||||
public DateTime Accepted{ get; set; }
|
||||
|
||||
public bool ClaimReward
|
||||
{
|
||||
get => GetFlag(MLQuestInstanceFlags.ClaimReward);
|
||||
set => SetFlag(MLQuestInstanceFlags.ClaimReward, value);
|
||||
}
|
||||
|
||||
public bool Removed
|
||||
{
|
||||
get => GetFlag(MLQuestInstanceFlags.Removed);
|
||||
set => SetFlag(MLQuestInstanceFlags.Removed, value);
|
||||
}
|
||||
|
||||
public bool Failed
|
||||
{
|
||||
get => GetFlag(MLQuestInstanceFlags.Failed);
|
||||
set => SetFlag(MLQuestInstanceFlags.Failed, value);
|
||||
}
|
||||
|
||||
public BaseObjectiveInstance[] Objectives{ get; set; }
|
||||
|
||||
public bool SkipReportBack => TextDefinition.IsNullOrEmpty(Quest.CompletionMessage);
|
||||
|
||||
private void Register()
|
||||
{
|
||||
Quest?.Instances?.Add(this);
|
||||
|
||||
if (Player != null)
|
||||
PlayerContext.QuestInstances.Add(this);
|
||||
}
|
||||
|
||||
private void Unregister()
|
||||
{
|
||||
Quest?.Instances?.Remove(this);
|
||||
|
||||
if (Player != null)
|
||||
PlayerContext.QuestInstances.Remove(this);
|
||||
|
||||
Removed = true;
|
||||
}
|
||||
|
||||
public bool AllowsQuestItem(Item item, Type type)
|
||||
{
|
||||
foreach (BaseObjectiveInstance objective in Objectives)
|
||||
if (!objective.Expired && objective.AllowsQuestItem(item, type))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsCompleted()
|
||||
{
|
||||
bool requiresAll = Quest.ObjectiveType == ObjectiveType.All;
|
||||
|
||||
foreach (BaseObjectiveInstance obj in Objectives)
|
||||
{
|
||||
bool complete = obj.IsCompleted();
|
||||
|
||||
if (complete && !requiresAll)
|
||||
return true;
|
||||
if (!complete && requiresAll)
|
||||
return false;
|
||||
}
|
||||
|
||||
return requiresAll;
|
||||
}
|
||||
|
||||
public void CheckComplete()
|
||||
{
|
||||
if (IsCompleted())
|
||||
{
|
||||
Player.PlaySound(0x5B5); // public sound
|
||||
|
||||
foreach (BaseObjectiveInstance obj in Objectives)
|
||||
obj.OnQuestCompleted();
|
||||
|
||||
TextDefinition.SendMessageTo(Player, Quest.CompletionNotice, 0x23);
|
||||
|
||||
/*
|
||||
* Advance to the ClaimReward=true stage if this quest has no
|
||||
* completion message to show anyway. This suppresses further
|
||||
* triggers of CheckComplete.
|
||||
*
|
||||
* For quests that require collections, this is done later when
|
||||
* the player double clicks the quester.
|
||||
*/
|
||||
if (!Removed && SkipReportBack && !Quest.RequiresCollection
|
||||
) // An OnQuestCompleted can potentially have removed this instance already
|
||||
ContinueReportBack(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void Fail()
|
||||
{
|
||||
Failed = true;
|
||||
}
|
||||
|
||||
private void Slice()
|
||||
{
|
||||
if (ClaimReward || Removed)
|
||||
{
|
||||
StopTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasAnyFails = false;
|
||||
bool hasAnyLeft = false;
|
||||
|
||||
foreach (BaseObjectiveInstance obj in Objectives)
|
||||
if (!obj.Expired)
|
||||
{
|
||||
if (obj.IsTimed && obj.EndTime <= DateTime.UtcNow)
|
||||
{
|
||||
Player.SendLocalizedMessage(1072258); // You failed to complete an objective in time!
|
||||
|
||||
obj.Expired = true;
|
||||
obj.OnExpire();
|
||||
|
||||
hasAnyFails = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
hasAnyLeft = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Quest.ObjectiveType == ObjectiveType.All && hasAnyFails || !hasAnyLeft)
|
||||
Fail();
|
||||
|
||||
if (!hasAnyLeft)
|
||||
StopTimer();
|
||||
}
|
||||
|
||||
public void SendProgressGump()
|
||||
{
|
||||
Player.SendGump(new QuestConversationGump(Quest, Player, Quest.InProgressMessage));
|
||||
}
|
||||
|
||||
public void SendRewardOffer()
|
||||
{
|
||||
Quest.GetRewards(this);
|
||||
}
|
||||
|
||||
// TODO: Split next quest stuff from SendRewardGump stuff?
|
||||
public void SendRewardGump()
|
||||
{
|
||||
Type nextQuestType = Quest.NextQuest;
|
||||
|
||||
if (nextQuestType != null)
|
||||
{
|
||||
ClaimRewards(); // skip reward gump
|
||||
|
||||
if (Removed) // rewards were claimed successfully
|
||||
{
|
||||
MLQuest nextQuest = MLQuestSystem.FindQuest(nextQuestType);
|
||||
|
||||
nextQuest?.SendOffer(m_Quester, Player);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Player.SendGump(new QuestRewardGump(this));
|
||||
}
|
||||
}
|
||||
|
||||
public void SendReportBackGump()
|
||||
{
|
||||
if (SkipReportBack)
|
||||
ContinueReportBack(true); // skip ahead
|
||||
else
|
||||
Player.SendGump(new QuestReportBackGump(this));
|
||||
}
|
||||
|
||||
public void ContinueReportBack(bool sendRewardGump)
|
||||
{
|
||||
// There is a backpack check here on OSI for the rewards as well (even though it's not needed...)
|
||||
|
||||
if (Quest.ObjectiveType == ObjectiveType.All)
|
||||
{
|
||||
// TODO: 1115877 - You no longer have the required items to complete this quest.
|
||||
foreach (BaseObjectiveInstance objective in Objectives)
|
||||
if (!objective.IsCompleted())
|
||||
return;
|
||||
|
||||
foreach (BaseObjectiveInstance objective in Objectives)
|
||||
if (!objective.OnBeforeClaimReward())
|
||||
return;
|
||||
|
||||
foreach (BaseObjectiveInstance objective in Objectives)
|
||||
objective.OnClaimReward();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The following behavior is unverified, as OSI (currently) has no collect quest requiring
|
||||
* only one objective to be completed. It is assumed that only one objective is claimed
|
||||
* (the first completed one), even when multiple are complete.
|
||||
*/
|
||||
bool complete = false;
|
||||
|
||||
foreach (BaseObjectiveInstance objective in Objectives)
|
||||
if (objective.IsCompleted())
|
||||
{
|
||||
if (objective.OnBeforeClaimReward())
|
||||
{
|
||||
complete = true;
|
||||
objective.OnClaimReward();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!complete)
|
||||
return;
|
||||
}
|
||||
|
||||
ClaimReward = true;
|
||||
|
||||
if (Quest.HasRestartDelay)
|
||||
PlayerContext.SetDoneQuest(Quest, DateTime.UtcNow + Quest.GetRestartDelay());
|
||||
|
||||
// This is correct for ObjectiveType.Any as well
|
||||
foreach (BaseObjectiveInstance objective in Objectives)
|
||||
objective.OnAfterClaimReward();
|
||||
|
||||
if (sendRewardGump)
|
||||
SendRewardOffer();
|
||||
}
|
||||
|
||||
public void ClaimRewards()
|
||||
{
|
||||
if (Quest == null || Player?.Deleted != false || !ClaimReward || Removed)
|
||||
return;
|
||||
|
||||
List<Item> rewards = new List<Item>();
|
||||
|
||||
foreach (BaseReward reward in Quest.Rewards)
|
||||
reward.AddRewardItems(Player, rewards);
|
||||
|
||||
if (rewards.Count != 0)
|
||||
{
|
||||
// On OSI a more naive method of checking is used.
|
||||
// For containers, only the actual container item counts.
|
||||
bool canFit = true;
|
||||
|
||||
foreach (Item rewardItem in rewards)
|
||||
if (!Player.AddToBackpack(rewardItem))
|
||||
{
|
||||
canFit = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!canFit)
|
||||
{
|
||||
foreach (Item rewardItem in rewards)
|
||||
rewardItem.Delete();
|
||||
|
||||
Player.SendLocalizedMessage(
|
||||
1078524); // Your backpack is full. You cannot complete the quest and receive your reward.
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Item rewardItem in rewards)
|
||||
{
|
||||
string rewardName = rewardItem.Name ?? string.Concat("#", rewardItem.LabelNumber);
|
||||
|
||||
if (rewardItem.Stackable)
|
||||
Player.SendLocalizedMessage(1115917,
|
||||
string.Concat(rewardItem.Amount, "\t",
|
||||
rewardName)); // You receive a reward: ~1_QUANTITY~ ~2_ITEM~
|
||||
else
|
||||
Player.SendLocalizedMessage(1074360, rewardName); // You receive a reward: ~1_REWARD~
|
||||
}
|
||||
}
|
||||
|
||||
foreach (BaseObjectiveInstance objective in Objectives)
|
||||
objective.OnRewardClaimed();
|
||||
|
||||
Quest.OnRewardClaimed(this);
|
||||
|
||||
MLQuestContext context = PlayerContext;
|
||||
|
||||
if (Quest.RecordCompletion && !Quest.HasRestartDelay) // Quests with restart delays are logged earlier as per OSI
|
||||
context.SetDoneQuest(Quest);
|
||||
|
||||
if (Quest.IsChainTriggered)
|
||||
context.ChainOffers.Remove(Quest);
|
||||
|
||||
Type nextQuestType = Quest.NextQuest;
|
||||
|
||||
if (nextQuestType != null)
|
||||
{
|
||||
MLQuest nextQuest = MLQuestSystem.FindQuest(nextQuestType);
|
||||
|
||||
if (nextQuest != null && !context.ChainOffers.Contains(nextQuest))
|
||||
context.ChainOffers.Add(nextQuest);
|
||||
}
|
||||
|
||||
Remove();
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
Cancel(false);
|
||||
}
|
||||
|
||||
public void Cancel(bool removeChain)
|
||||
{
|
||||
Remove();
|
||||
|
||||
Player.SendSound(0x5B3); // private sound
|
||||
|
||||
foreach (BaseObjectiveInstance obj in Objectives)
|
||||
obj.OnQuestCancelled();
|
||||
|
||||
Quest.OnCancel(this);
|
||||
|
||||
if (removeChain)
|
||||
PlayerContext.ChainOffers.Remove(Quest);
|
||||
}
|
||||
|
||||
public void Remove()
|
||||
{
|
||||
Unregister();
|
||||
StopTimer();
|
||||
}
|
||||
|
||||
private void StopTimer()
|
||||
{
|
||||
if (m_Timer == null)
|
||||
return;
|
||||
m_Timer.Stop();
|
||||
m_Timer = null;
|
||||
}
|
||||
|
||||
public void OnQuesterDeleted()
|
||||
{
|
||||
foreach (BaseObjectiveInstance obj in Objectives)
|
||||
obj.OnQuesterDeleted();
|
||||
|
||||
Quest.OnQuesterDeleted(this);
|
||||
}
|
||||
|
||||
public void OnPlayerDeath()
|
||||
{
|
||||
foreach (BaseObjectiveInstance obj in Objectives)
|
||||
obj.OnPlayerDeath();
|
||||
|
||||
Quest.OnPlayerDeath(this);
|
||||
}
|
||||
|
||||
private bool GetFlag(MLQuestInstanceFlags flag)
|
||||
{
|
||||
return (m_Flags & flag) != 0;
|
||||
}
|
||||
|
||||
private void SetFlag(MLQuestInstanceFlags flag, bool value)
|
||||
{
|
||||
if (value)
|
||||
m_Flags |= flag;
|
||||
else
|
||||
m_Flags &= ~flag;
|
||||
}
|
||||
|
||||
public void Serialize(GenericWriter writer)
|
||||
{
|
||||
// Version info is written in MLQuestPersistence.Serialize
|
||||
|
||||
MLQuestSystem.WriteQuestRef(writer, Quest);
|
||||
|
||||
writer.Write(m_Quester?.Deleted != false ? Serial.MinusOne : m_Quester.Serial);
|
||||
|
||||
writer.Write(ClaimReward);
|
||||
writer.Write(Objectives.Length);
|
||||
|
||||
foreach (BaseObjectiveInstance objInstance in Objectives)
|
||||
objInstance.Serialize(writer);
|
||||
}
|
||||
|
||||
public static MLQuestInstance Deserialize(GenericReader reader, int version, PlayerMobile pm)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.ReadQuestRef(reader);
|
||||
|
||||
// TODO: Serialize quester TYPE too, the quest giver reference then becomes optional (only for escorts)
|
||||
IQuestGiver quester = World.FindEntity(reader.ReadUInt()) as IQuestGiver;
|
||||
|
||||
bool claimReward = reader.ReadBool();
|
||||
int objectives = reader.ReadInt();
|
||||
|
||||
MLQuestInstance instance;
|
||||
|
||||
if (quest != null && quester != null && pm != null)
|
||||
{
|
||||
instance = quest.CreateInstance(quester, pm);
|
||||
instance.ClaimReward = claimReward;
|
||||
}
|
||||
else
|
||||
{
|
||||
instance = null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < objectives; ++i)
|
||||
BaseObjectiveInstance.Deserialize(reader, version,
|
||||
instance != null && i < instance.Objectives.Length ? instance.Objectives[i] : null);
|
||||
|
||||
instance?.Slice();
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
63
Projects/Scripts/Engines/MLQuests/MLQuestPersistence.cs
Normal file
63
Projects/Scripts/Engines/MLQuests/MLQuestPersistence.cs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
namespace Server.Engines.MLQuests
|
||||
{
|
||||
public class MLQuestPersistence : Item
|
||||
{
|
||||
private static MLQuestPersistence m_Instance;
|
||||
|
||||
private MLQuestPersistence()
|
||||
: base(1)
|
||||
{
|
||||
Movable = false;
|
||||
}
|
||||
|
||||
public MLQuestPersistence(Serial serial) : base(serial)
|
||||
{
|
||||
m_Instance = this;
|
||||
}
|
||||
|
||||
public override string DefaultName => "ML quests persistence - Internal";
|
||||
|
||||
public static void EnsureExistence()
|
||||
{
|
||||
if (m_Instance == null)
|
||||
m_Instance = new MLQuestPersistence();
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(2); // version
|
||||
writer.Write(MLQuestSystem.Contexts.Count);
|
||||
|
||||
foreach (MLQuestContext context in MLQuestSystem.Contexts.Values)
|
||||
context.Serialize(writer);
|
||||
|
||||
writer.Write(MLQuestSystem.Quests.Count);
|
||||
|
||||
foreach (MLQuest quest in MLQuestSystem.Quests.Values)
|
||||
MLQuest.Serialize(writer, quest);
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
int contexts = reader.ReadInt();
|
||||
|
||||
for (int i = 0; i < contexts; ++i)
|
||||
{
|
||||
MLQuestContext context = new MLQuestContext(reader, version);
|
||||
|
||||
if (context.Owner != null)
|
||||
MLQuestSystem.Contexts[context.Owner] = context;
|
||||
}
|
||||
|
||||
int quests = reader.ReadInt();
|
||||
|
||||
for (int i = 0; i < quests; ++i)
|
||||
MLQuest.Deserialize(reader, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
710
Projects/Scripts/Engines/MLQuests/MLQuestSystem.cs
Normal file
710
Projects/Scripts/Engines/MLQuests/MLQuestSystem.cs
Normal file
|
|
@ -0,0 +1,710 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Server.Commands;
|
||||
using Server.Commands.Generic;
|
||||
using Server.Engines.MLQuests.Gumps;
|
||||
using Server.Engines.MLQuests.Objectives;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests
|
||||
{
|
||||
public static class MLQuestSystem
|
||||
{
|
||||
public const int MaxConcurrentQuests = 10;
|
||||
public const int SpeechColor = 0x3B2;
|
||||
|
||||
public static readonly bool AutoGenerateNew = true;
|
||||
public static readonly bool Debug = false;
|
||||
|
||||
public static readonly List<MLQuest> EmptyList = new List<MLQuest>();
|
||||
|
||||
private static List<MLQuest> m_EligiblePool = new List<MLQuest>();
|
||||
|
||||
static MLQuestSystem()
|
||||
{
|
||||
Quests = new Dictionary<Type, MLQuest>();
|
||||
QuestGivers = new Dictionary<Type, List<MLQuest>>();
|
||||
Contexts = new Dictionary<PlayerMobile, MLQuestContext>();
|
||||
|
||||
string cfgPath = Path.Combine(Core.BaseDirectory, Path.Combine("Data", "MLQuests.cfg"));
|
||||
|
||||
Type baseQuestType = typeof(MLQuest);
|
||||
Type baseQuesterType = typeof(IQuestGiver);
|
||||
|
||||
if (File.Exists(cfgPath))
|
||||
using (StreamReader sr = new StreamReader(cfgPath))
|
||||
{
|
||||
string line;
|
||||
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
if (line.Length == 0 || line.StartsWith("#"))
|
||||
continue;
|
||||
|
||||
string[] split = line.Split('\t');
|
||||
|
||||
Type type = ScriptCompiler.FindTypeByName(split[0]);
|
||||
|
||||
if (type == null || !baseQuestType.IsAssignableFrom(type))
|
||||
{
|
||||
if (Debug)
|
||||
Console.WriteLine("Warning: {1} quest type '{0}'", split[0],
|
||||
type == null ? "Unknown" : "Invalid");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
MLQuest quest = null;
|
||||
|
||||
try
|
||||
{
|
||||
quest = Activator.CreateInstance(type) as MLQuest;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
if (quest == null)
|
||||
continue;
|
||||
|
||||
Register(type, quest);
|
||||
|
||||
for (int i = 1; i < split.Length; ++i)
|
||||
{
|
||||
Type questerType = ScriptCompiler.FindTypeByName(split[i]);
|
||||
|
||||
if (questerType == null || !baseQuesterType.IsAssignableFrom(questerType))
|
||||
{
|
||||
if (Debug)
|
||||
Console.WriteLine("Warning: {1} quester type '{0}'", split[i],
|
||||
questerType == null ? "Unknown" : "Invalid");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
RegisterQuestGiver(quest, questerType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Enabled => Core.ML;
|
||||
|
||||
public static Dictionary<Type, MLQuest> Quests{ get; }
|
||||
|
||||
public static Dictionary<Type, List<MLQuest>> QuestGivers{ get; }
|
||||
|
||||
public static Dictionary<PlayerMobile, MLQuestContext> Contexts{ get; }
|
||||
|
||||
private static void Register(Type type, MLQuest quest)
|
||||
{
|
||||
Quests[type] = quest;
|
||||
}
|
||||
|
||||
private static void RegisterQuestGiver(MLQuest quest, Type questerType)
|
||||
{
|
||||
if (!QuestGivers.TryGetValue(questerType, out List<MLQuest> questList))
|
||||
QuestGivers[questerType] = questList = new List<MLQuest>();
|
||||
|
||||
questList.Add(quest);
|
||||
}
|
||||
|
||||
public static void Register(MLQuest quest, params Type[] questerTypes)
|
||||
{
|
||||
Register(quest.GetType(), quest);
|
||||
|
||||
foreach (Type questerType in questerTypes)
|
||||
RegisterQuestGiver(quest, questerType);
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if (!Enabled)
|
||||
return;
|
||||
|
||||
if (AutoGenerateNew)
|
||||
foreach (MLQuest quest in Quests.Values)
|
||||
if (quest?.Deserialized == false)
|
||||
quest.Generate();
|
||||
|
||||
MLQuestPersistence.EnsureExistence();
|
||||
|
||||
CommandSystem.Register("MLQuestsInfo", AccessLevel.Administrator, MLQuestsInfo_OnCommand);
|
||||
CommandSystem.Register("SaveQuest", AccessLevel.Administrator, SaveQuest_OnCommand);
|
||||
CommandSystem.Register("SaveAllQuests", AccessLevel.Administrator, SaveAllQuests_OnCommand);
|
||||
CommandSystem.Register("InvalidQuestItems", AccessLevel.Administrator, InvalidQuestItems_OnCommand);
|
||||
|
||||
TargetCommands.Register(new ViewQuestsCommand());
|
||||
TargetCommands.Register(new ViewContextCommand());
|
||||
|
||||
EventSink.QuestGumpRequest += EventSink_QuestGumpRequest;
|
||||
}
|
||||
|
||||
[Usage("MLQuestsInfo")]
|
||||
[Description("Displays general information about the ML quest system, or a quest by type name.")]
|
||||
public static void MLQuestsInfo_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
Mobile m = e.Mobile;
|
||||
|
||||
if (e.Length == 0)
|
||||
{
|
||||
m.SendMessage("Quest table length: {0}", Quests.Count);
|
||||
return;
|
||||
}
|
||||
|
||||
Type index = ScriptCompiler.FindTypeByName(e.GetString(0));
|
||||
|
||||
if (index == null || !Quests.TryGetValue(index, out MLQuest quest))
|
||||
{
|
||||
m.SendMessage("Invalid quest type name.");
|
||||
return;
|
||||
}
|
||||
|
||||
m.SendMessage("Activated: {0}", quest.Activated);
|
||||
m.SendMessage("Number of objectives: {0}", quest.Objectives.Count);
|
||||
m.SendMessage("Objective type: {0}", quest.ObjectiveType);
|
||||
m.SendMessage("Number of active instances: {0}", quest.Instances.Count);
|
||||
}
|
||||
|
||||
[Usage("SaveQuest <type> [saveEnabled=true]")]
|
||||
[Description("Allows serialization for a specific quest to be turned on or off.")]
|
||||
public static void SaveQuest_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
Mobile m = e.Mobile;
|
||||
|
||||
if (e.Length == 0 || e.Length > 2)
|
||||
{
|
||||
m.SendMessage("Syntax: SaveQuest <id> [saveEnabled=true]");
|
||||
return;
|
||||
}
|
||||
|
||||
Type index = ScriptCompiler.FindTypeByName(e.GetString(0));
|
||||
|
||||
if (index == null || !Quests.TryGetValue(index, out MLQuest quest))
|
||||
{
|
||||
m.SendMessage("Invalid quest type name.");
|
||||
return;
|
||||
}
|
||||
|
||||
bool enable = e.Length == 2 ? e.GetBoolean(1) : true;
|
||||
|
||||
quest.SaveEnabled = enable;
|
||||
m.SendMessage("Serialization for quest {0} is now {1}.", quest.GetType().Name, enable ? "enabled" : "disabled");
|
||||
|
||||
if (AutoGenerateNew && !enable)
|
||||
m.SendMessage(
|
||||
"Please note that automatic generation of new quests is ON. This quest will be regenerated on the next server start.");
|
||||
}
|
||||
|
||||
[Usage("SaveAllQuests [saveEnabled=true]")]
|
||||
[Description("Allows serialization for all quests to be turned on or off.")]
|
||||
public static void SaveAllQuests_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
Mobile m = e.Mobile;
|
||||
|
||||
if (e.Length > 1)
|
||||
{
|
||||
m.SendMessage("Syntax: SaveAllQuests [saveEnabled=true]");
|
||||
return;
|
||||
}
|
||||
|
||||
bool enable = e.Length == 1 ? e.GetBoolean(0) : true;
|
||||
|
||||
foreach (MLQuest quest in Quests.Values)
|
||||
quest.SaveEnabled = enable;
|
||||
|
||||
m.SendMessage("Serialization for all quests is now {0}.", enable ? "enabled" : "disabled");
|
||||
|
||||
if (AutoGenerateNew && !enable)
|
||||
m.SendMessage(
|
||||
"Please note that automatic generation of new quests is ON. All quests will be regenerated on the next server start.");
|
||||
}
|
||||
|
||||
[Usage("InvalidQuestItems")]
|
||||
[Description("Provides an overview of all quest items not located in the top-level of a player's backpack.")]
|
||||
public static void InvalidQuestItems_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
Mobile m = e.Mobile;
|
||||
|
||||
List<object> found = new List<object>();
|
||||
|
||||
foreach (Item item in World.Items.Values)
|
||||
if (item.QuestItem)
|
||||
{
|
||||
if (item.Parent is Backpack pack)
|
||||
if (pack.Parent is PlayerMobile player && player.Backpack == pack)
|
||||
continue;
|
||||
|
||||
found.Add(item);
|
||||
}
|
||||
|
||||
if (found.Count == 0)
|
||||
m.SendMessage("No matching objects found.");
|
||||
else
|
||||
m.SendGump(new InterfaceGump(m, new[] { "Object" }, found, 0, null));
|
||||
}
|
||||
|
||||
private static bool FindQuest(IQuestGiver quester, PlayerMobile pm, MLQuestContext context, out MLQuest quest,
|
||||
out MLQuestInstance entry)
|
||||
{
|
||||
quest = null;
|
||||
entry = null;
|
||||
|
||||
List<MLQuest> quests = quester.MLQuests;
|
||||
Type questerType = quester.GetType();
|
||||
|
||||
// 1. Check quests in progress with this NPC (overriding deliveries is intended)
|
||||
if (context != null)
|
||||
foreach (MLQuest questEntry in quests)
|
||||
{
|
||||
MLQuestInstance instance = context.FindInstance(questEntry);
|
||||
|
||||
if (instance != null && (instance.Quester == quester ||
|
||||
!questEntry.IsEscort && instance.QuesterType == questerType))
|
||||
{
|
||||
entry = instance;
|
||||
quest = questEntry;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Check deliveries (overriding chain offers is intended)
|
||||
if ((entry = HandleDelivery(pm, quester, questerType)) != null)
|
||||
{
|
||||
quest = entry.Quest;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. Check chain quest offers
|
||||
if (context != null)
|
||||
foreach (MLQuest questEntry in quests)
|
||||
if (questEntry.IsChainTriggered && context.ChainOffers.Contains(questEntry))
|
||||
{
|
||||
quest = questEntry;
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4. Random quest
|
||||
quest = RandomStarterQuest(quester, pm, context);
|
||||
|
||||
return quest != null;
|
||||
}
|
||||
|
||||
public static void OnDoubleClick(IQuestGiver quester, PlayerMobile pm)
|
||||
{
|
||||
if (quester.Deleted || !pm.Alive)
|
||||
return;
|
||||
|
||||
MLQuestContext context = GetContext(pm);
|
||||
|
||||
if (!FindQuest(quester, pm, context, out MLQuest quest, out MLQuestInstance entry))
|
||||
{
|
||||
Tell(quester, pm, 1080107); // I'm sorry, I have nothing for you at this time.
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
TurnToFace(quester, pm);
|
||||
|
||||
if (entry.Failed)
|
||||
return; // Note: OSI sends no gump at all for failed quests, they have to be cancelled in the quest overview
|
||||
if (entry.ClaimReward)
|
||||
entry.SendRewardOffer();
|
||||
else if (entry.IsCompleted())
|
||||
entry.SendReportBackGump();
|
||||
else
|
||||
entry.SendProgressGump();
|
||||
}
|
||||
else if (quest.CanOffer(quester, pm, context, true))
|
||||
{
|
||||
TurnToFace(quester, pm);
|
||||
|
||||
quest.SendOffer(quester, pm);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanMarkQuestItem(PlayerMobile pm, Item item, Type type)
|
||||
{
|
||||
MLQuestContext context = GetContext(pm);
|
||||
|
||||
if (context != null)
|
||||
foreach (MLQuestInstance quest in context.QuestInstances)
|
||||
if (!quest.ClaimReward && quest.AllowsQuestItem(item, type))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void OnMarkQuestItem(PlayerMobile pm, Item item, Type type)
|
||||
{
|
||||
MLQuestContext context = GetContext(pm);
|
||||
|
||||
if (context == null)
|
||||
return;
|
||||
|
||||
List<MLQuestInstance> instances = context.QuestInstances;
|
||||
|
||||
// We don't foreach because CheckComplete() can potentially modify the MLQuests list
|
||||
for (int i = instances.Count - 1; i >= 0; --i)
|
||||
{
|
||||
MLQuestInstance instance = instances[i];
|
||||
|
||||
if (instance.ClaimReward)
|
||||
continue;
|
||||
|
||||
foreach (BaseObjectiveInstance objective in instance.Objectives)
|
||||
if (!objective.Expired && objective.AllowsQuestItem(item, type))
|
||||
{
|
||||
objective.CheckComplete(); // yes, this can happen multiple times (for multiple quests)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool MarkQuestItem(PlayerMobile pm, Item item)
|
||||
{
|
||||
Type type = item.GetType();
|
||||
|
||||
if (CanMarkQuestItem(pm, item, type))
|
||||
{
|
||||
item.QuestItem = true;
|
||||
OnMarkQuestItem(pm, item, type);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void HandleSkillGain(PlayerMobile pm, SkillName skill)
|
||||
{
|
||||
MLQuestContext context = GetContext(pm);
|
||||
|
||||
if (context == null)
|
||||
return;
|
||||
|
||||
List<MLQuestInstance> instances = context.QuestInstances;
|
||||
|
||||
for (int i = instances.Count - 1; i >= 0; --i)
|
||||
{
|
||||
MLQuestInstance instance = instances[i];
|
||||
|
||||
if (instance.ClaimReward)
|
||||
continue;
|
||||
|
||||
foreach (BaseObjectiveInstance objective in instance.Objectives)
|
||||
if (!objective.Expired && objective is GainSkillObjectiveInstance objectiveInstance &&
|
||||
objectiveInstance.Handles(skill))
|
||||
{
|
||||
objectiveInstance.CheckComplete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void HandleKill(PlayerMobile pm, Mobile mob)
|
||||
{
|
||||
MLQuestContext context = GetContext(pm);
|
||||
|
||||
if (context == null)
|
||||
return;
|
||||
|
||||
List<MLQuestInstance> instances = context.QuestInstances;
|
||||
|
||||
Type type = null;
|
||||
|
||||
for (int i = instances.Count - 1; i >= 0; --i)
|
||||
{
|
||||
MLQuestInstance instance = instances[i];
|
||||
|
||||
if (instance.ClaimReward)
|
||||
continue;
|
||||
|
||||
/* A kill only counts for a single objective within a quest,
|
||||
* but it can count for multiple quests. This is something not
|
||||
* currently observable on OSI, so it is assumed behavior.
|
||||
*/
|
||||
foreach (BaseObjectiveInstance objective in instance.Objectives)
|
||||
if (!objective.Expired && objective is KillObjectiveInstance kill)
|
||||
{
|
||||
if (type == null)
|
||||
type = mob.GetType();
|
||||
|
||||
if (kill.AddKill(mob, type))
|
||||
{
|
||||
kill.CheckComplete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static MLQuestInstance HandleDelivery(PlayerMobile pm, IQuestGiver quester, Type questerType)
|
||||
{
|
||||
MLQuestContext context = GetContext(pm);
|
||||
|
||||
if (context == null)
|
||||
return null;
|
||||
|
||||
List<MLQuestInstance> instances = context.QuestInstances;
|
||||
MLQuestInstance deliverInstance = null;
|
||||
|
||||
for (int i = instances.Count - 1; i >= 0; --i)
|
||||
{
|
||||
MLQuestInstance instance = instances[i];
|
||||
|
||||
// Do NOT skip quests on ClaimReward, because the quester still needs the quest ref!
|
||||
//if ( instance.ClaimReward )
|
||||
// continue;
|
||||
|
||||
foreach (BaseObjectiveInstance objective in instance.Objectives)
|
||||
// Note: On OSI, expired deliveries can still be completed. Bug?
|
||||
if (!objective.Expired && objective is DeliverObjectiveInstance deliver &&
|
||||
deliver.IsDestination(quester, questerType))
|
||||
{
|
||||
if (!deliver.HasCompleted) // objective completes only once
|
||||
{
|
||||
deliver.HasCompleted = true;
|
||||
deliver.CheckComplete();
|
||||
|
||||
// The quest is continued with this NPC (important for chains)
|
||||
instance.Quester = quester;
|
||||
}
|
||||
|
||||
if (deliverInstance == null)
|
||||
deliverInstance = instance;
|
||||
|
||||
break; // don't return, we may have to complete more deliveries
|
||||
}
|
||||
}
|
||||
|
||||
return deliverInstance;
|
||||
}
|
||||
|
||||
public static MLQuestContext GetContext(PlayerMobile pm)
|
||||
{
|
||||
Contexts.TryGetValue(pm, out MLQuestContext context);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
public static MLQuestContext GetOrCreateContext(PlayerMobile pm)
|
||||
{
|
||||
if (!Contexts.TryGetValue(pm, out MLQuestContext context))
|
||||
Contexts[pm] = context = new MLQuestContext(pm);
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
public static void HandleDeath(PlayerMobile pm)
|
||||
{
|
||||
MLQuestContext context = GetContext(pm);
|
||||
|
||||
context?.HandleDeath();
|
||||
}
|
||||
|
||||
public static void HandleDeletion(PlayerMobile pm)
|
||||
{
|
||||
MLQuestContext context = GetContext(pm);
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
context.HandleDeletion();
|
||||
Contexts.Remove(pm);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HandleDeletion(IQuestGiver quester)
|
||||
{
|
||||
foreach (MLQuest quest in quester.MLQuests)
|
||||
{
|
||||
List<MLQuestInstance> instances = quest.Instances;
|
||||
|
||||
for (int i = instances.Count - 1; i >= 0; --i)
|
||||
{
|
||||
MLQuestInstance instance = instances[i];
|
||||
|
||||
if (instance.Quester == quester)
|
||||
instance.OnQuesterDeleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void EventSink_QuestGumpRequest(QuestGumpRequestArgs args)
|
||||
{
|
||||
if (!Enabled || !(args.Mobile is PlayerMobile pm))
|
||||
return;
|
||||
|
||||
pm.SendGump(new QuestLogGump(pm));
|
||||
}
|
||||
|
||||
public static MLQuest RandomStarterQuest(IQuestGiver quester, PlayerMobile pm, MLQuestContext context)
|
||||
{
|
||||
List<MLQuest> quests = quester.MLQuests;
|
||||
|
||||
if (quests.Count == 0)
|
||||
return null;
|
||||
|
||||
m_EligiblePool.Clear();
|
||||
MLQuest fallback = null;
|
||||
|
||||
foreach (MLQuest quest in quests)
|
||||
{
|
||||
if (quest.IsChainTriggered || context?.IsDoingQuest(quest) == true)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Save first quest that reaches the CanOffer call.
|
||||
* If no quests are valid at all, return this quest for displaying the CanOffer error message.
|
||||
*/
|
||||
if (fallback == null)
|
||||
fallback = quest;
|
||||
|
||||
if (quest.CanOffer(quester, pm, context, false))
|
||||
m_EligiblePool.Add(quest);
|
||||
}
|
||||
|
||||
return m_EligiblePool.Count == 0 ? fallback : m_EligiblePool[Utility.Random(m_EligiblePool.Count)];
|
||||
}
|
||||
|
||||
public static void TurnToFace(IQuestGiver quester, Mobile mob)
|
||||
{
|
||||
if (quester is Mobile m)
|
||||
m.Direction = m.GetDirectionTo(mob);
|
||||
}
|
||||
|
||||
public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc)
|
||||
{
|
||||
TurnToFace(quester, pm);
|
||||
|
||||
if (quester is Mobile mobile)
|
||||
mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, pm.NetState);
|
||||
else if (quester is Item item)
|
||||
MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, SpeechColor);
|
||||
else
|
||||
pm.SendLocalizedMessage(cliloc);
|
||||
}
|
||||
|
||||
public static void Tell(IQuestGiver quester, PlayerMobile pm, int cliloc, string args)
|
||||
{
|
||||
TurnToFace(quester, pm);
|
||||
|
||||
if (quester is Mobile mobile)
|
||||
mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, cliloc, args, pm.NetState);
|
||||
else if (quester is Item item)
|
||||
MessageHelper.SendLocalizedMessageTo(item, pm, cliloc, args, SpeechColor);
|
||||
else
|
||||
pm.SendLocalizedMessage(cliloc, args);
|
||||
}
|
||||
|
||||
public static void Tell(IQuestGiver quester, PlayerMobile pm, string message)
|
||||
{
|
||||
TurnToFace(quester, pm);
|
||||
|
||||
if (quester is Mobile mobile)
|
||||
mobile.PrivateOverheadMessage(MessageType.Regular, SpeechColor, false, message, pm.NetState);
|
||||
else if (quester is Item item)
|
||||
MessageHelper.SendMessageTo(item, pm, message, SpeechColor);
|
||||
else
|
||||
pm.SendMessage(SpeechColor, message);
|
||||
}
|
||||
|
||||
public static void TellDef(IQuestGiver quester, PlayerMobile pm, TextDefinition def)
|
||||
{
|
||||
if (def == null)
|
||||
return;
|
||||
|
||||
if (def.Number > 0)
|
||||
Tell(quester, pm, def.Number);
|
||||
else if (def.String != null)
|
||||
Tell(quester, pm, def.String);
|
||||
}
|
||||
|
||||
public static void WriteQuestRef(GenericWriter writer, MLQuest quest)
|
||||
{
|
||||
writer.Write(quest?.SaveEnabled == true ? quest.GetType().FullName : null);
|
||||
}
|
||||
|
||||
public static MLQuest ReadQuestRef(GenericReader reader)
|
||||
{
|
||||
string typeName = reader.ReadString();
|
||||
|
||||
if (typeName == null)
|
||||
return null; // not serialized
|
||||
|
||||
Type questType = ScriptCompiler.FindTypeByFullName(typeName);
|
||||
|
||||
if (questType == null)
|
||||
return null; // no longer a type
|
||||
|
||||
return FindQuest(questType);
|
||||
}
|
||||
|
||||
public static MLQuest FindQuest(Type questType)
|
||||
{
|
||||
Quests.TryGetValue(questType, out MLQuest result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<MLQuest> FindQuestList(Type questerType)
|
||||
{
|
||||
return QuestGivers.TryGetValue(questerType, out List<MLQuest> result) ? result : EmptyList;
|
||||
}
|
||||
|
||||
public class ViewQuestsCommand : BaseCommand
|
||||
{
|
||||
public ViewQuestsCommand()
|
||||
{
|
||||
AccessLevel = AccessLevel.GameMaster;
|
||||
Supports = CommandSupport.Simple;
|
||||
Commands = new[] { "ViewQuests" };
|
||||
ObjectTypes = ObjectTypes.Mobiles;
|
||||
Usage = "ViewQuests";
|
||||
Description = "Displays a targeted mobile's quest overview.";
|
||||
}
|
||||
|
||||
public override void Execute(CommandEventArgs e, object obj)
|
||||
{
|
||||
Mobile from = e.Mobile;
|
||||
|
||||
if (!(obj is PlayerMobile pm))
|
||||
{
|
||||
LogFailure("That is not a player.");
|
||||
return;
|
||||
}
|
||||
|
||||
CommandLogging.WriteLine(from, "{0} {1} viewing quest overview of {2}", from.AccessLevel,
|
||||
CommandLogging.Format(from), CommandLogging.Format(pm));
|
||||
from.SendGump(new QuestLogGump(pm, false));
|
||||
}
|
||||
}
|
||||
|
||||
private class ViewContextCommand : BaseCommand
|
||||
{
|
||||
public ViewContextCommand()
|
||||
{
|
||||
AccessLevel = AccessLevel.GameMaster;
|
||||
Supports = CommandSupport.Simple;
|
||||
Commands = new[] { "ViewMLContext" };
|
||||
ObjectTypes = ObjectTypes.Mobiles;
|
||||
Usage = "ViewMLContext";
|
||||
Description = "Opens the ML quest context for a targeted mobile.";
|
||||
}
|
||||
|
||||
public override void Execute(CommandEventArgs e, object obj)
|
||||
{
|
||||
if (!(obj is PlayerMobile pm))
|
||||
LogFailure("They have no ML quest context.");
|
||||
else
|
||||
e.Mobile.SendGump(new PropertiesGump(e.Mobile, GetOrCreateContext(pm)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
426
Projects/Scripts/Engines/MLQuests/Mobiles/BoonCollector.cs
Normal file
426
Projects/Scripts/Engines/MLQuests/Mobiles/BoonCollector.cs
Normal file
|
|
@ -0,0 +1,426 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Engines.MLQuests.Definitions;
|
||||
using Server.Engines.MLQuests.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Mobiles
|
||||
{
|
||||
public abstract class DoneQuestCollector : BaseCreature, IRaceChanger
|
||||
{
|
||||
private static Type typeOfRaceChangeConfirmGump = typeof(RaceChangeConfirmGump);
|
||||
|
||||
private InternalTimer m_Timer;
|
||||
|
||||
public DoneQuestCollector()
|
||||
: base(AIType.AI_Vendor, FightMode.None, 2, 1, 0.5, 2)
|
||||
{
|
||||
}
|
||||
|
||||
public DoneQuestCollector(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsInvulnerable => true;
|
||||
|
||||
public abstract TextDefinition[] Offer{ get; }
|
||||
public abstract TextDefinition[] Incomplete{ get; }
|
||||
public abstract TextDefinition[] Complete{ get; }
|
||||
public abstract Type[] Needed{ get; }
|
||||
|
||||
public bool CheckComplete(PlayerMobile pm)
|
||||
{
|
||||
if (CompletedCount(pm) == Needed.Length)
|
||||
return true;
|
||||
|
||||
pm.SendLocalizedMessage(1073644); // You must complete all the tasks before proceeding...
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ConsumeNeeded(PlayerMobile pm)
|
||||
{
|
||||
MLQuestContext context = MLQuestSystem.GetContext(pm);
|
||||
|
||||
if (context != null)
|
||||
foreach (Type type in Needed)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.FindQuest(type);
|
||||
|
||||
if (quest != null)
|
||||
context.RemoveDoneQuest(quest);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCancel(PlayerMobile pm)
|
||||
{
|
||||
pm.SendLocalizedMessage(1073645); // You may try this again later...
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
TryTalkTo(from, true);
|
||||
}
|
||||
|
||||
public override void OnDoubleClickDead(Mobile from)
|
||||
{
|
||||
TryTalkTo(from, true);
|
||||
}
|
||||
|
||||
public override void OnMovement(Mobile m, Point3D oldLocation)
|
||||
{
|
||||
if (m.Player && InRange(m, 6) && !InRange(oldLocation, 6))
|
||||
TryTalkTo(m, false);
|
||||
|
||||
base.OnMovement(m, oldLocation);
|
||||
}
|
||||
|
||||
public void TryTalkTo(Mobile from, bool fromClick)
|
||||
{
|
||||
if (!from.Hidden && !from.HasGump<RaceChangeConfirmGump>() &&
|
||||
!RaceChangeConfirmGump.IsPending(from.NetState) && CanTalkTo(from))
|
||||
TalkTo(from as PlayerMobile);
|
||||
else if (fromClick)
|
||||
DenyTalk(from);
|
||||
}
|
||||
|
||||
public virtual bool CanTalkTo(Mobile from)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void DenyTalk(Mobile from)
|
||||
{
|
||||
}
|
||||
|
||||
public void TalkTo(PlayerMobile pm)
|
||||
{
|
||||
if (pm == null || m_Timer?.Running == true)
|
||||
return;
|
||||
|
||||
int completed = CompletedCount(pm);
|
||||
|
||||
if (completed == Needed.Length)
|
||||
{
|
||||
m_Timer = new InternalTimer(this, pm, Complete, true);
|
||||
}
|
||||
else if (completed == 0)
|
||||
{
|
||||
m_Timer = new InternalTimer(this, pm, Offer, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<TextDefinition> conversation = new List<TextDefinition>();
|
||||
conversation.AddRange(Incomplete);
|
||||
|
||||
MLQuestContext context = MLQuestSystem.GetContext(pm);
|
||||
|
||||
if (context != null)
|
||||
foreach (Type type in Needed)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.FindQuest(type);
|
||||
|
||||
if (quest == null || context.HasDoneQuest(quest))
|
||||
continue;
|
||||
|
||||
conversation.Add(quest.Title);
|
||||
}
|
||||
|
||||
m_Timer = new InternalTimer(this, pm, conversation, false);
|
||||
}
|
||||
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
private int CompletedCount(PlayerMobile pm)
|
||||
{
|
||||
MLQuestContext context = MLQuestSystem.GetContext(pm);
|
||||
|
||||
if (context == null)
|
||||
return 0;
|
||||
|
||||
int result = 0;
|
||||
|
||||
foreach (Type type in Needed)
|
||||
{
|
||||
MLQuest quest = MLQuestSystem.FindQuest(type);
|
||||
|
||||
if (quest == null || context.HasDoneQuest(quest))
|
||||
++result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual void OnComplete(PlayerMobile pm)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private IList<TextDefinition> m_Conversation;
|
||||
private int m_Index;
|
||||
private bool m_IsComplete;
|
||||
private DoneQuestCollector m_Owner;
|
||||
private PlayerMobile m_Target;
|
||||
|
||||
public InternalTimer(DoneQuestCollector owner, PlayerMobile target, IList<TextDefinition> conversation,
|
||||
bool isComplete)
|
||||
: base(TimeSpan.Zero, GetDelay())
|
||||
{
|
||||
m_Owner = owner;
|
||||
m_Target = target;
|
||||
m_Conversation = conversation;
|
||||
m_IsComplete = isComplete;
|
||||
m_Index = 0;
|
||||
}
|
||||
|
||||
private static TimeSpan GetDelay()
|
||||
{
|
||||
return TimeSpan.FromSeconds(Utility.RandomBool() ? 3 : 4);
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (m_Owner.Deleted)
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Index >= m_Conversation.Count)
|
||||
{
|
||||
if (m_IsComplete)
|
||||
m_Owner.OnComplete(m_Target);
|
||||
|
||||
Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_Index == 0)
|
||||
{
|
||||
if (m_Target.ShowFameTitle && m_Target.Fame >= 10000)
|
||||
m_Owner.Say(true, $"{(m_Target.Female ? "Lady" : "Lord")} {m_Target.Name}");
|
||||
else
|
||||
m_Owner.Say(true, m_Target.Name);
|
||||
}
|
||||
|
||||
TextDefinition.PublicOverheadMessage(m_Owner, MessageType.Regular, 0x3B2, m_Conversation[m_Index++]);
|
||||
Interval = GetDelay();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Darius : DoneQuestCollector
|
||||
{
|
||||
private static readonly TextDefinition[] m_Offer =
|
||||
{
|
||||
1073998, // Blessings of Sosaria to you and merry met, friend.
|
||||
1073999, // I am glad for your company and wonder if you seek the heritage of your people? I sense within you an elven bloodline -- the purity of which was lost when our brothers and sisters were exiled here in the Rupture.
|
||||
1074000, // If it is your desire to reclaim your place amongst the people, you must demonstrate that you understand and embrace the responsibilities expected of you as an elf.
|
||||
1074001, // The most basic lessons of our Sosaria are taught by her humblest children. Seek Maul, the great bear, who understands instictively the seasons.
|
||||
1074398, // Seek Strongroot, the great treefellow, whose very roots reach to the heart of the world. Seek Enigma, whose wisdom can only be conveyed in riddles and rhymes. Seek Bravehorn, the great hart, who exemplifies the fierce dedication of a protector of his people.
|
||||
1074399, // Seek the Huntsman, the centuar tasked with maintaining the balance. And lastly seek Arielle, the pixie, who has perhaps the most important lesson -- not to take yourself too seriously.
|
||||
1074400 // Or do none of these things. You must choose your own path in the world, and what use you'll make of your existence.
|
||||
};
|
||||
|
||||
private static readonly TextDefinition[] m_Incomplete =
|
||||
{
|
||||
1074002, // You have begun to walk the path of reclaiming your heritage, but you have not learned all the lessons before you.
|
||||
1074003 // You yet must perform these services:
|
||||
};
|
||||
|
||||
private static readonly TextDefinition[] m_Complete =
|
||||
{
|
||||
1074004, // You have carved a path in history, sought to understand the way from our sage companions.
|
||||
1074005, // And now you have returned full circle to the place of your origin within the arms of Mother Sosaria. There is but one thing left to do if you truly wish to embrace your elven heritage.
|
||||
1074006, // To be born once more an elf, you must strip of all worldly possessions. Nothing of man or beast much touch your skin.
|
||||
1074007 // Then you may step forth into history.
|
||||
};
|
||||
|
||||
private static readonly Type[] m_Needed =
|
||||
{
|
||||
typeof(Seasons),
|
||||
typeof(CaretakerOfTheLand),
|
||||
typeof(WisdomOfTheSphynx),
|
||||
typeof(DefendingTheHerd),
|
||||
typeof(TheBalanceOfNature),
|
||||
typeof(TheJoysOfLife)
|
||||
};
|
||||
|
||||
[Constructible]
|
||||
public Darius()
|
||||
{
|
||||
Title = "the wise";
|
||||
Race = Race.Elf;
|
||||
Hue = Race.RandomSkinHue();
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
|
||||
AddItem(new WildStaff());
|
||||
AddItem(new Sandals(0x1BB));
|
||||
AddItem(new GemmedCirclet());
|
||||
AddItem(new Tunic(Utility.RandomBrightHue()));
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
|
||||
SetStr(40, 50);
|
||||
SetDex(60, 70);
|
||||
SetInt(90, 100); // Verified int
|
||||
}
|
||||
|
||||
public Darius(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override TextDefinition[] Offer => m_Offer;
|
||||
public override TextDefinition[] Incomplete => m_Incomplete;
|
||||
public override TextDefinition[] Complete => m_Complete;
|
||||
public override Type[] Needed => m_Needed;
|
||||
|
||||
public override string DefaultName => "Darius";
|
||||
|
||||
public override bool CanTalkTo(Mobile from)
|
||||
{
|
||||
return from.Race == Race.Human;
|
||||
}
|
||||
|
||||
public override void DenyTalk(Mobile from)
|
||||
{
|
||||
from.SendLocalizedMessage(1074017); // He's too busy right now, so he ignores you.
|
||||
}
|
||||
|
||||
public override void OnComplete(PlayerMobile from)
|
||||
{
|
||||
from.SendGump(new RaceChangeConfirmGump(this, from, Race.Elf));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
public class Nedrick : DoneQuestCollector
|
||||
{
|
||||
private static readonly TextDefinition[] m_Offer =
|
||||
{
|
||||
1074403, // Greetings, traveler and welcome.
|
||||
1074404, // Perhaps you have heard of the service I offer? Perhaps you wish to avail yourself of the opportunity I lay before you.
|
||||
1074405, // Elves and humans; we lived together once in peace. Mighty relics that attest to our friendship remain, of course. Yet, memories faded when the Gem was shattered and the world torn asunder. Alone in The Heartwood, our elven brothers and sisters wondered what terrible evil had befallen Sosaria.
|
||||
1074406, // Violent change marked the sundering of our ties. We are different -- elves and humans. And yet we are much alike. I can give an elf the chance to walk as a human upon Sosaria. I can undertake the transformation.
|
||||
1074407, // But you must prove yourself to me. Humans possess a strength of character and back. Humans are quick-witted and able to pick up a smattering of nearly any talent. Humans are tough both mentally and physically. And of course, humans defend their own -- sometimes with their own lives.
|
||||
1074408, // Seek Sledge the Versatile and learn about human ingenuity and creativity. Seek Patricus and demonstrate your integrity and strength.
|
||||
1074409, // Seek out a human in need and prove your worth as a defender of humanity. Seek Belulah in Nu'Jelm and heartily challenge the elements in a display of toughness to rival any human.
|
||||
1074411 // Or turn away and embrace your heritage. It matters not to me.
|
||||
};
|
||||
|
||||
private static readonly TextDefinition[] m_Incomplete =
|
||||
{
|
||||
1074412, // You have made a good start but have more yet to do.
|
||||
1074413 // You must yet perform these deeds:
|
||||
};
|
||||
|
||||
private static readonly TextDefinition[] m_Complete =
|
||||
{
|
||||
1074410, // You have proven yourself capable and commited and so I will grant you the transformation you seek.
|
||||
1074531, // The first time you were born, you entered the world bare of all possessions and concerns. So too as you transform to your new life as a human, you must remove all worldly goods from the touch of your flesh.
|
||||
1074532 // I call upon all nearby to witness your rebirth!
|
||||
};
|
||||
|
||||
private static readonly Type[] m_Needed =
|
||||
{
|
||||
typeof(Ingenuity),
|
||||
typeof(HeaveHo),
|
||||
typeof(HumanInNeed),
|
||||
typeof(AllSeasonAdventurer)
|
||||
};
|
||||
|
||||
[Constructible]
|
||||
public Nedrick()
|
||||
{
|
||||
Title = "the iron worker";
|
||||
Race = Race.Human;
|
||||
Hue = Race.RandomSkinHue();
|
||||
SpeechHue = Utility.RandomDyedHue();
|
||||
|
||||
AddItem(new Boots());
|
||||
AddItem(new LongPants(Utility.RandomNondyedHue()));
|
||||
AddItem(new FancyShirt(Utility.RandomNondyedHue()));
|
||||
|
||||
Utility.AssignRandomHair(this);
|
||||
Utility.AssignRandomFacialHair(this, HairHue);
|
||||
|
||||
SetStr(70, 80);
|
||||
SetDex(50, 60);
|
||||
SetInt(60, 70); // Verified int
|
||||
}
|
||||
|
||||
public Nedrick(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override TextDefinition[] Offer => m_Offer;
|
||||
public override TextDefinition[] Incomplete => m_Incomplete;
|
||||
public override TextDefinition[] Complete => m_Complete;
|
||||
public override Type[] Needed => m_Needed;
|
||||
|
||||
public override string DefaultName => "Nedrick";
|
||||
|
||||
public override bool CanTalkTo(Mobile from)
|
||||
{
|
||||
return from.Race == Race.Elf;
|
||||
}
|
||||
|
||||
public override void DenyTalk(Mobile from)
|
||||
{
|
||||
from.SendLocalizedMessage(1074017); // He's too busy right now, so he ignores you.
|
||||
}
|
||||
|
||||
public override void OnComplete(PlayerMobile from)
|
||||
{
|
||||
from.SendGump(new RaceChangeConfirmGump(this, from, Race.Human));
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
141
Projects/Scripts/Engines/MLQuests/Mobiles/SirHelper.cs
Normal file
141
Projects/Scripts/Engines/MLQuests/Mobiles/SirHelper.cs
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
using System;
|
||||
using Server.Engines.MLQuests.Gumps;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.MLQuests.Mobiles
|
||||
{
|
||||
public class SirHelper : Mage
|
||||
{
|
||||
private static readonly Gump m_Gump = new InfoNPCGump(1078029, 1078028);
|
||||
private static readonly TimeSpan m_ShoutDelay = TimeSpan.FromSeconds(20);
|
||||
|
||||
private static readonly TimeSpan
|
||||
m_ShoutCooldown = TimeSpan.FromDays(1); // TODO: Verify, could be a lot longer... or until a restart even
|
||||
|
||||
private DateTime m_NextShout;
|
||||
|
||||
[Constructible]
|
||||
public SirHelper()
|
||||
{
|
||||
Title = "the Profession Guide"; // TODO: Don't display in paperdoll
|
||||
|
||||
Hue = 0x83EA;
|
||||
|
||||
Direction = Direction.South;
|
||||
Frozen = true;
|
||||
}
|
||||
|
||||
public SirHelper(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override string DefaultName => "Sir Helper";
|
||||
public override bool IsActiveVendor => false;
|
||||
|
||||
public override void InitSBInfo()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool GetGender()
|
||||
{
|
||||
return false; // male
|
||||
}
|
||||
|
||||
public override void CheckMorph()
|
||||
{
|
||||
}
|
||||
|
||||
public override void InitOutfit()
|
||||
{
|
||||
HairItemID = 0x203C;
|
||||
FacialHairItemID = 0x204D;
|
||||
HairHue = FacialHairHue = 0x8A7;
|
||||
|
||||
AddItem(new Sandals());
|
||||
|
||||
Item item;
|
||||
|
||||
item = new Cloak();
|
||||
item.ItemID = 0x26AD;
|
||||
item.Hue = 0x455;
|
||||
AddItem(item);
|
||||
|
||||
item = new Robe();
|
||||
item.ItemID = 0x26AE;
|
||||
item.Hue = 0x4AB;
|
||||
AddItem(item);
|
||||
|
||||
item = new Backpack();
|
||||
item.Movable = false;
|
||||
AddItem(item);
|
||||
}
|
||||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if (from.CanBeginAction(this))
|
||||
{
|
||||
from.BeginAction(this);
|
||||
Timer.DelayCall(m_ShoutCooldown, EndLock, from);
|
||||
}
|
||||
|
||||
MLQuestSystem.TurnToFace(this, from);
|
||||
from.SendGump(m_Gump);
|
||||
|
||||
// Paperdoll doesn't open
|
||||
//base.OnDoubleClick( from );
|
||||
}
|
||||
|
||||
public override void OnThink()
|
||||
{
|
||||
base.OnThink();
|
||||
|
||||
if (m_NextShout <= DateTime.UtcNow)
|
||||
{
|
||||
Packet shoutPacket = null;
|
||||
|
||||
foreach (NetState state in GetClientsInRange(12))
|
||||
{
|
||||
Mobile m = state.Mobile;
|
||||
|
||||
if (m.CanSee(this) && m.InLOS(this) && m.CanBeginAction(this))
|
||||
{
|
||||
if (shoutPacket == null)
|
||||
shoutPacket = Packet.Acquire(new MessageLocalized(Serial, Body, MessageType.Regular, 946, 3,
|
||||
1078099, Name, "")); // Double Click On Me For Help!
|
||||
|
||||
state.Send(shoutPacket);
|
||||
}
|
||||
}
|
||||
|
||||
Packet.Release(shoutPacket);
|
||||
|
||||
m_NextShout = DateTime.UtcNow + m_ShoutDelay;
|
||||
}
|
||||
}
|
||||
|
||||
private void EndLock(Mobile m)
|
||||
{
|
||||
m.EndAction(this);
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
Frozen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
189
Projects/Scripts/Engines/MLQuests/Objectives/BaseObjective.cs
Normal file
189
Projects/Scripts/Engines/MLQuests/Objectives/BaseObjective.cs
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
using System;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Objectives
|
||||
{
|
||||
public abstract class BaseObjective
|
||||
{
|
||||
public virtual bool IsTimed => false;
|
||||
public virtual TimeSpan Duration => TimeSpan.Zero;
|
||||
|
||||
public virtual bool CanOffer(IQuestGiver quester, PlayerMobile pm, bool message)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract void WriteToGump(Gump g, ref int y);
|
||||
|
||||
public virtual BaseObjectiveInstance CreateInstance(MLQuestInstance instance)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class BaseObjectiveInstance
|
||||
{
|
||||
public enum DataType : byte
|
||||
{
|
||||
None,
|
||||
EscortObjective,
|
||||
KillObjective,
|
||||
DeliverObjective
|
||||
}
|
||||
|
||||
public BaseObjectiveInstance(MLQuestInstance instance, BaseObjective obj)
|
||||
{
|
||||
Instance = instance;
|
||||
|
||||
if (obj.IsTimed)
|
||||
EndTime = DateTime.UtcNow + obj.Duration;
|
||||
}
|
||||
|
||||
public MLQuestInstance Instance{ get; }
|
||||
|
||||
public bool IsTimed => EndTime != DateTime.MinValue;
|
||||
|
||||
public DateTime EndTime{ get; set; }
|
||||
|
||||
public bool Expired{ get; set; }
|
||||
|
||||
public virtual DataType ExtraDataType => DataType.None;
|
||||
|
||||
public virtual void WriteToGump(Gump g, ref int y)
|
||||
{
|
||||
if (IsTimed)
|
||||
WriteTimeRemaining(g, ref y, EndTime > DateTime.UtcNow ? EndTime - DateTime.UtcNow : TimeSpan.Zero);
|
||||
}
|
||||
|
||||
public static void WriteTimeRemaining(Gump g, ref int y, TimeSpan timeRemaining)
|
||||
{
|
||||
g.AddHtmlLocalized(103, y, 120, 16, 1062379, 0x15F90); // Est. time remaining:
|
||||
g.AddLabel(223, y, 0x481, timeRemaining.TotalSeconds.ToString("F0"));
|
||||
y += 16;
|
||||
}
|
||||
|
||||
public virtual bool AllowsQuestItem(Item item, Type type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool IsCompleted()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void CheckComplete()
|
||||
{
|
||||
if (IsCompleted())
|
||||
{
|
||||
Instance.Player.PlaySound(0x5B6); // public sound
|
||||
Instance.CheckComplete();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnQuestAccepted()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnQuestCancelled()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnQuestCompleted()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual bool OnBeforeClaimReward()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual void OnClaimReward()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnAfterClaimReward()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnRewardClaimed()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnQuesterDeleted()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnPlayerDeath()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void OnExpire()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void Serialize(GenericWriter writer)
|
||||
{
|
||||
// Version info is written in MLQuestPersistence.Serialize
|
||||
|
||||
if (IsTimed)
|
||||
{
|
||||
writer.Write(true);
|
||||
writer.WriteDeltaTime(EndTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(false);
|
||||
}
|
||||
|
||||
// For type checks on deserialization
|
||||
// (This way quest objectives can be changed without breaking serialization)
|
||||
writer.Write((byte)ExtraDataType);
|
||||
}
|
||||
|
||||
public static void Deserialize(GenericReader reader, int version, BaseObjectiveInstance objInstance)
|
||||
{
|
||||
if (reader.ReadBool())
|
||||
{
|
||||
DateTime endTime = reader.ReadDeltaTime();
|
||||
|
||||
if (objInstance != null)
|
||||
objInstance.EndTime = endTime;
|
||||
}
|
||||
|
||||
DataType extraDataType = (DataType)reader.ReadByte();
|
||||
|
||||
switch (extraDataType)
|
||||
{
|
||||
case DataType.EscortObjective:
|
||||
{
|
||||
bool completed = reader.ReadBool();
|
||||
|
||||
if (objInstance is EscortObjectiveInstance instance)
|
||||
instance.HasCompleted = completed;
|
||||
|
||||
break;
|
||||
}
|
||||
case DataType.KillObjective:
|
||||
{
|
||||
int slain = reader.ReadInt();
|
||||
|
||||
if (objInstance is KillObjectiveInstance instance)
|
||||
instance.Slain = slain;
|
||||
|
||||
break;
|
||||
}
|
||||
case DataType.DeliverObjective:
|
||||
{
|
||||
bool completed = reader.ReadBool();
|
||||
|
||||
if (objInstance is DeliverObjectiveInstance instance)
|
||||
instance.HasCompleted = completed;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
214
Projects/Scripts/Engines/MLQuests/Objectives/CollectObjective.cs
Normal file
214
Projects/Scripts/Engines/MLQuests/Objectives/CollectObjective.cs
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Objectives
|
||||
{
|
||||
public class CollectObjective : BaseObjective
|
||||
{
|
||||
public CollectObjective(int amount = 0, Type type = null, TextDefinition name = null)
|
||||
{
|
||||
DesiredAmount = amount;
|
||||
AcceptedType = type;
|
||||
Name = name;
|
||||
|
||||
if (MLQuestSystem.Debug && ShowDetailed && name.Number > 0)
|
||||
{
|
||||
int itemid = LabelToItemID(name.Number);
|
||||
|
||||
if (itemid <= 0 || itemid > 0x4000)
|
||||
Console.WriteLine("Warning: cliloc {0} is likely giving the wrong item ID", name.Number);
|
||||
}
|
||||
}
|
||||
|
||||
public int DesiredAmount{ get; set; }
|
||||
|
||||
public Type AcceptedType{ get; set; }
|
||||
|
||||
public TextDefinition Name{ get; set; }
|
||||
|
||||
public virtual bool ShowDetailed => true;
|
||||
|
||||
public bool CheckType(Type type)
|
||||
{
|
||||
return AcceptedType?.IsAssignableFrom(type) == true;
|
||||
}
|
||||
|
||||
public virtual bool CheckItem(Item item)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public static int LabelToItemID(int label)
|
||||
{
|
||||
if (label < 1078872)
|
||||
return label - 1020000;
|
||||
return label - 1078872;
|
||||
}
|
||||
|
||||
public override void WriteToGump(Gump g, ref int y)
|
||||
{
|
||||
if (ShowDetailed)
|
||||
{
|
||||
string amount = DesiredAmount.ToString();
|
||||
|
||||
g.AddHtmlLocalized(98, y, 350, 16, 1072205, 0x15F90); // Obtain
|
||||
g.AddLabel(143, y, 0x481, amount);
|
||||
|
||||
if (Name.Number > 0)
|
||||
{
|
||||
g.AddHtmlLocalized(143 + amount.Length * 15, y, 190, 18, Name.Number, 0x77BF);
|
||||
g.AddItem(350, y, LabelToItemID(Name.Number));
|
||||
}
|
||||
else if (Name.String != null)
|
||||
{
|
||||
g.AddLabel(143 + amount.Length * 15, y, 0x481, Name.String);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Name.Number > 0)
|
||||
g.AddHtmlLocalized(98, y, 312, 32, Name.Number, 0x15F90);
|
||||
else if (Name.String != null)
|
||||
g.AddLabel(98, y, 0x481, Name.String);
|
||||
}
|
||||
|
||||
y += 32;
|
||||
}
|
||||
|
||||
public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance)
|
||||
{
|
||||
return new CollectObjectiveInstance(this, instance);
|
||||
}
|
||||
}
|
||||
|
||||
#region Timed
|
||||
|
||||
public class TimedCollectObjective : CollectObjective
|
||||
{
|
||||
public TimedCollectObjective(TimeSpan duration, int amount, Type type, TextDefinition name)
|
||||
: base(amount, type, name)
|
||||
{
|
||||
Duration = duration;
|
||||
}
|
||||
|
||||
public override bool IsTimed => true;
|
||||
public override TimeSpan Duration{ get; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public class CollectObjectiveInstance : BaseObjectiveInstance
|
||||
{
|
||||
public CollectObjectiveInstance(CollectObjective objective, MLQuestInstance instance)
|
||||
: base(instance, objective)
|
||||
{
|
||||
Objective = objective;
|
||||
}
|
||||
|
||||
public CollectObjective Objective{ get; set; }
|
||||
|
||||
private int GetCurrentTotal()
|
||||
{
|
||||
Container pack = Instance.Player.Backpack;
|
||||
|
||||
if (pack == null)
|
||||
return 0;
|
||||
|
||||
Item[] items = pack.FindItemsByType(Objective.AcceptedType, false); // Note: subclasses are included
|
||||
return items.Where(item => item.QuestItem && Objective.CheckItem(item)).Sum(item => item.Amount);
|
||||
}
|
||||
|
||||
public override bool AllowsQuestItem(Item item, Type type)
|
||||
{
|
||||
return Objective.CheckType(type) && Objective.CheckItem(item);
|
||||
}
|
||||
|
||||
public override bool IsCompleted()
|
||||
{
|
||||
return GetCurrentTotal() >= Objective.DesiredAmount;
|
||||
}
|
||||
|
||||
public override void OnQuestCancelled()
|
||||
{
|
||||
PlayerMobile pm = Instance.Player;
|
||||
Container pack = pm.Backpack;
|
||||
|
||||
if (pack == null)
|
||||
return;
|
||||
|
||||
Type checkType = Objective.AcceptedType;
|
||||
Item[] items = pack.FindItemsByType(checkType, false);
|
||||
|
||||
foreach (Item item in items)
|
||||
if (item.QuestItem && !MLQuestSystem.CanMarkQuestItem(pm, item, checkType)
|
||||
) // does another quest still need this item? (OSI just unmarks everything)
|
||||
item.QuestItem = false;
|
||||
}
|
||||
|
||||
// Should only be called after IsComplete() is checked to be true
|
||||
public override void OnClaimReward()
|
||||
{
|
||||
Container pack = Instance.Player.Backpack;
|
||||
|
||||
if (pack == null)
|
||||
return;
|
||||
|
||||
// TODO: OSI also counts the item in the cursor?
|
||||
|
||||
Item[] items = pack.FindItemsByType(Objective.AcceptedType, false);
|
||||
int left = Objective.DesiredAmount;
|
||||
|
||||
foreach (Item item in items)
|
||||
if (item.QuestItem && Objective.CheckItem(item))
|
||||
{
|
||||
if (left == 0)
|
||||
return;
|
||||
|
||||
if (item.Amount > left)
|
||||
{
|
||||
item.Consume(left);
|
||||
left = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Delete();
|
||||
left -= item.Amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnAfterClaimReward()
|
||||
{
|
||||
OnQuestCancelled(); // same thing, clear other quest items
|
||||
}
|
||||
|
||||
public override void OnExpire()
|
||||
{
|
||||
OnQuestCancelled();
|
||||
|
||||
// No message
|
||||
}
|
||||
|
||||
public override void WriteToGump(Gump g, ref int y)
|
||||
{
|
||||
Objective.WriteToGump(g, ref y);
|
||||
y -= 16;
|
||||
|
||||
if (Objective.ShowDetailed)
|
||||
{
|
||||
base.WriteToGump(g, ref y);
|
||||
|
||||
g.AddHtmlLocalized(103, y, 120, 16, 3000087, 0x15F90); // Total
|
||||
g.AddLabel(223, y, 0x481, GetCurrentTotal().ToString());
|
||||
y += 16;
|
||||
|
||||
g.AddHtmlLocalized(103, y, 120, 16, 1074782, 0x15F90); // Return to
|
||||
g.AddLabel(223, y, 0x481, QuesterNameAttribute.GetQuesterNameFor(Instance.QuesterType));
|
||||
y += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
229
Projects/Scripts/Engines/MLQuests/Objectives/DeliverObjective.cs
Normal file
229
Projects/Scripts/Engines/MLQuests/Objectives/DeliverObjective.cs
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Engines.MLQuests.Objectives
|
||||
{
|
||||
public class DeliverObjective : BaseObjective
|
||||
{
|
||||
public DeliverObjective(Type delivery, int amount, TextDefinition name, Type destination, bool spawnsDelivery = true)
|
||||
{
|
||||
Delivery = delivery;
|
||||
Amount = amount;
|
||||
Name = name;
|
||||
Destination = destination;
|
||||
SpawnsDelivery = spawnsDelivery;
|
||||
|
||||
if (MLQuestSystem.Debug && name.Number > 0)
|
||||
{
|
||||
int itemid = CollectObjective.LabelToItemID(name.Number);
|
||||
|
||||
if (itemid <= 0 || itemid > 0x4000)
|
||||
Console.WriteLine("Warning: cliloc {0} is likely giving the wrong item ID", name.Number);
|
||||
}
|
||||
}
|
||||
|
||||
public Type Delivery{ get; set; }
|
||||
|
||||
public int Amount{ get; set; }
|
||||
|
||||
public TextDefinition Name{ get; set; }
|
||||
|
||||
public Type Destination{ get; set; }
|
||||
|
||||
public bool SpawnsDelivery{ get; set; }
|
||||
|
||||
public virtual void SpawnDelivery(Container pack)
|
||||
{
|
||||
if (!SpawnsDelivery || pack == null)
|
||||
return;
|
||||
|
||||
List<Item> delivery = new List<Item>();
|
||||
|
||||
for (int i = 0; i < Amount; ++i)
|
||||
{
|
||||
if (!(Activator.CreateInstance(Delivery) is Item item))
|
||||
continue;
|
||||
|
||||
delivery.Add(item);
|
||||
|
||||
if (item.Stackable && Amount > 1)
|
||||
{
|
||||
item.Amount = Amount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Item item in delivery)
|
||||
pack.DropItem(item); // Confirmed: on OSI items are added even if your pack is full
|
||||
}
|
||||
|
||||
public override void WriteToGump(Gump g, ref int y)
|
||||
{
|
||||
string amount = Amount.ToString();
|
||||
|
||||
g.AddHtmlLocalized(98, y, 312, 16, 1072207, 0x15F90); // Deliver
|
||||
g.AddLabel(143, y, 0x481, amount);
|
||||
|
||||
if (Name.Number > 0)
|
||||
{
|
||||
g.AddHtmlLocalized(143 + amount.Length * 15, y, 190, 18, Name.Number, 0x77BF);
|
||||
g.AddItem(350, y, CollectObjective.LabelToItemID(Name.Number));
|
||||
}
|
||||
else if (Name.String != null)
|
||||
{
|
||||
g.AddLabel(143 + amount.Length * 15, y, 0x481, Name.String);
|
||||
}
|
||||
|
||||
y += 32;
|
||||
|
||||
g.AddHtmlLocalized(103, y, 120, 16, 1072379, 0x15F90); // Deliver to
|
||||
g.AddLabel(223, y, 0x481, QuesterNameAttribute.GetQuesterNameFor(Destination));
|
||||
|
||||
y += 16;
|
||||
}
|
||||
|
||||
public override BaseObjectiveInstance CreateInstance(MLQuestInstance instance)
|
||||
{
|
||||
return new DeliverObjectiveInstance(this, instance);
|
||||
}
|
||||
}
|
||||
|
||||
#region Timed
|
||||
|
||||
public class TimedDeliverObjective : DeliverObjective
|
||||
{
|
||||
public TimedDeliverObjective(TimeSpan duration, Type delivery, int amount, TextDefinition name, Type destination,
|
||||
bool spawnsDelivery = true)
|
||||
: base(delivery, amount, name, destination, spawnsDelivery)
|
||||
{
|
||||
Duration = duration;
|
||||
}
|
||||
|
||||
public override bool IsTimed => true;
|
||||
public override TimeSpan Duration{ get; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public class DeliverObjectiveInstance : BaseObjectiveInstance
|
||||
{
|
||||
public DeliverObjectiveInstance(DeliverObjective objective, MLQuestInstance instance)
|
||||
: base(instance, objective)
|
||||
{
|
||||
Objective = objective;
|
||||
}
|
||||
|
||||
public DeliverObjective Objective{ get; set; }
|
||||
|
||||
public bool HasCompleted{ get; set; }
|
||||
|
||||
public override DataType ExtraDataType => DataType.DeliverObjective;
|
||||
|
||||
public virtual bool IsDestination(IQuestGiver quester, Type type)
|
||||
{
|
||||
Type destType = Objective.Destination;
|
||||
|
||||
return destType?.IsAssignableFrom(type) == true;
|
||||
}
|
||||
|
||||
public override bool IsCompleted()
|
||||
{
|
||||
return HasCompleted;
|
||||
}
|
||||
|
||||
public override void OnQuestAccepted()
|
||||
{
|
||||
Objective.SpawnDelivery(Instance.Player.Backpack);
|
||||
}
|
||||
|
||||
// This is VERY similar to CollectObjective.GetCurrentTotal
|
||||
private int GetCurrentTotal()
|
||||
{
|
||||
Container pack = Instance.Player.Backpack;
|
||||
|
||||
if (pack == null)
|
||||
return 0;
|
||||
|
||||
Item[] items = pack.FindItemsByType(Objective.Delivery, false); // Note: subclasses are included
|
||||
return items.Sum(item => item.Amount);
|
||||
}
|
||||
|
||||
public override bool OnBeforeClaimReward()
|
||||
{
|
||||
PlayerMobile pm = Instance.Player;
|
||||
|
||||
int total = GetCurrentTotal();
|
||||
int desired = Objective.Amount;
|
||||
|
||||
if (total < desired)
|
||||
{
|
||||
pm.SendLocalizedMessage(1074861); // You do not have everything you need!
|
||||
pm.SendLocalizedMessage(1074885, $"{total}\t{desired}"); // You have ~1_val~ item(s) but require ~2_val~
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: This is VERY similar to CollectObjective.OnClaimReward
|
||||
public override void OnClaimReward()
|
||||
{
|
||||
Container pack = Instance.Player.Backpack;
|
||||
|
||||
if (pack == null)
|
||||
return;
|
||||
|
||||
Item[] items = pack.FindItemsByType(Objective.Delivery, false);
|
||||
int left = Objective.Amount;
|
||||
|
||||
foreach (Item item in items)
|
||||
{
|
||||
if (left == 0)
|
||||
break;
|
||||
|
||||
if (item.Amount > left)
|
||||
{
|
||||
item.Consume(left);
|
||||
left = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Delete();
|
||||
left -= item.Amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnQuestCancelled()
|
||||
{
|
||||
OnClaimReward(); // same effect
|
||||
}
|
||||
|
||||
public override void OnExpire()
|
||||
{
|
||||
OnQuestCancelled();
|
||||
|
||||
Instance.Player.SendLocalizedMessage(1074813); // You have failed to complete your delivery.
|
||||
}
|
||||
|
||||
public override void WriteToGump(Gump g, ref int y)
|
||||
{
|
||||
Objective.WriteToGump(g, ref y);
|
||||
|
||||
base.WriteToGump(g, ref y);
|
||||
|
||||
// No extra instance stuff printed for this objective
|
||||
}
|
||||
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(HasCompleted);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue