Karamja bug fixes and improvements

Improved Brimhaven NPC interactions
Both NPCs right click options now function
Dialogue converted to Kotlin for both NPCs
Minor dialogue modifications
Converted the Karamja Option Plugin to a Karamja Listener and Brimhaven Listener
Removed some duplicated handlers such at the ship yard gate and cart
Corrected the coins shown when paying to enter the Brimhaven dungeon
The palm tree now drops the leaf to the ground when shaken and has an animation
This commit is contained in:
Bonesy 2024-03-03 05:49:59 +00:00 committed by Ryan
parent 3df5097442
commit 0158d753f0
12 changed files with 584 additions and 763 deletions

View file

@ -2,6 +2,7 @@ package content.global.handlers.scenery;
import core.cache.def.impl.SceneryDefinition; import core.cache.def.impl.SceneryDefinition;
import core.game.container.impl.EquipmentContainer; import core.game.container.impl.EquipmentContainer;
import core.game.event.ResourceProducedEvent;
import core.game.interaction.OptionHandler; import core.game.interaction.OptionHandler;
import core.game.node.Node; import core.game.node.Node;
import core.game.node.entity.combat.ImpactHandler.HitsplatType; import core.game.node.entity.combat.ImpactHandler.HitsplatType;
@ -68,6 +69,7 @@ public final class FieldPickingPlugin extends OptionHandler {
player.setAttribute("delay:picking", GameWorld.getTicks() + (plant == PickingPlant.FLAX ? 2 : 3)); player.setAttribute("delay:picking", GameWorld.getTicks() + (plant == PickingPlant.FLAX ? 2 : 3));
player.animate(ANIMATION); player.animate(ANIMATION);
playAudio(player, Sounds.PICK_2581, 30); playAudio(player, Sounds.PICK_2581, 30);
player.dispatch(new ResourceProducedEvent(reward.getId(), reward.getAmount(), node, -1));
if (plant.name().startsWith("NETTLES") && (player.getEquipment().get(EquipmentContainer.SLOT_HANDS) == null || player.getEquipment().get(EquipmentContainer.SLOT_HANDS) != null && !player.getEquipment().get(EquipmentContainer.SLOT_HANDS).getName().contains("glove"))) { if (plant.name().startsWith("NETTLES") && (player.getEquipment().get(EquipmentContainer.SLOT_HANDS) == null || player.getEquipment().get(EquipmentContainer.SLOT_HANDS) != null && !player.getEquipment().get(EquipmentContainer.SLOT_HANDS).getName().contains("glove"))) {
player.getPacketDispatch().sendMessage("You have been stung by the nettles!"); player.getPacketDispatch().sendMessage("You have been stung by the nettles!");
player.getImpactHandler().manualHit(player, 2, HitsplatType.POISON); player.getImpactHandler().manualHit(player, 2, HitsplatType.POISON);
@ -108,12 +110,6 @@ public final class FieldPickingPlugin extends OptionHandler {
} else { } else {
player.getPacketDispatch().sendMessage("You pick a handful of nettles."); player.getPacketDispatch().sendMessage("You pick a handful of nettles.");
} }
if (banana && !player.getAchievementDiaryManager().hasCompletedTask(DiaryType.KARAMJA, 0, 0)) {
int picked = player.getAttribute("b-picked", 0);
picked++;
player.setAttribute("b-picked", picked);
player.getAchievementDiaryManager().updateTask(player, DiaryType.KARAMJA, 0, 0, picked == 5);
}
return true; return true;
} }
}); });
@ -131,17 +127,6 @@ public final class FieldPickingPlugin extends OptionHandler {
playAudio(player, Sounds.PICK_2581); playAudio(player, Sounds.PICK_2581);
player.getPacketDispatch().sendMessage("You pick some flax."); player.getPacketDispatch().sendMessage("You pick some flax.");
// Seers achievement diary
if (player.getViewport().getRegion().getId() == 10805
&& !player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(0,0)) {
if (player.getAttribute("diary:seers:flax-picked", 0) >= 4) {
player.setAttribute("/save:diary:seers:flax-picked", 5);
player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).updateTask(player,0,0,true);
} else {
player.setAttribute("/save:diary:seers:flax-picked", player.getAttribute("diary:seers:flax-picked", 0) + 1);
}
}
if (charge > 1000 + RandomFunction.random(2, 8)) { if (charge > 1000 + RandomFunction.random(2, 8)) {
object.setActive(false); object.setActive(false);
object.setCharge(1000); object.setCharge(1000);

View file

@ -24,6 +24,7 @@ class SeersVillageAchievementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE)
private const val ATTRIBUTE_ELEMENTAL_KILL_FLAGS = "diary:seers:elemental-kills" private const val ATTRIBUTE_ELEMENTAL_KILL_FLAGS = "diary:seers:elemental-kills"
private const val ATTRIBUTE_ARCHER_KILL_FLAGS = "diary:seers:archer-kills" private const val ATTRIBUTE_ARCHER_KILL_FLAGS = "diary:seers:archer-kills"
private const val ATTRIBUTE_COAL_TRUCK_FULL = "diary:seers:coal-truck-full" private const val ATTRIBUTE_COAL_TRUCK_FULL = "diary:seers:coal-truck-full"
private const val ATTRIBUTE_FLAX_PICKED = "diary:seers:flax-picked"
private val SEERS_VILLAGE_AREA = ZoneBorders(2687, 3455, 2742, 3507) private val SEERS_VILLAGE_AREA = ZoneBorders(2687, 3455, 2742, 3507)
private val SEERS_BANK_AREA = ZoneBorders(2721, 3490, 2730, 3493) private val SEERS_BANK_AREA = ZoneBorders(2721, 3490, 2730, 3493)
@ -98,11 +99,13 @@ class SeersVillageAchievementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE)
override fun onResourceProduced(player: Player, event: ResourceProducedEvent) { override fun onResourceProduced(player: Player, event: ResourceProducedEvent) {
when (player.viewport.region.id) { when (player.viewport.region.id) {
10807 -> if (event.itemId in CHURN_PRODUCT) { 10805 -> if (event.itemId == Items.FLAX_1779) {
finishTask( progressIncrementalTask(
player, player,
DiaryLevel.EASY, DiaryLevel.EASY,
EasyTasks.SINCLAIR_MANSION_USE_CHURN EasyTasks.PICK_5_FLAX,
ATTRIBUTE_FLAX_PICKED,
5
) )
} }
@ -116,6 +119,14 @@ class SeersVillageAchievementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE)
) )
} }
10807 -> if (event.itemId in CHURN_PRODUCT) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.SINCLAIR_MANSION_USE_CHURN
)
}
11317 -> when (event.itemId) { 11317 -> when (event.itemId) {
Items.RAW_MACKEREL_353 -> { Items.RAW_MACKEREL_353 -> {
finishTask( finishTask(

View file

@ -1,264 +0,0 @@
package content.region.karamja.brimhaven.dialogue;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.global.Skillcape;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.plugin.Initializable;
import core.game.node.item.Item;
/**
* Represents the dialogue plugin used for the capn izzy dialogue.
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class CapnIzzyDialogue extends DialoguePlugin {
/**
* Represents the parrot npc id.
*/
private static final int PARROT = 4535;
/**
* Constructs a new {@code CapnIzzyDialogue.java} {@code Object}.
*/
public CapnIzzyDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code CapnIzzyDialogue.java} {@code Object}.
* @param player the player.
*/
public CapnIzzyDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new CapnIzzyDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
if (args.length > 1) {
interpreter.sendDialogues(PARROT, null, "Clap him in irons!");
stage = 200;
return true;
}
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Ahoy Cap'n!");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Ahoy there!");
stage = 90;
break;
case 90:
interpreter.sendDialogues(PARROT, null, "Avast ye scurvy swabs!");
stage = 91;
break;
case 91:
interpreter.sendDialogues(player, null, "Huh?");
stage = 92;
break;
case 92:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Don't mind me parrot, he's Cracked Jenny's Tea Cup!");
stage = 1;
break;
case 1:
interpreter.sendOptions("Select an Option", "What is this place?", "What do I do in the arena?", "I'd like to use the Agility Arena, please.", "Can you tell me a bit about the Skillcape of Agility, please.", "See you later.");
stage = 2;
break;
case 2:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What is this place?");
stage = 10;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What do I do in the arena?");
stage = 20;
break;
case 3:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'd like to use the Agility Arena, please.");
stage = 30;
break;
case 4:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Can you tell me a bit about the Skillcape of Agility,", "please?");
stage = 40;
break;
case 5:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "See you later.");
stage = 50;
break;
}
break;
case 10:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "This, me hearty, is the entrance to the Brimhaven", "Agility Arena!");
stage = 11;
break;
case 11:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I were diffin for buried treasure when I found it!", "Amazed I was! It was a sight to behold!");
stage = 12;
break;
case 12:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "It were the biggest thing I'd ever seen! it must've been", "at least a league from side to side!");
stage = 13;
break;
case 13:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "It made me list, I were that excited!");
stage = 14;
break;
case 14:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I'd found a huge cave with all these platforms. I reckon", "it be an ancient civilisation that made it. I had to be", "mighty careful as there was these traps everywehre!", "Dangerous it was!");
stage = 15;
break;
case 15:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Entrance is only 200 coins!");
stage = 1;
break;
case 20:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Well, me hearty, it's simple. Ye can cross between two", "platforms by using the traps or obstacles strung across", "'em. Try and make your way to the pillar that is", "indicated by the flashing arrow.");
stage = 21;
break;
case 21:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Ye receive tickets for tagging more than one pillar in a", "row. So ye won't get a ticket from the first pillar but", "ye will for every platform ye tag in a row after that.");
stage = 22;
break;
case 22:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "If ye miss a platform ye will miss out on the next ticket", "so try and get every platform you can! When ye be", "done, take the tickets to Jackie over there and she'll", "exchange them for more stuff!");
stage = 23;
break;
case 23:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Thanks me hearty!");
stage = 24;
break;
case 24:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Thanks!");
stage = 1;
break;
case 30:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Aye, entrance be 200 coins.");
stage = 31;
break;
case 31:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "A word of warning me hearty! There are dangerous", "traps down there!");
stage = 32;
break;
case 32:
interpreter.sendOptions("Select an Option", "Ok, here's 200 coins.", "Never mind.");
stage = 33;
break;
case 33:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Ok, here's 200 coins.");
stage = 35;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Never mind.");
stage = 34;
break;
}
break;
case 34:
end();
break;
case 35:
if (!player.getAttribute("capn_izzy", false)) {
if (player.getInventory().contains(995, 200) && player.getInventory().remove(new Item(995, 200))) {
end();
player.getDialogueInterpreter().sendItemMessage(new Item(995, 200), "You give Cap'n Izzy the 200 coin entrance fee.");
player.getPacketDispatch().sendMessage("You give Cap'n Izzy the 200 coin entrance fee.");
player.setAttribute("/save:capn_izzy", true);
return true;
} else {
player.getPacketDispatch().sendMessage("You don't have the 200 coin entrance fee.");
end();
}
} else {
player.getDialogueInterpreter().sendDialogues(npc, null, "Avast there, ye've already paid!");
stage = 36;
}
break;
case 36:
end();
break;
case 40:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Aye, to be sure! The Skillcape of Agility be the symbol", "of the master of dexterity! One who wears it can climb", "like a cat, run like the wind and jump like...err, well", "jump like a jumping thing! Now, be there anything else");
stage = 41;
break;
case 41:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "ye'd like to know?");
if (!Skillcape.isMaster(player, Skills.AGILITY)) {
stage = 1;
} else {
stage = 99;
}
break;
case 99:
interpreter.sendDialogues(player, null, "I'd like to buy an Agility Skillcape.");
stage = 100;
break;
case 100:
interpreter.sendDialogues(npc, null, "That will cost you 99,000 gold coins.");
stage = 101;
break;
case 101:
interpreter.sendOptions("Select an Option", "Okay, I'll pay it.", "Nevermind.");
stage = 102;
break;
case 102:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, null, "Okay, I'll pay it.");
stage = 104;
break;
case 2:
interpreter.sendDialogues(player, null, "Nevermind.");
stage = 103;
break;
}
break;
case 104:
if (Skillcape.purchase(player, Skills.AGILITY)) {
interpreter.sendDialogues(npc, null, "There you go hearty! You're truly a master of Agility.");
}
stage = 105;
break;
case 105:
end();
break;
case 103:
end();
break;
case 50:
end();
break;
case 200:
interpreter.sendDialogues(npc, null, "Ahoy there! Pay up first!");
stage = 201;
break;
case 201:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 437 };
}
}

