diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallListeners.kt b/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallListeners.kt index eb99eef08..8358b1a5a 100644 --- a/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallListeners.kt +++ b/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallListeners.kt @@ -1,23 +1,573 @@ package content.region.kandarin.quest.waterfall -import core.game.world.map.Location -import org.rs09.consts.NPCs +import content.data.Quests +import content.global.skill.agility.AgilityHandler +import core.api.* +import core.cache.def.impl.ItemDefinition +import core.game.dialogue.ChatAnim +import core.game.global.action.DoorActionHandler import core.game.interaction.InteractionListener import core.game.interaction.IntType +import core.game.interaction.QueueStrength +import core.game.node.entity.combat.ImpactHandler.HitsplatType +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.scenery.Scenery +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import core.game.world.update.flag.context.Graphics +import org.rs09.consts.Items +import org.rs09.consts.NPCs +import org.rs09.consts.Scenery as SceneryObj + +/** + * Listeners for the Waterfall Quest. + * In Loving Memory of WaterfallPlugin.java 2015/02/28 - 2026/07/27, about which was said: + * "This is one of the most disgusting files I have ever seen." - Ceikry + * @author Bishop + */ class WaterfallListeners : InteractionListener { - val HUDON = NPCs.HUDON_305 + companion object { + // Animations + private val animationSwim = Animation(164) + private val animationRopeToss = Animation(774) + private val animationRopeWalk = Animation(273) + private val animationRopeDone = Animation(780) + // Attributes + private const val attributeRunes = "waterfall:runes-placed" + // Graphics + private val graphicsSplash = Graphics(68) + private val graphicsRunePoof = Graphics(580) + private val graphicsRocksFall = Graphics(74) + // Lists + private val listOfSwimmers : MutableList = ArrayList(20) + // Locations + private val locHudonTalk = Location(2512, 3481) + private val locIslandAfterRaft = Location(2512, 3481) + private val locIslandBeforeRock = Location(2512, 3476) + private val locSwimmingGoal = Location(2512, 3471) + private val locInFrontOfRock = Location(2512, 3469) + private val locRock = Location(2512, 3468) + private val locIslandAfterRock = Location(2513, 3468) + private val locWaterfallLedge = Location(2511, 3463) + private val locDownstream = Location(2527, 3413) + private val locInsideTomb = Location(2555, 9844) + private val locInWaterfallCave = Location(2575, 9861) + private val locWaterfallDoorSouth = Location(2568, 9893) + private val locWaterfallDoorNorth = Location(2566, 9901) + private val locWaterfallDoorChamber = Location(2604, 9900) + private val locBeforeFinalStatue = Location(2603, 9914) + // Misc data + private val ropeYSpan = intArrayOf(3469, 3475) + private const val locGnomeCaveDoorY = 9576 + private val pedestalLocations = arrayOf( + Location(2562, 9914), Location(2562, 9912), Location(2562, 9910), + Location(2569, 9914), Location(2569, 9912), Location(2569, 9910), + ) + private val runes = intArrayOf( + Items.WATER_RUNE_555, Items.AIR_RUNE_556, Items.EARTH_RUNE_557, + ) + } + override fun defineListeners() { - on(HUDON, IntType.NPC, "talk-to"){ player, node -> - player.dialogueInterpreter.open(HUDON,node.asNpc()) + // Speak to Hudon + on(NPCs.HUDON_305, IntType.NPC, "talk-to") { player, node -> + openDialogue(player, node as NPC) return@on true } + + // Ride the raft + on(SceneryObj.LOG_RAFT_1987, IntType.SCENERY, "board") { player, _ -> + if (getQuestStage(player, Quests.WATERFALL_QUEST) >= 10) { + lock(player, 13) + queueScript(player, 2, QueueStrength.SOFT) { stage -> + when (stage) { + 0 -> { + sendMessage(player, "You board the small raft") + return@queueScript delayScript(player, 4) + } + 1 -> { + sendMessage(player, "and push off down stream.") + return@queueScript delayScript(player, 3) + } + 2 -> { + sendMessage(player, "The raft is pulled down stream by strong currents") + return@queueScript delayScript(player, 3) + } + 3 -> { + sendMessage(player, "You crash into a small land mound.") + teleport(player, locIslandAfterRaft) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } else { + sendDialogue(player, "You have no reason to board this raft.") + } + return@on true + } + + // Try to swim to the rock at the waterfall, or just swim in general + on(intArrayOf(SceneryObj.ROCK_1996, SceneryObj.ROCK_1997, SceneryObj.RIVER_10283), IntType.SCENERY, "swim to", "swim") { player, _ -> + registerLogoutListener(player, "waterfall") { player: Player -> + teleport(player, locIslandBeforeRock) + } + sendMessage(player, "It looks like a long distance, but you swim out into the water.") + sendGraphics(graphicsSplash, player.location) + AgilityHandler.walk( + player, -1, player.location, locSwimmingGoal, animationSwim, 0.0, null + ) + lock(player, 6) + queueScript(player, 3, QueueStrength.SOFT) { stage -> + when (stage) { + 0 -> { + sendMessage(player, "The current is too strong, you feel yourself being pulled under") + return@queueScript delayScript(player, 3) + } + 1 -> { + sendMessage(player, "You are washed downstream but feel lucky to be alive.") + teleport(player, locDownstream) + clearLogoutListener(player, "waterfall") + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + return@on true + } + + // Correctly use a rope on the rock at the waterfall + onUseWith(IntType.SCENERY, Items.ROPE_954, SceneryObj.ROCK_1996, SceneryObj.ROCK_1997) { player, _, _ -> + registerLogoutListener(player, "waterfall") { player: Player -> + teleport(player, locIslandBeforeRock) + } + lock(player, 8) + animate(player, animationRopeToss) + if (listOfSwimmers.isEmpty()) { + listOfSwimmers.add(player) + replaceScenery(getScenery(locRock)!!, SceneryObj.ROCK_1997, -1) + for (y in ropeYSpan[0]..ropeYSpan[1]) { + addScenery(Scenery(SceneryObj.ROPE_1998, Location(locRock.x, y), 10, 0)) + } + } + queueScript(player, 2, QueueStrength.SOFT) { stage -> + when (stage) { + 0 -> { + face(player, locRock) + AgilityHandler.walk( + player, -1, player.location, locInFrontOfRock, animationRopeWalk, 0.0, null + ) + return@queueScript delayScript(player, 8) + } + 1 -> { + teleport(player, locIslandAfterRock) + return@queueScript keepRunning(player) + } + 2 -> { + face(player, locRock) + animate(player, animationRopeDone) + return@queueScript animationFinished(player) + } + 3 -> { + clearLogoutListener(player, "waterfall") + if (listOfSwimmers.remove(player) && listOfSwimmers.isEmpty()) { + replaceScenery(getScenery(locRock)!!, SceneryObj.ROCK_1996, -1) + for (y in ropeYSpan[0]..ropeYSpan[1]) { + removeScenery(Scenery(SceneryObj.ROPE_1998, Location(locRock.x, y), 10, 0)) + } + } + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + return@onUseWith true + } + + // Try to climb down the tree at the waterfall barehanded + on(SceneryObj.DEAD_TREE_2020, IntType.SCENERY, "climb") { player, _ -> + player.dialogueInterpreter.open("waterfall_tree_dialogue", 0) + return@on true + } + + // Correctly use a rope on the tree at the waterfall + onUseWith(IntType.SCENERY, Items.ROPE_954, SceneryObj.DEAD_TREE_2020) { player, _, _ -> + sendMessage(player, "You tie the rope to the tree and let yourself down on the ledge.") + teleport(player, locWaterfallLedge) + return@onUseWith true + } + + // Get in the barrel on the waterfall's ledge + on(SceneryObj.BARREL_2022, IntType.SCENERY, "get in") { player, _ -> + sendMessage(player, "You get in the barrel and start rocking.") + sendMessage(player, "The barrel falls off the ledge.") + teleport(player, locDownstream) + return@on true + } + + // Search the bookcase at the tourism center + on(SceneryObj.BOOKCASE_1989, IntType.SCENERY, "search") { player, _ -> + if (inInventory(player, Items.BOOK_ON_BAXTORIAN_292) || getQuestStage(player, Quests.WATERFALL_QUEST) != 20) { + sendMessage(player, "You search the bookcase and find nothing of interest.") + } else { + sendMessage(player, "You search the bookcase and find a book named 'Book on Baxtorian'") + addItemOrDrop(player, Items.BOOK_ON_BAXTORIAN_292) + } + return@on true + } + + // Search the crate that contains the key + on(SceneryObj.CRATE_1990, IntType.SCENERY, "search") { player, _ -> + if (inInventory(player, Items.A_KEY_293) || getQuestStage(player, Quests.WATERFALL_QUEST) < 30) { + sendMessage(player, "You search the crate and find nothing.") + } else { + sendMessage(player, "You find a large key.") + addItemOrDrop(player, Items.A_KEY_293) + } + return@on true + } + + // Access the door in the gnome cave + on(SceneryObj.DOOR_1991, IntType.SCENERY, "open") { player, node -> + if (player.getLocation().y >= locGnomeCaveDoorY) { + sendMessage(player, "You open the gate and walk through.") + DoorActionHandler.handleAutowalkDoor(player, node as Scenery) + } else if (inInventory(player, Items.A_KEY_293)) { + sendMessage(player, "The gate is locked. You need to use the key on the door to enter.") + } else { + sendNPCDialogueLines( + player, NPCs.GOLRIE_306, ChatAnim.HALF_GUILTY, false, + "Hello? Ah yes, the door is still locked.", + "If you want to get in here, you'll need to find the key", + "that I hid in some crates in the eastern room." + ) + } + return@on true + } + + // Use the key on the door in the gnome cave + onUseWith(IntType.SCENERY, Items.A_KEY_293, SceneryObj.DOOR_1991) { player, _, with -> + sendMessage(player, "The key fits the gate.") + sendMessage(player, "You open the gate and walk through.") + DoorActionHandler.handleAutowalkDoor(player, with as Scenery) + return@onUseWith true + } + + // Enter the waterfall cave + on(SceneryObj.LEDGE_37247, IntType.SCENERY, "open") { player, _ -> + sendMessage(player, "The door opens...") + queueScript(player, 2, QueueStrength.SOFT) { + if ((inInventory(player, Items.GLARIALS_AMULET_295) || inEquipment(player, Items.GLARIALS_AMULET_295)) || isQuestComplete(player, Quests.WATERFALL_QUEST)) { + sendMessage(player, "You walk through the door.") + teleport(player, locInWaterfallCave) + } else { + sendMessage(player, "The cave floods and washes you away!") + teleport(player, locDownstream) + } + return@queueScript stopExecuting(player) + } + return@on true + } + + // Exit the waterfall cave through the entrance + on(SceneryObj.DOOR_32711, IntType.SCENERY, "open") { player, _ -> + teleport(player, locWaterfallLedge) + return@on true + } + + // Read Glarial's tombstone + on(SceneryObj.GLARIAL_S_TOMBSTONE_1992, IntType.SCENERY, "read") { player, _ -> + lock(player, 16) + queueScript(player, 1, QueueStrength.SOFT) { stage -> + when (stage) { + 0 -> { + sendMessage(player, "The grave is covered in elven script.") + return@queueScript delayScript(player, 2) + } + 1 -> { + sendMessage(player, "Some of the writing is in common tongue, it reads:") + return@queueScript delayScript(player, 3) + } + 2 -> { + sendMessage(player, "Here lies Glarial, wife of Baxtorian,") + return@queueScript delayScript(player, 3) + } + 3 -> { + sendMessage(player, "true friend of nature in life and death.") + return@queueScript delayScript(player, 3) + } + 4 -> { + sendMessage(player, "May she now rest knowing") + return@queueScript delayScript(player, 3) + } + 5 -> { + sendMessage(player, "only visitors with peaceful intent can enter.") + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + return@on true + } + + // Enter Glarial's tomb with the pebble + onUseWith(IntType.SCENERY, Items.GLARIALS_PEBBLE_294, SceneryObj.GLARIAL_S_TOMBSTONE_1992) { player, _, _ -> + if (ItemDefinition.canEnterEntrana(player)) { + if (player.familiarManager.hasFamiliar()) { + sendMessage(player, "You can't take a follower into the tomb.") + return@onUseWith true + } + sendMessage(player, "You place the pebble in the gravestone's small indent.") + sendMessage(player, "It fits perfectly.") + lock(player, 13) + queueScript(player, 4, QueueStrength.SOFT) { stage -> + when (stage) { + 0 -> { + sendMessage(player, "You hear a loud creak.") + return@queueScript delayScript(player, 3) + } + 1 -> { + sendMessage(player, "The stone slab slides back revealing a ladder down.") + return@queueScript delayScript(player, 5) + } + 2 -> { + sendMessage(player, "You climb down to an underground passage.") + return@queueScript delayScript(player, 1) + } + 3 -> { + player.skills.setPrayerPoints(0.0) + teleport(player, locInsideTomb) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } else { + sendMessage(player, "You place the pebble in the gravestone's small indent.") + sendMessage(player, "It fits perfectly.") + queueScript(player, 4, QueueStrength.SOFT) { + sendMessage(player, "But nothing happens.") + return@queueScript stopExecuting(player) + } + } + return@onUseWith true + } + + // Open the treasure chest in Glarial's tomb + on(SceneryObj.CLOSED_CHEST_33046, IntType.SCENERY, "open") { _, node -> + replaceScenery(node as Scenery, SceneryObj.OPEN_CHEST_33047, -1) + return@on true + } + + // Search the treasure chest in Glarial's tomb + on(SceneryObj.OPEN_CHEST_33047, IntType.SCENERY, "search") { player, _ -> + if (getQuestStage(player, Quests.WATERFALL_QUEST) >= 30) { + if (inInventory(player, Items.GLARIALS_AMULET_295)) { + sendMessage(player, "You search the chest and find nothing.") + } else { + sendMessage(player, "You search the chest and find a small amulet.") + addItemOrDrop(player, Items.GLARIALS_AMULET_295) + } + } + return@on true + } + + // Close the treasure chest in Glarial's tomb + on(SceneryObj.OPEN_CHEST_33047, IntType.SCENERY, "close") { _, node -> + replaceScenery(node as Scenery, SceneryObj.CLOSED_CHEST_33046, -1) + return@on true + } + + // Search Glarial's Tomb + on(SceneryObj.GLARIAL_S_TOMB_33066, IntType.SCENERY, "search") { player, _ -> + if (getQuestStage(player, Quests.WATERFALL_QUEST) >= 30) { + if (inInventory(player, Items.GLARIALS_URN_296)) { + sendMessage(player, "You search the coffin and find nothing.") + } else { + sendMessage(player, "You search the coffin and inside you find an urn full of ashes.") + addItemOrDrop(player, Items.GLARIALS_URN_296) + } + } + return@on true + } + + // Search the crate in the waterfall cave + on(SceneryObj.CRATE_1999, IntType.SCENERY, "search") { player, _ -> + if (inInventory(player, Items.A_KEY_298, 1) || getQuestStage(player, Quests.WATERFALL_QUEST) < 30) { + sendMessage(player, "You search the crate and find nothing.") + } else { + sendMessage(player, "You find a large key.") + addItemOrDrop(player, Items.A_KEY_298, 1) + } + return@on true + } + + // Interact with the doors directly ahead of the waterfall cave's inner chamber + on(SceneryObj.DOOR_2002, IntType.SCENERY, "open") { player, node -> + when (player.location) { + locWaterfallDoorSouth -> { + sendMessage(player, "The door is locked.") + } + locWaterfallDoorSouth.transform(0, 1, 0) -> { + DoorActionHandler.handleAutowalkDoor(player, node as Scenery) + } + locWaterfallDoorNorth -> { + if (isQuestComplete(player, Quests.WATERFALL_QUEST)) { + teleport(player, locWaterfallDoorChamber.transform(0, 1, 0)) + } else { + DoorActionHandler.handleAutowalkDoor(player, node as Scenery) + } + } + locWaterfallDoorChamber.transform(0, 1, 0) -> { + teleport(player, locWaterfallDoorNorth) + removeAttribute(player, attributeRunes) + } + else -> return@on false + } + return@on true + } + + // Use the key on the door to the waterfall cave's inner chamber + onUseWith(IntType.SCENERY, Items.A_KEY_298, SceneryObj.DOOR_2002) { player, _, with -> + if (player.location == locWaterfallDoorSouth) { + sendMessage(player, "You open the door and walk through.") + DoorActionHandler.handleAutowalkDoor(player, with as Scenery) + return@onUseWith true + } + return@onUseWith false + } + + // Use runes on the pedestals + onUseWith(IntType.SCENERY, runes, SceneryObj.PILLAR_2004) { player, used, with -> + val pIndex = pedestalLocations.indexOf(with.location) + val rIndex = runes.indexOf(used.id) + val activeIndex = (pIndex * runes.size) + rIndex + var activeState = getAttribute(player, attributeRunes, 0) + if (pIndex == -1) return@onUseWith false + if (activeState and (1 shl activeIndex) == 0) { + if (removeItem(player, used)) { + sendMessage(player, "You place the rune on the stand.") + lock(player, 1) + queueScript(player, 1, QueueStrength.SOFT) { + sendMessage(player, "The rune stone disappears in a puff of smoke.") + sendGraphics(graphicsRunePoof, with.location) + return@queueScript stopExecuting(player) + } + activeState = activeState or (1 shl activeIndex) + setAttribute(player, attributeRunes, activeState) + } + } else { + sendMessage(player, "Nothing interesting happens.") + } + return@onUseWith true + } + + // Use the amulet on the statue + onUseWith(IntType.SCENERY, Items.GLARIALS_AMULET_295, SceneryObj.STATUE_OF_GLARIAL_2006) { player, used, _ -> + if (isQuestComplete(player, Quests.WATERFALL_QUEST) || player.location == locBeforeFinalStatue) { + return@onUseWith false + } + if (getAttribute(player, attributeRunes, 0) != (-1 shl 18).inv()) { + sendMessage(player, "You place the amulet around the neck of the statue.") + lock(player, 4) + queueScript(player, 3, QueueStrength.SOFT) { + sendMessage(player, "Rocks fall from the ceiling and hit you in the head.") + sendGraphics(graphicsRocksFall, player.location) + impact(player, 20, HitsplatType.NORMAL) + return@queueScript stopExecuting(player) + } + return@onUseWith true + } else if (removeItem(player, used)) { + sendMessage(player, "You place the amulet around the neck of the statue.") + lock(player, 7) + queueScript(player, 3, QueueStrength.SOFT) { stage -> + when (stage) { + 0 -> { + sendMessage(player, "You hear a loud rumble from beneath...") + return@queueScript delayScript(player, 3) + } + 1 -> { + sendMessage(player, "The ground raises up before you!") + return@queueScript delayScript(player, 6) + } + 2 -> { + teleport(player, locBeforeFinalStatue) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + return@onUseWith true + } + return@onUseWith false + } + + // Try to loot the chalice + on(SceneryObj.CHALICE_OF_ETERNITY_2014, IntType.SCENERY, "take treasure") { player, _ -> + if (!isQuestComplete(player, Quests.WATERFALL_QUEST)) { + sendMessage(player, "The cavern floods!") + lock(player, 6) + queueScript(player, 5, QueueStrength.SOFT) { + sendMessage(player, "You are washed out of the chalice room.") + teleport(player, locWaterfallDoorNorth) + removeAttribute(player, attributeRunes) + return@queueScript stopExecuting(player) + } + } else { + sendMessage(player, "You have already looted the treasure.") + } + return@on true + } + + // Use the urn on the chalice + onUseWith(IntType.SCENERY, Items.GLARIALS_URN_296, SceneryObj.CHALICE_OF_ETERNITY_2014) { player, used, _ -> + if (isQuestComplete(player, Quests.WATERFALL_QUEST)) { + return@onUseWith false + } + if (freeSlots(player) < 5) { + sendMessage(player, "You'll need 5 free inventory slots to take Glarial's treasure.") + return@onUseWith true + } + if (removeItem(player, used)) { + addItemOrDrop(player, Items.GLARIALS_URN_297) + sendMessage(player, "You carefully pour the ashes into the chalice") + lock(player, 10) + queueScript(player, 3, QueueStrength.SOFT) { stage -> + when (stage) { + 0 -> { + sendMessage(player, "as you remove the Treasure of Baxtorian") + return@queueScript delayScript(player, 3) + } + 1 -> { + sendMessage(player, "The chalice remains standing.") + sendMessage(player, "Inside you find a mithril case") + sendMessage(player, "containing 40 seeds,") + sendMessage(player, "two diamonds and two gold bars.") + return@queueScript delayScript(player, 2) + } + 2 -> { + finishQuest(player, Quests.WATERFALL_QUEST) + return@queueScript stopExecuting(player) + } + else -> return@queueScript stopExecuting(player) + } + } + } + return@onUseWith true + } } override fun defineDestinationOverrides() { - setDest(IntType.NPC,HUDON){ _, _ -> - return@setDest Location.create(2512, 3481, 0) + setDest(IntType.NPC, NPCs.HUDON_305) { _, _ -> + return@setDest locHudonTalk + } + + setDest(IntType.SCENERY, intArrayOf(SceneryObj.ROCK_1996, SceneryObj.ROCK_1997)) { _, _ -> + return@setDest locIslandBeforeRock } } + } \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallPlugin.java b/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallPlugin.java deleted file mode 100644 index 2a10ebe5c..000000000 --- a/Server/src/main/content/region/kandarin/quest/waterfall/WaterfallPlugin.java +++ /dev/null @@ -1,584 +0,0 @@ -package content.region.kandarin.quest.waterfall; - -import java.util.ArrayList; -import java.util.List; - -import content.data.Quests; -import core.cache.def.impl.ItemDefinition; -import core.cache.def.impl.NPCDefinition; -import core.cache.def.impl.SceneryDefinition; -import core.game.dialogue.FacialExpression; -import core.game.global.action.ClimbActionHandler; -import core.game.global.action.DoorActionHandler; -import content.global.skill.agility.AgilityHandler; -import core.game.interaction.NodeUsageEvent; -import core.game.interaction.OptionHandler; -import core.game.interaction.UseWithHandler; -import core.game.node.Node; -import core.game.node.entity.combat.ImpactHandler.HitsplatType; -import core.game.node.entity.npc.NPC; -import core.game.node.entity.player.Player; -import core.game.node.entity.player.link.quest.Quest; -import core.game.node.item.Item; -import core.game.node.scenery.Scenery; -import core.game.node.scenery.SceneryBuilder; -import core.game.system.task.Pulse; -import core.game.world.map.Location; -import core.game.world.update.flag.context.Animation; -import core.plugin.Plugin; -import kotlin.Unit; -import core.plugin.ClassScanner; - -import static core.api.ContentAPIKt.*; - -/** - * Master plugin file for the Waterfall quest. - * - * This is one of the most disgusting files I have ever seen. -Ceikry - * - * @author Splinter - * @version 1.0 - Feb 28th, 2015 - */ -public final class WaterfallPlugin extends OptionHandler { - - /** - * The rope - */ - public final static Item ROPE = new Item(954); - - /** - * The first ket - */ - public final static Item KEY = new Item(293); - - /** - * The second key - */ - public final static Item KEY_2 = new Item(298); - - /** - * The glarial's pebble - */ - public final static Item PEBBLE = new Item(294); - - /** - * The glarial's amulet - */ - public final static Item AMULET = new Item(295); - - /** - * The glarial's urn - */ - public final static Item URN = new Item(296); - - /** - * The glarial's urn - */ - public final static Item URN_EMPTY = new Item(297); - - /** - * Air rune - */ - public final static Item AIR_RUNE = new Item(556, 6); - - /** - * Water rune - */ - public final static Item WATER_RUNE = new Item(555, 6); - - /** - * Earth rune - */ - public final static Item EARTH_RUNE = new Item(557, 6); - - /** - * The swimmer swimming. - */ - private static final List SWIMMERS = new ArrayList<>(20); - - /** - * The ropes. - */ - private static final List ROPES = new ArrayList<>(20); - - @Override - public Plugin newInstance(Object arg) throws Throwable { - ClassScanner.definePlugin(new WaterfallUseWithHandler()); - NPCDefinition.forId(305).getHandlers().put("option:talk-to", this); - SceneryDefinition.forId(1987).getHandlers().put("option:board", this); - SceneryDefinition.forId(2020).getHandlers().put("option:climb", this); - SceneryDefinition.forId(2022).getHandlers().put("option:get in", this); - SceneryDefinition.forId(10283).getHandlers().put("option:swim", this); - SceneryDefinition.forId(1996).getHandlers().put("option:swim to", this); - SceneryDefinition.forId(1989).getHandlers().put("option:search", this); - SceneryDefinition.forId(1990).getHandlers().put("option:search", this); - SceneryDefinition.forId(1991).getHandlers().put("option:open", this); - SceneryDefinition.forId(37247).getHandlers().put("option:open", this); - SceneryDefinition.forId(32711).getHandlers().put("option:open", this); - SceneryDefinition.forId(33046).getHandlers().put("option:open", this); - SceneryDefinition.forId(42313).getHandlers().put("option:open",this); - SceneryDefinition.forId(33047).getHandlers().put("option:search", this); - SceneryDefinition.forId(33047).getHandlers().put("option:close", this); - SceneryDefinition.forId(33066).getHandlers().put("option:search", this); - SceneryDefinition.forId(1999).getHandlers().put("option:search", this); - SceneryDefinition.forId(42319).getHandlers().put("option:climb-up", this); - SceneryDefinition.forId(2002).getHandlers().put("option:open", this); - SceneryDefinition.forId(1992).getHandlers().put("option:read", this); - SceneryDefinition.forId(2014).getHandlers().put("option:take treasure", this); - return this; - } - - @Override - public boolean handle(final Player player, Node node, String option) { - final int id = node.getId(); - final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST); - if (quest == null) { - player.sendMessage("Error! Waterfall quest cannot be found."); - return true; - } - switch (id) { - case 37247: - player.getPacketDispatch().sendMessage("The door opens..."); - player.getPulseManager().run(new Pulse(2, player) { - @Override - public boolean pulse() { - if ((player.getEquipment().containsAtLeastOneItem(295) || player.getInventory().contains(295, 1)) || player.getQuestRepository().isComplete(Quests.WATERFALL_QUEST)) { - player.getPacketDispatch().sendMessage("You walk through the door."); - player.teleport(new Location(2575, 9861)); - } else { - player.getPacketDispatch().sendMessage("The cave floods and washes you away!"); - player.teleport(new Location(2527, 3413)); - } - return true; - } - }); - break; - case 1992: - player.lock(16); - player.getPacketDispatch().sendMessage("The grave is covered in elven script.", 1); - player.getPacketDispatch().sendMessage("Some of the writing is in common tongue, it reads:", 3); - player.getPacketDispatch().sendMessage("Here lies Glarial, wife of Baxtorian,", 6); - player.getPacketDispatch().sendMessage("true friend of nature in life and death.", 9); - player.getPacketDispatch().sendMessage("May she now rest knowing", 12); - player.getPacketDispatch().sendMessage("only visitors with peaceful intent can enter.", 15); - break; - case 2014: - if (quest.getStage(player) != 100) { - player.getPacketDispatch().sendMessage("The cavern floods!"); - player.lock(6); - player.getPulseManager().run(new Pulse(5, player) { - @Override - public boolean pulse() { - player.teleport(new Location(2566, 9901)); - player.getPacketDispatch().sendMessage("You are washed out of the chalice room."); - player.removeAttribute("waterfall_placed_runes"); - return true; - } - }); - } else { - player.getPacketDispatch().sendMessage("You have already looted the treasure."); - } - break; - case 1999:// Second key (in the actual waterfall dungeon) - if (inInventory(player, 298,1) || quest.getStage(player) < 30) { - sendMessage(player, "You search the crate and find nothing."); - } else if (quest.getStage(player) >= 30 && !inInventory(player,298, 1)) { - sendMessage(player, "You find a large key."); - addItemOrDrop(player, 298, 1); - } - break; - case 2002:// - if (player.getLocation().equals(new Location(2568, 9893))) { - player.getPacketDispatch().sendMessage("The door is locked."); - } else if (node.getLocation().equals(new Location(2566, 9901)) || player.getLocation().equals(new Location(2568, 9894, 0))) { - if (quest.getStage(player) >= 100 && node.getLocation().equals(new Location(2566, 9901)) && player.getLocation().equals(new Location(2566, 9901))) { - player.teleport(new Location(2604, 9901)); - } else { - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); - } - } - if (node.getLocation().equals(new Location(2604, 9900))) { - player.teleport(new Location(2566, 9901)); - player.removeAttribute("waterfall_placed_runes"); - } - break; - case 33046: - SceneryBuilder.add(new Scenery(33047, Location.create(2530, 9844, 0), 10, 1)); - break; - case 42319: - if (node.getLocation().equals(new Location(2556, 9844))) { - ClimbActionHandler.climb(player, new Animation(828), Location.create(2557, 3444, 0)); - } else { - ClimbActionHandler.climbLadder(player, (Scenery) node, option); - } - break; - case 33047: - switch (option) { - case "open": - case "search": - if (quest.getStage(player) >= 30) { - if (!player.hasItem(new Item(295))) { - player.getPacketDispatch().sendMessage("You search the chest and find a small amulet."); - player.getInventory().add(new Item(295, 1)); - } else { - player.getPacketDispatch().sendMessage("You search the chest and find nothing."); - } - } - break; - case "close": - SceneryBuilder.add(new Scenery(33046, Location.create(2530, 9844, 0), 10, 1)); - break; - } - break; - case 33066: - if (quest.getStage(player) >= 30) { - if (!player.getInventory().contains(296, 1)) { - player.getPacketDispatch().sendMessage("You search the coffin and inside you find an urn full of ashes."); - player.getInventory().add(new Item(296, 1)); - } else { - player.getPacketDispatch().sendMessage("You search the coffin and find nothing."); - } - } - break; - case 32711: - player.teleport(new Location(2511, 3463)); - break; - case 2020: - player.getDialogueInterpreter().open("waterfall_tree_dialogue", 0); - break; - case 305: - player.getDialogueInterpreter().open(305, ((NPC) node)); - break; - case 1990: - if (inInventory(player,293, 1) || quest.getStage(player) < 30) { - sendMessage(player,"You search the crate and find nothing."); - } else if (quest.getStage(player) >= 30 && !inInventory(player,293, 1)) { - sendMessage(player, "You find a large key."); - addItemOrDrop(player,293, 1); - } - break; - case 1991: - if (player.getLocation().getY() >= 9576) { - DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); - player.getPacketDispatch().sendMessage("You open the gate and walk through."); - } else if (player.getInventory().contains(293, 1) && player.getLocation().getY() < 9576) { - player.getPacketDispatch().sendMessage("The gate is locked. You need to use the key on the door to enter."); - } else { - player.getDialogueInterpreter().sendDialogues(306, FacialExpression.HALF_GUILTY, "Hello? Ah yes, the door is still locked.", "If you want to get in here, you'll need to find the key", "that I hid in some crates in the eastern room."); - } - break; - case 1989: - if (player.getInventory().contains(292, 1) || quest.getStage(player) != 20) { - player.getPacketDispatch().sendMessage("You search the bookcase and find nothing of interest."); - break; - } else if (!player.hasItem(new Item(292)) && quest.getStage(player) == 20) { - player.getInventory().add(new Item(292, 1)); - player.getPacketDispatch().sendMessage("You search the bookcase and find a book named 'Book on Baxtorian'"); - } - break; - case 10283: - case 1996: - player.logoutListeners.put("waterfall", player1 -> { - player1.setLocation(player.getLocation().transform(0,0,0)); - return Unit.INSTANCE; - }); - player.getPacketDispatch().sendGraphic(68); - player.lock(6); - AgilityHandler.walk(player, -1, player.getLocation(), new Location(2512, 3471, 0), Animation.create(164), 0, null); - player.getPacketDispatch().sendMessage("It looks like a long distance, but you swim out into the water."); - player.getPacketDispatch().sendMessage("The current is too strong, you feel yourself being pulled under", 3); - player.getPulseManager().run(new Pulse(6, player) { - @Override - public boolean pulse() { - player.getPacketDispatch().sendMessage("You are washed downstream but feel lucky to be alive."); - player.teleport(new Location(2527, 3413)); - return true; - } - }); - break; - case 2022:// Barrel - player.getPacketDispatch().sendMessage("You get in the barrel and start rocking."); - player.getPacketDispatch().sendMessage("The barrel falls off the ledge."); - player.teleport(new Location(2527, 3413)); - break; - case 1987:// Raft - if (quest.getStage(player) >= 10) { - player.getPacketDispatch().sendMessage("You board the small raft", 2); - player.lock(13); - player.getPacketDispatch().sendMessage("and push off down stream.", 6); - player.getPacketDispatch().sendMessage("The raft is pulled down stream by strong currents", 9); - player.getPulseManager().run(new Pulse(12, player) { - @Override - public boolean pulse() { - player.getPacketDispatch().sendMessage("You crash into a small land mound."); - player.teleport(new Location(2512, 3481)); - return true; - } - }); - } else { - player.getDialogueInterpreter().sendDialogue("You have no reason to board this raft."); - } - return true; - } - return true; - } - - @Override - public Location getDestination(Node node, Node n) { - if (n instanceof NPC) { - NPC npc = ((NPC) n); - if (npc.getId() == 305) { - return Location.create(2512, 3481, 0); - } - } - if (n instanceof Scenery) { - Scenery obj = ((Scenery) n); - if (obj.getId() == 1996 || obj.getId() == 1997) { - return Location.create(2512, 3476, 0); - } - } - return null; - } - - @Override - public boolean isWalk(Player player, Node node) { - return !(node instanceof Item); - } - - @Override - public boolean isWalk() { - return false; - } - - public void handleObjects(boolean add, final Player player) {// very ugly - // code - if (add) { - ROPES.add(new Scenery(1997, Location.create(2512, 3468, 0), 10, 0)); - ROPES.add(new Scenery(1998, Location.create(2512, 3469, 0), 10, 0)); - ROPES.add(new Scenery(1998, Location.create(2512, 3470, 0), 10, 0)); - ROPES.add(new Scenery(1998, Location.create(2512, 3471, 0), 10, 0)); - ROPES.add(new Scenery(1998, Location.create(2512, 3472, 0), 10, 0)); - ROPES.add(new Scenery(1998, Location.create(2512, 3473, 0), 10, 0)); - ROPES.add(new Scenery(1998, Location.create(2512, 3474, 0), 10, 0)); - ROPES.add(new Scenery(1998, Location.create(2512, 3475, 0), 10, 0)); - for (Scenery rope : ROPES) { - SceneryBuilder.add(rope); - } - } else { - for (Scenery rope : ROPES) { - SceneryBuilder.remove(rope); - } - ROPES.clear(); - SceneryBuilder.add(new Scenery(1996, Location.create(2512, 3468, 0), 10, 0)); - - } - } - - /** - * Handles the runestone graphic. - * @param player the player. - */ - public void playRunestoneGraphics(final Player player) { - player.getPacketDispatch().sendGlobalPositionGraphic(580, new Location(2562, 9914)); - player.getPacketDispatch().sendGlobalPositionGraphic(580, new Location(2562, 9912)); - player.getPacketDispatch().sendGlobalPositionGraphic(580, new Location(2562, 9910)); - player.getPacketDispatch().sendGlobalPositionGraphic(580, new Location(2569, 9914)); - player.getPacketDispatch().sendGlobalPositionGraphic(580, new Location(2569, 9912)); - player.getPacketDispatch().sendGlobalPositionGraphic(580, new Location(2569, 9910)); - } - - /** - * Handles using items on objects for the quest. - * @author Splinter - */ - public class WaterfallUseWithHandler extends UseWithHandler { - - private final int[] OBJECTS = new int[] { 1996, 1997, 2020, 1991, 1992, 2002, 2006, 2014, 2004 }; - - /** - * Constructs a new {@Code WaterfallUseWithItemHandler} {@Code - * Object} - */ - public WaterfallUseWithHandler() { - super(ROPE.getId(), KEY.getId(), PEBBLE.getId(), KEY_2.getId(), AMULET.getId(), URN.getId(), AIR_RUNE.getId(), EARTH_RUNE.getId(), WATER_RUNE.getId()); - } - - @Override - public Plugin newInstance(Object arg) throws Throwable { - for (int id : OBJECTS) { - addHandler(id, OBJECT_TYPE, this); - } - return this; - } - - @Override - public Location getDestination(Player playa, Node n) { - if (n instanceof Scenery) { - Scenery obj = (Scenery) n; - if (obj.getId() == 1996 || obj.getId() == 1997) { - return Location.create(2512, 3476, 0); - } - } - return null; - } - - @Override - public boolean handle(NodeUsageEvent event) { - final Player player = event.getPlayer(); - Item useditem = event.getUsedItem(); - final Quest quest = player.getQuestRepository().getQuest(Quests.WATERFALL_QUEST); - final Scenery object = (Scenery) event.getUsedWith(); - - if (useditem.getId() == ROPE.getId() && object.getId() == 1996 || object.getId() == 1997) { - player.lock(8); - player.animate(Animation.create(774)); - SWIMMERS.add(player); - if (SWIMMERS.size() == 0 || ROPES.size() == 0) { - handleObjects(true, player); - } - player.logoutListeners.put("waterfall", player1 -> { - player1.setLocation(player.getLocation().transform(0,0,0)); - return Unit.INSTANCE; - }); - player.getPulseManager().run(new Pulse(2, player) { - @Override - public boolean pulse() { - player.faceLocation(new Location(2512, 3468, 0)); - AgilityHandler.walk(player, -1, player.getLocation(), new Location(2512, 3469, 0), Animation.create(273), 0, null); - player.getPulseManager().run(new Pulse(8, player) { - @Override - public boolean pulse() { - player.teleport(new Location(2513, 3468)); - player.faceLocation(new Location(2512, 3468, 0)); - player.animate(Animation.create(780)); - player.logoutListeners.remove("waterfall"); - return true; - } - - @Override - public void stop() { - super.stop(); - if (SWIMMERS.remove(player) && SWIMMERS.size() == 0) { - handleObjects(false, player); - } - } - }); - return true; - } - }); - } - - if (useditem.getId() == ROPE.getId() && object.getId() == 2020) { - player.getPacketDispatch().sendMessage("You tie the rope to the tree and let yourself down on the ledge."); - player.teleport(new Location(2511, 3463)); - } - - if (useditem.getId() == KEY.getId() && object.getId() == 1991) { - player.getPacketDispatch().sendMessage("The key fits the gate."); - player.getPacketDispatch().sendMessage("You open the gate and walk through."); - DoorActionHandler.handleAutowalkDoor(player, object); - } - - if (useditem.getId() == KEY_2.getId() && object.getId() == 2002 && !object.getLocation().equals(new Location(2566, 9901))) { - player.getPacketDispatch().sendMessage("You open the door and walk through."); - DoorActionHandler.handleAutowalkDoor(player, object); - } - - if (useditem.getId() == PEBBLE.getId() && object.getId() == 1992 && ItemDefinition.canEnterEntrana(player)) { - if (player.getFamiliarManager().hasFamiliar()) { - sendMessage(player, "You can't take a follower into the tomb."); - return false; - } - player.getPacketDispatch().sendMessage("You place the pebble in the gravestone's small indent."); - player.getPacketDispatch().sendMessage("It fits perfectly."); - player.getPacketDispatch().sendMessage("You hear a loud creak.", 4); - player.getPacketDispatch().sendMessage("The stone slab slides back revealing a ladder down.", 7); - player.getPacketDispatch().sendMessage("You climb down to an underground passage.", 12); - player.getPulseManager().run(new Pulse(13, player) { - @Override - public boolean pulse() { - player.getSkills().setPrayerPoints(0); - player.teleport(new Location(2555, 9844)); - return true; - } - }); - } else if (!ItemDefinition.canEnterEntrana(player) && useditem.getId() == PEBBLE.getId() && object.getId() == 1992) { - player.getPacketDispatch().sendMessage("You place the pebble in the gravestone's small indent."); - player.getPacketDispatch().sendMessage("It fits perfectly."); - player.getPacketDispatch().sendMessage("But nothing happens.", 4); - } - - if ((useditem.getId() == AIR_RUNE.getId() || useditem.getId() == EARTH_RUNE.getId() || useditem.getId() == WATER_RUNE.getId()) && object.getId() == 2004) { - if (player.getInventory().contains(555, 6) && player.getInventory().contains(556, 6) && player.getInventory().contains(557, 6)) { - if (player.getAttribute("waterfall_placed_runes") != null) { - player.getPacketDispatch().sendMessage("You have already placed the runes on the pillars."); - return false; - } - playRunestoneGraphics(player); - player.getPacketDispatch().sendMessage("You place one of each runestone on all six of the pillars."); - player.setAttribute("waterfall_placed_runes", 1); - player.getInventory().remove(new Item(AIR_RUNE.getId(), 6)); - player.getInventory().remove(new Item(EARTH_RUNE.getId(), 6)); - player.getInventory().remove(new Item(WATER_RUNE.getId(), 6)); - } else { - player.getPacketDispatch().sendMessage("You do not have enough runestones to place on the pillars."); - } - } - - if (useditem.getId() == AMULET.getId() && object.getId() == 2006 && quest.getStage(player) != 100 && !player.getLocation().equals(new Location(2603, 9914))) { - if (player.getAttribute("waterfall_placed_runes") == null) { - player.getPacketDispatch().sendMessage("You place the amulet around the neck of the statue."); - player.lock(4); - player.getPulseManager().run(new Pulse(3, player) { - @Override - public boolean pulse() { - player.getPacketDispatch().sendGraphic(74); - player.getImpactHandler().manualHit(player, 20, HitsplatType.NORMAL); - player.getPacketDispatch().sendMessage("Rocks fall from the ceiling and hit you in the head."); - return true; - } - }); - } else if (player.getAttribute("waterfall_placed_runes") != null) { - player.lock(7); - player.getInventory().remove(AMULET); - player.getPacketDispatch().sendMessage("You place the amulet around the neck of the statue."); - player.getPacketDispatch().sendMessage("You hear a loud rumble from beneath...", 3); - player.getPacketDispatch().sendMessage("The ground raises up before you!", 6); - player.getPulseManager().run(new Pulse(6, player) { - @Override - public boolean pulse() { - player.teleport(new Location(2603, 9914)); - return true; - } - }); - } - } - - if (useditem.getId() == URN.getId() && object.getId() == 2014 && quest.getStage(player) != 100) { - if (player.getInventory().freeSlots() < 5) { - player.getPacketDispatch().sendMessage("You'll need 5 free inventory slots to take Glarial's treasure."); - return false; - } else { - player.lock(10); - player.getInventory().remove(URN); - player.getInventory().add(URN_EMPTY); - player.getPacketDispatch().sendMessage("You carefully pour the ashes into the chalice"); - player.getPacketDispatch().sendMessage("as you remove the Treasure of Baxtorian", 3); - player.getPacketDispatch().sendMessage("The chalice remains standing.", 6); - player.getPacketDispatch().sendMessage("Inside you find a mithril case", 6); - player.getPacketDispatch().sendMessage("containing 40 seeds,", 6); - player.getPacketDispatch().sendMessage("two diamonds and two gold bars.", 6); - player.getPulseManager().run(new Pulse(8, player) { - @Override - public boolean pulse() { - quest.finish(player); - return true; - } - }); - - } - } - return true; - } - } -}