From 854b8cdc6ba0a2aa4b3d04574f8d4893e82858ae Mon Sep 17 00:00:00 2001 From: MatthewGould123 Date: Wed, 14 Sep 2022 08:59:41 +0000 Subject: [PATCH] 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 --- .../members/lostcity/DramenStaffPlugin.java | 54 ---- .../quest/members/lostcity/LostCity.java | 104 ------- .../members/lostcity/LostCityPlugin.java | 139 --------- .../members/lostcity/ShamusDialogue.java | 164 ---------- .../quest/members/lostcity/TreeSpiritNPC.java | 101 ------- .../members/lostcity/WarriorDialogue.java | 282 ------------------ .../entity/player/link/TeleportManager.java | 10 - .../entity/skill/gather/SkillingResource.java | 2 +- .../gather/woodcutting/WoodcuttingNode.java | 2 +- .../DramenTreeListener.kt | 31 +- .../quest/members/lostcity/LostCity.kt | 74 +++++ .../members/lostcity/LostCityListeners.kt | 69 +++++ .../quest/members/lostcity/ShamusDialogue.kt | 70 +++++ .../members/lostcity/ShamusTreeListener.kt | 10 +- .../quest/members/lostcity/TreeSpiritNPC.kt | 65 ++++ .../quest/members/lostcity/WarriorDialogue.kt | 100 +++++++ .../item/ItemQuestRequirementListener.kt | 18 +- .../interaction/object/FairyRingPlugin.kt | 37 ++- 18 files changed, 445 insertions(+), 887 deletions(-) delete mode 100644 Server/src/main/java/core/game/content/quest/members/lostcity/DramenStaffPlugin.java delete mode 100644 Server/src/main/java/core/game/content/quest/members/lostcity/LostCity.java delete mode 100644 Server/src/main/java/core/game/content/quest/members/lostcity/LostCityPlugin.java delete mode 100644 Server/src/main/java/core/game/content/quest/members/lostcity/ShamusDialogue.java delete mode 100644 Server/src/main/java/core/game/content/quest/members/lostcity/TreeSpiritNPC.java delete mode 100644 Server/src/main/java/core/game/content/quest/members/lostcity/WarriorDialogue.java rename Server/src/main/kotlin/rs09/game/content/quest/members/{thelostcity => lostcity}/DramenTreeListener.kt (54%) create mode 100644 Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/LostCity.kt create mode 100644 Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/LostCityListeners.kt create mode 100644 Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/ShamusDialogue.kt create mode 100644 Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/TreeSpiritNPC.kt create mode 100644 Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/WarriorDialogue.kt diff --git a/Server/src/main/java/core/game/content/quest/members/lostcity/DramenStaffPlugin.java b/Server/src/main/java/core/game/content/quest/members/lostcity/DramenStaffPlugin.java deleted file mode 100644 index 9b3e929e4..000000000 --- a/Server/src/main/java/core/game/content/quest/members/lostcity/DramenStaffPlugin.java +++ /dev/null @@ -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 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; - } - -} diff --git a/Server/src/main/java/core/game/content/quest/members/lostcity/LostCity.java b/Server/src/main/java/core/game/content/quest/members/lostcity/LostCity.java deleted file mode 100644 index 5654f0276..000000000 --- a/Server/src/main/java/core/game/content/quest/members/lostcity/LostCity.java +++ /dev/null @@ -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, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

Apparently there is a leprechaun hiding in a tree nearby

who can tell me how to enter the Lost City of Zanaris", 4+ 7); - break; - case 20: - line(player, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

I found the Leprechaun hiding in a nearby tree.

He told me that the entrance to Zanaris is in the shed in

Lumbridge swamp but only if I am carrying a Dramen Staff

I can find a Dramen Tree in a cave on Entrana somewhere", 4+ 7); - break; - case 21: - if (player.getBank().containsItem(DRAMEN_STAFF) || player.getInventory().containsItem(DRAMEN_STAFF) || player.getEquipment().containsItem(DRAMEN_STAFF)) { - line(player, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

I found the Leprechaun hiding in a nearby tree.

He told me that the entrance to Zanaris is in the shed in

Lumbridge swamp but only if I am carrying a Dramen Staff.

The Dramen Tree was guarded by a powerful Tree Spirit.

I cut a branch from the tree and crafted a Dramen Staff.

I should enter Zanaris by going to the shed in Lumbridge