View file

@ -0,0 +1,159 @@
package content.region.karamja.brimhaven.dialogue
import core.api.*
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.global.Skillcape
import core.game.node.entity.npc.NPC
import core.game.node.entity.skill.Skills
import core.game.node.item.Item
import core.tools.END_DIALOGUE
import org.rs09.consts.Items
import org.rs09.consts.NPCs
class CapnIzzyDialogue(private val it: Int) : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (it) {
0 -> when (stage) {
0 -> playerl(FacialExpression.HAPPY, "Ahoy Cap'n!").also { stage++ }
1 -> npcl(FacialExpression.HAPPY, "Ahoy there!").also { stage++ }
2 -> npcl(NPCs.PARROT_4535, FacialExpression.ANGRY, "Avast ye scurvy swabs!").also { stage++ }
3 -> playerl(FacialExpression.THINKING, "Huh?").also { stage++ }
4 -> npcl(FacialExpression.HAPPY, "Don't mind me parrot, he's Cracked Jenny's Tea Cup!").also { stage++ }
5 -> {
if (Skillcape.isMaster(player!!, Skills.AGILITY)) {
options(
"What is this place?",
"What do I do in the arena?",
"I'd like to use the Agility Arena, please.",
"Is it true you sell the Skillcape of Agility?",
"See you later."
).also { stage++ }
} else {
options(
"What is this place?",
"What do I do in the arena?",
"I'd like to use the Agility Arena, please.",
"Can you tell me a bit about the Skillcape of Agility, please?",
"See you later."
).also { stage = 7 }
}
}
6 -> when (buttonID) {
1 -> playerl(FacialExpression.NEUTRAL, "What is this place?").also { stage = 10 }
2 -> playerl(FacialExpression.NEUTRAL, "What do I do in the arena?").also { stage = 20 }
3 -> playerl(FacialExpression.NEUTRAL, "I'd like to use the Agility Arena, please.").also { stage = 30 }
4 -> playerl(FacialExpression.HALF_ASKING, "May I buy a Skillcape of Agility, please?").also { stage = 40 }
5 -> playerl(FacialExpression.NEUTRAL, "See you later.").also { stage = END_DIALOGUE }
}
7 -> when (buttonID) {
1 -> playerl(FacialExpression.NEUTRAL, "What is this place?").also { stage = 10 }
2 -> playerl(FacialExpression.NEUTRAL, "What do I do in the arena?").also { stage = 20 }
3 -> playerl(FacialExpression.NEUTRAL, "I'd like to use the Agility Arena, please.").also { stage = 30 }
4 -> playerl(FacialExpression.NEUTRAL, "Can you tell me a bit about the Skillcape of Agility, please?").also { stage = 50 }
5 -> playerl(FacialExpression.NEUTRAL, "See you later.").also { stage = END_DIALOGUE }
}
10 -> npcl(FacialExpression.NEUTRAL, "This, me hearty, is the entrance to the Brimhaven, Agility Arena!").also { stage++ }
11 -> npcl(FacialExpression.NEUTRAL, "I were diggin for buried treasure when I found it! Amazed I was! It was a sight to behold!").also { stage++ }
12 -> npcl(FacialExpression.NEUTRAL, "It were the biggest thing I'd ever seen! it must've been at least a league from side to side!").also { stage++ }
13 -> npcl(FacialExpression.NEUTRAL, "It made me list, I were that excited!").also { stage++ }
14 -> npcl(FacialExpression.NEUTRAL, "I'd found a huge cave with all these platforms. I reckon it be an ancient civilisation that made it. I had " +
"to be mighty careful as there was these traps everywhere! Dangerous it was!").also { stage++ }
15 -> npcl(FacialExpression.NEUTRAL, "Entrance is only 200 coins!").also { stage = 5 }
20 -> npcl(FacialExpression.NEUTRAL, "Well, me hearty, it's simple. Ye can cross between two platforms by using the traps or obstacles " +
"strung across 'em. Try and make your way to the pillar that is indicated by the flashing arrow.").also { stage++ }
21 -> npcl(FacialExpression.NEUTRAL, "Ye receive tickets for tagging more than one pillar in a row. So ye won't get a ticket from the " +
"first pillar but ye will for every platform ye tag in a row after that.").also { stage++ }
22 -> npcl(FacialExpression.NEUTRAL, "If ye miss a platform ye will miss out on the next ticket so try and get every platform you can! " +
"When ye be done, take the tickets to Jackie over there and she'll exchange them for more stuff!").also { stage++ }
23 -> playerl(FacialExpression.NEUTRAL, "Thanks!").also { stage = 5 }
30 -> npcl(FacialExpression.NEUTRAL, "Aye, entrance be 200 coins.").also { stage++ }
31 -> npcl(NPCs.PARROT_4535, FacialExpression.ANGRY, "Pieces of eight!").also { stage++ }
32 -> npcl(FacialExpression.AMAZED, "A word of warning me hearty! There are dangerous traps down there!").also { stage++ }
33 -> options("Ok, here's 200 coins.", "Never mind.").also { stage++ }
34 -> when (buttonID) {
1 -> playerl(FacialExpression.NEUTRAL, "Ok, here's 200 coins.").also { stage++ }
2 -> playerl(FacialExpression.NEUTRAL, "Never mind.").also { stage = END_DIALOGUE }
}
35 -> {
if (!getAttribute(player!!, "capn_izzy", false)) {
if (inInventory(player!!, Items.COINS_995, 200) && removeItem(player!!, Item(Items.COINS_995, 200))) {
sendItemDialogue(player!!, Items.COINS_6964, "You give Cap'n Izzy 200 coins.").also { stage++ }
npcl(FacialExpression.HAPPY, "May the wind be in ye sails!").also { stage = END_DIALOGUE }
sendMessage(player!!, "You give Cap'n Izzy 200 coins.")
setAttribute(player!!, "/save:capn_izzy", true)
} else {
end()
sendMessage(player!!, "You don't have the 200 coin entrance fee.")
}
} else {
npcl(FacialExpression.NEUTRAL, "Avast there, ye've already paid!").also { stage = END_DIALOGUE }
}
}
40 -> npcl(FacialExpression.NEUTRAL, "Most certainly, I think it'll really suit you. All that remains to be done is pay me 99000 gold!").also { stage++ }
41 -> options("I'm afraid I can't afford that.", "Certainly, here you go.").also { stage++ }
42 -> when (buttonID) {
1 -> playerl(FacialExpression.NEUTRAL, "I'm afraid I can't afford that.").also { stage++ }
2 -> playerl(FacialExpression.HAPPY, "Certainly, here you go.").also { stage = 44 }
}
43 -> npcl(FacialExpression.NEUTRAL, "So sad, too bad. Go and pickpocket some wealthy people and come back here once you're richer.").also { stage = END_DIALOGUE }
44 -> {
when {
(!inInventory(player!!, Items.COINS_995, 99000)) -> {
playerl(FacialExpression.NEUTRAL, "But, unfortunately, I don't have enough money with me.").also { stage = 45 }
}
(freeSlots(player!!)) < 2 -> {
npcl(FacialExpression.NEUTRAL, "Unfortunately all Skillcapes are only available with a free hood, it's part of a skill promotion deal; " +
"buy one get one free, you know. So you'll need to free up some inventory space before I can sell you one.").also { stage = END_DIALOGUE }
}
else -> {
Skillcape.purchase(player!!, Skills.AGILITY)
npcl(FacialExpression.HAPPY, "Excellent! That cape really does suit you.").also { stage = END_DIALOGUE }
}
}
}
45 -> npcl(FacialExpression.NEUTRAL, "Well, come back and see me when you do.").also { stage = END_DIALOGUE }
// The below text was too long when using npcl's automatic line splitting.
50 -> sendNormalDialogue(
NPC(NPCs.CAPN_IZZY_NO_BEARD_437),
FacialExpression.NEUTRAL,
"Aye, to be sure! The Skillcape of Agility be the symbol",
"of the master of dexterity! One who wears it can climb",
"like a cat, run like the wind and jump like...err, well",
"jump like a jumping thing!"
).also { stage++ }
51 -> npcl(FacialExpression.NEUTRAL, "Now, be there anything else ye'd like to know?").also { stage = 5 }
}
1 -> when (stage) {
0 -> npcl(NPCs.PARROT_4535, FacialExpression.ANGRY, "Clap him in irons!").also { stage++ }
1 -> npcl(NPCs.CAPN_IZZY_NO_BEARD_437, FacialExpression.NEUTRAL, "Ahoy there! Pay up first!").also { stage = END_DIALOGUE }
}
2 -> {
if (!getAttribute(player!!, "capn_izzy", false)) {
if (inInventory(player!!, Items.COINS_995, 200) && removeItem(player!!, Item(Items.COINS_995, 200))) {
sendItemDialogue(player!!, Items.COINS_6964, "You give Cap'n Izzy the 200 coin entrance fee.").also { stage = END_DIALOGUE }
sendMessage(player!!, "You give Cap'n Izzy the 200 coin entrance fee.")
setAttribute(player!!, "/save:capn_izzy", true)
} else {
sendMessage(player!!, "You don't have the 200 coin entrance fee.")
}
} else {
npcl(NPCs.CAPN_IZZY_NO_BEARD_437, FacialExpression.NEUTRAL, "Avast there, ye've already paid!").also { stage = END_DIALOGUE }
}
}
}
}
}

