Lost City Update

Convert Lost City quest from Java to Kotlin
Fixed certain weapons not being properly locked behind Lost City quest
Fixed bugs in quest level requirements
Zanaris entry fairy ring now returns players to the shed when they use it
Warrior dialogue missing lines and facial expressions added in
Fixed warrior dialogue issue, you can now start the lost city quest
Fairy rings are now enabled when the lost city quest is complete and you are wielding a dramen staff or lunar staff
This commit is contained in:
MatthewGould123
2022-09-14 08:59:41 +00:00
committed by Ryan
parent 0db90b60f1
commit 854b8cdc6b
18 changed files with 445 additions and 887 deletions
@@ -1,54 +0,0 @@
package core.game.content.quest.members.lostcity;
import core.game.interaction.NodeUsageEvent;
import core.game.interaction.UseWithHandler;
import core.game.node.entity.player.Player;
import core.game.node.entity.skill.Skills;
import core.game.node.item.Item;
import core.plugin.Plugin;
/**
* Handles the dramen staff cutting plugin.
* @author Vexia
*/
public final class DramenStaffPlugin extends UseWithHandler {
/**
* The dramen branch item.
*/
private static final Item DRAMEN_BRANCH = new Item(771);
/**
* The dramen staff item.
*/
private static final Item DRAMEN_STAFF = new Item(772);
/**
* Constructs a new {@code DramenStaffPlugin} {@code Object}.
*/
public DramenStaffPlugin() {
super(DRAMEN_BRANCH.getId());
}
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
addHandler(946, ITEM_TYPE, this);
return this;
}
@Override
public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer();
if (player.getInventory().containsItem(DRAMEN_BRANCH) && player.getSkills().hasLevel(Skills.CRAFTING,31)) {
player.getInventory().remove(DRAMEN_BRANCH);
player.getInventory().add(DRAMEN_STAFF);
player.getDialogueInterpreter().sendDialogue("You carve the branch into a staff.");
}else{
player.getDialogueInterpreter().sendDialogue("You need a crafting level of 31 to do this.");
return false;
}
player.lock(1);
return true;
}
}
@@ -1,104 +0,0 @@
package core.game.content.quest.members.lostcity;
import core.game.node.entity.skill.Skills;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.quest.Quest;
import core.game.node.item.Item;
import core.plugin.Initializable;
import rs09.plugin.ClassScanner;
/**
* The main type for the lost city Quest.
* @author Vexia
* @author Aero
*/
@Initializable
public class LostCity extends Quest {
/**
* The requirement titles.
*/
private static final String[] TITLES = new String[] { "Level 31 Crafting", "Level 36 Woodcutting" };
/**
* The dramen staff item.
*/
private static final Item DRAMEN_STAFF = new Item(772);
/**
* The quest requirements.
*/
private boolean[] questRequirements = new boolean[2];
/**
* Constructs a new {@code LostCity} {@code Object}.
*/
public LostCity() {
super("Lost City", 83, 82, 3, 147, 0, 1, 6);
}
@Override
public void drawJournal(Player player, int stage) {
super.drawJournal(player, stage);
switch (stage) {
case 0:
line(player, BLUE + "I can start this quest by speaking to the Adventurers in", 4+ 7);
line(player, BLUE + "the Swamp just south of Lumbridge.", 5+ 7);
drawQuestRequirements(player);
break;
case 10:
line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><blue>Apparently there is a <red>leprechaun<blue> hiding in a <red>tree<blue> nearby<br><br><blue>who can tell me how to enter the <red>Lost City of Zanaris", 4+ 7);
break;
case 20:
line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><str>I found the Leprechaun hiding in a nearby tree.<br><br><blue>He told me that the entrance to <red>Zanaris<blue> is in the <red>shed<blue> in<br><br><red>Lumbridge swamp<blue> but only if I am carrying a <red>Dramen Staff<br><br><blue>I can find a <red>Dramen Tree <blue>in a cave on <red>Entrana <blue>somewhere", 4+ 7);
break;
case 21:
if (player.getBank().containsItem(DRAMEN_STAFF) || player.getInventory().containsItem(DRAMEN_STAFF) || player.getEquipment().containsItem(DRAMEN_STAFF)) {
line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><str>I found the Leprechaun hiding in a nearby tree.<br><br><str>He told me that the entrance to Zanaris is in the shed in<br><br><str>Lumbridge swamp but only if I am carrying a Dramen Staff.<br><br><str>The Dramen Tree was guarded by a powerful Tree Spirit.<br><br><str>I cut a branch from the tree and crafted a Dramen Staff.<br><br><blue>I should enter <red>Zanaris <blue>by going to the <red>shed <blue>in <red>Lumbridge<br><br><red>Swamp <blue>while keeping the <red>Dramen staff<blue> with me", 4+ 7);
} else {
line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><str>I found the Leprechaun hiding in a nearby tree.<br><br><str>He told me that the entrance to Zanaris is in the shed in<br><br><str>Lumbridge swamp but only if I am carrying a Dramen Staff.<br><br><str>The Dramen Tree was guarded by a powerful Tree Spirit.<br><br><blue>With the <red>Spirit <blue>defeated I can cut a <red>branch <blue>from the tree", 4+ 7);
}
break;
case 100:
line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><str>I found the Leprechaun hiding in a nearby tree.<br><br><str>He told me that the entrance to Zanaris is in the shed in<br><br><str>Lumbridge swamp but only if I am carrying a Dramen Staff.<br><br><str>The Dramen Tree was guarded by a powerful Tree Spirit.<br><br><str>I cut a branch from the tree and crafted a Dramen Staff.<br><br><str>With the mystical Dramen Staff in my possession I was<br><br><str>able to enter Zanaris through the shed in Lumbridge<br><br><str>swamp.<br><br><br><col=FF0000>QUEST COMPLETE!", 4+ 7);
break;
}
}
@Override
public void finish(Player player) {
super.finish(player);
player.getPacketDispatch().sendString("3 Quest Points", 277, 8+ 2);
player.getPacketDispatch().sendString("Access to Zanaris", 277, 9+ 2);
player.getPacketDispatch().sendItemZoomOnInterface(772, 235, 277, 3+ 2);
player.getQuestRepository().syncronizeTab(player);
}
/**
* Draws the quest requirements onto the journal component.
* @param player The player to draw the requirements for.
*/
private final void drawQuestRequirements(final Player player) {
int line = 7 + 7;
questRequirements[0] = player.getSkills().getStaticLevelByExperience(Skills.CRAFTING) > 30;
questRequirements[1] = player.getSkills().getStaticLevelByExperience(Skills.WOODCUTTING) > 35;
line(player, BLUE + "To complete this quest I will need:", 6);
for (int i = 0; i < questRequirements.length; i++) {
boolean bool = !questRequirements[i];
String str = TITLES[i];
line(player, (bool ? RED + str : str), line++, !bool);
}
line(player, BLUE + "and be able to defeat a " + RED + "Level 101 Spirit without weapons", line++);
}
@Override
public Quest newInstance(Object object) {
ClassScanner.definePlugin(new LostCityPlugin());
ClassScanner.definePlugin(new TreeSpiritNPC());
ClassScanner.definePlugin(new ShamusDialogue());
ClassScanner.definePlugin(new WarriorDialogue());
ClassScanner.definePlugin(new DramenStaffPlugin());
return this;
}
}
@@ -1,139 +0,0 @@
package core.game.content.quest.members.lostcity;
import core.cache.def.impl.ItemDefinition;
import core.cache.def.impl.SceneryDefinition;
import core.game.content.dialogue.FacialExpression;
import core.game.content.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.TeleportManager.TeleportType;
import core.game.node.entity.player.link.quest.Quest;
import core.game.node.entity.skill.gather.SkillingTool;
import core.game.node.item.Item;
import core.game.node.scenery.Scenery;
import core.game.system.task.Pulse;
import core.game.world.map.Location;
import core.plugin.Plugin;
import rs09.game.interaction.InteractionListeners;
import rs09.game.world.GameWorld;
/**
* Handles the lost city quest.
* @author Vexia
*/
public final class LostCityPlugin extends OptionHandler {
/**
* The dramen staff item.
*/
private static final Item DRAMEN_STAFF = new Item(772);
/**
* The shamus npc.
*/
public static NPC SHAMUS;
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
ItemDefinition.forId(1305).getHandlers().put("option:wield", this);
ItemDefinition.forId(1215).getHandlers().put("option:wield", this);
ItemDefinition.forId(1231).getHandlers().put("option:wield", this);
ItemDefinition.forId(5680).getHandlers().put("option:wield", this);
SceneryDefinition.forId(2409).getHandlers().put("option:chop", this);
SceneryDefinition.forId(2406).getHandlers().put("option:open", this);
return this;
}
@Override
public boolean handle(Player player, Node node, String option) {
final Quest quest = player.getQuestRepository().getQuest("Lost City");
switch (node.getId()) {
case 2409:
handleShamusTree(player, quest);
break;
case 2406:
final boolean dramenTeleport = player.getEquipment().containsItem(DRAMEN_STAFF) && quest.getStage(player) > 20 && player.getLocation().getX() <= 3201;
DoorActionHandler.handleAutowalkDoor(player, (Scenery) node);
if (dramenTeleport) {
player.getPacketDispatch().sendMessage("The world starts to shimmer...");
player.getTeleporter().send(Location.create(2452, 4473, 0), TeleportType.FAIRY_RING);
}
break;
case 1305:
case 1215:
case 1231:
case 5680:
if (!player.getQuestRepository().isComplete("Lost City")) {
player.getPacketDispatch().sendMessage("You need to have completed the Lost City quest in order to wield that weapon.");
return true;
}
return InteractionListeners.run(node.getId(),0,"equip",player,node);
}
return true;
}
/**
* Handles the shamus tree interaction.
* @param player the player.
* @param quest the quest.
*/
private void handleShamusTree(Player player, Quest quest) {
if (SkillingTool.getHatchet(player) == null) {
player.getPacketDispatch().sendMessage("You do not have an axe which you have the level to use.");
return;
}
if (SHAMUS == null) {
initializeShamus();
}
if (SHAMUS.isInvisible()) {
showShamus();
return;
}
player.getDialogueInterpreter().sendDialogues(SHAMUS, FacialExpression.FURIOUS, "Hey! Yer big elephant! Don't go choppin' down me", "house, now!");
}
/**
* Shows the shamus npc.
*/
private void showShamus() {
if (SHAMUS == null) {
initializeShamus();
}
SHAMUS.setInvisible(false);
SHAMUS.getProperties().setTeleportLocation(SHAMUS.getProperties().getSpawnLocation());
GameWorld.getPulser().submit(new Pulse(100, SHAMUS) {
@Override
public boolean pulse() {
if (SHAMUS.getDialoguePlayer() != null) {
return false;
}
SHAMUS.setInvisible(true);
return true;
}
});
}
/**
* Initializes the shamus npc.
*/
private void initializeShamus() {
if (SHAMUS == null) {
SHAMUS = NPC.create(654, Location.create(3138, 3211, 0));
}
SHAMUS.init();
SHAMUS.setWalks(true);
SHAMUS.setInvisible(true);
}
@Override
public boolean isWalk(Player player, Node node) {
return !(node instanceof Item);
}
@Override
public boolean isWalk() {
return false;
}
}
@@ -1,164 +0,0 @@
package core.game.content.quest.members.lostcity;
import core.game.content.dialogue.DialoguePlugin;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.quest.Quest;
import rs09.game.content.quest.members.lostcity.ShamusTreeListener;
/**
* Handles the shamus npc dialogue.
* @author Vexia
*/
public final class ShamusDialogue extends DialoguePlugin {
/**
* The quest.
*/
private Quest quest;
/**
* Constructs a new {@code ShamusDialogue} {@code Object}.
*/
public ShamusDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code ShamusDialogue} {@code Object}.
* @param player the player.
*/
public ShamusDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new ShamusDialogue(player);
}
@Override
public boolean open(Object... args) {
quest = player.getQuestRepository().getQuest("Lost City");
npc("Ay yer big elephant! Yer've caught me, to be sure!", "What would an elephant like yer be wanting wid ol'", "Shamus then?");
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (quest.getStage(player)) {
case 0:
switch (stage) {
case 0:
player("I'm not sure.");
stage++;
break;
case 1:
npc("Well you'll have to be catchin' me again when yer are,", "elephant!");
stage++;
break;
case 2:
disappear();
break;
case 3:
end();
break;
}
break;
case 10:
switch (stage) {
case 0:
player("I want to find Zanaris.");
stage++;
break;
case 1:
npc("Zanaris is it now? Well well well... Yer'll be needing to", "be going further to that funny little shed out there in the", "swamp, so you will.");
stage++;
break;
case 2:
player("...but... I thought... Zanaris was a city?");
stage++;
break;
case 3:
npc("Aye that it is!");
stage++;
break;
case 4:
player("...How does it fit in a shed then?");
stage++;
break;
case 5:
npc("Ah yer stupid elephant! The city isn't IN the shed! The", "doorway to the shed is being a portal to Zanaris, so it", "is.");
stage++;
break;
case 6:
player("So I just walk into the shed and end up in Zanaris", "then?");
stage++;
break;
case 7:
npc("Oh, was I fergetting to say? Yer need to be carrying a", "Dramenwood staff to be getting there! Otherwise Yer'll", "just be ending up in the shed.");
stage++;
break;
case 8:
player("So where would I get a staff?");
stage++;
break;
case 9:
npc("Dramenwood staffs are crafted from branches of the", "Dramen tree, so they are. I hear there's a Dramen", "tree over on the island of Entrana in a cave.");
stage++;
break;
case 10:
npc("or some such. There would be probably be a good place", "for an elephant like yer to be starting looking I reckon.");
stage++;
break;
case 11:
npc("The monks are running a ship from Port Sarim to", "Entrana, I hear too. Now leave me alone yer elephant!");
stage++;
break;
case 12:
disappear();
break;
case 13:
quest.setStage(player, 20);
end();
break;
}
break;
default:
switch (stage) {
case 0:
player("I'm not sure.");
stage++;
break;
case 1:
npc("HA! Look at yer! Look at the supid elephant who tries", "to go catching a leprechaun when he don't even be", "knowing what he wants!");
increment();
break;
case 2:
disappear();
break;
case 3:
end();
break;
}
break;
}
return true;
}
/**
* Makes dhamus disappear.
*/
private void disappear() {
ShamusTreeListener.Companion.disappearShamus();
interpreter.sendPlainMessage(false, "The leprechaun magically disappears.");
stage++;
}
@Override
public int[] getIds() {
return new int[] { 654 };
}
}
@@ -1,101 +0,0 @@
package core.game.content.quest.members.lostcity;
import core.game.node.entity.Entity;
import core.game.node.entity.combat.CombatStyle;
import core.game.node.entity.npc.AbstractNPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.quest.Quest;
import core.game.world.map.Location;
/**
* Handles the tree spirit npc.
* @author Vexia
*/
public final class TreeSpiritNPC extends AbstractNPC {
/**
* The player.
*/
private Player player;
/**
* Constructs a new {@code TreeSpiritNPC} {@code Object}.
* @param id the id.
* @param location the location.
*/
public TreeSpiritNPC(int id, Location location) {
super(id, location);
}
/**
* Constructs a new {@code TreeSpiritNPC} {@code Object}.
*/
public TreeSpiritNPC() {
super(0, null);
}
@Override
public void handleTickActions() {
super.handleTickActions();
if (!inCombat()) {
attack(player);
}
if (!player.isActive() || player.getLocation().getDistance(getLocation()) > 15) {
clear();
}
}
@Override
public void clear() {
super.clear();
player.removeAttribute("treeSpawned");
}
@Override
public boolean isAttackable(Entity entity, CombatStyle style, boolean message) {
if (entity != player) {
return false;
}
return super.isAttackable(entity, style, message);
}
@Override
public void finalizeDeath(Entity killer) {
super.finalizeDeath(killer);
if (killer instanceof Player) {
Player player = (Player) killer;
Quest quest = player.getQuestRepository().getQuest("Lost City");
if (quest.getStage(player) == 20) {
quest.setStage(player, 21);
player.getDialogueInterpreter().sendPlainMessage(false, "With the Tree Spirit defeated you can now chop the tree.");
}
}
}
@Override
public AbstractNPC construct(int id, Location location, Object... objects) {
return new TreeSpiritNPC(id, location);
}
@Override
public int[] getIds() {
return new int[] { 655 };
}
/**
* Sets the player.
* @param player the player.
*/
public void setPlayer(Player player) {
this.player = player;
}
/**
* Gets the player.
* @return The player.
*/
public Player getPlayer() {
return player;
}
}
@@ -1,282 +0,0 @@
package core.game.content.quest.members.lostcity;
import core.game.content.dialogue.DialoguePlugin;
import core.game.content.dialogue.FacialExpression;
import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.quest.Quest;
/**
* Handles the warriors dialogue in the lost city quest.
* @author Vexia
* @version 1.0
*/
public final class WarriorDialogue extends DialoguePlugin {
/**
* Represents the quest.
*/
private Quest quest;
/**
* Constructs a new {@code WarriorDialogue} {@code Object}.
*/
public WarriorDialogue() {
/**
* empty.
*/
}
/**
* Constructs a new {@code WarriorDialogue} {@code Object}.
* @param player the player.
*/
public WarriorDialogue(Player player) {
super(player);
}
@Override
public DialoguePlugin newInstance(Player player) {
return new WarriorDialogue(player);
}
@Override
public boolean open(Object... args) {
npc = (NPC) args[0];
quest = player.getQuestRepository().getQuest("Lost City");
switch (quest.getStage(player)) {
case 10:
player("So let me get this straight: I need to search the trees", "around here for a leprechaun; and then when I find", "him, he will tell me where this 'Zanaris' is?");
break;
case 20:
case 21:
player("Have you found anything yet?");
break;
case 100:
player("Hey, thanks for all the information. It REALLY helped", "me out in finding the lost city of Zanaris and all.");
break;
default:
interpreter.sendDialogues(npc, FacialExpression.HALF_GUILTY, "Hello there traveller.");
break;
}
return true;
}
@Override
public boolean handle(int interfaceId, int buttonId) {
switch (quest.getStage(player)) {
case 0:
handleFirstStage(buttonId);
break;
case 10:
switch (stage) {
case 0:
npc("What? How did you know that? Uh... I mean, no, no", "you're very wrong. Very wrong, and not right at all,", "and I definitely didn't tell you about that at all.");
stage++;
break;
case 1:
end();
break;
}
break;
case 20:
case 21:
switch (stage) {
case 0:
npc("We're still searching for Zanaris...GAH! I mean we're", "not doing anything here at all.");
stage++;
break;
case 1:
player("I haven't found it yet either.");
stage++;
break;
case 2:
end();
break;
}
break;
case 100:
switch (stage) {
case 0:
npc("Oh please don't say that anymore! If the rest of my", "party knew I'd helped you they'd probably throw me", "out and make me walk home by myself!");
stage++;
break;
case 1:
end();
break;
}
break;
}
return true;
}
/**
* Handles the first dialogue quest stage.
* @param buttonId the buttonId.
*/
private void handleFirstStage(int buttonId) {
switch (stage) {
case 0:
options("Why are you camped out here for?", "Do you know any good adventures I can go on?");
stage++;
break;
case 1:
switch (buttonId) {
case 1:
player("What are you camped here for?");
stage++;
break;
case 2:
player("Do you know any good adventurers I can go on?");
stage = 50;
break;
}
break;
case 2:
npc("We're looking for Zanaris...GAH! I mean we're not", "here for any particular reason at all.");
stage++;
break;
case 3:
options("Who's Zanaris?", "What's Zanaris?", "What makes you think it's out here?");
stage++;
break;
case 4:
switch (buttonId) {
case 1:
player("Who's Zanaris?");
stage = 10;
break;
case 2:
player("What's Zanaris?");
stage = 20;
break;
case 3:
player("What makes you think it's out here?");
stage = 30;
break;
}
break;
case 10:
npc("Ahahahaha! Zanaris isn't a person! It's a magical hidden", "city filled with treasure and rich... uh, nothing. It's", "nothing.");
stage = 31;
break;
case 20:
npc("I don't think we want other people competing with us to", "find it. Forget I said anything.");
stage = 34;
break;
case 30:
npc("Don't you know of the legends that tell of the magical", "city, hidden in the swamp... Uh, no, you're right, we're", "wasting our time here.");
stage++;
break;
case 31:
options("If it's hidden how are you planning to find it?", "There's no such thing!");
stage++;
break;
case 32:
switch (buttonId) {
case 1:
player("If it's hidden how are you planning to find it?");
stage = 33;
break;
case 2:
player("There's no such thing!");
stage = 33;
break;
}
break;
case 33:
npc("Well, we don't want to tell anyone else about that,", "because we don't want anyone else sharing in all that", "glory and treasure.");
stage++;
break;
case 34:
options("Please tell me.", "Looks like you don't know either.");
stage++;
break;
case 35:
switch (buttonId) {
case 1:
player("Please tell me?");
stage = 37;
break;
case 2:
player("Well, it looks to me like YOU don't know EITHER", "seeing as you're all just sat around here.");
stage = 60;
break;
}
break;
case 37:
npc("No.");
stage++;
break;
case 38:
player("Please?");
stage++;
break;
case 39:
npc("No!");
stage++;
break;
case 40:
player("PLEEEEEEEEEEEEEEEEEEEEEEEEESE???");
stage = 42;
break;
case 42:
npc("NO!");
stage++;
break;
case 43:
end();
break;
case 41:
npc("When we've found Zanaris you'll... GAH! I mean, we're", "not here for any particular reason at all.");
stage = 3;
break;
case 50:
npc("Well we're on an adventure right now. Mind you, this", "is OUR adventure and we don't want to share it - find", "your own!");
stage++;
break;
case 51:
end();
break;
case 60:
if (quest.hasRequirements(player)) {
npc("Of course we know! We just haven't found which tree", "the stupid leprechaun's hiding in yet!");
stage++;
} else {
npc("When we've found Zanaris you'll... GAH! I mean, we're", "not here for any particular reason at all.");
stage = 3;
}
break;
case 61:
npc("GAH! I didn't mean to tell you that! Look, just forget I", "said anything okay?");
stage++;
break;
case 62:
player("So a leprechaun knows where Zanaris is eh?");
stage++;
break;
case 63:
npc("Ye.. uh, no. No, not at all. And even if he did - which", "he doesn't he DEFINITELY ISN'T hiding in some", "tree around here. Nope, definitely not. Honestly.");
stage++;
break;
case 64:
player("Thanks for the help!");
stage++;
break;
case 65:
npc("Help? What help? I didn't help! Please don't say I did,", "I'll get in trouble!");
stage++;
break;
case 66:
end();
quest.start(player);
break;
}
}
@Override
public int[] getIds() {
return new int[] { 650 };
}
}
@@ -4,7 +4,6 @@ import rs09.ServerConstants;
import core.game.node.entity.Entity; import core.game.node.entity.Entity;
import core.game.node.entity.impl.Animator.Priority; import core.game.node.entity.impl.Animator.Priority;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.entity.player.link.quest.Quest;
import core.game.node.entity.player.link.audio.Audio; import core.game.node.entity.player.link.audio.Audio;
import core.game.system.task.Pulse; import core.game.system.task.Pulse;
import rs09.game.world.GameWorld; import rs09.game.world.GameWorld;
@@ -448,15 +447,6 @@ public class TeleportManager {
} }
break; break;
case 4: case 4:
Quest quest = null;
if (entity instanceof Player) {
quest = ((Player) entity).getQuestRepository().getQuest("Lost City");
}
if (quest != null) {
if (quest.getStage(entity.asPlayer()) == 21) {
quest.finish(entity.asPlayer());
}
}
entity.animate(Animation.create(3266)); entity.animate(Animation.create(3266));
entity.getProperties().setTeleportLocation(location); entity.getProperties().setTeleportLocation(location);
entity.unlock(); entity.unlock();
@@ -83,7 +83,7 @@ public enum SkillingResource {
/** /**
* Dramen tree (Woodcutting/Lost city quest). * Dramen tree (Woodcutting/Lost city quest).
*/ */
DRAMEN_TREE(1292, 1, 0.05, -1, 25.0, 771, Integer.MAX_VALUE, "dramen tree", null, -1, Skills.WOODCUTTING), DRAMEN_TREE(1292, 36, 0.05, -1, 25.0, 771, Integer.MAX_VALUE, "dramen tree", null, -1, Skills.WOODCUTTING),
/** /**
* Evergreen (Woodcutting). * Evergreen (Woodcutting).
@@ -306,7 +306,7 @@ public enum WoodcuttingNode {
respawnRate = -1; respawnRate = -1;
rate = 0.05; rate = 0.05;
experience = 25.0; experience = 25.0;
level = 1; level = 36;
rewardAmount = Integer.MAX_VALUE; rewardAmount = Integer.MAX_VALUE;
break; break;
case 30: case 30:
@@ -1,41 +1,44 @@
package rs09.game.content.quest.members.thelostcity package rs09.game.content.quest.members.lostcity
import core.game.content.quest.members.lostcity.TreeSpiritNPC
import core.game.node.scenery.Scenery import core.game.node.scenery.Scenery
import core.game.node.entity.skill.gather.woodcutting.WoodcuttingSkillPulse
import core.game.node.entity.skill.gather.SkillingTool import core.game.node.entity.skill.gather.SkillingTool
import core.game.node.entity.skill.gather.woodcutting.WoodcuttingSkillPulse
import core.game.world.map.Location import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery as Sceneries
import rs09.game.interaction.InteractionListener import rs09.game.interaction.InteractionListener
import api.questStage
import api.sendMessage
@Initializable
class DramenTreeListener : InteractionListener { class DramenTreeListener : InteractionListener {
val DRAMEN_TREE = 1292
override fun defineListeners() { override fun defineListeners() {
on(DRAMEN_TREE,SCENERY,"chop down"){ player, node -> on(Sceneries.DRAMEN_TREE_1292,SCENERY,"chop down"){ player, node ->
val quest = player.questRepository.getQuest("Lost City") val questStage = questStage(player,"Lost City")
if (SkillingTool.getHatchet(player) == null) { if (SkillingTool.getHatchet(player) == null) {
player.getPacketDispatch().sendMessage("You do not have an axe which you have the level to use.") sendMessage(player,"You do not have an axe which you have the level to use.")
return@on true return@on true
} }
if (quest.getStage(player) < 20) { if (questStage < 20) {
return@on true return@on true
} }
if (quest.getStage(player) == 20) { if (questStage == 20) {
if (player.getAttribute("treeSpawned", false)) { if (player.getAttribute("treeSpawned", false)) {
return@on true return@on true
} }
val spirit = TreeSpiritNPC.create(655, Location.create(2862, 9734, 0)) as TreeSpiritNPC val spirit = TreeSpiritNPC(NPCs.TREE_SPIRIT_655, Location(2862, 9734, 0))
spirit.player = player spirit.target = player
spirit.isRespawn = false
spirit.init() spirit.init()
spirit.attack(player) spirit.attack(player)
player.setAttribute("treeSpawned", true) player.setAttribute("treeSpawned", true)
spirit.sendChat("You must defeat me before touching the tree!") spirit.sendChat("You must defeat me before touching the tree!")
return@on true return@on true
} }
player.getPulseManager().run(WoodcuttingSkillPulse(player, node as Scenery?))
player.pulseManager.run(WoodcuttingSkillPulse(player, node as Scenery))
return@on true return@on true
} }
@@ -0,0 +1,74 @@
package rs09.game.content.quest.members.lostcity
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.game.node.item.Item
import core.plugin.Initializable
import org.rs09.consts.Items
/**
* LostCity class for the Lost City quest
* @author lila
* @author Vexia
* @author Aero
*/
@Initializable
class LostCity : Quest("Lost City", 83, 82, 3, 147, 0, 1, 6) {
class SkillRequirement(val skill: Int?, val level: Int?)
val requirements = arrayListOf<LostCity.SkillRequirement>()
override fun finish(player: Player?) {
player ?: return
super.finish(player)
var line = 10
player.packetDispatch.sendItemZoomOnInterface(Items.DRAMEN_STAFF_772, 235, 277, 3 + 2)
drawReward(player,"3 Quest points",line++)
drawReward(player,"Access to Zanaris",line++)
player.questRepository.syncronizeTab(player)
}
override fun drawJournal(player: Player, stage: Int) {
super.drawJournal(player, stage)
when (stage) {
0 -> {
line(player, BLUE + "I can start this quest by speaking to the Adventurers in", 4 + 7)
line(player, BLUE + "the Swamp just south of Lumbridge.", 5 + 7)
drawQuestRequirements(player)
}
10 -> line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><blue>Apparently there is a <red>leprechaun<blue> hiding in a <red>tree<blue> nearby<br><br><blue>who can tell me how to enter the <red>Lost City of Zanaris", 4 + 7)
20 -> line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><str>I found the Leprechaun hiding in a nearby tree.<br><br><blue>He told me that the entrance to <red>Zanaris<blue> is in the <red>shed<blue> in<br><br><red>Lumbridge swamp<blue> but only if I am carrying a <red>Dramen Staff<br><br><blue>I can find a <red>Dramen Tree <blue>in a cave on <red>Entrana <blue>somewhere", 4 + 7)
21 -> if (player.hasItem(Item(Items.DRAMEN_STAFF_772,1))) {
line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><str>I found the Leprechaun hiding in a nearby tree.<br><br><str>He told me that the entrance to Zanaris is in the shed in<br><br><str>Lumbridge swamp but only if I am carrying a Dramen Staff.<br><br><str>The Dramen Tree was guarded by a powerful Tree Spirit.<br><br><str>I cut a branch from the tree and crafted a Dramen Staff.<br><br><blue>I should enter <red>Zanaris <blue>by going to the <red>shed <blue>in <red>Lumbridge<br><br><red>Swamp <blue>while keeping the <red>Dramen staff<blue> with me", 4 + 7)
} else {
line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><str>I found the Leprechaun hiding in a nearby tree.<br><br><str>He told me that the entrance to Zanaris is in the shed in<br><br><str>Lumbridge swamp but only if I am carrying a Dramen Staff.<br><br><str>The Dramen Tree was guarded by a powerful Tree Spirit.<br><br><blue>With the <red>Spirit <blue>defeated I can cut a <red>branch <blue>from the tree", 4 + 7)
}
100 -> line(player, "<str>According to one of the adventurers in Lumbridge Swamp<br><br><str>the entrance to Zanaris is somewhere around there.<br><br><str>I found the Leprechaun hiding in a nearby tree.<br><br><str>He told me that the entrance to Zanaris is in the shed in<br><br><str>Lumbridge swamp but only if I am carrying a Dramen Staff.<br><br><str>The Dramen Tree was guarded by a powerful Tree Spirit.<br><br><str>I cut a branch from the tree and crafted a Dramen Staff.<br><br><str>With the mystical Dramen Staff in my possession I was<br><br><str>able to enter Zanaris through the shed in Lumbridge<br><br><str>swamp.<br><br><br><col=FF0000>QUEST COMPLETE!", 4 + 7)
}
}
private fun drawQuestRequirements(player: Player) {
var line = 7 + 7
val questRequirements = arrayOf<String>(
"Level 31 Crafting",
"Level 36 Woodcutting"
)
val hasRequirements = booleanArrayOf(
player.getSkills().hasLevel(Skills.CRAFTING, 31),
player.getSkills().hasLevel(Skills.WOODCUTTING,35)
)
line(player, BLUE + "To complete this quest I will need:", 6)
for (i in 0..1) {
line(player, questRequirements[i], line++, hasRequirements[i])
}
line(player, BLUE + "and be able to defeat a " + RED + "Level 101 Spirit without weapons", line++)
}
override fun newInstance(`object`: Any?): Quest {
requirements.add(SkillRequirement(Skills.WOODCUTTING, 36))
requirements.add(SkillRequirement(Skills.CRAFTING, 31))
return this
}
}
@@ -0,0 +1,69 @@
package rs09.game.content.quest.members.lostcity
import api.*
import core.game.content.global.action.DoorActionHandler
import core.game.node.entity.player.link.TeleportManager.TeleportType
import core.game.node.entity.skill.Skills
import core.game.node.item.Item
import core.game.node.scenery.Scenery
import core.game.system.task.Pulse
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.Scenery as Sceneries
import rs09.game.interaction.InteractionListener
import rs09.game.world.GameWorld
/**
* This class covers some listeners for the Lost City quest
* @author lila
*/
@Initializable
class LostCityListeners : InteractionListener {
override fun defineListeners() {
// the shed teleport, to allow players to access zanaris if they enter the shed while wielding the dramen staff
on(Sceneries.DOOR_2406,SCENERY,"open"){ player, node ->
DoorActionHandler.handleAutowalkDoor(player,node as Scenery)
val quest = "Lost City"
val isOutsideShed = player.location.x < node.location.x
val canDramenTeleport = inEquipment(player,Items.DRAMEN_STAFF_772) && ( questStage(player,quest) > 20 ) && isOutsideShed
if(canDramenTeleport) {
var count = 0
// pulser to handle the teleport. after 2 ticks it checks if the player hasnt completed lost city; if so, then it finishes the quest after the teleport
GameWorld.Pulser.submit(object : Pulse(2) {
override fun pulse(): Boolean {
when (count++) {
0 -> {
sendMessage(player,"The world starts to shimmer...")
teleport(player, Location(2452, 4473, 0), TeleportType.FAIRY_RING)
}
1 -> return isQuestComplete(player,quest)
2 -> {
finishQuest(player,quest)
return true
}
}
return false
}
})
}
return@on true
}
// creating the dramen staff via using knife on dramen branch
onUseWith(ITEM,Items.KNIFE_946,Items.DRAMEN_BRANCH_771){ player, _, _ ->
if(!player.skills.hasLevel(Skills.CRAFTING,31)) {
sendDialogue(player,"You need a crafting level of 31 to do this.")
return@onUseWith false
}
runTask(player, 2) {
if (removeItem(player, Item(Items.DRAMEN_BRANCH_771, 1), Container.INVENTORY)) {
sendDialogue(player,"You carve the branch into a staff.")
addItem(player, Items.DRAMEN_STAFF_772, 1, Container.INVENTORY)
}
}
return@onUseWith true
}
}
}
@@ -0,0 +1,70 @@
package rs09.game.content.quest.members.lostcity
import core.game.content.dialogue.DialoguePlugin
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
import api.questStage
import api.setQuestStage
/**
* ShamusDialogue, to handle the dialogue of Shamus the Leprechaun from the Lost City quest
* @author lila
* @author Vexia
*/
@Initializable
class ShamusDialogue(player: Player? = null) : DialoguePlugin(player) {
val quest = "Lost City"
override fun open(vararg args: Any?): Boolean {
npcl(FacialExpression.ANNOYED,"Ay yer big elephant! Yer've caught me, to be sure! What would an elephant like yer be wanting wid ol' Shamus then?")
stage = 0
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(questStage(player,quest)) {
0 -> when(stage++) {
0 -> playerl(FacialExpression.THINKING, "I'm not sure.")
1 -> npcl(FacialExpression.ANNOYED,"Well you'll have to be catchin' me again when yer are, elephant!")
2 -> end().also { ShamusTreeListener.disappearShamus() }
}
10 -> when(stage++) {
0 -> playerl(FacialExpression.NEUTRAL,"I want to find Zanaris.")
1 -> npcl(FacialExpression.NEUTRAL,"Zanaris is it now? Well well well... Yer'll be needing to be going to that funny little shed out there in the swamp, so you will.")
2 -> playerl(FacialExpression.THINKING,"...but... I thought... Zanaris was a city?")
3 -> npcl(FacialExpression.HAPPY,"Aye that it is!")
4 -> playerl(FacialExpression.THINKING,"...How does it fit in a shed then?")
5 -> npcl(FacialExpression.LAUGH,"Ah yer stupid elephant! The city isn't IN the shed! The doorway to the shed is being a portal to Zanaris, so it is.")
6 -> playerl(FacialExpression.HALF_THINKING,"So I just walk into the shed and end up in Zanaris then?")
7 -> npcl(FacialExpression.NEUTRAL, "Oh, was I fergetting to say? Yer need to be carrying a Dramenwood staff to be getting there! Otherwise Yer'll just be ending up in the shed.")
8 -> playerl(FacialExpression.ASKING,"So where would I get a staff?")
9 -> npcl(FacialExpression.NEUTRAL,"Dramenwood staffs are crafted from branches of the Dramen tree, so they are. I hear there's a Dramen tree over on the island of Entrana in a cave.")
10 -> npcl(FacialExpression.HALF_THINKING,"or some such. There would be probably be a good place for an elephant like yer to be starting looking I reckon.")
11 -> npcl(FacialExpression.NEUTRAL,"The monks are running a ship from Port Sarim to Entrana, I hear too. Now leave me alone yer elephant!")
12 -> end().also {
ShamusTreeListener.disappearShamus()
sendDialogue("The leprechaun magically disappears.")
setQuestStage(player,quest,20)
}
}
else -> when(stage++) {
0 -> playerl(FacialExpression.THINKING, "I'm not sure.")
1 -> {
val pronoun = if(player.isMale) "he" else "she"
npcl(FacialExpression.ANNOYED,"HA! Look at yer! Look at the stupid elephant who tries to go catching a leprechaun when $pronoun don't even be knowing what $pronoun wants!")
}
2 -> end().also { ShamusTreeListener.disappearShamus() }
}
}
return true
}
override fun newInstance(player: Player): DialoguePlugin {
return ShamusDialogue(player)
}
override fun getIds(): IntArray = intArrayOf(NPCs.SHAMUS_654)
}
@@ -1,5 +1,7 @@
package rs09.game.content.quest.members.lostcity package rs09.game.content.quest.members.lostcity
import api.sendMessage
import api.sendNPCDialogue
import core.game.content.dialogue.FacialExpression import core.game.content.dialogue.FacialExpression
import core.game.node.entity.npc.NPC import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
@@ -35,21 +37,21 @@ class ShamusTreeListener : InteractionListener {
} }
} }
fun handleShamusTree(player: Player): Boolean { private fun handleShamusTree(player: Player): Boolean {
if (SkillingTool.getHatchet(player) == null) { if (SkillingTool.getHatchet(player) == null) {
player.packetDispatch.sendMessage("You do not have an axe which you have the level to use.") sendMessage(player,"You do not have an axe which you have the level to use.")
return true return true
} }
showShamus(player) showShamus(player)
return true return true
} }
fun showShamus(player: Player) { private fun showShamus(player: Player) {
if(SHAMUS.isInvisible) { if(SHAMUS.isInvisible) {
SHAMUS.isInvisible = false SHAMUS.isInvisible = false
SHAMUS.properties.teleportLocation = SHAMUS.properties.spawnLocation SHAMUS.properties.teleportLocation = SHAMUS.properties.spawnLocation
} }
player.dialogueInterpreter.sendDialogues(SHAMUS, FacialExpression.FURIOUS, "Hey! Yer big elephant! Don't go choppin' down me", "house, now!") sendNPCDialogue(player,NPCs.SHAMUS_654,"Hey! Yer big elephant! Don't go choppin' down me house, now!",FacialExpression.FURIOUS)
GameWorld.Pulser.submit(object : Pulse(100) { GameWorld.Pulser.submit(object : Pulse(100) {
override fun pulse(): Boolean { override fun pulse(): Boolean {
if (SHAMUS.dialoguePlayer == null) { if (SHAMUS.dialoguePlayer == null) {
@@ -0,0 +1,65 @@
package rs09.game.content.quest.members.lostcity
import core.game.node.entity.Entity
import core.game.node.entity.combat.CombatStyle
import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.player.Player
import core.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.NPCs
import api.questStage
import api.sendDialogue
import api.setQuestStage
/**
* TreeSpiritNPC class to handle the tree spirit that spawns out of the dramen tree
*/
@Initializable
class TreeSpiritNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
var target: Player? = null
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return TreeSpiritNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.TREE_SPIRIT_655)
}
init {
isWalks = true
isRespawn = false
}
override fun handleTickActions() {
if(target==null) {
clear()
return
}
super.handleTickActions()
if (!inCombat()) {
attack(target)
}
if (!target!!.isActive() || target!!.getLocation().getDistance(getLocation()) > 15) {
clear()
target!!.removeAttribute("treeSpawned")
}
}
override fun finalizeDeath(killer: Entity) {
super.finalizeDeath(killer)
if (killer is Player) {
val quest = "Lost City"
if (questStage(killer,quest) == 20) {
setQuestStage(killer,quest,21)
sendDialogue(killer, "With the Tree Spirit defeated you can now chop the tree.")
}
}
}
override fun isAttackable(entity: Entity, style: CombatStyle, message: Boolean): Boolean {
if(entity != target) {
return false
}
return super.isAttackable(entity, style, message)
}
}
@@ -0,0 +1,100 @@
package rs09.game.content.quest.members.lostcity
import core.game.content.dialogue.DialoguePlugin
import core.game.content.dialogue.FacialExpression
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
import rs09.game.content.dialogue.Topic
import rs09.tools.END_DIALOGUE
import api.questStage
import api.startQuest
/**
* WarriorDialogue, to handle the dialogue for the Warrior in the Lost City quest
* @author lila
* @author Vexia
*/
@Initializable
class WarriorDialogue(player: Player? = null) : DialoguePlugin(player) {
override fun open(vararg args: Any?): Boolean {
when(questStage(player,"Lost City")) {
10 -> playerl(FacialExpression.THINKING,"So let me get this straight: I need to search the trees around here for a leprechaun; and then when I find him, he will tell me where this 'Zanaris' is?").also { stage = 1000 }
20, 21 -> playerl(FacialExpression.HAPPY,"Have you found anything yet?").also { stage = 2000 }
100 -> playerl(FacialExpression.HAPPY,"Hey, thanks for all the information. It REALLY helped me out in finding the lost city of Zanaris and all.").also { stage = 3000 }
else -> npcl(FacialExpression.NEUTRAL,"Hello there traveller.").also { stage = 1 }
}
return true
}
override fun handle(interfaceId: Int, buttonId: Int): Boolean {
when(stage) {
1 -> showTopics(
Topic(FacialExpression.THINKING,"What are you camped out here for?",100),
Topic(FacialExpression.HALF_THINKING,"Do you know any good adventures I can go on?",101)
)
2 -> showTopics(
Topic(FacialExpression.ASKING,"Please tell me.",200),
Topic(FacialExpression.ANGRY,"I don't think you've found a good adventure at all!",250)
)
3 -> showTopics(
Topic(FacialExpression.ASKING,"Who's Zanaris?",301),
Topic(FacialExpression.ASKING,"What's Zanaris?",302),
Topic(FacialExpression.ASKING,"What makes you think it's out here?",300)
)
4 -> showTopics(
Topic(FacialExpression.ASKING,"If it's hidden how are you planning to find it?",400),
Topic(FacialExpression.LAUGH,"There's no such thing!",450)
)
5 -> options("Please tell me.", "Looks like you don't know either.").also { stage = 500 }
6 -> playerl(FacialExpression.HAPPY,"So a leprechaun knows where Zanaris is eh?").also { stage = 600 }
7 -> playerl(FacialExpression.HAPPY,"Thanks for the help!").also { stage = 700 }
8 -> end().also {
startQuest(player,"Lost City")
}
100 -> npcl(FacialExpression.HAPPY,"We're looking for Zanaris...GAH! I mean we're not here for any particular reason at all.").also { stage = 3 }
101 -> npcl(FacialExpression.NEUTRAL,"Well we're on an adventure right now. Mind you, this is OUR adventure and we don't want to share it - find your own!").also { stage = 2 }
200 -> npcl(FacialExpression.NEUTRAL,"No.").also { stage++ }
201 -> playerl(FacialExpression.SAD,"Please?").also { stage++ }
202 -> npcl(FacialExpression.ANNOYED,"No!").also { stage++ }
203 -> playerl(FacialExpression.SAD,"PLEEEEEEEEEEEEEEEEEEEEEEEEASE???").also { stage++ }
204 -> npcl(FacialExpression.ANGRY,"NO!").also { stage = END_DIALOGUE }
250 -> npcl(FacialExpression.ANGRY,"Hah! Adventurers of our calibre don't just hang around in forests for fun, whelp!").also { stage++ }
251 -> playerl(FacialExpression.THINKING,"Oh Really?").also { stage++ }
252 -> playerl(FacialExpression.THINKING,"What are you camped out here for?").also{ stage = 100 }
300 -> npcl(FacialExpression.HAPPY,"Don't you know of the legends that tell of the magical city, hidden in the swamp... Uh, no, you're right, we're wasting our time here.").also { stage = 4 }
301 -> npcl(FacialExpression.NEUTRAL,"Ahahahaha! Zanaris isn't a person! It's a magical hidden city filled with treasure and rich... uh, nothing. It's nothing.").also { stage = 4 }
302 -> npcl(FacialExpression.HALF_THINKING,"I don't think we want other people competing with us to find it. Forget I said anything.").also { stage = 5 }
400 -> npcl(FacialExpression.NEUTRAL,"Well, we don't want to tell anyone else about that, because we don't want anyone else sharing in all that glory and treasure.").also { stage = 5 }
450 -> npcl(FacialExpression.NEUTRAL,"When we've found Zanaris you'll... GAH! I mean, we're not here for any particular reason at all.").also { stage = 3 }
500 -> when(buttonId) {
1 -> playerl(FacialExpression.ASKING,"Please tell me.").also{ stage = 200 }
2 -> playerl(FacialExpression.THINKING,"Well, it looks to ME like YOU don't know EITHER, seeing as you're all just sat around here.").also { stage++ }
}
501 -> npcl(FacialExpression.ANGRY,"Of course we know! We just haven't found which tree the stupid leprechaun's hiding in yet!").also { stage++ }
502 -> npcl(FacialExpression.NEUTRAL,"GAH! I didn't mean to tell you that! Look, just forget I said anything okay?").also { stage = 6 }
600 -> npcl(FacialExpression.NEUTRAL,"Ye.. uh, no. No, not at all. And even if he did - which he doesn't - he DEFINITELY ISN'T hiding in some tree around here. Nope, definitely not. Honestly.").also { stage = 7 }
700 -> npcl(FacialExpression.WORRIED,"Help? What help? I didn't help! Please don't say I did, I'll get in trouble!").also { stage = 8 }
1000 -> npcl(FacialExpression.WORRIED,"What? How did you know that? Uh... I mean, no, no you're very wrong. Very wrong, and not right at all, and I definitely didn't tell you about that at all.").also { stage = END_DIALOGUE }
2000 -> npcl(FacialExpression.SAD,"We're still searching for Zanaris...GAH! I mean we're not doing anything here at all.").also { stage++ }
2001 -> playerl(FacialExpression.SAD,"I haven't found it yet either.").also { stage = END_DIALOGUE }
3000 -> npcl(FacialExpression.SAD,"Oh please don't say that anymore! If the rest of my party knew I'd helped you they'd probably throw me out and make me walk home by myself!").also { stage++ }
3001 -> npcl(FacialExpression.ASKING,"So anyway, what have you found out? Where is the fabled Zanaris? Is it all the legends say it is?").also { stage++ }
3002 -> playerl(FacialExpression.HAPPY,"You know.... I think I'll keep that to myself.").also { stage = END_DIALOGUE }
}
return true
}
override fun newInstance(player: Player): DialoguePlugin {
return WarriorDialogue(player)
}
override fun getIds(): IntArray = intArrayOf(NPCs.WARRIOR_650)
}
/*
Some evidence from early/mid 2009 to help determine facial expressions, and contains some lines not previously included in this warrior's dialogue
this also functions as evidence for most of the warrior's dialogue
https://www.youtube.com/watch?v=nFDifUB8dxQ
https://www.youtube.com/watch?v=4BKRG4yw16o
*/
@@ -36,6 +36,14 @@ class ItemQuestRequirementListener : InteractionListener {
private val avasBackpacks = intArrayOf(Items.AVAS_ACCUMULATOR_10499, Items.AVAS_ATTRACTOR_10498) private val avasBackpacks = intArrayOf(Items.AVAS_ACCUMULATOR_10499, Items.AVAS_ATTRACTOR_10498)
private val lostCityWeapons = intArrayOf(
Items.DRAGON_DAGGER_1215,
Items.DRAGON_DAGGERP_1231,
Items.DRAGON_DAGGERP_PLUS_5680,
Items.DRAGON_DAGGERP_PLUS_PLUS_5698,
Items.DRAGON_LONGSWORD_1305
)
private val questCapes = intArrayOf(9813,9814) private val questCapes = intArrayOf(9813,9814)
override fun defineListeners() { override fun defineListeners() {
@@ -74,6 +82,14 @@ class ItemQuestRequirementListener : InteractionListener {
return@onEquip true return@onEquip true
} }
onEquip(lostCityWeapons){ player, _ ->
if (!isQuestComplete(player, "Lost City")) {
sendMessage(player, "You must have completed Lost City to equip this.")
return@onEquip false
}
return@onEquip true
}
onEquip(Items.CAPE_OF_LEGENDS_1052) { player, _ -> onEquip(Items.CAPE_OF_LEGENDS_1052) { player, _ ->
if(!isQuestComplete(player, "Legends' Quest")) { if(!isQuestComplete(player, "Legends' Quest")) {
player.packetDispatch.sendMessage("You must have completed Legends' Quest to equip this.") player.packetDispatch.sendMessage("You must have completed Legends' Quest to equip this.")
@@ -123,4 +139,4 @@ class ItemQuestRequirementListener : InteractionListener {
return@onEquip true return@onEquip true
} }
} }
} }
@@ -1,9 +1,12 @@
package rs09.game.interaction.`object` package rs09.game.interaction.`object`
import api.isEquipped
import api.isQuestComplete
import core.game.component.Component import core.game.component.Component
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager.TeleportType import core.game.node.entity.player.link.TeleportManager.TeleportType
import core.game.world.map.Location import core.game.world.map.Location
import org.rs09.consts.Items
import rs09.game.interaction.InteractionListener import rs09.game.interaction.InteractionListener
/** /**
@@ -11,34 +14,44 @@ import rs09.game.interaction.InteractionListener
* @author Ceikry * @author Ceikry
*/ */
private val RINGS = intArrayOf(12003, 12094, 12095, 14058, 14061, 14064, 14067, 14070, 14073, 14076, 14079, 14082, 14085, 14088, 14091, 14094, 14097, 14100, 14103, 14106, 14109, 14112, 14115, 14118, 14121, 14124, 14127, 14130, 14133, 14136, 14139, 14142, 14145, 14148, 14151, 14154, 14157, 14160, 16181, 16184, 23047, 27325, 37727) private val RINGS = intArrayOf(12003, 12095, 14058, 14061, 14064, 14067, 14070, 14073, 14076, 14079, 14082, 14085, 14088, 14091, 14094, 14097, 14100, 14103, 14106, 14109, 14112, 14115, 14118, 14121, 14124, 14127, 14130, 14133, 14136, 14139, 14142, 14145, 14148, 14151, 14154, 14157, 14160, 16181, 16184, 23047, 27325, 37727)
private const val MAIN_RING = 12128 private const val MAIN_RING = 12128
private const val ENTRY_RING = 12094
class FairyRingPlugin : InteractionListener { class FairyRingPlugin : InteractionListener {
override fun defineListeners() { override fun defineListeners() {
on(RINGS,SCENERY,"use"){ player, _ -> on(RINGS,SCENERY,"use"){ player, _ ->
if (!player.equipment.contains(772, 1) && !player.equipment.contains(9084, 1)) { if (!fairyMagic(player)) return@on true
player.sendMessage("The fairy ring only works for those who wield fairy magic.")
return@on true
}
player.teleporter.send(Location.create(2412, 4434, 0), TeleportType.FAIRY_RING) player.teleporter.send(Location.create(2412, 4434, 0), TeleportType.FAIRY_RING)
return@on true return@on true
} }
on(MAIN_RING,SCENERY,"use"){ player, _ -> on(MAIN_RING,SCENERY,"use"){ player, _ ->
if (!player.equipment.contains(772, 1) && !player.equipment.contains(9084, 1)) { if (!fairyMagic(player)) return@on true
player.sendMessage("The fairy ring only works for those who wield fairy magic.")
return@on true
}
openFairyRing(player) openFairyRing(player)
return@on true return@on true
} }
on(ENTRY_RING,SCENERY,"use") { player, _ ->
if (!fairyMagic(player)) return@on true
player.teleporter.send(Location.create(3203, 3168, 0), TeleportType.FAIRY_RING)
return@on true
}
} }
private fun fairyMagic(player: Player) : Boolean {
if(!isQuestComplete(player,"Lost City")) { // should be converted to a FTP2 stage requirement once FTP2 is implemented
player.sendMessage("The fairy ring is inert.")
return false
}
if(!isEquipped(player, Items.DRAMEN_STAFF_772) && !isEquipped(player,Items.LUNAR_STAFF_9084)) {
player.sendMessage("The fairy ring only works for those who wield fairy magic.")
return false
}
return true
}
private fun reset(player: Player) { private fun reset(player: Player) {
player.removeAttribute("fairy-delay") player.removeAttribute("fairy-delay")
player.removeAttribute("fairy_location_combo") player.removeAttribute("fairy_location_combo")
@@ -52,4 +65,4 @@ class FairyRingPlugin : InteractionListener {
player.interfaceManager.openSingleTab(Component(735)) player.interfaceManager.openSingleTab(Component(735))
player.interfaceManager.open(Component(734)) player.interfaceManager.open(Component(734))
} }
} }