diff --git a/Server/data/configs/ground_spawns.json b/Server/data/configs/ground_spawns.json
index 1893b6df3..a953bb958 100644
--- a/Server/data/configs/ground_spawns.json
+++ b/Server/data/configs/ground_spawns.json
@@ -111,6 +111,10 @@
"item_id": "278",
"loc_data": "{1,2604,3358,0,50}-"
},
+ {
+ "item_id": "298",
+ "loc_data": "{1,2569,9897,0,50}-"
+ },
{
"item_id": "301",
"loc_data": "{1,2608,3397,0,90}-"
@@ -145,7 +149,7 @@
},
{
"item_id": "444",
- "loc_data": "{1,3231,3739,0,250}-{1,3236,3741,0,250}-{1,3195,9821,0,150}-{1,2732,3224,0,250}-"
+ "loc_data": "{1,2732,3224,0,250}-{1,3231,3739,0,250}-{1,3236,3741,0,250}-{1,3195,9821,0,150}-"
},
{
"item_id": "480",
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.java b/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.java
deleted file mode 100644
index 6d3f2bee6..000000000
--- a/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package content.region.kandarin.quest.waterfall;
-
-import content.data.Quests;
-import core.game.dialogue.DialogueInterpreter;
-import core.game.dialogue.DialoguePlugin;
-import core.game.dialogue.FacialExpression;
-import core.game.node.entity.player.Player;
-import core.game.node.entity.player.link.quest.Quest;
-
-/**
- * Handles Almera's Dialogue for the Waterfall Quest.
- * @author Splinter
- */
-public class AlmeraDialogue extends DialoguePlugin {
-
- public AlmeraDialogue() {
-
- }
-
- public AlmeraDialogue(Player player) {
- super(player);
- }
-
- @Override
- public int[] getIds() {
- return new int[] { DialogueInterpreter.getDialogueKey("almera_dialogue"), 304 };
- }
-
- @Override
- public boolean handle(int interfaceId, int buttonId) {
- final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST);
- switch (stage) {
- /* Main dialogue sequence */
- case 0:
- if (quest.getStage(player) == 0) {
- interpreter.sendDialogues(304, FacialExpression.ASKING, "Ah, hello there. Nice to see an outsider for a change,", "are you busy? I have a problem.");
- stage = 1;
- } else if (quest.getStage(player) == 10) {
- interpreter.sendDialogues(304, FacialExpression.JOLLY, "Hello brave adventurer, have you seen my boy yet?");
- stage = 200;
- } else if (quest.getStage(player) >= 20) {
- interpreter.sendDialogues(304, FacialExpression.JOLLY, "Well hello, you're still around then.");
- stage = 202;
- } else {
-
- }
- break;
- case 1:
- interpreter.sendOptions("Select an Option", "I'm afraid I'm in a rush.", "How can I help?");
- stage = 2;
- break;
- case 2:
- switch (buttonId) {
- case 1:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm afraid I am in a rush.");
- stage = 99;
- break;
- case 2:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "How can I help?");
- stage = 3;
- break;
- }
- break;
- case 3:
- interpreter.sendDialogues(304, FacialExpression.DISGUSTED, "It's my son Hudon, he's always getting into trouble, the", "boy's convinced there's hidden treasure in the river and", "I'm a bit worried about his safety, the poor lad can't", "even swim.");
- stage = 4;
- break;
- case 4:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I could go and take a look for you if you like?");
- stage = 5;
- break;
- case 5:
- interpreter.sendDialogues(304, FacialExpression.DISGUSTED, "Would you? You are kind. You can use the small raft", "out back if you wish, do be careful, the current down", "stream is very strong.");
- quest.start(player);
- stage = 100;
- break;
- case 6:
- interpreter.sendDialogues(304, FacialExpression.HALF_GUILTY, "Perhaps you can speak to Hadley a further bit down", "south for more information on how to find the treasure.");
- stage = 100;
- break;
- case 7:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I did it, I found the treasure under the waterfall!");
- stage = 8;
- break;
- case 8:
- interpreter.sendDialogues(304, FacialExpression.HALF_GUILTY, "Ah, very well done, adventurer!", "My boy Hudon was searching for that treasure too.");
- stage = 9;
- break;
- case 9:
- interpreter.sendDialogues(304, FacialExpression.HALF_GUILTY, "Maybe you could share it with him, he's just a boy.");
- stage = 10;
- break;
- case 10:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "On second thought, I really have to go.");
- stage = 100;
- break;
-
- case 99:
- interpreter.sendDialogues(304, FacialExpression.HALF_GUILTY, "Oh okay, never mind.");
- stage = 100;
- break;
- case 100:
- end();
- break;
- case 200:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'm afraid not, but I'm sure he hasn't gone far.");
- stage = 201;
- break;
- case 201:
- interpreter.sendDialogues(304, FacialExpression.HALF_GUILTY, "I do hope so, you can't be too careful these days.");
- stage = 100;
- break;
- case 202:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I saw Hudon by the river but he refused to come back", "with me.");
- stage = 203;
- break;
- case 203:
- interpreter.sendDialogues(304, FacialExpression.HALF_GUILTY, "Yes he told me, the foolish lad came in drenched to the", "bone, he had fallen into the waterfall, lucky he wasn't", "killed! Now he can spend the rest of the summer in his", "room.");
- stage = 204;
- break;
- case 204:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Any ideas on what I could do while I'm here?");
- stage = 205;
- break;
- case 205:
- interpreter.sendDialogues(304, FacialExpression.HALF_GUILTY, "Why don't you visit the tourist centre south of the", "waterfall?");
- stage = 100;
- break;
- }
- return true;
- }
-
- @Override
- public DialoguePlugin newInstance(Player player) {
- return new AlmeraDialogue(player);
- }
-
- @Override
- public boolean open(Object... args) {
- final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST);
- if (quest.getStage(player) == 100) {
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello Almera.");
- stage = 7;
- } else {
- interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Hello.");
- stage = 0;
- }
- return true;
- }
-}
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.kt b/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.kt
new file mode 100644
index 000000000..4da028e98
--- /dev/null
+++ b/Server/src/main/content/region/kandarin/quest/waterfall/AlmeraDialogue.kt
@@ -0,0 +1,84 @@
+package content.region.kandarin.quest.waterfall
+
+import content.data.Quests
+import core.api.*
+import core.game.dialogue.ChatAnim
+import core.game.dialogue.DialogueLabeller
+import core.game.dialogue.DialogueOption
+import core.game.interaction.IntType
+import core.game.interaction.InteractionListener
+import core.game.node.entity.npc.NPC
+import org.rs09.consts.NPCs
+
+class AlmeraDialogue : InteractionListener {
+ override fun defineListeners() {
+ on(NPCs.ALMERA_304, IntType.NPC, "talk-to") { player, node ->
+ DialogueLabeller.open(player, AlmeraDialogueFile(), node as NPC)
+ return@on true
+ }
+ }
+}
+
+class AlmeraDialogueFile : DialogueLabeller() {
+ override fun addConversation() {
+ exec { player, _ ->
+ when (getQuestStage(player, Quests.WATERFALL_QUEST)) {
+ 0 -> loadLabel(player, "quest_not_started")
+ 10 -> loadLabel(player, "quest_stage_10")
+ 20 -> loadLabel(player, "quest_stage_20")
+ 30 -> loadLabel(player, "quest_stage_30")
+ 100 -> loadLabel(player, "quest_complete")
+ }
+ }
+
+ label("quest_not_started")
+ player(ChatAnim.NEUTRAL, "Hello.")
+ npc(ChatAnim.NEUTRAL, "Ah, hello there. Nice to see an outsider for a change,", "are you busy? I have a problem.")
+ options(
+ DialogueOption("rush", "I'm afraid I'm in a rush.", expression = ChatAnim.NEUTRAL),
+ DialogueOption("help", "How can I help?", expression = ChatAnim.NEUTRAL)
+ )
+
+ label("rush")
+ npc(ChatAnim.HALF_GUILTY, "Oh okay, never mind.")
+
+ label("help")
+ npc(ChatAnim.THINKING, "It's my son Hudon, he's always getting into trouble, the", "boy's convinced there's hidden treasure in the river and",
+ "I'm a bit worried about his safety, the poor lad can't", "even swim.")
+ player(ChatAnim.THINKING, "I could go and take a look for you if you like?")
+ exec { player, _ ->
+ startQuest(player, Quests.WATERFALL_QUEST)
+ }
+ npc(ChatAnim.HAPPY, "Would you? You are kind. You can use the small raft", "out back if you wish, do be careful, the current down",
+ "stream is very strong.")
+
+ label("quest_stage_10")
+ npc(ChatAnim.NEUTRAL, "Hello brave adventurer, have you seen my boy yet?")
+ player(ChatAnim.NEUTRAL, "I'm afraid not, but I'm sure he hasn't gone far.")
+ npc(ChatAnim.NEUTRAL, "I do hope so, you can't be too careful these days.")
+
+ label("quest_stage_20")
+ player(ChatAnim.NEUTRAL, "Hello again.")
+ npc(ChatAnim.NEUTRAL, "Well hello, you're still around then.")
+ player(ChatAnim.NEUTRAL, "I saw Hudon by the river but he refused to come back", "with me.")
+ npc(ChatAnim.NEUTRAL, "Yes he told me, the foolish lad came in drenched to the", "bone, he had fallen into the waterfall, lucky he wasn't",
+ "killed! Now he can spend the rest of the summer in his", "room.")
+ player(ChatAnim.NEUTRAL, "Any ideas on what I could do while I'm here?")
+ npc(ChatAnim.NEUTRAL, "Why don't you visit the tourist centre south of the", "waterfall?")
+
+ label("quest_stage_30")
+ player(ChatAnim.NEUTRAL, "Hello Almera.")
+ npc(ChatAnim.NEUTRAL, "Hello adventurer, how's your treasure hunt going?")
+ player(ChatAnim.NEUTRAL, "Oh, I'm just sight seeing.")
+ npc(ChatAnim.NEUTRAL, "No adventurer stays this long just to sight see. But", "your business is yours alone, if you need to use the",
+ "raft go ahead. But please try not to crash it this time!")
+ player(ChatAnim.NEUTRAL, "Thanks Almera.")
+
+ label("quest_complete")
+ player(ChatAnim.NEUTRAL, "Hello Almera.")
+ player(ChatAnim.NEUTRAL, "I did it, I found the treasure under the waterfall!")
+ npc(ChatAnim.NEUTRAL, "Ah, very well done, adventurer!", "My boy Hudon was searching for that treasure too.")
+ npc(ChatAnim.NEUTRAL, "Maybe you could share it with him, he's just a boy.")
+ player(ChatAnim.NEUTRAL, "On second thought, I really have to go.")
+ }
+}
\ No newline at end of file
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/BaxtorianBook.kt b/Server/src/main/content/region/kandarin/quest/waterfall/BaxtorianBook.kt
index c4c0d1ef0..bb35340b0 100644
--- a/Server/src/main/content/region/kandarin/quest/waterfall/BaxtorianBook.kt
+++ b/Server/src/main/content/region/kandarin/quest/waterfall/BaxtorianBook.kt
@@ -5,148 +5,205 @@ import content.global.handlers.iface.BookInterface
import content.global.handlers.iface.BookLine
import content.global.handlers.iface.Page
import content.global.handlers.iface.PageSet
-import core.api.setAttribute
+import core.api.getQuestStage
+import core.api.lock
+import core.api.queueScript
+import core.api.sendMessage
+import core.api.setQuestStage
+import core.api.stopExecuting
import core.api.storeBookInHouse
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
+import core.game.interaction.QueueStrength
import core.game.node.entity.player.Player
import org.rs09.consts.Items
/**
- * Baxtorian Book
+ * The Book on Baxtorian
* @author ovenbreado
- * @author Splinter
+ * @author Bishop
*/
+
class BaxtorianBook : InteractionListener {
companion object {
+ private const val RED = "
"
+
private val TITLE = "Book on Baxtorian"
private val CONTENTS = arrayOf(
PageSet(
Page(
- BookLine("The missing relics", 55),
+ BookLine(RED + "The missing relics", 55),
BookLine("", 56),
- BookLine(" Many artefacts of", 57),
- BookLine("elven history were lost", 58),
- BookLine("after the fourth age. The", 59),
- BookLine("greatest loss to our", 60),
- BookLine("collections of elf history", 61),
- BookLine("were the hidden treasures", 62),
- BookLine("of Baxtorian.", 63),
- BookLine(" Some believe these", 64),
- BookLine("treasures are still", 65)
+ BookLine("Many artefacts of elven", 57),
+ BookLine("history were lost after the", 58),
+ BookLine("fourth age, following the", 59),
+ BookLine("departure of the elven", 60),
+ BookLine("colonies from these lands.", 61),
+ BookLine("The greatest loss to our", 62),
+ BookLine("collections of elf history", 63),
+ BookLine("were the hidden treasures", 64),
+ BookLine("of Baxtorian. Some", 65)
),
Page(
- BookLine("unclaimed, but it is more", 66),
- BookLine("commonly believed that", 67),
- BookLine("dwarf miners recovered", 68),
- BookLine("the treasure at the", 69),
- BookLine("beginning of the third", 70),
- BookLine("age. Another great loss", 71),
- BookLine("was Glarial's pebble, a key", 72),
- BookLine("which allowed her family", 73),
- BookLine("to visit her tomb.", 74),
- BookLine(" The stone was taken", 75),
- BookLine("by a gnome family over a", 76)
- )
- ),
- PageSet(
- Page(
- BookLine("century ago. It is", 55),
- BookLine("believed that the gnomes'", 56),
- BookLine("descendant Golrie still has", 57),
- BookLine("the stone hidden in the", 58),
- BookLine("caves under the gnome", 59),
- BookLine("tree village.", 60),
- BookLine("", 61),
- BookLine("The sonnet of Baxtorian", 62),
- BookLine("", 63),
- BookLine("The love between", 64),
- BookLine("Baxtorian and Glarial was", 65)
- ), Page(
- BookLine("said to have lasted over a", 66),
- BookLine("century. They lived a", 67),
- BookLine("peaceful life learning and", 68),
- BookLine("teaching the laws of", 69),
- BookLine("nature. When Baxtorian's", 70),
- BookLine("kingdom was invaded by", 71),
- BookLine("the dark forces he left on", 72),
- BookLine("a five year campaign. He", 73),
- BookLine("returned to find his", 74),
- BookLine("people slaughtered and his", 75),
- BookLine("wife taken by the enemy.", 76)
- )
- ),
- PageSet(
- Page(
- BookLine(" After years of", 55),
- BookLine("searching for his love he", 56),
- BookLine("finally gave up and", 57),
- BookLine("returned to the home he", 58),
- BookLine("made for Glarial under", 59),
- BookLine("the Baxtorian Waterfall.", 60),
- BookLine("Once he entered he", 61),
- BookLine("never returned. Only", 62),
- BookLine("Glarial had the power to", 63),
- BookLine("also enter the waterfall.", 64),
- BookLine(" Since Baxtorian", 65)
- ),
- Page(
- BookLine("entered no one but her", 66),
- BookLine("can follow him in, it's as if", 67),
- BookLine("the powers of nature still", 68),
- BookLine("work to protect him.", 69),
- BookLine("", 70),
- BookLine("The power of nature", 71),
+ BookLine("believe these treasures", 66),
+ BookLine("are still unclaimed, but it", 67),
+ BookLine("is more commonly", 68),
+ BookLine("believed that dwarf miners", 69),
+ BookLine("recovered the treasure", 70),
+ BookLine("early in the 5th Age.", 71),
BookLine("", 72),
- BookLine(" Glarial and Baxtorian", 73),
- BookLine("were masters of nature.", 74),
- BookLine("Trees would grow, hills", 75),
- BookLine("form and rivers flood on", 76)
+ BookLine("Another great loss was", 73),
+ BookLine("Glarial's pebble, a key", 74),
+ BookLine("which allowed her family", 75),
+ BookLine("to visit her tomb.", 76)
)
),
PageSet(
Page(
- BookLine("their command. Baxtorian", 55),
- BookLine("in particular had", 56),
- BookLine("perfected rune lore. It", 57),
- BookLine("was said that he could", 58),
- BookLine("uses the stones to control", 59),
- BookLine("water, earth, and air.", 60),
- BookLine("", 61),
- BookLine("Ode to eternity", 62),
+ BookLine("The pebble was taken by", 55),
+ BookLine("a gnome many years", 56),
+ BookLine("ago. It is hoped that", 57),
+ BookLine("descendents " /*sic*/+ "of that", 58),
+ BookLine("gnome may still have the", 59),
+ BookLine("pebble hidden in their", 60),
+ BookLine("cave under the Tree", 61),
+ BookLine("Gnome Village.", 62),
BookLine("", 63),
- BookLine("A short piece written by", 64),
- BookLine("Baxtorian himself.", 65)
+ BookLine("Unfortunately the maze", 64),
+ BookLine("around that village makes", 65)
),
Page(
- BookLine("", 66),
- BookLine("What care I for this", 67),
- BookLine("mortal coil,", 68),
- BookLine("where treasures are yet", 69),
- BookLine("so frail,", 70),
- BookLine("for it is you that is my", 71),
- BookLine("life blood,", 72),
- BookLine("the wine to my holy grail", 73),
- BookLine("and if I see the", 74),
- BookLine("judgement day,", 75),
- BookLine("when the gods fill the air", 76)
+ BookLine("it difficult to contact the", 66),
+ BookLine("gnomes to investigate this", 67),
+ BookLine("matter.", 68),
+ BookLine("", 69),
+ BookLine("", 70),
+ BookLine("", 71),
+ BookLine("", 72),
+ BookLine("", 73),
+ BookLine("", 74),
+ BookLine("", 75),
+ BookLine("", 76)
)
),
PageSet(
Page(
- BookLine("with dust,", 55),
- BookLine("I'll happily choke on your", 56),
- BookLine("memory,", 57),
- BookLine("as my kingdom turns to", 58),
- BookLine("rust", 59)
+ BookLine(RED + "The fall of Baxtorian", 55),
+ BookLine("", 56),
+ BookLine("The love between", 57),
+ BookLine("Baxtorian and Glarial was", 58),
+ BookLine("said to have lasted over a", 59),
+ BookLine("century. They lived a", 60),
+ BookLine("peaceful life learning and", 61),
+ BookLine("teaching the laws of", 62),
+ BookLine("nature.", 63),
+ BookLine("", 64),
+ BookLine("When their homeland in", 65)
+ ),
+ Page(
+ BookLine("the far west was plunged", 66),
+ BookLine("into chaos by dark forces,", 67),
+ BookLine("Baxtorian left on a", 68),
+ BookLine("dangerous campaign that", 69),
+ BookLine("lasted for five years. He", 70),
+ BookLine("survived to return to this", 71),
+ BookLine("land, but found his people", 72),
+ BookLine("slaughtered and his wife", 73),
+ BookLine("taken by the enemy.", 74),
+ BookLine("", 75),
+ BookLine("After years of searching", 76)
)
- )
+ ),
+ PageSet(
+ Page(
+ BookLine("for his love he finally", 55),
+ BookLine("gave up and returned to", 56),
+ BookLine("the home he made for", 57),
+ BookLine("Glarial under the", 58),
+ BookLine("Baxtorian Waterfall.", 59),
+ BookLine("Once he entered he", 60),
+ BookLine("never returned.", 61),
+ BookLine("", 62),
+ BookLine("Only he and Glarial had", 63),
+ BookLine("the power to enter the", 64),
+ BookLine("waterfall. Since Baxtorian", 65)
+ ),
+ Page(
+ BookLine("entered, no-one else can", 66),
+ BookLine("follow him in, it's as if the", 67),
+ BookLine("powers of nature still", 68),
+ BookLine("work to protect his peace.", 69),
+ BookLine("", 70),
+ BookLine("", 71),
+ BookLine("", 72),
+ BookLine("", 73),
+ BookLine("", 74),
+ BookLine("", 75),
+ BookLine("", 76)
+ )
+ ),
+ PageSet(
+ Page(
+ BookLine(RED + "The power of nature", 55),
+ BookLine("", 56),
+ BookLine("Glarial and Baxtorian", 57),
+ BookLine("were masters of nature.", 58),
+ BookLine("Trees and flowers would", 59),
+ BookLine("grow, hills form and", 60),
+ BookLine("rivers flood on their", 61),
+ BookLine("command.", 62),
+ BookLine("", 63),
+ BookLine("Baxtorian in particular", 64),
+ BookLine("had perfected rune lore.", 65)
+ ),
+ Page(
+ BookLine("It was said that he could", 66),
+ BookLine("use the stones to control", 67),
+ BookLine("water, earth and air.", 68),
+ BookLine("", 69),
+ BookLine("", 70),
+ BookLine("", 71),
+ BookLine("", 72),
+ BookLine("", 73),
+ BookLine("", 74),
+ BookLine("", 75),
+ BookLine("", 76)
+ )
+ ),
+ PageSet(
+ Page(
+ BookLine(RED + "Ode to eternity", 55),
+ BookLine("", 56),
+ BookLine("(A short piece written by", 57),
+ BookLine("Baxtorian himself.)", 58),
+ BookLine("", 59),
+ BookLine("What care I for this", 60),
+ BookLine("mortal coil,", 61),
+ BookLine("where treasures are yet", 62),
+ BookLine("so frail,", 63),
+ BookLine("for it is you that is my", 64),
+ BookLine("life blood,", 65)
+ ),
+ Page(
+ BookLine("the wine to my holy grail", 66),
+ BookLine("and if I see the", 67),
+ BookLine("judgement day,", 68),
+ BookLine("when the gods fill the air", 69),
+ BookLine("with dust,", 70),
+ BookLine("I'll happily choke on your", 71),
+ BookLine("memory,", 72),
+ BookLine("as my kingdom turns to", 73),
+ BookLine("rust.", 74),
+ BookLine("", 75),
+ BookLine("", 76)
+ )
+ ),
)
private fun display(player: Player, pageNum: Int, buttonID: Int) : Boolean {
BookInterface.pageSetup(player, BookInterface.FANCY_BOOK_3_49, TITLE, CONTENTS)
- if (player.questRepository.getQuest(Quests.WATERFALL_QUEST).getStage(player) == 20) {
- player.questRepository.getQuest(Quests.WATERFALL_QUEST).setStage(player, 30)
+ if (getQuestStage(player, Quests.WATERFALL_QUEST) == 20) {
+ setQuestStage(player, Quests.WATERFALL_QUEST, 30)
}
return true
}
@@ -154,8 +211,14 @@ class BaxtorianBook : InteractionListener {
override fun defineListeners() {
on(Items.BOOK_ON_BAXTORIAN_292, IntType.ITEM, "read") { player, node ->
- BookInterface.openBook(player, BookInterface.FANCY_BOOK_3_49, ::display)
- storeBookInHouse(player, node)
+ sendMessage(player, "The book is old with many pages missing.")
+ sendMessage(player, "A few are translated from elven into common tongue.")
+ lock(player, 2)
+ queueScript(player, 2, QueueStrength.STRONG) {
+ BookInterface.openBook(player, BookInterface.FANCY_BOOK_3_49, ::display)
+ storeBookInHouse(player, node)
+ return@queueScript stopExecuting(player)
+ }
return@on true
}
}
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/GolrieDialogue.java b/Server/src/main/content/region/kandarin/quest/waterfall/GolrieDialogue.java
deleted file mode 100644
index f16af0ea8..000000000
--- a/Server/src/main/content/region/kandarin/quest/waterfall/GolrieDialogue.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package content.region.kandarin.quest.waterfall;
-
-import core.game.dialogue.DialogueInterpreter;
-import core.game.dialogue.DialoguePlugin;
-import core.game.dialogue.FacialExpression;
-import core.game.node.entity.player.Player;
-import core.game.node.item.Item;
-
-import static core.api.ContentAPIKt.*;
-
-/**
- * Handles Golrie's Dialogue for the Waterfall quest
- * @author Splinter
- */
-public class GolrieDialogue extends DialoguePlugin {
-
- public GolrieDialogue() {
-
- }
-
- public GolrieDialogue(Player player) {
- super(player);
- }
-
- @Override
- public int[] getIds() {
- return new int[] { DialogueInterpreter.getDialogueKey("golrie_dialogue"), 306 };
- }
-
- @Override
- public boolean handle(int interfaceId, int buttonId) {
- switch (stage) {
- case 100:
- end();
- break;
-
- /* Main dialogue sequence */
- case 0:
- interpreter.sendDialogues(306, FacialExpression.OLD_NORMAL, "That's me. I've been stuck in here for weeks, those", "goblins are trying to steal my family's heirlooms. My", "grandad gave me all sorts of old junk.");
- stage = 1;
- break;
- case 1:
- interpreter.sendDialogues(player, FacialExpression.ASKING, "Do you mind if I have a look?");
- stage = 2;
- break;
- case 2:
- interpreter.sendDialogues(306, FacialExpression.OLD_HAPPY, "No, of course not.");
- stage = 3;
- break;
- case 3:
- //TODO: Possibly change this to chat message
- interpreter.sendDialogue("You look amongst the junk on the floor.");
- if (hasAnItem(player, 294).getContainer() != null) {
- stage = 50;
- } else {
- stage = 4;
- }
- break;
- case 4:
- //TODO: Possibly change this to chat message
- interpreter.sendDialogue("Mixed with the junk on the floor you find Glarial's pebble.");
- stage = 5;
- break;
- case 5:
- //TODO: Possibly change to HAPPY
- interpreter.sendDialogues(player, FacialExpression.ASKING, "Could I take this old pebble?");
- stage = 6;
- break;
- case 6:
- interpreter.sendDialogues(306, FacialExpression.OLD_NORMAL, "Oh that, yes have it, it's just some old elven junk I", "believe.");
- player.getInventory().add(new Item(294, 1));
- stage = 7;
- break;
- case 7:
- //TODO: Possibly change this to chat message
- interpreter.sendDialogue("You give the key to Golrie.");
- stage = 8;
- break;
- case 8:
- interpreter.sendDialogues(306, FacialExpression.OLD_HAPPY, "Thanks a lot for the key traveller. I think I'll wait in", "here until those goblins get bored and leave.");
- player.getInventory().remove(new Item(293, 1));
- stage = 9;
- break;
- case 9:
- interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "OK... Take care Golrie.");
- stage = 100;
- break;
- case 50:
- //TODO: Possibly change this to chat message
- interpreter.sendDialogue("You find nothing of interest.");
- stage = 100;
- break;
- }
- return true;
- }
-
- @Override
- public DialoguePlugin newInstance(Player player) {
- return new GolrieDialogue(player);
- }
-
- @Override
- public boolean open(Object... args) {
- interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Hello, is your name Golrie?");
- stage = 0;
- return true;
- }
-}
\ No newline at end of file
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/GolrieDialogue.kt b/Server/src/main/content/region/kandarin/quest/waterfall/GolrieDialogue.kt
new file mode 100644
index 000000000..2417f89b3
--- /dev/null
+++ b/Server/src/main/content/region/kandarin/quest/waterfall/GolrieDialogue.kt
@@ -0,0 +1,107 @@
+package content.region.kandarin.quest.waterfall
+
+import core.api.*
+import core.game.dialogue.ChatAnim
+import core.game.dialogue.DialogueLabeller
+import core.game.interaction.IntType
+import core.game.interaction.InteractionListener
+import core.game.interaction.QueueStrength
+import core.game.node.entity.npc.NPC
+import org.rs09.consts.Items
+import org.rs09.consts.NPCs
+
+class GolrieDialogue : InteractionListener {
+ override fun defineListeners() {
+ on(NPCs.GOLRIE_306, IntType.NPC, "talk-to") { player, node ->
+ DialogueLabeller.open(player, GolrieDialogueFile(null), node as NPC)
+ return@on true
+ }
+ }
+}
+
+class GolrieDialogueFile(val startLabel: String?) : DialogueLabeller() {
+ override fun addConversation() {
+ exec { player, _ ->
+ loadLabel(player, startLabel?: "init")
+ return@exec
+ }
+
+ label("init")
+ player(ChatAnim.NEUTRAL, "Hello, is your name Golrie?")
+ npc(ChatAnim.OLD_CALM_TALK2, "That's me. I've been stuck in here for weeks, those", "goblins are trying to steal my family's heirlooms. My",
+ "grandad gave me all sorts of old junk.")
+ player(ChatAnim.NEUTRAL, "Do you mind if I have a look?")
+ afterClose { player ->
+ queueScript(player, 0, QueueStrength.NORMAL) { stage ->
+ when (stage) {
+ 0 -> {
+ lock(player, 4)
+ sendMessage(player, "You look amongst the junk on the floor")
+ return@queueScript delayScript(player, 2)
+ }
+ 1 -> {
+ if (hasAnItem(player, Items.GLARIALS_PEBBLE_294).exists()) {
+ sendMessage(player, "You find nothing of interest.")
+ return@queueScript stopExecuting(player)
+ } else {
+ sendMessage(player, "Mixed with the junk on the floor you find Glarial's pebble.")
+ return@queueScript delayScript(player, 2)
+ }
+ }
+ 2 -> {
+ DialogueLabeller.open(player, GolrieDialogueFile("got_pebble"),
+ findLocalNPC(player, NPCs.GOLRIE_306)?: return@queueScript stopExecuting(player))
+ return@queueScript stopExecuting(player)
+ }
+ else -> return@queueScript stopExecuting(player)
+ }
+ }
+ return@afterClose
+ }
+ npc(ChatAnim.OLD_HAPPY, "No, of course not.")
+
+ label("got_pebble")
+ player(ChatAnim.NEUTRAL, "Could I take this old pebble?")
+ afterClose { player ->
+ addItemOrDrop(player, Items.GLARIALS_PEBBLE_294)
+ if (removeItem(player, Items.A_KEY_293)) {
+ sendMessage(player, "You give Golrie the key.")
+ queueScript(player, 2, QueueStrength.NORMAL) {
+ DialogueLabeller.open(player, GolrieDialogueFile("thanks"),
+ findLocalNPC(player, NPCs.GOLRIE_306)?: return@queueScript stopExecuting(player))
+ return@queueScript stopExecuting(player)
+ }
+ }
+ return@afterClose
+ }
+ npc(ChatAnim.OLD_CALM_TALK1, "Oh that, yes have it, it's just some old elven junk I", "believe.")
+
+ label("thanks")
+ npc(ChatAnim.OLD_CALM_TALK1, "Thanks a lot for the key traveller. I think I'll wait in", "here until those goblins get bored and leave.")
+ player(ChatAnim.NEUTRAL, "OK... Take care Golrie.")
+
+ label("door_no_business_here")
+ npc(ChatAnim.OLD_CALM_TALK1, "What are you doing down here?", "Leave before you get yourself into trouble.")
+
+ label("door_on_quest")
+ player(ChatAnim.NEUTRAL, "Hello, are you ok?")
+ npc(ChatAnim.OLD_CALM_TALK1, "It's just those blasted hobgoblins. I locked myself in here for protection. But I've left the key somewhere and now I'm stuck.")
+ exec { player, _ ->
+ if (inInventory(player, Items.A_KEY_293)) {
+ loadLabel(player, "door_yes_key")
+ } else {
+ loadLabel(player, "door_no_key")
+ }
+ return@exec
+ }
+
+ label("door_no_key")
+ player(ChatAnim.NEUTRAL, "OK... I'll have a look for a key.")
+
+ label("door_yes_key")
+ player(ChatAnim.NEUTRAL, "I found a key.")
+ npc(ChatAnim.OLD_CALM_TALK2, "Well don't wait all day, give it a try!")
+ player(ChatAnim.NEUTRAL, "OK...")
+
+ }
+}
\ No newline at end of file
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/HadleyDialogue.java b/Server/src/main/content/region/kandarin/quest/waterfall/HadleyDialogue.java
deleted file mode 100644
index 6ac9e47f9..000000000
--- a/Server/src/main/content/region/kandarin/quest/waterfall/HadleyDialogue.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package content.region.kandarin.quest.waterfall;
-
-import core.game.dialogue.DialogueInterpreter;
-import core.game.dialogue.DialoguePlugin;
-import core.game.dialogue.FacialExpression;
-import core.game.node.entity.player.Player;
-import core.game.world.GameWorld;
-
-/**
- * Handles Almera's Dialogue for the Waterfall Quest.
- * @author Splinter
- */
-public class HadleyDialogue extends DialoguePlugin {
-
- public HadleyDialogue() {
-
- }
-
- public HadleyDialogue(Player player) {
- super(player);
- }
-
- @Override
- public int[] getIds() {
- return new int[] { DialogueInterpreter.getDialogueKey("hadley_dialogue"), 302 };
- }
-
- @Override
- public boolean handle(int interfaceId, int buttonId) {
- switch (stage) {
- case 100:
- end();
- break;
-
- /* Main dialogue sequence */
- case 0:
- if (player.getInventory().contains(292, 1)) {
- interpreter.sendDialogues(302, FacialExpression.HALF_GUILTY, "I hope you're enjoying your stay, there should be lots", "of useful information in that book: places to go, people to", "see.");
- stage = 100;
- } else {
- interpreter.sendDialogues(302, FacialExpression.HALF_GUILTY, "Are you on holiday? If so you've come to the right", "place. I'm Hadley the tourist guide, anything you need", "to know just ask me. We have some of the most unspoilt", "wildlife and scenery in " + GameWorld.getSettings().getName() + ".");
- stage = 1;
- }
- break;
- case 1:
- interpreter.sendDialogues(302, FacialExpression.HALF_GUILTY, "People come from miles around to fish in the clear lakes", "or to wander the beautiful hill sides.");
- stage = 2;
- break;
- case 2:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "It is quite pretty.");
- stage = 3;
- break;
- case 3:
- interpreter.sendDialogues(302, FacialExpression.HALF_GUILTY, "Surely pretty is an understatement kind " + (player.isMale() ? "Sir. " : "Lady. ") + "Beautiful,", "amazing or possibly life-changing would be more suitable", "wording. Have you seen the Baxtorian waterfall?", "Named after the elf king who was buried underneath.");
- stage = 4;
- break;
- case 4:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Thanks then, goodbye.");
- stage = 5;
- break;
- case 5:
- interpreter.sendDialogues(302, FacialExpression.HALF_GUILTY, "Enjoy your visit.");
- stage = 100;
- break;
- }
- return true;
- }
-
- @Override
- public DialoguePlugin newInstance(Player player) {
- return new HadleyDialogue(player);
- }
-
- @Override
- public boolean open(Object... args) {
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello there.");
- stage = 0;
- return true;
- }
-}
\ No newline at end of file
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/HadleyDialogue.kt b/Server/src/main/content/region/kandarin/quest/waterfall/HadleyDialogue.kt
new file mode 100644
index 000000000..90f5eeba9
--- /dev/null
+++ b/Server/src/main/content/region/kandarin/quest/waterfall/HadleyDialogue.kt
@@ -0,0 +1,96 @@
+package content.region.kandarin.quest.waterfall
+
+import core.ServerConstants
+import core.api.*
+import core.game.dialogue.ChatAnim
+import core.game.dialogue.DialogueLabeller
+import core.game.dialogue.DialogueOption
+import core.game.interaction.IntType
+import core.game.interaction.InteractionListener
+import core.game.node.entity.npc.NPC
+import org.rs09.consts.Items
+import org.rs09.consts.NPCs
+
+class HadleyDialogue : InteractionListener {
+ override fun defineListeners() {
+ on(NPCs.HADLEY_302, IntType.NPC, "talk-to") { player, node ->
+ DialogueLabeller.open(player, HadleyDialogueFile(), node as NPC)
+ return@on true
+ }
+ }
+}
+
+class HadleyDialogueFile : DialogueLabeller() {
+ override fun addConversation() {
+ val gender = if (player!!.isMale) "Sir" else "Lady"
+
+ player(ChatAnim.NEUTRAL, "Hello there.")
+ exec { player, _ ->
+ if (inInventory(player, Items.BOOK_ON_BAXTORIAN_292)) {
+ loadLabel(player, "book")
+ } else {
+ loadLabel(player, "no_book")
+ }
+ }
+
+ label("book")
+ npc(ChatAnim.HALF_GUILTY, "I hope you're enjoying your stay, there should be lots", "of useful information in that book: places to go, people to", "see.")
+
+ label("no_book")
+ npc(ChatAnim.NEUTRAL_FAST, "Are you on holiday? If so you've come to the right", "place. I'm Hadley the tourist guide, anything you need",
+ "to know just ask me " /*sic*/+ "we have some of the most unspoilt", "wildlife and scenery in ${ServerConstants.SERVER_NAME}.")
+ npc(ChatAnim.NEUTRAL, "People come from miles around to fish in the clear lakes", "or to wander the beautiful hillsides")
+ player(ChatAnim.NEUTRAL, "It is quite pretty.")
+ npc(ChatAnim.NEUTRAL_FAST, "Surely pretty is an understatement kind $gender.", "Beautiful, amazing or possibly life-changing would be",
+ "more suitable wording. Have you seen the Baxtorian", "waterfall? Named after the elf king who was buried")
+ npc(ChatAnim.NEUTRAL, "beneath.")
+ options(
+ DialogueOption("elf_king", "Can you tell me what happened to the elf king?", expression = ChatAnim.NEUTRAL),
+ DialogueOption("visiting", "Where else is worth visiting around here?", expression = ChatAnim.NEUTRAL),
+ DialogueOption("treasure", "Is there treasure under the waterfall?", expression = ChatAnim.NEUTRAL),
+ DialogueOption("bye", "Thanks then, goodbye.", expression = ChatAnim.NEUTRAL),
+ )
+
+ label("elf_king")
+ npc(ChatAnim.NEUTRAL_FAST, "There are many myths about Baxtorian. One popular", "story is that after defending his kingdom against the",
+ "invading dark forces from the west, Baxtorian returned", "to find his wife Glarial had been captured by the")
+ npc(ChatAnim.NEUTRAL, "enemy!")
+ npc(ChatAnim.NEUTRAL_FAST, "This destroyed Baxtorian, after years of searching he", "became a recluse. In the secret home he had made for",
+ "Glarial under the waterfall, he never came out and it is", "told that only Glarial could enter.")
+ player(ChatAnim.NEUTRAL, "What happened to him?")
+ npc(ChatAnim.NEUTRAL, "Oh, I don't know. I believe we have some pages on him", "upstairs in our archives. If you wish to look at them",
+ "please be careful, they're all pretty delicate.")
+ options(
+ DialogueOption("visiting", "Where else is worth visiting around here?", expression = ChatAnim.NEUTRAL),
+ DialogueOption("treasure", "Is there treasure under the waterfall?", expression = ChatAnim.NEUTRAL),
+ DialogueOption("bye", "Thanks then, goodbye.", expression = ChatAnim.NEUTRAL),
+ )
+
+ label("visiting")
+ npc(ChatAnim.NEUTRAL, "There is a lovely spot for a picnic on the hill to the", "north east, there lies a monument to the deceased elven",
+ "queen Glarial. It really is quite pretty.")
+ player(ChatAnim.NEUTRAL, "Who was queen Glarial?")
+ npc(ChatAnim.NEUTRAL, "Baxtorian's wife, the only person who could also enter", "the waterfall. She was queen when this land was",
+ "inhabited by elven kind. Glarial was kidnapped while")
+ npc(ChatAnim.NEUTRAL, "Baxtorian was away, but they eventually recovered her", "body and brought her home to rest.")
+ player(ChatAnim.SAD, "That's sad.")
+ npc(ChatAnim.NEUTRAL, "True, I believe there's some information about her", "upstairs, if you look at them please be careful.")
+ options(
+ DialogueOption("elf_king", "Can you tell me what happened to the elf king?", expression = ChatAnim.NEUTRAL),
+ DialogueOption("treasure", "Is there treasure under the waterfall?", expression = ChatAnim.NEUTRAL),
+ DialogueOption("bye", "Thanks then, goodbye.", expression = ChatAnim.NEUTRAL),
+ )
+
+ label("treasure")
+ npc(ChatAnim.NEUTRAL, "Ha ha... another treasure hunter. Well if there is " /*sic*/+ "no", "one's been able to get to it. They've been searching that",
+ "river for decades, all to no avail.")
+ options(
+ DialogueOption("elf_king", "Can you tell me what happened to the elf king?", expression = ChatAnim.NEUTRAL),
+ DialogueOption("visiting", "Where else is worth visiting around here?", expression = ChatAnim.NEUTRAL),
+ DialogueOption("bye", "Thanks then, goodbye.", expression = ChatAnim.NEUTRAL),
+ )
+
+ label("bye")
+ npc(ChatAnim.NEUTRAL, "Enjoy your visit.")
+ }
+}
\ No newline at end of file
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogue.java b/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogue.java
deleted file mode 100644
index e8c3262ad..000000000
--- a/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogue.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package content.region.kandarin.quest.waterfall;
-
-import content.data.Quests;
-import core.game.dialogue.DialogueInterpreter;
-import core.game.dialogue.DialoguePlugin;
-import core.game.dialogue.FacialExpression;
-import core.game.node.entity.player.Player;
-import core.game.node.entity.player.link.quest.Quest;
-
-/**
- * Handles Hudon's Dialogue for the Waterfall Quest.
- * @author Splinter
- */
-public class HudonDialogue extends DialoguePlugin {
-
- public HudonDialogue() {
-
- }
-
- public HudonDialogue(Player player) {
- super(player);
- }
-
- @Override
- public int[] getIds() {
- return new int[] { DialogueInterpreter.getDialogueKey("hudon_dialogue"), 305 };
- }
-
- @Override
- public boolean handle(int interfaceId, int buttonId) {
- final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST);
- switch (stage) {
-
- case 100: // Generic end to the dlg
- end();
- break;
- case 101: // Generic end to the dlg
- player.getPacketDispatch().sendMessage("Hudon is refusing to leave the waterfall.");
- end();
- break;
-
- /* Main dialogue sequence */
- case 0:
- if (quest.getStage(player) == 10) {
- interpreter.sendDialogues(305, FacialExpression.CHILD_NORMAL, "It looks like you need the help.");
- stage = 1;
- }
- break;
- case 1:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Your mum sent me to find you.");
- stage = 2;
- break;
- case 2:
- interpreter.sendDialogues(305, FacialExpression.CHILD_NORMAL, "Don't play nice with me, I know you're looking for the", "treasure too.");
- stage = 3;
- break;
- case 3:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Where is this treasure you talk of?");
- stage = 4;
- break;
- case 4:
- interpreter.sendDialogues(305, FacialExpression.CHILD_SUSPICIOUS, "Just because I'm small doesn't mean I'm dumb! If I", "told you, you would take it all for yourself.");
- stage = 5;
- break;
- case 5:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Maybe I could help.");
- stage = 6;
- break;
- case 6:
- interpreter.sendDialogues(305, FacialExpression.CHILD_NORMAL, "I'm fine alone.");
- quest.setStage(player, 20);
- stage = 101;
- break;
- case 20:
- interpreter.sendDialogues(305, FacialExpression.CHILD_NORMAL, "I'll find that treasure soon, just you wait and see.");
- if (quest.getStage(player) == 100) {
- stage = 21;
- } else {
- stage = 100;
- }
- break;
- case 21:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I hate to break it to you kid, but I found the treasure.");
- stage = 22;
- break;
- case 22:
- interpreter.sendDialogues(305, FacialExpression.CHILD_NORMAL, "Wha- are you serious? Are you going to at least share?");
- stage = 23;
- break;
- case 23:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "No.");
- stage = 24;
- break;
- case 24:
- interpreter.sendDialogues(305, FacialExpression.CHILD_NORMAL, "Aww, come on... I helped you find it.", "This isn't fair!");
- stage = 25;
- break;
- case 25:
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Life ain't fair kid.");
- stage = 100;
- break;
- }
- return true;
- }
-
- @Override
- public DialoguePlugin newInstance(Player player) {
- return new HudonDialogue(player);
- }
-
- @Override
- public boolean open(Object... args) {
- final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST);
- if (quest.getStage(player) >= 20) {
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "So you're still here.");
- stage = 20;
- } else {
- interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Hello son, are you okay? You need help?");
- stage = 0;
- }
- return true;
- }
-}
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogueFile.kt b/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogueFile.kt
new file mode 100644
index 000000000..cbfd042c8
--- /dev/null
+++ b/Server/src/main/content/region/kandarin/quest/waterfall/HudonDialogueFile.kt
@@ -0,0 +1,54 @@
+package content.region.kandarin.quest.waterfall
+
+import content.data.Quests
+import core.api.*
+import core.game.dialogue.ChatAnim
+import core.game.dialogue.DialogueLabeller
+
+class HudonDialogueFile : DialogueLabeller() {
+ override fun addConversation() {
+ exec { player, _ ->
+ when (getQuestStage(player, Quests.WATERFALL_QUEST)) {
+ 10 -> loadLabel(player, "quest_stage_10")
+ 20 -> loadLabel(player, "quest_stage_20")
+ 30 -> loadLabel(player, "quest_stage_30")
+ 100 -> loadLabel(player, "quest_complete")
+ }
+ }
+
+ label("quest_stage_10")
+ player(ChatAnim.NEUTRAL, "Hello son, are you okay? You need help?")
+ npc(ChatAnim.CHILD_NORMAL, "It looks like you need the help.")
+ player(ChatAnim.NEUTRAL, "Your mum sent me to find you.")
+ npc(ChatAnim.CHILD_NORMAL, "Don't play nice with me, I know you're looking for the", "treasure too.")
+ player(ChatAnim.NEUTRAL, "Where is this treasure you talk of?")
+ npc(ChatAnim.CHILD_NORMAL, "Just because I'm small doesn't mean I'm dumb! If I", "told you, you would take it all for yourself.")
+ player(ChatAnim.NEUTRAL, "Maybe I could help.")
+ exec { player, _ ->
+ setQuestStage(player, Quests.WATERFALL_QUEST, 20)
+ sendMessage(player, "Hudon is refusing to leave the waterfall") /*sic*/
+ }
+ npc(ChatAnim.CHILD_NORMAL, "I'm fine alone.")
+
+ label("quest_stage_20")
+ player(ChatAnim.NEUTRAL, "So you're still here.")
+ npc(ChatAnim.CHILD_NORMAL, "I'll find that treasure soon, just you wait and see.")
+
+ label("quest_stage_30")
+ player(ChatAnim.NEUTRAL, "Hello again.")
+ npc(ChatAnim.CHILD_NORMAL, "Not you still, why don't you give up?")
+ player(ChatAnim.NEUTRAL, "And miss all the fun!")
+ npc(ChatAnim.CHILD_NORMAL, "You do understand that anything you find you have to share with me.")
+ player(ChatAnim.NEUTRAL, "Why's that?")
+ npc(ChatAnim.CHILD_NORMAL, "Because I told you about the treasure.")
+ player(ChatAnim.NEUTRAL, "Well, I wouldn't count on it.")
+ npc(ChatAnim.CHILD_NORMAL, "That's not fair.")
+ player(ChatAnim.NEUTRAL, "Neither is life, kid.")
+
+ label("quest_complete")
+ player(ChatAnim.NEUTRAL, "Hello again.")
+ npc(ChatAnim.CHILD_NORMAL, "You stole my treasure. I saw you!")
+ player(ChatAnim.NEUTRAL, "I'll make sure it goes to a good cause.")
+ npc(ChatAnim.CHILD_NORMAL, "Hmmmm!")
+ }
+}
\ No newline at end of file
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/MithrilSeedsDialogue.java b/Server/src/main/content/region/kandarin/quest/waterfall/MithrilSeedsDialogue.java
deleted file mode 100644
index 4a6c28e70..000000000
--- a/Server/src/main/content/region/kandarin/quest/waterfall/MithrilSeedsDialogue.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package content.region.kandarin.quest.waterfall;
-
-import core.game.dialogue.DialoguePlugin;
-import core.game.node.entity.player.Player;
-import core.game.node.item.Item;
-import core.game.node.scenery.Scenery;
-import core.game.node.scenery.SceneryBuilder;
-import core.game.system.task.Pulse;
-import core.game.world.GameWorld;
-import core.game.world.update.flag.context.Animation;
-import core.plugin.Initializable;
-
-/**
- * Represents the dialogue plugin used for mithril seeds.
- * @author 'Vexia
- * @version 1.0
- */
-@Initializable
-public final class MithrilSeedsDialogue extends DialoguePlugin {
-
- /**
- * Represents the animation to use.
- */
- private static final Animation ANIMATION = new Animation(827);
-
- /**
- * Represents the flower object.
- */
- private Scenery flower;
-
- /**
- * Constructs a new {@code MithrilSeedPluginDialogue}.
- */
- public MithrilSeedsDialogue() {
- /**
- * empty.
- */
- }
-
- /**
- * Constructs a new {@code MithrilSeedPluginDialogue}.
- */
- public MithrilSeedsDialogue(Player player) {
- super(player);
- }
-
- @Override
- public DialoguePlugin newInstance(Player player) {
- return new MithrilSeedsDialogue(player);
- }
-
- @Override
- public boolean open(Object... args) {
- flower = (Scenery) args[0];
- player.getDialogueInterpreter().sendOptions("Select an Option", "Pick the flowers.", "Leave the flowers.");
- return true;
- }
-
- @Override
- public boolean handle(int interfaceId, int buttonId) {
- switch (interfaceId) {
- case 228: // Options chatbox interface id.
- switch (buttonId) {
- case 1: // First option
- player.lock(2);
- player.faceLocation(flower.getFaceLocation(player.getLocation()));
- player.animate(ANIMATION);
- GameWorld.getPulser().submit(new Pulse(2, player, flower) {
- @Override
- public boolean pulse() {
- Item reward = new Item(2460 + ((flower.getId() - 2980) << 1));
- if (reward == null || !player.getInventory().hasSpaceFor(reward)) {
- player.getPacketDispatch().sendMessage("Not enough space in your inventory!");
- return true;
- }
- if (SceneryBuilder.remove(flower)) {
- player.getInventory().add(reward);
- player.getPacketDispatch().sendMessage("You pick the flowers.");
- }
- return true;
- }
- });
- break;
- }
- break;
- }
- end();
- return true;
- }
-
- @Override
- public int[] getIds() {
- return new int[] { 1 << 16 | 1 };
- }
-
-}
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/MithrilSeedsListener.kt b/Server/src/main/content/region/kandarin/quest/waterfall/MithrilSeedsListener.kt
new file mode 100644
index 000000000..b0b194769
--- /dev/null
+++ b/Server/src/main/content/region/kandarin/quest/waterfall/MithrilSeedsListener.kt
@@ -0,0 +1,107 @@
+package content.region.kandarin.quest.waterfall
+
+import core.api.*
+import core.game.dialogue.DialogueFile
+import core.game.interaction.IntType
+import core.game.interaction.InteractionListener
+import core.game.interaction.QueueStrength
+import core.game.node.scenery.Scenery
+import core.game.world.GameWorld.ticks
+import core.game.world.map.RegionManager.getObject
+import core.game.world.update.flag.context.Animation
+import core.tools.RandomFunction
+import org.rs09.consts.Animations
+import org.rs09.consts.Items
+import org.rs09.consts.Scenery as SceneryObj
+
+/**
+ * Handles planting flowers with mithril seeds.
+ * @author Bishop
+ */
+
+class MithrilSeedsListener : InteractionListener {
+
+ companion object {
+ private val attributeDelay = "mithril-flowers:delay"
+ private val flowersToItems = mapOf(
+ SceneryObj.FLOWERS_2980 to Items.FLOWERS_2460, // multicolored pastels
+ SceneryObj.FLOWERS_2981 to Items.FLOWERS_2462, // red
+ SceneryObj.FLOWERS_2982 to Items.FLOWERS_2464, // blue
+ SceneryObj.FLOWERS_2983 to Items.FLOWERS_2466, // yellow
+ SceneryObj.FLOWERS_2984 to Items.FLOWERS_2468, // magenta
+ SceneryObj.FLOWERS_2985 to Items.FLOWERS_2470, // orange
+ SceneryObj.FLOWERS_2986 to Items.FLOWERS_2472, // multicolored primaries
+ SceneryObj.FLOWERS_2987 to Items.FLOWERS_2474, // white
+ SceneryObj.FLOWERS_2988 to Items.FLOWERS_2476, // black
+ )
+ }
+
+ override fun defineListeners() {
+ on(Items.MITHRIL_SEEDS_299, IntType.ITEM, "plant") { player, _ ->
+ closeAllInterfaces(player)
+ val flowerLoc = player.location
+ if (getAttribute(player, attributeDelay, -1) > ticks) {
+ return@on false
+ }
+ if (getObject(flowerLoc) != null) {
+ sendMessage(player, "You can't plant a flower here.")
+ return@on true
+ }
+ if (removeItem(player, Items.MITHRIL_SEEDS_299)) {
+ // Source: Mod Ash https://reldo.runescape.wiki/i/106311
+ val flowerObj = when (RandomFunction.random(1001)) {
+ in 0..897 -> RandomFunction.random(SceneryObj.FLOWERS_2981, SceneryObj.FLOWERS_2986 + 1) // normal flowers
+ in 898..997 -> SceneryObj.FLOWERS_2980 // multicolored pastels, 100/1001
+ in 998..999 -> SceneryObj.FLOWERS_2988 // black flowers, 2/1001
+ else -> SceneryObj.FLOWERS_2987 // white flowers, 1/1001
+ }
+ val thisFlower = addScenery(flowerObj, flowerLoc, 0, 10)
+ sendMessage(player, "You open the small mithril case and drop a seed by your feet.")
+ setAttribute(player, attributeDelay, ticks + 3)
+ animate(player, Animations.HUMAN_BURYING_BONES_827)
+ stopWalk(player)
+ player.moveStep()
+ lock(player, 1)
+ queueScript(player, 1, QueueStrength.SOFT) {
+ face(player, flowerLoc)
+ openDialogue(player, MithrilSeedsDialogue(thisFlower, flowersToItems[thisFlower.id]!!))
+ return@queueScript stopExecuting(player)
+ }
+ queueScript(player, 100, QueueStrength.SOFT) {
+ removeScenery(thisFlower)
+ return@queueScript stopExecuting(player)
+ }
+ }
+ return@on true
+ }
+ }
+
+}
+
+private class MithrilSeedsDialogue(val flower: Scenery, val flowerItem: Int) : DialogueFile() {
+
+ override fun handle(componentID: Int, buttonID: Int) {
+ when (stage) {
+ 0 -> sendDialogueOptions(player!!, "Select an Option", "Pick the flowers.", "Leave the flowers.").also { stage++ }
+ 1 -> {
+ when (buttonID) {
+ 1 -> {
+ animate(player!!, Animations.HUMAN_BURYING_BONES_827)
+ lock(player!!, 2)
+ queueScript(player!!, 2, QueueStrength.SOFT) {
+ if (getScenery(flower.location) == flower) {
+ sendMessage(player!!, "You pick the flowers.")
+ removeScenery(flower)
+ addItemOrDrop(player!!, flowerItem)
+ }
+ return@queueScript stopExecuting(player!!)
+ }
+ end()
+ }
+ else -> end()
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/MithrilSeedsPlugin.java b/Server/src/main/content/region/kandarin/quest/waterfall/MithrilSeedsPlugin.java
deleted file mode 100644
index b085e42e2..000000000
--- a/Server/src/main/content/region/kandarin/quest/waterfall/MithrilSeedsPlugin.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package content.region.kandarin.quest.waterfall;
-
-import core.cache.def.impl.ItemDefinition;
-import core.game.interaction.OptionHandler;
-import core.game.node.Node;
-import core.game.node.entity.player.Player;
-import core.game.node.item.Item;
-import core.game.node.scenery.Scenery;
-import core.game.node.scenery.SceneryBuilder;
-import core.game.system.task.Pulse;
-import core.game.world.GameWorld;
-import core.game.world.map.RegionManager;
-import core.game.world.update.flag.context.Animation;
-import core.plugin.Initializable;
-import core.plugin.Plugin;
-import core.tools.RandomFunction;
-
-/**
- * Represents the plugin used for mithril seeds.
- * @author 'Vexia
- * @version 1.2
- */
-@Initializable
-public final class MithrilSeedsPlugin extends OptionHandler {
-
- /**
- * Represents the item to use.
- */
- private static final Item ITEM = new Item(299, 1);
-
- /**
- * Represents the common flower ids.
- */
- private static final int FLOWERS[] = { 2980, 2981, 2982, 2983, 2984, 2985, 2986 };
-
- /**
- * Represents the rare flower ids.
- */
- private static final int RARE[] = new int[] { 2987, 2988 };
-
- /**
- * Represents the animation.
- */
- private static final Animation ANIMATION = new Animation(827);
-
- @Override
- public Plugin