View file

@ -1,217 +0,0 @@
package content.region.karamja.brimhaven.dialogue;
import core.game.component.Component;
import core.game.dialogue.DialoguePlugin;
import core.game.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.diary.AchievementDiary;
import core.game.node.entity.player.link.diary.DiaryType;
import core.plugin.Initializable;
/**
* Represents the dialogue plugin used for pirate jackie.
* @author Vexia
*/
@Initializable
public final class PirateJackieDialogue extends DialoguePlugin {
/**
* Represents the interface component.
*/
private static final Component COMPONENT = new Component(6);
/**
* Constructs a new {@code PirateJackieDialogue} {@code Object}.
*/
public PirateJackieDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code PirateJackieDialogue} {@code Object}.
* @param player the player.
*/
public PirateJackieDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new PirateJackieDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Ahoy there!");
stage = 0;
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (stage) {
case 0:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Ahoy!");
stage = 1;
break;
case 1:
interpreter.sendOptions("Select an Option", "What is this place?", "What do you do?", "I'd like to trade in my tickets, please.", "I have a question about my Achievement Diary.", "See you later.");
stage = 2;
break;
case 2:
switch (buttonId) {
case 1:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What is this place?");
stage = 10;
break;
case 2:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "What do you do?");
stage = 20;
break;
case 3:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "I'd like to trade in my tickets, please.");
stage = 30;
break;
case 4:
player("I have a question about my Achievement Diary.");
stage = 41;
break;
case 5:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "See you later.");
stage = 50;
break;
}
break;
case 10:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Welcome to the Brimhaven Agility Arena!");
stage = 11;
break;
case 11:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "If ye want to know more talk to Cap'n Izzy, he found", "it!");
stage = 12;
break;
case 12:
end();
break;
case 20:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "I be the Jack o' tickets. I exchange the tickets ye", "collect in the Agility Arena for more stuff. Ye can", "obtain more agility experience or some items ye won't", "find anywhere else!");
stage = 21;
break;
case 21:
interpreter.sendDialogues(player, FacialExpression.HALF_GUILTY, "Sounds good!");
stage = 22;
break;
case 22:
end();
break;
case 30:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Aye, ye be on the right track.");
stage = 31;
break;
case 31:
end();
player.getInterfaceManager().open(COMPONENT);
break;
case 41:
if (AchievementDiary.canClaimLevelRewards(player, DiaryType.KARAMJA, 0)) {
player("I've done all the easy tasks in my Karamja Achievement", "Diary.");
stage = 440;
break;
}
if (AchievementDiary.canReplaceReward(player, DiaryType.KARAMJA, 0)) {
player("I've seemed to have lost my gloves..");
stage = 450;
break;
}
options("What is the Achievement Diary?", "What are the rewards?", "How do I claim the rewards?", "See you later.");
stage++;
break;
case 42:
switch (buttonId) {
case 1:
player("What is the Achievement Diary?");
stage = 410;
break;
case 2:
player("What are the rewards?");
stage = 420;
break;
case 3:
player("How do I claim the rewards?");
stage = 430;
break;
case 4:
end();
break;
}
break;
case 440:
npc("Arr, ye have that, I see yer list. I s'pose ye'll be wanting", "yer reward then!");
stage++;
break;
case 441:
player("Yes please.");
stage++;
break;
case 442:
AchievementDiary.flagRewarded(player, DiaryType.KARAMJA, 0);
npc("These 'ere Karamja gloves be a symbol of yer explorin'", "on the island. All the merchants will recognise 'em when", "yer wear 'em and mabe give ye a little discount. I'll", "ave a word with some of the seafarin' folk who sail to");
stage++;
break;
case 443:
npc("Port Sarim and Ardougne, so they'll take ye on board", "half price if year wearin' them. Arrr, take this lamp I", "found washed ashore too.");
stage++;
break;
case 444:
player("Wow, thanks!");
stage = 41;
break;
case 450:
AchievementDiary.grantReplacement(player, DiaryType.KARAMJA, 0);
npc("Arr matey, have another pair. Ye better be more", "careful this time.");
stage = 41;
break;
case 410:
npc("It's a diary that helps you keep track of particular", "achievements. Here on Karamja it can help you", "discover some quite useful things. Eventually, with", "enough exploration, the people of Karamja will reward");
stage++;
break;
case 411:
npc("you.");
stage++;
break;
case 412:
npc("You can see what tasks you have listed by clicking on", "the green button in the Quest List.");
stage = 41;
break;
case 420:
npc("Well, there's three different pairs of Karamja gloves,", "which match up with the three levels of difficulty. Each", "has the same rewards as the previous level, and an", "additional one too... but I won't spoil your surprise.");
stage++;
break;
case 421:
npc("Rest assured, the people of Karamja are happy to see", "you visiting the island.");
stage = 41;
break;
case 430:
npc("Just complete the tasks so they're all ticked off, then", "you can claim yer reward. Most of them are", "straightforward; you might find some require quests to", "be started, if not finished.");
stage++;
break;
case 431:
npc("To claim the different Karamja gloves, speak to Kaleb", "Paramaya in Shilo Village, one of the jungle foresters", "near the Kharazi Jungle, or me.");
stage = 41;
break;
case 50:
end();
break;
}
return true;
}
@Override
public int[] getIds() {
return new int[] { 1055 };
}
}