Swamp while keeping the Dramen staff with me", 4+ 7); - } else { - line(player, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

I found the Leprechaun hiding in a nearby tree.

He told me that the entrance to Zanaris is in the shed in

Lumbridge swamp but only if I am carrying a Dramen Staff.

The Dramen Tree was guarded by a powerful Tree Spirit.

With the Spirit defeated I can cut a branch from the tree", 4+ 7); - } - break; - case 100: - line(player, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

I found the Leprechaun hiding in a nearby tree.

He told me that the entrance to Zanaris is in the shed in

Lumbridge swamp but only if I am carrying a Dramen Staff.

The Dramen Tree was guarded by a powerful Tree Spirit.

I cut a branch from the tree and crafted a Dramen Staff.

With the mystical Dramen Staff in my possession I was

able to enter Zanaris through the shed in Lumbridge

swamp.


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; - } - -} diff --git a/Server/src/main/java/core/game/content/quest/members/lostcity/LostCityPlugin.java b/Server/src/main/java/core/game/content/quest/members/lostcity/LostCityPlugin.java deleted file mode 100644 index c7bb339a7..000000000 --- a/Server/src/main/java/core/game/content/quest/members/lostcity/LostCityPlugin.java +++ /dev/null @@ -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 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; - } -} diff --git a/Server/src/main/java/core/game/content/quest/members/lostcity/ShamusDialogue.java b/Server/src/main/java/core/game/content/quest/members/lostcity/ShamusDialogue.java deleted file mode 100644 index 08daad853..000000000 --- a/Server/src/main/java/core/game/content/quest/members/lostcity/ShamusDialogue.java +++ /dev/null @@ -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 }; - } - -} diff --git a/Server/src/main/java/core/game/content/quest/members/lostcity/TreeSpiritNPC.java b/Server/src/main/java/core/game/content/quest/members/lostcity/TreeSpiritNPC.java deleted file mode 100644 index fb3e58d15..000000000 --- a/Server/src/main/java/core/game/content/quest/members/lostcity/TreeSpiritNPC.java +++ /dev/null @@ -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; - } - -} diff --git a/Server/src/main/java/core/game/content/quest/members/lostcity/WarriorDialogue.java b/Server/src/main/java/core/game/content/quest/members/lostcity/WarriorDialogue.java deleted file mode 100644 index 91723e22f..000000000 --- a/Server/src/main/java/core/game/content/quest/members/lostcity/WarriorDialogue.java +++ /dev/null @@ -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 }; - } -} \ No newline at end of file diff --git a/Server/src/main/java/core/game/node/entity/player/link/TeleportManager.java b/Server/src/main/java/core/game/node/entity/player/link/TeleportManager.java index 40a7c9e9b..34b2a68e2 100644 --- a/Server/src/main/java/core/game/node/entity/player/link/TeleportManager.java +++ b/Server/src/main/java/core/game/node/entity/player/link/TeleportManager.java @@ -4,7 +4,6 @@ import rs09.ServerConstants; import core.game.node.entity.Entity; import core.game.node.entity.impl.Animator.Priority; 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.system.task.Pulse; import rs09.game.world.GameWorld; @@ -448,15 +447,6 @@ public class TeleportManager { } break; 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.getProperties().setTeleportLocation(location); entity.unlock(); diff --git a/Server/src/main/java/core/game/node/entity/skill/gather/SkillingResource.java b/Server/src/main/java/core/game/node/entity/skill/gather/SkillingResource.java index 2d4bf79a6..5ba227009 100644 --- a/Server/src/main/java/core/game/node/entity/skill/gather/SkillingResource.java +++ b/Server/src/main/java/core/game/node/entity/skill/gather/SkillingResource.java @@ -83,7 +83,7 @@ public enum SkillingResource { /** * 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). diff --git a/Server/src/main/java/core/game/node/entity/skill/gather/woodcutting/WoodcuttingNode.java b/Server/src/main/java/core/game/node/entity/skill/gather/woodcutting/WoodcuttingNode.java index 577ec4683..d8c1de7c5 100644 --- a/Server/src/main/java/core/game/node/entity/skill/gather/woodcutting/WoodcuttingNode.java +++ b/Server/src/main/java/core/game/node/entity/skill/gather/woodcutting/WoodcuttingNode.java @@ -306,7 +306,7 @@ public enum WoodcuttingNode { respawnRate = -1; rate = 0.05; experience = 25.0; - level = 1; + level = 36; rewardAmount = Integer.MAX_VALUE; break; case 30: diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/thelostcity/DramenTreeListener.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/DramenTreeListener.kt similarity index 54% rename from Server/src/main/kotlin/rs09/game/content/quest/members/thelostcity/DramenTreeListener.kt rename to Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/DramenTreeListener.kt index fa18e472a..c66f433cf 100644 --- a/Server/src/main/kotlin/rs09/game/content/quest/members/thelostcity/DramenTreeListener.kt +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/DramenTreeListener.kt @@ -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.entity.skill.gather.woodcutting.WoodcuttingSkillPulse 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.plugin.Initializable +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery as Sceneries import rs09.game.interaction.InteractionListener +import api.questStage +import api.sendMessage +@Initializable class DramenTreeListener : InteractionListener { - val DRAMEN_TREE = 1292 - override fun defineListeners() { - on(DRAMEN_TREE,SCENERY,"chop down"){ player, node -> - val quest = player.questRepository.getQuest("Lost City") + on(Sceneries.DRAMEN_TREE_1292,SCENERY,"chop down"){ player, node -> + val questStage = questStage(player,"Lost City") 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 } - if (quest.getStage(player) < 20) { + if (questStage < 20) { return@on true } - if (quest.getStage(player) == 20) { + if (questStage == 20) { if (player.getAttribute("treeSpawned", false)) { return@on true } - val spirit = TreeSpiritNPC.create(655, Location.create(2862, 9734, 0)) as TreeSpiritNPC - spirit.player = player - spirit.isRespawn = false + val spirit = TreeSpiritNPC(NPCs.TREE_SPIRIT_655, Location(2862, 9734, 0)) + spirit.target = player spirit.init() spirit.attack(player) player.setAttribute("treeSpawned", true) spirit.sendChat("You must defeat me before touching the tree!") return@on true } - player.getPulseManager().run(WoodcuttingSkillPulse(player, node as Scenery?)) + + player.pulseManager.run(WoodcuttingSkillPulse(player, node as Scenery)) return@on true } diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/LostCity.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/LostCity.kt new file mode 100644 index 000000000..1ccb758e9 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/LostCity.kt @@ -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() + + 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, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

Apparently there is a leprechaun hiding in a tree nearby

who can tell me how to enter the Lost City of Zanaris", 4 + 7) + 20 -> line(player, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

I found the Leprechaun hiding in a nearby tree.

He told me that the entrance to Zanaris is in the shed in

Lumbridge swamp but only if I am carrying a Dramen Staff

I can find a Dramen Tree in a cave on Entrana somewhere", 4 + 7) + 21 -> if (player.hasItem(Item(Items.DRAMEN_STAFF_772,1))) { + line(player, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

I found the Leprechaun hiding in a nearby tree.

He told me that the entrance to Zanaris is in the shed in

Lumbridge swamp but only if I am carrying a Dramen Staff.

The Dramen Tree was guarded by a powerful Tree Spirit.

I cut a branch from the tree and crafted a Dramen Staff.

I should enter Zanaris by going to the shed in Lumbridge

Swamp while keeping the Dramen staff with me", 4 + 7) + } else { + line(player, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

I found the Leprechaun hiding in a nearby tree.

He told me that the entrance to Zanaris is in the shed in

Lumbridge swamp but only if I am carrying a Dramen Staff.

The Dramen Tree was guarded by a powerful Tree Spirit.

With the Spirit defeated I can cut a branch from the tree", 4 + 7) + } + 100 -> line(player, "According to one of the adventurers in Lumbridge Swamp

the entrance to Zanaris is somewhere around there.

I found the Leprechaun hiding in a nearby tree.

He told me that the entrance to Zanaris is in the shed in

Lumbridge swamp but only if I am carrying a Dramen Staff.

The Dramen Tree was guarded by a powerful Tree Spirit.

I cut a branch from the tree and crafted a Dramen Staff.

With the mystical Dramen Staff in my possession I was

able to enter Zanaris through the shed in Lumbridge

swamp.


QUEST COMPLETE!", 4 + 7) + } + } + + private fun drawQuestRequirements(player: Player) { + var line = 7 + 7 + val questRequirements = arrayOf( + "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 + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/LostCityListeners.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/LostCityListeners.kt new file mode 100644 index 000000000..f3c24c66c --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/LostCityListeners.kt @@ -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 + } + } +} diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/ShamusDialogue.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/ShamusDialogue.kt new file mode 100644 index 000000000..90c9d3d17 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/ShamusDialogue.kt @@ -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) +} diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/ShamusTreeListener.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/ShamusTreeListener.kt index 51ceea09f..08465dd14 100644 --- a/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/ShamusTreeListener.kt +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/ShamusTreeListener.kt @@ -1,5 +1,7 @@ package rs09.game.content.quest.members.lostcity +import api.sendMessage +import api.sendNPCDialogue import core.game.content.dialogue.FacialExpression import core.game.node.entity.npc.NPC 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) { - 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 } showShamus(player) return true } - fun showShamus(player: Player) { + private fun showShamus(player: Player) { if(SHAMUS.isInvisible) { SHAMUS.isInvisible = false 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) { override fun pulse(): Boolean { if (SHAMUS.dialoguePlayer == null) { diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/TreeSpiritNPC.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/TreeSpiritNPC.kt new file mode 100644 index 000000000..0703e883c --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/TreeSpiritNPC.kt @@ -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) + } + +} diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/WarriorDialogue.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/WarriorDialogue.kt new file mode 100644 index 000000000..fdd571824 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/lostcity/WarriorDialogue.kt @@ -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 + */ diff --git a/Server/src/main/kotlin/rs09/game/interaction/item/ItemQuestRequirementListener.kt b/Server/src/main/kotlin/rs09/game/interaction/item/ItemQuestRequirementListener.kt index 224f301b1..d484e7aca 100644 --- a/Server/src/main/kotlin/rs09/game/interaction/item/ItemQuestRequirementListener.kt +++ b/Server/src/main/kotlin/rs09/game/interaction/item/ItemQuestRequirementListener.kt @@ -36,6 +36,14 @@ class ItemQuestRequirementListener : InteractionListener { 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) override fun defineListeners() { @@ -74,6 +82,14 @@ class ItemQuestRequirementListener : InteractionListener { 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, _ -> if(!isQuestComplete(player, "Legends' Quest")) { player.packetDispatch.sendMessage("You must have completed Legends' Quest to equip this.") @@ -123,4 +139,4 @@ class ItemQuestRequirementListener : InteractionListener { return@onEquip true } } -} \ No newline at end of file +} diff --git a/Server/src/main/kotlin/rs09/game/interaction/object/FairyRingPlugin.kt b/Server/src/main/kotlin/rs09/game/interaction/object/FairyRingPlugin.kt index 25067ba9c..5877d2845 100644 --- a/Server/src/main/kotlin/rs09/game/interaction/object/FairyRingPlugin.kt +++ b/Server/src/main/kotlin/rs09/game/interaction/object/FairyRingPlugin.kt @@ -1,9 +1,12 @@ package rs09.game.interaction.`object` +import api.isEquipped +import api.isQuestComplete import core.game.component.Component import core.game.node.entity.player.Player import core.game.node.entity.player.link.TeleportManager.TeleportType import core.game.world.map.Location +import org.rs09.consts.Items import rs09.game.interaction.InteractionListener /** @@ -11,34 +14,44 @@ import rs09.game.interaction.InteractionListener * @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 ENTRY_RING = 12094 class FairyRingPlugin : InteractionListener { override fun defineListeners() { on(RINGS,SCENERY,"use"){ player, _ -> - if (!player.equipment.contains(772, 1) && !player.equipment.contains(9084, 1)) { - player.sendMessage("The fairy ring only works for those who wield fairy magic.") - return@on true - } + if (!fairyMagic(player)) return@on true player.teleporter.send(Location.create(2412, 4434, 0), TeleportType.FAIRY_RING) return@on true } - on(MAIN_RING,SCENERY,"use"){ player, _ -> - if (!player.equipment.contains(772, 1) && !player.equipment.contains(9084, 1)) { - player.sendMessage("The fairy ring only works for those who wield fairy magic.") - return@on true - } + if (!fairyMagic(player)) return@on true openFairyRing(player) 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) { player.removeAttribute("fairy-delay") player.removeAttribute("fairy_location_combo") @@ -52,4 +65,4 @@ class FairyRingPlugin : InteractionListener { player.interfaceManager.openSingleTab(Component(735)) player.interfaceManager.open(Component(734)) } -} \ No newline at end of file +}