Implemented Rag and Bone Man quest (part 1)

This commit is contained in:
Oven Bread
2023-11-11 05:09:54 +00:00
committed by Ryan
parent 6d0ca0d6fc
commit 2dce4fe98c
23 changed files with 1275 additions and 351 deletions
@@ -14,7 +14,7 @@ public class ShopNPC extends AbstractNPC {
/**
* The NPC ids of NPCs using this plugin.
*/
private static final int[] ID = { 410, 528, 529, 525, 524, 1436, 590, 591, 971, 1917, 597, 1083, 3541, 7396, 1040, 563, 5798, 582, 526, 527, 873, 532, 533, 568, 2154, 1334, 2352, 4516, 520, 521, 4716, 3922, 1254, 2086, 1866, 530, 531, 836, 516, 560, 471, 522, 523, 4651, 4652, 4653, 4654, 4655, 4656, 4650, 534, 588, 2356, 1860, 550, 575, 683, 682, 4563, 4558, 4559, 519, 559, 562, 581, 554, 601, 1301, 1039, 2353, 3166, 2161, 2162, 600, 593, 545, 585, 5268, 2305, 2307, 2304, 1783, 557, 1038, 1433, 7053, 571, 5487, 536, 4294, 4293, 584, 570, 540, 2157, 69669, 569, 572, 573, 1303, 595, 297, 704, 587, 5110, 5109, 556, 1865, 543, 2198, 580, 1862, 583, 553, 461, 4513, 3097, 903, 1435, 606, 2623, 594, 579, 2160, 6750, 6898, 6893, 589, 5485, 542, 549, 3038, 544, 1434, 209, 1980, 546, 6988, 3671, 558, 576, 5266, 586, 602, 552, 551, 541, 692, 797, 564, 2152, 1208, 2233, 3205, 70, 1598, 1596, 1597, 1599, 2259, 3162, 1167, 2620, 2151, 5486, 4250, 1079, 970, 793, 2572 };
private static final int[] ID = { 410, 528, 529, 525, 524, 1436, 590, 591, 971, 1917, 597, 1083, 3541, 7396, 1040, 563, 5798, 582, 526, 527, 873, 532, 533, 568, 2154, 1334, 2352, 4516, 520, 521, 4716, 3922, 1254, 2086, 1866, 530, 531, 836, 516, 560, 471, 522, 523, 4651, 4652, 4653, 4654, 4655, 4656, 4650, 534, 588, 2356, 1860, 550, 575, 683, 682, 4563, 4558, 4559, 519, 559, 562, 581, 554, 601, 1301, 1039, 2353, 3166, 2161, 2162, 600, 593, 545, 585, 5268, 2305, 2307, 2304, 1783, 557, 1038, 1433, 7053, 571, 5487, 536, 4294, 4293, 584, 570, 540, 2157, 69669, 569, 572, 573, 1303, 595, 297, 704, 587, 5110, 5109, 556, 1865, 543, 2198, 580, 1862, 583, 553, 461, 4513, 3097, 903, 1435, 606, 2623, 594, 579, 2160, 6750, 6898, 6893, 589, 5485, 542, 549, 3038, 544, 1434, 209, 1980, 546, 6988, 558, 576, 5266, 586, 602, 552, 551, 541, 692, 797, 564, 2152, 1208, 2233, 3205, 70, 1598, 1596, 1597, 1599, 2259, 3162, 1167, 2620, 2151, 5486, 4250, 1079, 793, 2572 };
/**
* Constructs a new {@code ShopNPC} {@code Object}.
@@ -1,115 +0,0 @@
package content.region.misthalin.draynor.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.plugin.Initializable;
import core.game.node.entity.player.Player;
/**
* Represents the dialogue plugin used for fortunato.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class FortunatoDialogue extends DialoguePlugin {
/**
* Constructs a new {@code FortunatoDialogue} {@code Object}.
*/
public FortunatoDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code FortunatoDialogue} {@code Object}.
* @param player the player.
*/
public FortunatoDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new FortunatoDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(npc, FacialExpression.ASKING, "Can I help you at all?");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
interpreter.sendOptions("Select an Option", "Yes, what are you selling?", "Not at the moment.");
stage = 1;
break;
case 1:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HAPPY, "Yes, what are you selling?");
stage = 10;
break;
case 2:
interpreter.sendDialogues(npc, FacialExpression.ANGRY, "Then move along, you filthy ragamuffin, I have customers", "to server!");
stage = 24;
break;
}
break;
case 10:
end();
npc.openShop(player);
break;
case 20:
interpreter.sendDialogues(npc, FacialExpression.HAPPY, "Yes, indeed. The finest wine in Misthalin.");
stage = 21;
break;
case 21:
interpreter.sendDialogues(npc, FacialExpression.ASKING, "Care to take a look at my wares?");
stage = 269;
break;
case 269:
interpreter.sendOptions("Select an Option", "Yes.", "Not at the moment.");
stage = 22;
break;
case 22:
switch (buttonId) {
case 1:
end();
stage = 10;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.NEUTRAL, "Not at the moment.");
stage = 23;
break;
}
break;
case 23:
interpreter.sendDialogues(npc, FacialExpression.ANGRY, "Then move along, you filthy ragamuffin, I have customers", "to server!");
stage = 24;
break;
case 24:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 3671 };
}
}
@@ -0,0 +1,41 @@
package content.region.misthalin.draynor.dialogue
// import content.region.misthalin.silvarea.quest.ragandboneman.FortunatoDialogueFile
import core.api.*
import core.game.dialogue.DialoguePlugin
import core.game.dialogue.FacialExpression
import core.game.dialogue.Topic
import core.game.node.entity.player.Player
import core.plugin.Initializable
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
import org.rs09.consts.NPCs
@Initializable
class FortunatoDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
// openDialogue(player!!, FortunatoDialogueFile(), npc)
when (stage) {
START_DIALOGUE -> npcl(FacialExpression.ASKING, "Can I help you at all?").also { stage++ }
1 -> showTopics(
Topic(FacialExpression.FRIENDLY, "Yes, what are you selling?", 2),
Topic(FacialExpression.FRIENDLY, "Not at the moment", 3),
)
2 -> openNpcShop(player, NPCs.FORTUNATO_3671).also {
end()
}
3 -> npcl(FacialExpression.ANGRY, "Then move along, you filthy ragamuffin, I have customers to serve!").also {
stage = END_DIALOGUE
}
}
return true
}
override fun newInstance(player: Player?): DialoguePlugin {
return FortunatoDialogue(player)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.FORTUNATO_3671)
}
}
@@ -0,0 +1,25 @@
package content.region.misthalin.silvarea.dialogue
import content.region.misthalin.silvarea.quest.ragandboneman.OddOldManDialogueFile
import core.api.openDialogue
import core.game.dialogue.DialoguePlugin
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
@Initializable
class OddOldManDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
// Fallback to default. Always the start of Rag and Bone Man
openDialogue(player!!, OddOldManDialogueFile(), npc)
return true
}
override fun newInstance(player: Player?): DialoguePlugin {
return OddOldManDialogue(player)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.ODD_OLD_MAN_3670)
}
}
@@ -0,0 +1,36 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import core.api.*
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.npc.drop.DropFrequency
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class BearBehavior : NPCBehavior(*bearIds) {
companion object {
private val bearIds = intArrayOf(
NPCs.GRIZZLY_BEAR_105,
NPCs.BLACK_BEAR_106,
NPCs.GRIZZLY_BEAR_1195,
NPCs.GRIZZLY_BEAR_CUB_1196,
NPCs.GRIZZLY_BEAR_CUB_1197,
NPCs.BEAR_CUB_1326,
NPCs.BEAR_CUB_1327,
)
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
// Drops the Bear Ribs during Rag and Bone Man quest
if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) {
if(RandomFunction.roll(4)) {
drops.add(Item(Items.BEAR_RIBS_7815));
}
}
}
}
@@ -0,0 +1,30 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import core.api.isQuestInProgress
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.npc.drop.DropFrequency
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class BigFrogBehavior : NPCBehavior(*bigFrogIds) {
companion object {
private val bigFrogIds = intArrayOf(
NPCs.BIG_FROG_1829,
)
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
// Drops the Big Frog Leg during Rag and Bone Man quest
if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) {
if(RandomFunction.roll(4)) {
drops.add(Item(Items.BIG_FROG_LEG_7908));
}
}
}
}
@@ -0,0 +1,65 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import org.rs09.consts.Items
enum class BoneBoilerEnum(val bone: Int, val boneInVinegar: Int, val polishedBone: Int, val boneDescription: String) {
GOBLIN_SKULL(Items.GOBLIN_SKULL_7812, Items.BONE_IN_VINEGAR_7813, Items.GOBLIN_SKULL_7814, "goblin bone"),
BEAR_RIBS(Items.BEAR_RIBS_7815, Items.BONE_IN_VINEGAR_7816, Items.BEAR_RIBS_7817, "bear bone"),
RAM_SKULL(Items.RAM_SKULL_7818, Items.BONE_IN_VINEGAR_7819, Items.RAM_SKULL_7820, "ram bone"),
UNICORN_BONE(Items.UNICORN_BONE_7821, Items.BONE_IN_VINEGAR_7822, Items.UNICORN_BONE_7823, "unicorn bone"),
GIANT_RAT_BONE(Items.GIANT_RAT_BONE_7824, Items.BONE_IN_VINEGAR_7825, Items.GIANT_RAT_BONE_7826, "giant rat bone"),
GIANT_BAT_WING(Items.GIANT_BAT_WING_7827, Items.BONE_IN_VINEGAR_7828, Items.GIANT_BAT_WING_7829, "giant bat bone"),
WOLF_BONE(Items.WOLF_BONE_7830, Items.BONE_IN_VINEGAR_7831, Items.WOLF_BONE_7832, "wolf bone"),
BAT_WING(Items.BAT_WING_7833, Items.BONE_IN_VINEGAR_7834, Items.BAT_WING_7835, "bat bone"),
RAT_BONE(Items.RAT_BONE_7836, Items.BONE_IN_VINEGAR_7837, Items.RAT_BONE_7838, "rat bone"),
BABY_DRAGON_BONE(Items.BABY_DRAGON_BONE_7839, Items.BONE_IN_VINEGAR_7840, Items.BABY_DRAGON_BONE_7841, "baby blue dragon bone"),
OGRE_RIBS(Items.OGRE_RIBS_7842, Items.BONE_IN_VINEGAR_7843, Items.OGRE_RIBS_7844, "ogre bone"),
JOGRE_BONE(Items.JOGRE_BONE_7845, Items.BONE_IN_VINEGAR_7846, Items.JOGRE_BONE_7847, "jogre bone"),
ZOGRE_BONE(Items.ZOGRE_BONE_7848, Items.BONE_IN_VINEGAR_7849, Items.ZOGRE_BONE_7850, "zogre bone"),
MOGRE_BONE(Items.MOGRE_BONE_7851, Items.BONE_IN_VINEGAR_7852, Items.MOGRE_BONE_7853, "mogre bone"),
MONKEY_PAW(Items.MONKEY_PAW_7854, Items.BONE_IN_VINEGAR_7855, Items.MONKEY_PAW_7856, "monkey bone"),
DAGANNOTH_RIBS(Items.DAGANNOTH_RIBS_7857, Items.BONE_IN_VINEGAR_7858, Items.DAGANNOTH_RIBS_7859, "Dagannoth bone"),
SNAKE_SPINE(Items.SNAKE_SPINE_7860, Items.BONE_IN_VINEGAR_7861, Items.SNAKE_SPINE_7862, "snake bone"),
ZOMBIE_BONE(Items.ZOMBIE_BONE_7863, Items.BONE_IN_VINEGAR_7864, Items.ZOMBIE_BONE_7865, "zombie bone"),
WEREWOLF_BONE(Items.WEREWOLF_BONE_7866, Items.BONE_IN_VINEGAR_7867, Items.WEREWOLF_BONE_7868, "werewolf bone"),
MOSS_GIANT_BONE(Items.MOSS_GIANT_BONE_7869, Items.BONE_IN_VINEGAR_7870, Items.MOSS_GIANT_BONE_7871, "moss giant bone"),
FIRE_GIANT_BONE(Items.FIRE_GIANT_BONE_7872, Items.BONE_IN_VINEGAR_7873, Items.FIRE_GIANT_BONE_7874, "fire giant bone"),
ICE_GIANT_RIBS(Items.ICE_GIANT_RIBS_7875, Items.BONE_IN_VINEGAR_7876, Items.ICE_GIANT_RIBS_7877, "ice giant bone"),
TERRORBIRD_WING(Items.TERRORBIRD_WING_7878, Items.BONE_IN_VINEGAR_7879, Items.TERRORBIRD_WING_7880, "terrorbird bone"),
GHOUL_BONE(Items.GHOUL_BONE_7881, Items.BONE_IN_VINEGAR_7882, Items.GHOUL_BONE_7883, "ghoul bone"),
TROLL_BONE(Items.TROLL_BONE_7884, Items.BONE_IN_VINEGAR_7885, Items.TROLL_BONE_7886, "troll bone"),
SEAGULL_WING(Items.SEAGULL_WING_7887, Items.BONE_IN_VINEGAR_7888, Items.SEAGULL_WING_7889, "seagull bone"),
UNDEAD_COW_RIBS(Items.UNDEAD_COW_RIBS_7890, Items.BONE_IN_VINEGAR_7891, Items.UNDEAD_COW_RIBS_7892, "undead cow bone"),
EXPERIMENT_BONE(Items.EXPERIMENT_BONE_7893, Items.BONE_IN_VINEGAR_7894, Items.EXPERIMENT_BONE_7895, "experiment bone"),
RABBIT_BONE(Items.RABBIT_BONE_7896, Items.BONE_IN_VINEGAR_7897, Items.RABBIT_BONE_7898, "rabbit bone"),
BASILISK_BONE(Items.BASILISK_BONE_7899, Items.BONE_IN_VINEGAR_7900, Items.BASILISK_BONE_7901, "basilisk bone"),
DESERT_LIZARD_BONE(Items.DESERT_LIZARD_BONE_7902, Items.BONE_IN_VINEGAR_7903, Items.DESERT_LIZARD_BONE_7904, "desert lizard bone"),
CAVE_GOBLIN_SKULL(Items.CAVE_GOBLIN_SKULL_7905, Items.BONE_IN_VINEGAR_7906, Items.CAVE_GOBLIN_SKULL_7907, "cave goblin bone"),
BIG_FROG_LEG(Items.BIG_FROG_LEG_7908, Items.BONE_IN_VINEGAR_7909, Items.BIG_FROG_LEG_7910, "big frog bone"),
VULTURE_WING(Items.VULTURE_WING_7911, Items.BONE_IN_VINEGAR_7912, Items.VULTURE_WING_7913, "vulture bone"),
JACKAL_BONE(Items.JACKAL_BONE_7914, Items.BONE_IN_VINEGAR_7915, Items.JACKAL_BONE_7916, "jackal bone");
companion object {
@JvmField
val boneList = BoneBoilerEnum.values().map { it.bone }.toIntArray()
@JvmField
val boneInVinegarList = BoneBoilerEnum.values().map { it.boneInVinegar }.toIntArray()
@JvmField
val boneMap = values().associateBy { it.bone }
@JvmField
val boneInVinegarMap = values().associateBy { it.boneInVinegar }
@JvmStatic
fun forBone(id: Int): BoneBoilerEnum? {
return boneMap[id]
}
@JvmStatic
fun forBoneInVinegar(id: Int): BoneBoilerEnum? {
return boneInVinegarMap[id]
}
}
}
@@ -0,0 +1,39 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import core.api.isQuestInProgress
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.npc.drop.DropFrequency
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class GiantBatBehavior : NPCBehavior(*giantBatIds) {
companion object {
private val giantBatIds = intArrayOf(
NPCs.GIANT_BAT_78,
NPCs.GIANT_BAT_1005,
NPCs.GIANT_BAT_2482,
NPCs.GIANT_BAT_2483,
NPCs.GIANT_BAT_2484,
NPCs.GIANT_BAT_2485,
NPCs.GIANT_BAT_2486,
NPCs.GIANT_BAT_2487,
NPCs.GIANT_BAT_2488,
NPCs.GIANT_BAT_3711,
)
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
// Drops the Giant Bat Wing during Rag and Bone Man quest
if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) {
if(RandomFunction.roll(4)) {
drops.add(Item(Items.GIANT_BAT_WING_7827));
}
}
}
}
@@ -0,0 +1,44 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import core.api.isQuestInProgress
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.npc.drop.DropFrequency
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class GiantRatBehavior : NPCBehavior(*giantRatIds) {
companion object {
private val giantRatIds = intArrayOf(
NPCs.GIANT_RAT_4395,
NPCs.GIANT_RAT_446,
NPCs.GIANT_RAT_4922,
NPCs.GIANT_RAT_4923,
NPCs.GIANT_RAT_4924,
NPCs.GIANT_RAT_4925,
NPCs.GIANT_RAT_4926,
NPCs.GIANT_RAT_4927,
NPCs.GIANT_RAT_4942,
NPCs.GIANT_RAT_4943,
NPCs.GIANT_RAT_4944,
NPCs.GIANT_RAT_4945,
NPCs.GIANT_RAT_86,
NPCs.GIANT_RAT_87,
NPCs.GIANT_RAT_950,
)
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
// Drops the Giant Rat Bone during Rag and Bone Man quest
if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) {
if(RandomFunction.roll(4)) {
drops.add(Item(Items.GIANT_RAT_BONE_7824));
}
}
}
}
@@ -0,0 +1,188 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import content.global.handlers.npc.ChromaticDragonBehavior
import core.api.isQuestInProgress
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.npc.drop.DropFrequency
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class GoblinBehavior : NPCBehavior(*goblinIds) {
companion object {
private val goblinIds = intArrayOf(
NPCs.GOBLIN_100,
NPCs.GOBLIN_101,
NPCs.GOBLIN_102,
NPCs.GOBLIN_1769,
NPCs.GOBLIN_1770,
NPCs.GOBLIN_1771,
NPCs.GOBLIN_1772,
NPCs.GOBLIN_1773,
NPCs.GOBLIN_1774,
NPCs.GOBLIN_1775,
NPCs.GOBLIN_1776,
NPCs.GOBLIN_2274,
NPCs.GOBLIN_2275,
NPCs.GOBLIN_2276,
NPCs.GOBLIN_2277,
NPCs.GOBLIN_2278,
NPCs.GOBLIN_2279,
NPCs.GOBLIN_2280,
NPCs.GOBLIN_2281,
NPCs.GOBLIN_2678,
NPCs.GOBLIN_2679,
NPCs.GOBLIN_2680,
NPCs.GOBLIN_2681,
NPCs.GOBLIN_3264,
NPCs.GOBLIN_3265,
NPCs.GOBLIN_3266,
NPCs.GOBLIN_3267,
NPCs.GOBLIN_3726,
NPCs.GOBLIN_4261,
NPCs.GOBLIN_4262,
NPCs.GOBLIN_4263,
NPCs.GOBLIN_4264,
NPCs.GOBLIN_4265,
NPCs.GOBLIN_4266,
NPCs.GOBLIN_4267,
NPCs.GOBLIN_4268,
NPCs.GOBLIN_4269,
NPCs.GOBLIN_4270,
NPCs.GOBLIN_4271,
NPCs.GOBLIN_4272,
NPCs.GOBLIN_4273,
NPCs.GOBLIN_4274,
NPCs.GOBLIN_4275,
NPCs.GOBLIN_4276,
NPCs.GOBLIN_4407,
NPCs.GOBLIN_4408,
NPCs.GOBLIN_4409,
NPCs.GOBLIN_4410,
NPCs.GOBLIN_4411,
NPCs.GOBLIN_4412,
NPCs.GOBLIN_444,
NPCs.GOBLIN_445,
NPCs.GOBLIN_4479,
NPCs.GOBLIN_4480,
NPCs.GOBLIN_4481,
NPCs.GOBLIN_4482,
NPCs.GOBLIN_4483,
NPCs.GOBLIN_4484,
NPCs.GOBLIN_4485,
NPCs.GOBLIN_4486,
NPCs.GOBLIN_4487,
NPCs.GOBLIN_4488,
NPCs.GOBLIN_4489,
NPCs.GOBLIN_4490,
NPCs.GOBLIN_4491,
NPCs.GOBLIN_4492,
NPCs.GOBLIN_4499,
NPCs.GOBLIN_4633,
NPCs.GOBLIN_4634,
NPCs.GOBLIN_4635,
NPCs.GOBLIN_4636,
NPCs.GOBLIN_4637,
NPCs.GOBLIN_5855,
NPCs.GOBLIN_5856,
NPCs.GOBLIN_6125,
NPCs.GOBLIN_6126,
NPCs.GOBLIN_6132,
NPCs.GOBLIN_6133,
NPCs.GOBLIN_6279,
NPCs.GOBLIN_6280,
NPCs.GOBLIN_6281,
NPCs.GOBLIN_6282,
NPCs.GOBLIN_6283,
NPCs.GOBLIN_6284,
NPCs.GOBLIN_6402,
NPCs.GOBLIN_6403,
NPCs.GOBLIN_6404,
NPCs.GOBLIN_6405,
NPCs.GOBLIN_6406,
NPCs.GOBLIN_6407,
NPCs.GOBLIN_6408,
NPCs.GOBLIN_6409,
NPCs.GOBLIN_6410,
NPCs.GOBLIN_6411,
NPCs.GOBLIN_6412,
NPCs.GOBLIN_6413,
NPCs.GOBLIN_6414,
NPCs.GOBLIN_6415,
NPCs.GOBLIN_6416,
NPCs.GOBLIN_6417,
NPCs.GOBLIN_6418,
NPCs.GOBLIN_6419,
NPCs.GOBLIN_6420,
NPCs.GOBLIN_6421,
NPCs.GOBLIN_6422,
NPCs.GOBLIN_6423,
NPCs.GOBLIN_6424,
NPCs.GOBLIN_6425,
NPCs.GOBLIN_6426,
NPCs.GOBLIN_6427,
NPCs.GOBLIN_6428,
NPCs.GOBLIN_6429,
NPCs.GOBLIN_6430,
NPCs.GOBLIN_6431,
NPCs.GOBLIN_6432,
NPCs.GOBLIN_6433,
NPCs.GOBLIN_6434,
NPCs.GOBLIN_6435,
NPCs.GOBLIN_6436,
NPCs.GOBLIN_6437,
NPCs.GOBLIN_6438,
NPCs.GOBLIN_6439,
NPCs.GOBLIN_6440,
NPCs.GOBLIN_6441,
NPCs.GOBLIN_6442,
NPCs.GOBLIN_6443,
NPCs.GOBLIN_6444,
NPCs.GOBLIN_6445,
NPCs.GOBLIN_6446,
NPCs.GOBLIN_6447,
NPCs.GOBLIN_6448,
NPCs.GOBLIN_6449,
NPCs.GOBLIN_6450,
NPCs.GOBLIN_6451,
NPCs.GOBLIN_6452,
NPCs.GOBLIN_6453,
NPCs.GOBLIN_6454,
NPCs.GOBLIN_6455,
NPCs.GOBLIN_6456,
NPCs.GOBLIN_6457,
NPCs.GOBLIN_6458,
NPCs.GOBLIN_6459,
NPCs.GOBLIN_6460,
NPCs.GOBLIN_6461,
NPCs.GOBLIN_6462,
NPCs.GOBLIN_6463,
NPCs.GOBLIN_6464,
NPCs.GOBLIN_6465,
NPCs.GOBLIN_6466,
NPCs.GOBLIN_6467,
NPCs.GOBLIN_6490,
NPCs.GOBLIN_6491,
NPCs.GOBLIN_6492,
NPCs.GOBLIN_6493,
NPCs.GOBLIN_6494,
NPCs.GOBLIN_6495,
NPCs.GOBLIN_7964,
NPCs.GOBLIN_7965,
)
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
// Drops the Goblin Skull during Rag and Bone Man quest
if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) {
if(RandomFunction.roll(4)) {
drops.add(Item(Items.GOBLIN_SKULL_7812))
}
}
}
}
@@ -0,0 +1,54 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import core.api.isQuestInProgress
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.npc.drop.DropFrequency
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class MonkeyBehavior : NPCBehavior(*monkeyIds) {
companion object {
private val monkeyIds = intArrayOf(
NPCs.MONKEY_132,
NPCs.MONKEY_1463,
NPCs.MONKEY_1464,
NPCs.MONKEY_1487,
NPCs.MONKEY_2301,
NPCs.MONKEY_2302,
NPCs.MONKEY_2303,
NPCs.MONKEY_4344,
NPCs.MONKEY_4363,
NPCs.MONKEY_5852,
NPCs.MONKEY_5853,
NPCs.MONKEY_6943,
NPCs.MONKEY_7211,
NPCs.MONKEY_7213,
NPCs.MONKEY_7215,
NPCs.MONKEY_7217,
NPCs.MONKEY_7219,
NPCs.MONKEY_7221,
NPCs.MONKEY_7223,
NPCs.MONKEY_7225,
NPCs.MONKEY_7227,
NPCs.MONKEY_ZOMBIE_1465,
NPCs.MONKEY_ZOMBIE_1466,
NPCs.MONKEY_ZOMBIE_1467,
)
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
// Drops the Monkey Paw during Rag and Bone Man quest
if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) {
if(RandomFunction.roll(4)) {
drops.add(Item(Items.MONKEY_PAW_7854));
}
}
}
}
@@ -0,0 +1,233 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import content.region.asgarnia.burthorpe.quest.deathplateau.DeathPlateau
import core.api.*
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.dialogue.Topic
import core.game.node.entity.player.Player
import core.tools.END_DIALOGUE
import core.tools.START_DIALOGUE
import org.rs09.consts.NPCs
class OddOldManDialogueFile : DialogueFile() {
// BONES_3674 is the Sack on ODD_OLD_MAN_3670
// There are probably FacialExpressions for the bone sack, but that's too much work.
override fun handle(componentID: Int, buttonID: Int) {
when (getQuestStage(player!!, RagAndBoneMan.questName)) {
0 -> {
when (stage) {
START_DIALOGUE -> npcl(FacialExpression.FRIENDLY, "Can I help you with something?").also { stage++ }
1 -> playerl(FacialExpression.FRIENDLY, "Well, err...who are you, and what are all these bones doing here?").also { stage++ }
2 -> npcl(FacialExpression.FRIENDLY, "Errr...").also { stage++ }
3 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble").also { stage++ }
4 -> npcl(FacialExpression.FRIENDLY, "I'm an archaeologist. I work with the museum.").also { stage++ }
5 -> playerl(FacialExpression.FRIENDLY, "An archaeologist?").also { stage++ }
6 -> npcl(FacialExpression.FRIENDLY, "Yes.").also { stage++ }
7 -> playerl(FacialExpression.FRIENDLY, "Well that explains the bones...sort of...but what are you doing all the way out here?").also { stage++ }
8 -> npcl(FacialExpression.FRIENDLY, "Errr...").also { stage++ }
9 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble. Mumblemumblemumble.").also { stage++ }
10 -> npcl(FacialExpression.FRIENDLY, "I'm collecting bones for the museum.").also { stage++ }
11 -> npcl(FacialExpression.FRIENDLY, "They have asked me to rig up some displays of second and third age creatures using their bones, so that people can come and...well, look at them.").also { stage++ }
12 -> npcl(FacialExpression.FRIENDLY, "I need to get them into some sort of order before I begin, but I've run into a bit of a snag.").also { stage++ }
13 -> playerl(FacialExpression.FRIENDLY, "What sort of a snag?").also { stage++ }
14 -> npcl(FacialExpression.FRIENDLY, "Well, I need to have all the bones I'm going to use here, and placed into some sort of order.").also { stage++ }
15 -> npcl(FacialExpression.FRIENDLY, "However, I seem to have discovered I am a few short.").also { stage++ }
16 -> showTopics(
Topic("Anything I can do to help?", 20, true),
Topic("Well, good luck with that.", 70),
Topic("Where is that mumbling coming from?", 80)
)
20 -> playerl(FacialExpression.FRIENDLY, "Anything I can do to help?").also { stage++ }
21 -> npcl(FacialExpression.FRIENDLY, "Errr...").also { stage++ }
22 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble").also { stage++ }
23 -> npcl(FacialExpression.FRIENDLY, "There is something you could do for me. I'm going to be busy...err...").also { stage++ }
24 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumble").also { stage++ }
25 -> npcl(FacialExpression.FRIENDLY, "Sorting, yes, sorting these bones out ready for the museum, but I need a few more.").also { stage++ }
26 -> npcl(FacialExpression.FRIENDLY, "Will you help me out by grabbing some?").also { stage++ }
27 -> showTopics(
Topic(FacialExpression.FRIENDLY, "Yes", 28, true),
Topic(FacialExpression.FRIENDLY, "No", 60),
Topic("Where is that mumbling coming from?", 80)
)
28 -> playerl(FacialExpression.FRIENDLY, "Yes. I'll give you a hand.").also { stage++ }
29 -> npcl(FacialExpression.FRIENDLY, "You will? Excellent!").also { stage++ }
30 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Sniggersnigger").also { stage++ }
31 -> playerl(FacialExpression.FRIENDLY, "Where do you need me to dig?").also { stage++ }
32 -> npcl(FacialExpression.FRIENDLY, "Dig?").also { stage++ }
33 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble").also { stage++ }
34 -> npcl(FacialExpression.FRIENDLY, "Oh, you must have got the wrong end of the stick.").also { stage++ }
35 -> npcl(FacialExpression.FRIENDLY, "I need some fresh, whole bones to replace ones that have become damaged.").also { stage++ }
36 -> playerl(FacialExpression.FRIENDLY, "What?").also { stage++ }
37 -> npcl(FacialExpression.FRIENDLY, "Err...").also { stage++ }
38 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumblemumblemumblemumble. Mumblemumblemumblemumble. Mumble.").also { stage++ }
39 -> playerl(FacialExpression.FRIENDLY, "Excuse me...").also { stage++ }
40 -> npcl(FacialExpression.FRIENDLY, "Shhh!").also { stage++ }
41 -> playerl(FacialExpression.FRIENDLY, "Sorry...").also { stage++ }
42 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble. Mumblemumblemumble.").also { stage++ }
43 -> npcl(FacialExpression.FRIENDLY, "Ok, got it.").also { stage++ }
44 -> npcl(FacialExpression.FRIENDLY, "Ok, here is the thing. While sorting out what bones I do have I managed to lose or damage a few. If you can get me some fresh, unbroken bones to use as replacements then I can get on with things.").also { stage++ }
45 -> npcl(FacialExpression.FRIENDLY, "That make things clearer?").also { stage++ }
46 -> playerl(FacialExpression.FRIENDLY, "Well, it makes some sense I suppose...").also { stage++ }
47 -> npcl(FacialExpression.FRIENDLY, "Great. If you can get me a bone from a Goblin, a Bear, a Big Frog, a Ram, a Unicorn, a Monkey, a Giant rat and a Giant Bat then I'll be able to move on with the...").also { stage++ }
48 -> npcl(FacialExpression.FRIENDLY, "Displays...").also { stage++ }
49 -> playerl(FacialExpression.FRIENDLY, "So you just want me to bring you these bones and that will be that?").also { stage++ }
50 -> npcl(FacialExpression.FRIENDLY, "Well, I wouldn't mind you sticking them in a pot and boiling them in vinegar first, if you don't mind.").also { stage++ }
51 -> npcl(FacialExpression.FRIENDLY, "There is a Wine Merchant in Draynor called Fortunato that sells the stuff you'll need.").also { stage++ }
52 -> npcl(FacialExpression.FRIENDLY, "You can even use my pot-boiler if you want.").also { stage++ }
53 -> playerl(FacialExpression.FRIENDLY, "Why do I need to boil them in vinegar?").also { stage++ }
54 -> npcl(FacialExpression.FRIENDLY, "It gets them bright and sparking white.").also { stage++ }
55 -> npcl(FacialExpression.FRIENDLY, "It's an archaeologist thing.").also { stage++ }
56 -> npcl(FacialExpression.FRIENDLY, "Just put the bone in a pot of vinegar, throw some logs on the fire, put the pot in the holder and light the logs.").also { stage++ }
57 -> npcl(FacialExpression.FRIENDLY, "It takes a while for the vinegar to evaporate, but the bone will be nice and clean in the end.").also { stage++ }
58 -> playerl(FacialExpression.FRIENDLY, "All right, I'll be back later.").also { stage++ }
59 -> npcl(FacialExpression.FRIENDLY, "Bye!").also {
setQuestStage(player!!, RagAndBoneMan.questName, 1)
stage = END_DIALOGUE
}
60 -> npcl(FacialExpression.FRIENDLY, "Oh...I see.").also { stage++ }
61 -> npcl(FacialExpression.FRIENDLY, "Well, never mind me young man, I'll just stagger over here under my massive burden, and continue my thankless task.").also { stage++ }
62 -> npcl(FacialExpression.FRIENDLY, "Unaided and alone...").also { stage++ }
63 -> playerl(FacialExpression.FRIENDLY, "Wow, trying a guilt trip much?").also {
stage = END_DIALOGUE
}
70 -> npcl(FacialExpression.FRIENDLY, "Thanks stranger!").also { stage++ }
71 -> npcl(FacialExpression.FRIENDLY, "What a polite young man...").also { stage++ }
72 -> npcl(FacialExpression.FRIENDLY, "Well, back to work!").also {
stage = END_DIALOGUE
}
80 -> npcl(FacialExpression.FRIENDLY, "Errr...").also { stage++ }
81 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble").also { stage++ }
82 -> npcl(FacialExpression.FRIENDLY, "What mumbling?").also { stage++ }
83 -> npcl(FacialExpression.FRIENDLY, "Anyway, I have enough problems of my own without dealing with a delusional adventurer.").also {
stage = 16
}
}
}
in 1 .. 3 -> {
when(stage) {
START_DIALOGUE -> {
if (checkBonesInInventory(player!!)) {
playerl(FacialExpression.FRIENDLY, "I have some bones for you...").also { stage = 1 }
} else {
npcl(FacialExpression.FRIENDLY, "Have you brought me any bones?").also { stage = 20 }
}
}
1 -> npcl(FacialExpression.FRIENDLY, "Great! Let me take a look at them.").also {
stage++
}
2 -> {
submitBonesInInventory(player!!)
if (hasAllBones(player!!)) {
npcl(FacialExpression.FRIENDLY, "That's the last of them!").also { stage = 4 }
} else {
npcl(FacialExpression.FRIENDLY, "Thanks the museum will be so pleased.").also { stage = 3 }
}
}
3 -> npcl(FacialExpression.FRIENDLY, "Come and see me when you have the rest.").also {
stage = END_DIALOGUE
}
4 -> npcl(FacialExpression.FRIENDLY, "The museum will be thrilled to know I've completed the collection.").also { stage++ }
5 -> playerl(FacialExpression.FRIENDLY, "Well I'm just glad I could help.").also { stage++ }
6 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble").also { stage++ }
7 -> npcl(FacialExpression.FRIENDLY, "Well you've been a big help and no mistake.").also { stage++ }
8 -> npcl(FacialExpression.FRIENDLY, "I'm always on the lookout for fresh bones, so if you see some bring them right over.").also { stage++ }
9 -> playerl(FacialExpression.FRIENDLY, "No problem, I'll be sure to bring anything you might like over if I find something.").also { stage++ }
10 -> playerl(FacialExpression.FRIENDLY, "I can't wait to see the displays once they are finished.").also { stage++ }
11 -> finishQuest(player!!, RagAndBoneMan.questName).also {
end()
}
20 -> playerl(FacialExpression.FRIENDLY, "Not at the moment. Can you just give me a run down on which bones I have left to get?").also { stage++ }
21 -> npcl(FacialExpression.FRIENDLY, "Sure.").also {stage = 30 }
30, 40, 50, 60, 70, 80, 90, 100, 110 -> {
if (!getAttribute(player!!, RagAndBoneMan.attributeGoblinBone, false) && stage <= 30) { npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble"); stage = 31 }
else if (!getAttribute(player!!, RagAndBoneMan.attributeBearBone, false) && stage <= 40) { npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble"); stage = 41 }
else if (!getAttribute(player!!, RagAndBoneMan.attributeBigFrogBone, false) && stage <= 50) { npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble"); stage = 51 }
else if (!getAttribute(player!!, RagAndBoneMan.attributeRamBone, false) && stage <= 60) { npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble"); stage = 61 }
else if (!getAttribute(player!!, RagAndBoneMan.attributeUnicornBone, false) && stage <= 70) { npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble"); stage = 71 }
else if (!getAttribute(player!!, RagAndBoneMan.attributeMonkeyBone, false) && stage <= 80) { npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble"); stage = 81 }
else if (!getAttribute(player!!, RagAndBoneMan.attributeGiantRatBone, false) && stage <= 90) { npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble"); stage = 91 }
else if (!getAttribute(player!!, RagAndBoneMan.attributeGiantBatBone, false) && stage <= 100) { npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble"); stage = 101 }
else {
npcl(FacialExpression.FRIENDLY, "Did you get all that?")
stage = 111
}
}
31 -> npcl(FacialExpression.FRIENDLY, "You still need to bring me a Goblin bone.").also { stage++ }
32 -> npcl(FacialExpression.FRIENDLY, "Goblins are relatively common. I hear there is a house full of them around Lumbridge in fact.").also { stage = 40 }
41 -> npcl(FacialExpression.FRIENDLY, "You still need to bring me a Bear bone.").also { stage++ }
42 -> npcl(FacialExpression.FRIENDLY, "I heard that there are some Bears over by the Legends' Guild, near Ardougne.").also { stage = 50 }
51 -> npcl(FacialExpression.FRIENDLY, "You still need to bring me a Big Frog bone.").also { stage++ }
52 -> npcl(FacialExpression.FRIENDLY, "This might be a little tricky as you will need to go into the Lumbridge Swamp caves. You will need a light source! Never forget your light source down there!").also { stage = 60 }
61 -> npcl(FacialExpression.FRIENDLY, "You still need to bring me a Ram bone.").also { stage++ }
62 -> npcl(FacialExpression.FRIENDLY, "I'm sure you will be able to find a ram wherever there are sheep.").also { stage = 70 }
71 -> npcl(FacialExpression.FRIENDLY, "You still need to bring me a Unicorn bone.").also { stage++ }
72 -> npcl(FacialExpression.FRIENDLY, "I seem to remember that there were Unicorns south of Varrock, I think they might be there still.").also { stage = 80 }
81 -> npcl(FacialExpression.FRIENDLY, "You still need to bring me a Monkey bone.").also { stage++ }
82 -> npcl(FacialExpression.FRIENDLY, "Monkeys tend to live in Jungle areas, like Karamja. I think they are pretty plentiful there if I remember correctly.").also { stage = 90 }
91 -> npcl(FacialExpression.FRIENDLY, "You still need to bring me a Giant Rat bone.").also { stage++ }
92 -> npcl(FacialExpression.FRIENDLY, "If you can't find one in a sewer, then you might want to try looking in some caves.").also { stage = 100 }
101 -> npcl(FacialExpression.FRIENDLY, "You still need to bring me a Giant Bat bone.").also { stage++ }
102 -> npcl(FacialExpression.FRIENDLY, "Giant bats tend to live underground, but I have heard there are a few near the Coal Pits.").also { stage = 110 }
111 -> playerl(FacialExpression.FRIENDLY, "Yes. I'll get right on it.").also { stage++ }
112 -> npcl(NPCs.BONES_3674, "Sack", FacialExpression.OLD_HAPPY, "Mumblemumble").also { stage++ }
113 -> npcl(FacialExpression.FRIENDLY, "Don't forget to boil them in vinegar first.").also { stage++ }
114 -> npcl(FacialExpression.FRIENDLY, "Just chuck some logs into the pit, put the bone in the pot of vinegar and drop it onto the pot-boiler. Then light the logs and wait for the the vinegar to boil away.").also { stage++ }
115 -> playerl(FacialExpression.FRIENDLY, "Ok, I'll remember.").also {
stage = END_DIALOGUE
}
}
}
}
/*
Unfortunately from OSRS 2016: https://www.youtube.com/watch?v=31QNg1E0qf0
Wonderful! I'll put this with the rest.
No problem. I'll be back if I find some more.
This one is closest RS 2012: https://www.youtube.com/watch?v=0I8fNTeAwA8
I have some bones for you...
Great! Let me take a look at them.
Thanks the museum will be so pleased.
Come and see me when you have the rest.
*/
}
private fun checkBonesInInventory(player: Player) : Boolean {
var hasBone = false
RagAndBoneMan.requiredBonesMap.forEach {
if (inInventory(player, it.key)) {
hasBone = true
}
}
return hasBone
}
private fun submitBonesInInventory(player: Player) {
RagAndBoneMan.requiredBonesMap.forEach {
if (!getAttribute(player, it.value, false) && removeItem(player, it.key)) {
setAttribute(player, it.value, true)
}
}
}
private fun hasAllBones(player: Player) : Boolean {
var hasBoneAllBones = true
RagAndBoneMan.requiredBonesMap.values.forEach {
if (!getAttribute(player, it, false)) {
hasBoneAllBones = false
}
}
return hasBoneAllBones
}
}
@@ -0,0 +1,145 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import core.api.*
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.quest.Quest
import core.game.node.entity.skill.Skills
import core.plugin.Initializable
import org.rs09.consts.Items
/**
* Rag and Bone Man Quest
* @author ovenbread
*
* Do note:
* Before, the Rag and Bone Man WISHLIST(a.k.a part 2) used to reward 1 quest point,
* thus required to wear the quest cape.
* This was changed on 11 August 2009.
* Rag and Bone Man Quest now rewards 2 quest points.
* The follow-up hidden quest called Rag and Bone Man WISHLIST is not a quest cape req.
*
* https://www.youtube.com/watch?v=6tdNqNa4zGw
* https://www.youtube.com/watch?v=aVyBzqyuPYs
*
* Quest Journal 2012 https://www.youtube.com/watch?v=0I8fNTeAwA8&t=764
*/
@Initializable
class RagAndBoneMan : Quest("Rag and Bone Man",100, 99, 2, 714, 0, 1, 4) {
companion object {
const val questName = "Rag and Bone Man"
const val attributeGoblinBone = "/save:quest:ragandboneman-goblinbonesubmit"
const val attributeBearBone = "/save:quest:ragandboneman-bearbonesubmit"
const val attributeBigFrogBone = "/save:quest:ragandboneman-bigfrogbonesubmit"
const val attributeRamBone = "/save:quest:ragandboneman-rambonesubmit"
const val attributeUnicornBone = "/save:quest:ragandboneman-unicornbonesubmit"
const val attributeMonkeyBone = "/save:quest:ragandboneman-monkeybonesubmit"
const val attributeGiantRatBone = "/save:quest:ragandboneman-giantratbonesubmit"
const val attributeGiantBatBone = "/save:quest:ragandboneman-giantbatbonesubmit"
val requiredBonesMap = mapOf(
Items.GOBLIN_SKULL_7814 to attributeGoblinBone,
Items.BEAR_RIBS_7817 to attributeBearBone,
Items.BIG_FROG_LEG_7910 to attributeBigFrogBone,
Items.RAM_SKULL_7820 to attributeRamBone,
Items.UNICORN_BONE_7823 to attributeUnicornBone,
Items.MONKEY_PAW_7856 to attributeMonkeyBone,
Items.GIANT_RAT_BONE_7826 to attributeGiantRatBone,
Items.GIANT_BAT_WING_7829 to attributeGiantBatBone
)
}
override fun drawJournal(player: Player?, stage: Int) {
super.drawJournal(player, stage)
var line = 12
var stage = getStage(player)
when (stage) {
0 -> {
line(player, "I can start this quest by talking to the !!Odd Old Man?? to the", line++)
line(player, "West of the !!Limestone Mine??", line++)
}
in 1 .. 3 -> {
line(player, "I have spoken to the Odd Old Man and have agreed to help him ", line++, true)
line(player, "complete his collection of bones. I should check which ones", line++, true)
line(player, "he needs.", line++, true)
line++
line(player,"The !!Odd Old Man?? has instructed me on which bones to collect", line++, false)
line(player,"and how to prepare them. I must find !!whole, unbroken bones??", line++, false)
line(player,"and put them into a !!pot of vinegar??. I must then put some", line++, false)
line(player,"!!logs?? under the !!pot boiler??, !!put the bone in vinegar on it??,", line++, false)
line(player,"!!and light the logs??. This will clean the bone.", line++, false)
line++
line(player,"I need to buy the !!vinegar?? from the !!wine merchant?? in !!Draynor??.", line++, false)
line++
line(player,"I need to give the !!Odd Old Man?? the following polished bones:", line++, false)
boneChecklist(player, line, "Goblin", BoneBoilerEnum.GOBLIN_SKULL, attributeGoblinBone)
line++
boneChecklist(player, line, "Bear", BoneBoilerEnum.BEAR_RIBS, attributeBearBone)
line++
boneChecklist(player, line, "Big frog", BoneBoilerEnum.BIG_FROG_LEG, attributeBigFrogBone)
line++
boneChecklist(player, line, "Ram", BoneBoilerEnum.RAM_SKULL, attributeRamBone)
line++
boneChecklist(player, line, "Unicorn", BoneBoilerEnum.UNICORN_BONE, attributeUnicornBone)
line++
boneChecklist(player, line, "Monkey", BoneBoilerEnum.MONKEY_PAW, attributeMonkeyBone)
line++
boneChecklist(player, line, "Giant rat", BoneBoilerEnum.GIANT_RAT_BONE, attributeGiantRatBone)
line++
boneChecklist(player, line, "Giant bat", BoneBoilerEnum.GIANT_BAT_WING, attributeGiantBatBone)
line++
}
100 -> {
line(player, "I have spoken to the Odd Old Man and have agreed to help him ", line++, true)
line(player, "complete his collection of bones. I should check which ones", line++, true)
line(player, "he needs.", line++, true)
line++
line(player,"The !!Odd Old Man?? has instructed me on which bones to collect", line++, true)
line(player,"and how to prepare them. I must find !!whole, unbroken bones??", line++, true)
line(player,"and put them into a !!pot of vinegar??. I must then put some", line++, true)
line(player,"!!logs?? under the !!pot boiler??, !!put the bone in vinegar on it??,", line++, true)
line(player,"!!and light the logs??. This will clean the bone.", line++, true)
line++
line(player,"I have given the last of the bones to the Odd Old Man.", line++, true)
line(player,"I am sure he will reward me.", line++, true)
line++
line(player,"The Odd Old Man has given me a reward. I will see if I can", line++, false)
line(player,"find any more bones from his wish list, and will bring them", line++, false)
line(player,"them to him if I do.", line++, false)
line++
line(player,"%%QUEST COMPLETE!&&",line++)
}
}
}
private fun boneChecklist(player: Player?, line: Int, mob: String, boneEnum: BoneBoilerEnum, questAttribute: String) {
line(player,
if (getAttribute(player!!, questAttribute, false))
"!!$mob.??"
else if (inInventory(player, boneEnum.polishedBone))
"!!$mob.?? (I have a prepared one !!with me.??)"
else if (inInventory(player, boneEnum.bone) || inInventory(player, boneEnum.boneInVinegar))
"!!$mob.?? (I have an unprepared one !!with me.??)"
else
"!!$mob.??",
line, getAttribute(player, questAttribute, false))
}
override fun finish(player: Player) {
var ln = 10
super.finish(player)
player.packetDispatch.sendString("You have completed Rag and Bone Man!", 277, 4)
player.packetDispatch.sendItemZoomOnInterface(Items.BONE_IN_VINEGAR_7813, 240, 277, 5)
drawReward(player,"2 Quest Points", ln++)
drawReward(player,"500 Cooking XP and 500", ln++)
drawReward(player,"Prayer XP", ln++)
player.skills.addExperience(Skills.COOKING, 500.0)
player.skills.addExperience(Skills.PRAYER, 500.0)
}
override fun newInstance(`object`: Any?): Quest {
return this
}
}
@@ -0,0 +1,102 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import core.api.*
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.impl.PulseType
import core.game.system.task.Pulse
import org.rs09.consts.Animations
import org.rs09.consts.Items
import org.rs09.consts.Scenery
class RagAndBoneManListeners : InteractionListener {
companion object {
const val ATTRIBUTE_ACTIVE_POT_OF_VINEGAR = "ragandboneman:potofvinegar"
}
override fun defineListeners() {
// Pouring vinegar from jug to pot.
onUseWith(IntType.ITEM, Items.JUG_OF_VINEGAR_7810, Items.EMPTY_POT_1931) { player, _, _ ->
if (removeItem(player, Items.JUG_OF_VINEGAR_7810) && (removeItem(player, Items.EMPTY_POT_1931))) {
addItem(player, Items.POT_OF_VINEGAR_7811)
addItem(player, Items.JUG_1935)
sendMessage(player, "You pour the vinegar into the pot.")
}
return@onUseWith true
}
// Adding a bone to the pot.
onUseWith(IntType.ITEM, BoneBoilerEnum.boneList, Items.POT_OF_VINEGAR_7811) { player, used, with ->
if (removeItem(player, used) && (removeItem(player, with))) {
addItem(player, BoneBoilerEnum.forBone(used.id)!!.boneInVinegar)
sendMessage(player, "You add the bone to the pot of vinegar.")
}
return@onUseWith true
}
// Scenery: Placing logs on grate.
onUseWith(IntType.SCENERY, intArrayOf(Items.LOGS_1511, Items.OAK_LOGS_1521, Items.WILLOW_LOGS_1519, Items.MAPLE_LOGS_1517, Items.YEW_LOGS_1515, Items.MAGIC_LOGS_1513), Scenery.POT_BOILER_14006) { player, used, _ ->
if (removeItem(player, used)) {
sendMessage(player, "You place the logs into the grate.")
setVarbit(player, 2046, 1)
}
return@onUseWith true
}
// Scenery: Placing bone in vinegar pot on pot boiler.
onUseWith(IntType.SCENERY, BoneBoilerEnum.boneInVinegarList, Scenery.POT_BOILER_14005) { player, used, _ ->
val potOfVinegar = used.id
if ((removeItem(player, potOfVinegar))) {
setAttribute(player, ATTRIBUTE_ACTIVE_POT_OF_VINEGAR, potOfVinegar)
sendMessage(player, "You place the pot on the pot boiler.")
setVarbit(player, 2046, 2)
}
return@onUseWith true
}
// Scenery: Remove bone in vinegar pot from pot boiler.
on(Scenery.POT_BOILER_14007, SCENERY, "remove-pot") { player, _ ->
val potOfVinegar = getAttribute(player, ATTRIBUTE_ACTIVE_POT_OF_VINEGAR, 0)
if (BoneBoilerEnum.forBoneInVinegar(potOfVinegar) != null) {
setAttribute(player, ATTRIBUTE_ACTIVE_POT_OF_VINEGAR, 0)
addItemOrDrop(player, potOfVinegar)
sendMessage(player, "You remove the pot from the pot boiler.")
}
setVarbit(player, 2046, 1)
return@on true
}
// Scenery: Lighting pot boiler and cooking the bone in vinegar to yield bone.
onUseWith(IntType.SCENERY, Items.TINDERBOX_590, Scenery.POT_BOILER_14007) { player, _, _ ->
sendMessage(player, "You light the logs under the pot.")
animate(player, Animations.HUMAN_LIGHT_FIRE_WITH_TINDERBOX_733)
runTask(player, 3) {
animate(player, -1, true)
setVarbit(player, 2046, 3)
// Player can do something else while the pot is lit, so a side pulse should be used.
player.pulseManager.run(object : Pulse(20) { // 20 * 600ms(1 tick) = 12000ms = 12s
override fun pulse(): Boolean {
setVarbit(player, 2046, 4)
return true
}
}, PulseType.CUSTOM_1)
}
return@onUseWith true
}
// Taking bone and pot from boiled pot boiler.
on(Scenery.POT_BOILER_14009, SCENERY, "remove-bone") { player, _ ->
val potOfVinegar = getAttribute(player, ATTRIBUTE_ACTIVE_POT_OF_VINEGAR, 0)
if (BoneBoilerEnum.forBoneInVinegar(potOfVinegar) != null) {
val boneBoiler = BoneBoilerEnum.forBoneInVinegar(potOfVinegar)!!
setAttribute(player, ATTRIBUTE_ACTIVE_POT_OF_VINEGAR, 0)
addItemOrDrop(player, boneBoiler.polishedBone)
addItemOrDrop(player, Items.EMPTY_POT_1931)
sendMessage(player, "You retrieve a polished " + boneBoiler.boneDescription + " from the pot.")
}
setVarbit(player, 2046, 0)
return@on true
}
}
}
@@ -0,0 +1,34 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import core.api.*
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.npc.drop.DropFrequency
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class RamBehavior : NPCBehavior(*ramIds) {
companion object {
private val ramIds = intArrayOf(
NPCs.RAM_3672,
NPCs.RAM_3673,
NPCs.RAM_5168,
NPCs.RAM_5169,
NPCs.RAM_5170,
)
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
// Drops the Ram Skull during Rag and Bone Man quest
if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) {
if(RandomFunction.roll(4)) {
drops.add(Item(Items.RAM_SKULL_7818));
}
}
}
}
@@ -0,0 +1,32 @@
package content.region.misthalin.silvarea.quest.ragandboneman
import core.api.isQuestInProgress
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.node.entity.npc.drop.DropFrequency
import core.game.node.entity.player.Player
import core.game.node.item.Item
import core.tools.RandomFunction
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class UnicornBehavior : NPCBehavior(*unicornIds) {
companion object {
private val unicornIds = intArrayOf(
NPCs.UNICORN_89,
NPCs.UNICORN_987,
NPCs.BLACK_UNICORN_133,
)
}
override fun onDropTableRolled(self: NPC, killer: Entity, drops: ArrayList<Item>) {
super.onDropTableRolled(self, killer, drops)
// Drops the Unicorn Bone during Rag and Bone Man quest
if (killer is Player && isQuestInProgress(killer, RagAndBoneMan.questName, 1, 99)) {
if(RandomFunction.roll(4)) {
drops.add(Item(Items.UNICORN_BONE_7821));
}
}
}
}
@@ -1,6 +1,7 @@
package core.game.dialogue
import core.api.splitLines
import core.cache.def.impl.NPCDefinition
import core.game.component.Component
import core.game.node.entity.Entity
import core.game.node.entity.npc.NPC
@@ -46,6 +47,17 @@ abstract class DialogueFile {
} else interpreter!!.sendDialogues(npc, expression, *messages)
}
open fun npc(id: Int, expression: FacialExpression?, vararg messages: String?): Component? {
val chatBoxComponent = interpreter!!.sendDialogues(id, expression, *messages)
return chatBoxComponent
}
open fun npc(id: Int, title: String, expression: FacialExpression?, vararg messages: String?): Component? {
val chatBoxComponent = interpreter!!.sendDialogues(id, expression, *messages)
player!!.packetDispatch.sendString(title, chatBoxComponent.id, 3)
return chatBoxComponent
}
open fun player(vararg messages: String?): Component? {
return interpreter!!.sendDialogues(player, null, *messages)
}
@@ -63,6 +75,14 @@ abstract class DialogueFile {
return npc(expr, *splitLines(msg!!))
}
open fun npcl(id: Int, expr: FacialExpression?, msg: String?): Component? {
return npc(id, expr, *splitLines(msg!!))
}
open fun npcl(id: Int, title: String, expr: FacialExpression?, msg: String?): Component? {
return npc(id, title, expr, *splitLines(msg!!))
}
open fun npcl(msg: String?): Component? {
return npc(*splitLines(msg!!))
}