View file

@ -0,0 +1,120 @@
package content.region.karamja.brimhaven.dialogue
import core.api.openInterface
import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.link.diary.AchievementDiary
import core.game.node.entity.player.link.diary.DiaryType
import core.tools.END_DIALOGUE
import org.rs09.consts.Components
import org.rs09.consts.NPCs
class PirateJackieDialogue : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> playerl(FacialExpression.NEUTRAL, "Ahoy there!").also { stage++ }
1 -> npcl(FacialExpression.NEUTRAL, "Ahoy!").also { stage++ }
2 -> options(
"What is this place?",
"What do you do?",
"I'd like to trade in my tickets, please.",
"I have a question about my Achievement Diary.",
"See you later."
).also { stage++ }
3 -> when (buttonID) {
1 -> playerl(FacialExpression.NEUTRAL, "What is this place?").also { stage = 10 }
2 -> playerl(FacialExpression.NEUTRAL, "What do you do?").also { stage = 20 }
3 -> playerl(FacialExpression.NEUTRAL, "I'd like to trade in my tickets, please.").also { stage = 30 }
4 -> playerl(FacialExpression.NEUTRAL, "I have a question about my Achievement Diary.").also {
stage = 40
}
5 -> playerl(FacialExpression.NEUTRAL, "See you later.").also { stage = END_DIALOGUE }
}
10 -> npcl(FacialExpression.NEUTRAL, "Welcome to the Brimhaven Agility Arena!").also { stage++ }
11 -> npcl(
FacialExpression.NEUTRAL,
"If ye want to know more talk to Cap'n Izzy, he found it!"
).also { stage = END_DIALOGUE }
20 -> npcl(
FacialExpression.NEUTRAL,
"I be the Jack o' tickets. I exchange the tickets ye collect in the Agility Arena for " +
"more stuff. Ye can obtain more agility experience or some items ye won't find anywhere else!"
).also { stage++ }
21 -> playerl(FacialExpression.NEUTRAL, "Sounds good!").also { stage = END_DIALOGUE }
30 -> {
npcl(FacialExpression.NEUTRAL, "Aye, ye be on the right track.").also { stage = END_DIALOGUE }
end()
openInterface(player!!, Components.AGILITYARENA_TRADE_6)
}
40 -> when {
AchievementDiary.canClaimLevelRewards(player!!, DiaryType.KARAMJA, 0) ->
playerl(FacialExpression.NEUTRAL, "I've done all the easy tasks in my Karamja Achievement Diary.").also { stage = 410 }
AchievementDiary.canReplaceReward(player, DiaryType.KARAMJA, 0) ->
playerl(FacialExpression.NEUTRAL, "I've seemed to have lost my gloves..").also { stage = 420 }
else -> options(
"What is the Achievement Diary?",
"What are the rewards?",
"How do I claim the rewards?",
"See you later."
).also { stage++ }
}
41 -> when (buttonID) {
1 -> playerl(FacialExpression.NEUTRAL, "What is the Achievement Diary?").also { stage = 430 }
2 -> playerl(FacialExpression.NEUTRAL, "What are the rewards?").also { stage = 440 }
3 -> playerl(FacialExpression.NEUTRAL, "How do I claim the rewards?").also { stage = 450 }
4 -> playerl(FacialExpression.NEUTRAL, "See you later.").also { stage = END_DIALOGUE }
}
410 -> npcl(FacialExpression.NEUTRAL, "Arr, ye have that, I see yer list. I s'pose ye'll be wanting yer reward then!").also { stage++ }
411 -> playerl(FacialExpression.NEUTRAL, "Yes please.").also { stage++ }
412 -> {
AchievementDiary.flagRewarded(player, DiaryType.KARAMJA, 0)
npcl(FacialExpression.NEUTRAL,
"These 'ere Karamja gloves be a symbol of yer explorin' on the island. All the merchants will recognise" +
" 'em when yer wear 'em and mabe give ye a little discount. I'll ave a word with some of the seafarin' folk who ").also { stage++ }
}
413 -> npcl(FacialExpression.NEUTRAL, "sail to Port Sarim and Ardougne, so they'll take ye on board half price if year wearin' them. Arrr, take this" +
" lamp I found washed ashore too.").also { stage++ }
414 -> playerl(FacialExpression.NEUTRAL, "Wow, thanks!").also { stage = 40 }
420 -> {
AchievementDiary.grantReplacement(player, DiaryType.KARAMJA, 0)
npcl(FacialExpression.NEUTRAL, "Arr matey, have another pair. Ye better be more careful this time.").also { stage = 40 }
}
430 -> npcl(
FacialExpression.NEUTRAL,
"It's a diary that helps you keep track of particular achievements. Here on Karamja it can help " +
"you discover some quite useful things. Eventually, with enough exploration, the people of Karamja will reward you.").also { stage++ }
431 -> npcl(FacialExpression.NEUTRAL, "You can see what tasks you have listed by clicking on the green button in the Quest List.").also { stage = 40 }
// The below text was too long when using npcl's automatic line splitting.
440 -> sendNormalDialogue(
NPC(NPCs.PIRATE_JACKIE_THE_FRUIT_1055),
FacialExpression.NEUTRAL,
"Well, there's three different pairs of Karamja gloves,",
"which match up with the three levels of difficulty. Each",
"has the same rewards as the previous level, and an",
"additional one too... but I won't spoil your surprise."
).also { stage++ }
441 -> npcl(FacialExpression.NEUTRAL,
"Rest assured, the people of Karamja are happy to see you visiting the island.").also { stage = 40 }
450 -> npcl(FacialExpression.NEUTRAL, "To claim the different Karamja gloves, speak to Kaleb Paramaya in Shilo Village, one of the jungle " +
"foresters near the Kharazi Jungle, or me.").also { stage = 40 }
}
}
}

View file

@ -6,6 +6,7 @@ import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.game.node.item.Item; import core.game.node.item.Item;
import org.rs09.consts.Items;
/** /**
* Handles the SanibochDialogue dialogue. * Handles the SanibochDialogue dialogue.
@ -129,7 +130,7 @@ public class SanibochDialogue extends DialoguePlugin {
if (player.getInventory().remove(item)) { if (player.getInventory().remove(item)) {
player.getPacketDispatch().sendMessage("You pay Saniboch 875 coins."); player.getPacketDispatch().sendMessage("You pay Saniboch 875 coins.");
player.setAttribute("saniboch:paid", true); player.setAttribute("saniboch:paid", true);
interpreter.sendItemMessage(item, "You give Saniboch 875 coins."); interpreter.sendItemMessage(Items.COINS_6964, "You give Saniboch 875 coins.");
stage = 33; stage = 33;
break; break;
} }

View file

@ -1,16 +1,22 @@
package content.region.karamja.brimhaven.handlers package content.region.karamja.brimhaven.handlers
import core.game.node.entity.skill.Skills
import content.global.skill.agility.AgilityHandler import content.global.skill.agility.AgilityHandler
import core.api.*
import core.game.dialogue.FacialExpression
import core.game.global.action.ClimbActionHandler
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.player.link.diary.DiaryType
import core.game.node.entity.skill.Skills
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.update.flag.context.Animation import core.game.world.update.flag.context.Animation
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import core.game.interaction.InteractionListener import org.rs09.consts.Scenery
import core.game.interaction.IntType
class BrimhavenDungeonListeners : InteractionListener { class BrimhavenDungeonListeners : InteractionListener {
val EXIT = 5084 val ENTRANCE = Scenery.DUNGEON_ENTRANCE_5083
val EXIT = Scenery.EXIT_5084
val SANIBOCH = NPCs.SANIBOCH_1595 val SANIBOCH = NPCs.SANIBOCH_1595
val VINES = intArrayOf(5103,5104,5105,5106,5107) val VINES = intArrayOf(5103,5104,5105,5106,5107)
val STEPPING_STONES = intArrayOf(5110,5111) val STEPPING_STONES = intArrayOf(5110,5111)
@ -18,6 +24,16 @@ class BrimhavenDungeonListeners : InteractionListener {
val LOGS = intArrayOf(5088,5090) val LOGS = intArrayOf(5088,5090)
override fun defineListeners() { override fun defineListeners() {
on(ENTRANCE, IntType.SCENERY, "enter"){ player, node ->
if (getAttribute(player, "saniboch:paid", false) || player.achievementDiaryManager.getDiary(DiaryType.KARAMJA).isComplete()) {
ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, location(2713, 9564, 0))
removeAttribute(player, "saniboch:paid")
} else {
sendNPCDialogue(player, SANIBOCH, "You can't go in there without paying!", FacialExpression.NEUTRAL)
}
return@on true
}
on(EXIT, IntType.SCENERY, "leave"){ player, _ -> on(EXIT, IntType.SCENERY, "leave"){ player, _ ->
player.properties.teleportLocation = Location.create(2745, 3152, 0) player.properties.teleportLocation = Location.create(2745, 3152, 0)
return@on true return@on true

View file

@ -0,0 +1,136 @@
package content.region.karamja.brimhaven.handlers
import content.region.karamja.brimhaven.dialogue.CapnIzzyDialogue
import content.region.karamja.brimhaven.dialogue.PirateJackieDialogue
import core.api.*
import core.game.dialogue.FacialExpression
import core.game.global.action.ClimbActionHandler
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.world.repository.Repository
import org.rs09.consts.Components
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
class BrimhavenListeners : InteractionListener {
companion object {
/**
* Represents the ladder that exits the Agility Arena.
*/
private const val AGILITY_ARENA_EXIT_LADDER = Scenery.LADDER_3618
/**
* Represents the ladder that enters the Agility Arena.
*/
private const val AGILITY_ARENA_ENTRANCE_LADDER = Scenery.LADDER_3617
/**
* Represents the area inside Brimhaven Agility Arena.
*/
private val AGILITY_ARENA = location(2805, 9589, 3)
/**
* Represents the area within the hut outside the Brimhaven Agility Arena.
*/
private val AGILITY_ARENA_HUT = location(2809, 3193, 0)
/**
* Represents the agility ticket exchange interface/component.
*/
private const val TICKET_EXCHANGE_IFACE = Components.AGILITYARENA_TRADE_6
/**
* Represents the back door of the Shrimp and Parrot restaurant used in the Heroes' Quest.
*/
private const val RESTAURANT_REAR_DOOR = Scenery.DOOR_1591
/**
* Represents the door of the Black Arm Gang office used in the Heroes' Quest.
*/
private const val GANG_OFFICE_DOOR = Scenery.DOOR_2626
/**
* Represents the door guarded by Garv on ScarFace Pete's mansion used in the Heroes' Quest.
*/
private const val MANSION_DOOR = Scenery.DOOR_2627
/**
* Represents the kitchen door in the Shrimp and Parrot restaurant used in the Heroes' Quest.
*/
private const val RESTAURANT_KITCHEN_DOOR = Scenery.DOOR_2628
/**
* Represents Lubufu's karambwan fishing spot unlocked in Tai Bwo Wannai Trio.
*/
private const val KARAMBWAN_FISHING_SPOT = NPCs.FISHING_SPOT_1178
}
override fun defineListeners() {
on(AGILITY_ARENA_EXIT_LADDER, IntType.SCENERY, "climb-up") { player, _ ->
ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, AGILITY_ARENA_HUT)
return@on true
}
on(AGILITY_ARENA_ENTRANCE_LADDER, IntType.SCENERY, "climb-down") { player, _ ->
if (!getAttribute(player, "capn_izzy", false)) {
openDialogue(player, CapnIzzyDialogue(1))
return@on true
} else {
ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_DOWN, AGILITY_ARENA)
removeAttribute(player, "capn_izzy")
}
return@on true
}
on(NPCs.CAPN_IZZY_NO_BEARD_437, IntType.NPC, "talk-to") { player, node ->
openDialogue(player, CapnIzzyDialogue(0), node)
return@on true
}
on(NPCs.CAPN_IZZY_NO_BEARD_437, IntType.NPC, "pay") { player, node ->
openDialogue(player, CapnIzzyDialogue(2), node)
return@on true
}
on(NPCs.PIRATE_JACKIE_THE_FRUIT_1055, IntType.NPC, "talk-to") { player, node ->
openDialogue(player, PirateJackieDialogue(), node)
return@on true
}
on(NPCs.PIRATE_JACKIE_THE_FRUIT_1055, IntType.NPC, "trade") { player, _ ->
openInterface(player, TICKET_EXCHANGE_IFACE)
return@on true
}
on(RESTAURANT_REAR_DOOR, IntType.SCENERY, "open") { player, _ ->
sendMessage(player, "You try and open the door...")
sendMessage(player, "The door is locked tight, I can't open it.")
return@on true
}
on(GANG_OFFICE_DOOR, IntType.SCENERY, "open") { player, _ ->
openDialogue(player, 789, Repository.findNPC(789)!!)
return@on true
}
on(MANSION_DOOR, IntType.SCENERY, "open") { player, _ ->
openDialogue(player, 788, Repository.findNPC(788)!!, true)
return@on true
}
on(RESTAURANT_KITCHEN_DOOR, IntType.SCENERY, "open") { player, _ ->
sendMessage(player, "The door is securely closed.")
return@on true
}
on(KARAMBWAN_FISHING_SPOT, IntType.NPC, "fish") { player, _ ->
sendNPCDialogue(
player,
NPCs.LUBUFU_1171,
"Keep off my fishing spot, whippersnapper!",
FacialExpression.FURIOUS
)
return@on true
}
}
}

View file

@ -16,6 +16,7 @@ class KaramjaAchievementDiary : DiaryEventHookBase(DiaryType.KARAMJA) {
companion object { companion object {
private const val ATTRIBUTE_SEAWEED_PICKED = "diary:karamja:seaweed-picked" private const val ATTRIBUTE_SEAWEED_PICKED = "diary:karamja:seaweed-picked"
private const val ATTRIBUTE_PALM_LEAF_PICKED = "diary:karamja:palm-leaf-picked" private const val ATTRIBUTE_PALM_LEAF_PICKED = "diary:karamja:palm-leaf-picked"
private const val ATTRIBUTE_BANANA_PICKED = "diary:karamja:banana-picked"
private val MAIN_ISLAND_AREA = ZoneBorders(2749, 2886, 2972, 3132) private val MAIN_ISLAND_AREA = ZoneBorders(2749, 2886, 2972, 3132)
private val BANANA_FISHING_SPOT_AREA = ZoneBorders(2923, 3173, 2928, 3182) private val BANANA_FISHING_SPOT_AREA = ZoneBorders(2923, 3173, 2928, 3182)
@ -83,6 +84,14 @@ class KaramjaAchievementDiary : DiaryEventHookBase(DiaryType.KARAMJA) {
override fun onResourceProduced(player: Player, event: ResourceProducedEvent) { override fun onResourceProduced(player: Player, event: ResourceProducedEvent) {
when (player.viewport.region.id) { when (player.viewport.region.id) {
10802 -> if (event.itemId == Items.GOLD_ORE_444) {
finishTask(
player,
DiaryLevel.EASY,
EasyTasks.BRIMHAVEN_MINE_GOLD
)
}
11310, 11410 -> if (event.itemId == Items.UNCUT_RED_TOPAZ_1629) { 11310, 11410 -> if (event.itemId == Items.UNCUT_RED_TOPAZ_1629) {
finishTask( finishTask(
player, player,
@ -91,11 +100,13 @@ class KaramjaAchievementDiary : DiaryEventHookBase(DiaryType.KARAMJA) {
) )
} }
10802 -> if (event.itemId == Items.GOLD_ORE_444) { 11569 -> if (event.itemId == Items.BANANA_1963) {
finishTask( progressIncrementalTask(
player, player,
DiaryLevel.EASY, DiaryLevel.EASY,
EasyTasks.BRIMHAVEN_MINE_GOLD EasyTasks.PICK_5_BANANAS,
ATTRIBUTE_BANANA_PICKED,
5
) )
} }
} }

View file

@ -1,254 +0,0 @@
package content.region.karamja.handlers;
import core.cache.def.impl.NPCDefinition;
import core.cache.def.impl.SceneryDefinition;
import core.game.component.Component;
import core.plugin.Initializable;
import org.rs09.consts.Items;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.dialogue.FacialExpression;
import core.game.global.action.ClimbActionHandler;
import core.game.global.action.DoorActionHandler;
import core.game.interaction.OptionHandler;
import core.game.node.Node;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.diary.DiaryType;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.game.node.scenery.SceneryBuilder;
import core.game.world.map.Location;
import core.game.world.repository.Repository;
import core.plugin.Plugin;
/**
* Represents the option plugin used to handle karamaja options.
*
* @author 'Vexia
* @version 1.0
*/
@Initializable
public final class KaramajaOptionPlugin extends OptionHandler {
/**
* Represents the pineapple item.
*/
private static final Item PINEAPPLE = new Item(2114);
/**
* Represents the pine apple objects.
*/
private static final int[] PINEAPPLE_OBJECTS = new int[]{ 1408, 1409, 1410, 1411, 1412, 1413 };
/**
* Represents the musa point dungeon.
*/
private static final Location MUSA_POINT_DUNGEON = Location.create(2856, 9567, 0);
/**
* Represents the volacno rim location.
*/
private static final Location VOLCANO_RIM = new Location(2856, 3167, 0);
/**
* Represents the agility brimhaven location.
*/
private static final Location AGILITY_LOCATION = new Location(2805, 9589, 3);
/**
* Represents the main base asgility location (ground floor)
*/
private static final Location AGILITY_MAIN = new Location(2809, 3193, 0);
/**
* Represents the component.
*/
private static final Component TICKET_EXCHANGE = new Component(6);
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
SceneryDefinition.forId(2078).getHandlers().put("option:search", this);// random crate.
SceneryDefinition.forId(492).getHandlers().put("option:climb-down", this);// musa point rock
SceneryDefinition.forId(1764).getHandlers().put("option:climb", this);// musa dungeon rope
SceneryDefinition.forId(3617).getHandlers().put("option:climb-down", this);// agility ladder
SceneryDefinition.forId(3618).getHandlers().put("option:climb-up", this);// agility ladder
NPCDefinition.forId(437).getHandlers().put("option:pay", this);// capn izzy
NPCDefinition.forId(1055).getHandlers().put("option:trade", this);// capn izzy trader (tickets)
SceneryDefinition.forId(2626).getHandlers().put("option:open", this);// grubors locked door
SceneryDefinition.forId(2628).getHandlers().put("option:open", this);// the shrimp and parrot door (chef)
SceneryDefinition.forId(2627).getHandlers().put("option:open", this);// garv door
SceneryDefinition.forId(1591).getHandlers().put("option:open", this);// garv door
NPCDefinition.forId(1178).getHandlers().put("option:fish", this);// lubufu fishing spot
SceneryDefinition.forId(5083).getHandlers().put("option:enter", this);// sanibock dungeon entrance
SceneryDefinition.forId(2439).getHandlers().put("option:open", this);
for (int pineapple : PINEAPPLE_OBJECTS) {
SceneryDefinition.forId(pineapple).getHandlers().put("option:pick", this);// pineapple picking
}
SceneryDefinition.forId(2975).getHandlers().put("option:shake", this); // leafy palm tree
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
switch (option) {
case "pick":// pineapples.
if (player.getInventory().freeSlots() == 0) {
player.getPacketDispatch().sendMessage("Not enough inventory space.");
return true;
}
final Scenery pineApple = ((Scenery) node);
if (pineApple.getId() == 1413) {
player.getPacketDispatch().sendMessage("There are no pineapples left on this plant.");
return true;
}
boolean last = pineApple.getId() == 14012;
if (player.getInventory().add(PINEAPPLE)) {
SceneryBuilder.replace(pineApple, pineApple.transform(pineApple.getId() + 1), last ? 270 : 40);
player.getPacketDispatch().sendMessage("You pick a pineapple.");
}
break;
case "enter":
switch (((Scenery) node).getId()) {
case 5083:
if (player.getAttribute("saniboch:paid", false) || player.getAchievementDiaryManager().getDiary(DiaryType.KARAMJA).isComplete()) {
ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, Location.create(2713, 9564, 0));
player.removeAttribute("saniboch:paid");
break;
}
player.getDialogueInterpreter().sendDialogues(1595, null, "You can't go in there without paying!");
break;
}
break;
case "trade":
switch (((NPC) node).getId()) {
case 1055:
player.getInterfaceManager().open(TICKET_EXCHANGE);
break;
}
break;
case "fish":
player.getDialogueInterpreter().sendDialogues(1171, FacialExpression.FURIOUS, "Keep off my fishing spot, whippersnapper!");
break;
case "pay":
if (!player.getAttribute("capn_izzy", false)) {
if (player.getInventory().contains(995, 200) && player.getInventory().remove(new Item(995, 200))) {
player.getDialogueInterpreter().sendItemMessage(new Item(995, 200), "You give Cap'n Izzy the 200 coin entrance fee.");
player.getPacketDispatch().sendMessage("You give Cap'n Izzy the 200 coin entrance fee.");
player.setAttribute("/save:capn_izzy", true);
return true;
} else {
player.getPacketDispatch().sendMessage("You don't have the 200 coin entrance fee.");
}
} else {
player.getDialogueInterpreter().sendDialogues(437, null, "Avast there, ye've already paid!");
}
break;
case "pay-fare":
switch (((Scenery) node).getId()) {
case 2230:
player.getPacketDispatch().sendMessage("This cart appears to have been out of reward for some time.");
break;
}
break;
case "climb-up":
switch (((Scenery) node).getId()) {
case 3618:
player.getProperties().setTeleportLocation(AGILITY_MAIN);
break;
}
break;
case "climb-down":
switch (((Scenery) node).getId()) {
case 492:
player.getPacketDispatch().sendMessage("You climb down through the pot hole.");
player.getProperties().setTeleportLocation(MUSA_POINT_DUNGEON);
break;
case 3617:
if (!player.getAttribute("capn_izzy", false)) {
player.getDialogueInterpreter().open(437, Repository.findNPC(437), true);
return true;
}
player.removeAttribute("capn_izzy");
player.getProperties().setTeleportLocation(AGILITY_LOCATION);
break;
}
break;
case "climb":
switch (((Scenery) node).getId()) {
case 1764:
player.getProperties().setTeleportLocation(VOLCANO_RIM);
player.getPacketDispatch().sendMessage("You climb up the hanging rope...");
player.getPacketDispatch().sendMessage("You appear on the volcano rim.");
break;
}
break;
case "open":
switch (((Scenery) node).getId()) {
case 2626:
player.getDialogueInterpreter().open(789, Repository.findNPC(789));
break;
case 2628:
player.getPacketDispatch().sendMessage("The door is securely closed.");
break;
case 2627:
player.getDialogueInterpreter().open(788, Repository.findNPC(788), true);
break;
case 1591:
player.getPacketDispatch().sendMessage("You try and open the door...");
player.getPacketDispatch().sendMessage("The door is locked tight, I can't open it.");
break;
case 2439:
player.getPacketDispatch().sendMessage("The gate doesn't open.");
break;
}
break;
case "search":
switch (((Scenery) node).getId()) {
case 2078:
player.getPacketDispatch().sendMessage("There are no bananas left on the tree.");
break;
}
break;
case "shake":
if (player.getInventory().hasSpaceFor(new Item(Items.PALM_LEAF_2339))) {
player.getPacketDispatch().sendMessage("You shake the tree...");
SceneryBuilder.replace(node.asScenery(), node.asScenery().transform(2976), 60); // 35 second cool-down
player.lock();
final Pulse palmPulse = new Pulse(2) {
@Override
public boolean pulse() {
player.getPacketDispatch().sendMessage("You pick up a fallen palm leaf off of the ground.");
player.getInventory().add(new Item(Items.PALM_LEAF_2339));
// Collect five palm leaves
if (!player.getAchievementDiaryManager().hasCompletedTask(DiaryType.KARAMJA, 2, 7)) {
int palms = player.getAttribute("palms", 0);
palms++;
player.setAttribute("palms", palms);
player.getAchievementDiaryManager().updateTask(player, DiaryType.KARAMJA, 2, 7, palms >= 5);
}
player.unlock();
return true;
}
};
GameWorld.getPulser().submit(palmPulse);
} else {
player.getPacketDispatch().sendMessage("You don't have enough inventory space.");
}
break;
}
return true;
}
@Override
public Location getDestination(Node node, Node n) {
if (n instanceof Scenery) {
if (((Scenery) n).getDefinition().hasAction("open")) {
return DoorActionHandler.getDestination((Player) node, (Scenery) n);
}
}
return null;
}
}

View file

@ -0,0 +1,117 @@
package content.region.karamja.handlers
import core.api.*
import core.game.global.action.ClimbActionHandler
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.interaction.QueueStrength
import core.game.node.item.Item
import org.rs09.consts.*
class KaramjaListeners : InteractionListener {
companion object {
/**
* Represents the Musa Point dungeon location.
*/
private val MUSA_POINT_DUNGEON = location(2856, 9567, 0)
/**
* Represents the volcano rim location.
*/
private val VOLCANO_RIM = location(2856, 3167, 0)
/**
* Represents the rocks used to enter the Musa Point dungeon.
*/
private const val MUSA_POINT_DUNGEON_ENTRANCE = Scenery.ROCKS_492
/**
* Represents the rope used to exit the Musa Point dungeon.
*/
private const val MUSA_POINT_DUNGEON_EXIT = Scenery.CLIMBING_ROPE_1764
/**
* Represents the pineapple plant objects.
*/
private val PINEAPPLE_PLANT = intArrayOf(
Scenery.PINEAPPLE_PLANT_1408, Scenery.PINEAPPLE_PLANT_1409,
Scenery.PINEAPPLE_PLANT_1410, Scenery.PINEAPPLE_PLANT_1411,
Scenery.PINEAPPLE_PLANT_1412, Scenery.PINEAPPLE_PLANT_1413
)
private const val PICK_PINEAPPLE_ANIMATION = 2282
private const val PINEAPPLE = Items.PINEAPPLE_2114
private const val SHAKE_TREE_ANIMATION = 2572
private const val PALM_LEAF = Items.PALM_LEAF_2339
private const val PALM_TREE_FULL = Scenery.LEAFY_PALM_TREE_2975
private const val PALM_TREE_EMPTY = Scenery.LEAFY_PALM_TREE_2976
}
override fun defineListeners() {
on(MUSA_POINT_DUNGEON_ENTRANCE, IntType.SCENERY, "climb-down") { player, _ ->
ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_DOWN, MUSA_POINT_DUNGEON)
sendMessage(player, "You climb down through the pot hole.")
return@on true
}
on(MUSA_POINT_DUNGEON_EXIT, IntType.SCENERY, "climb-up") { player, _ ->
ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, VOLCANO_RIM)
sendMessage(player, "You climb up the hanging rope...")
sendMessage(player, "You appear on the volcano rim.")
return@on true
}
on(PINEAPPLE_PLANT, IntType.SCENERY, "pick") { player, node ->
// TODO: Convert FieldPickingPlugin to Kotlin & include this.
if (!hasSpaceFor(player, Item(PINEAPPLE))) {
sendMessage(player, "You don't have enough space in your inventory.")
return@on true
}
if (node.id == Scenery.PINEAPPLE_PLANT_1413) {
sendMessage(player, "There are no pineapples left on this plant.")
return@on true
}
val last: Boolean = node.id == Scenery.PINEAPPLE_PLANT_1412
if (addItem(player, PINEAPPLE)) {
animate(player, PICK_PINEAPPLE_ANIMATION)
playAudio(player, Sounds.PICK_2581, 30)
replaceScenery(node.asScenery(), node.id + 1, if (last) 270 else 40)
sendMessage(player, "You pick a pineapple.")
}
return@on true
}
on(Scenery.BANANA_TREE_2078, IntType.SCENERY, "search") { player, _ ->
// TODO: Convert FieldPickingPlugin to Kotlin & include this.
sendMessage(player, "There are no bananas left on the tree.")
return@on true
}
on(PALM_TREE_FULL, IntType.SCENERY, "Shake") { player, node ->
queueScript(player, 0, QueueStrength.WEAK) { stage: Int ->
when (stage) {
0 -> {
lock(player, 2)
face(player, node)
animate(player, SHAKE_TREE_ANIMATION)
sendMessage(player, "You give the tree a good shake.")
replaceScenery(node.asScenery(), PALM_TREE_EMPTY, 60)
return@queueScript delayScript(player, 2)
}
1 -> {
produceGroundItem(
player,
PALM_LEAF,
1,
getPathableRandomLocalCoordinate(player, 1, node.location)
)
sendMessage(player, "A palm leaf falls to the ground.")
return@queueScript stopExecuting(player)
}
else -> return@queueScript stopExecuting(player)
}
}
return@on true
}
}
}