From 3c2810b539a0813273fe036945b627a35d436eb7 Mon Sep 17 00:00:00 2001 From: Byte Date: Mon, 10 Oct 2022 13:20:56 +0000 Subject: [PATCH] Added agility grappling shortcut from Catherby to Taverley (one way) Updated ContentAPI to have a method for checking if any item from a given set of items is equipped by the player --- Server/src/main/kotlin/api/ContentAPI.kt | 12 ++ .../shortcuts/CatherbyGrappleShortcut.kt | 114 ++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 Server/src/main/kotlin/rs09/game/node/entity/skill/agility/shortcuts/CatherbyGrappleShortcut.kt diff --git a/Server/src/main/kotlin/api/ContentAPI.kt b/Server/src/main/kotlin/api/ContentAPI.kt index 3c039cef8..20262ae7f 100644 --- a/Server/src/main/kotlin/api/ContentAPI.kt +++ b/Server/src/main/kotlin/api/ContentAPI.kt @@ -150,6 +150,18 @@ fun areEquipped(player: Player, vararg ids: Int): Boolean { } } +/** + * Check that at least one item from a set of items is equipped by the given player + * @param player the player + * @param ids the set of item ids to check + * @return true if the player has at least one of the items equipped, false if none are equipped + */ +fun areAnyEquipped(player: Player, vararg ids: Int): Boolean { + return ids.any { id -> + amountInEquipment(player, id) > 0 + } +} + data class ContainerisedItem(val container: core.game.container.Container?, val itemId: Int) /** diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/agility/shortcuts/CatherbyGrappleShortcut.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/agility/shortcuts/CatherbyGrappleShortcut.kt new file mode 100644 index 000000000..339fad7a3 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/agility/shortcuts/CatherbyGrappleShortcut.kt @@ -0,0 +1,114 @@ +package rs09.game.node.entity.skill.agility.shortcuts + +import api.* +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills +import core.game.system.task.Pulse +import core.game.world.map.Location +import core.game.world.update.flag.context.Animation +import org.rs09.consts.Items +import org.rs09.consts.Scenery +import rs09.game.interaction.IntType +import rs09.game.interaction.InteractionListener + +/** + * Handles the Catherby to Taverley grapple shortcut + * @author Byte + */ +class CatherbyGrappleShortcut : InteractionListener { + + companion object { + private val START_LOCATION: Location = Location.create(2866, 3429, 0) + private val END_LOCATION: Location = Location.create(2869,3430,0) + + private val REQUIREMENTS = hashMapOf( + Skills.AGILITY to 32, + Skills.RANGE to 35, + Skills.STRENGTH to 35 + ) + + private val VALID_CROSSBOWS = intArrayOf( + Items.MITH_CROSSBOW_9181, + Items.ADAMANT_CROSSBOW_9183, + Items.RUNE_CROSSBOW_9185, + Items.DORGESHUUN_CBOW_8880 + ) + } + + private var rocks = getScenery(Location.create(2869,3429, 0)) + + override fun defineListeners() { + flagInstant() // execute listeners instantly without determining path + + on(Scenery.ROCKS_17042, IntType.SCENERY, "grapple") { player, _ -> + if (isPlayerInRangeToGrapple(player)) { + forceWalk(player, START_LOCATION, "smart") + } else { + sendMessage(player, "Nothing interesting happens.") + return@on true + } + + if (!doesPlayerHaveRequiredItemsEquipped(player)) { + sendDialogue(player, "You need a Mithril crossbow and a Mithril grapple in order to do this.") + return@on true + } + + if (!doesPlayerHaveRequiredLevels(player)) { + sendDialogueLines(player, + "You need at least " + + REQUIREMENTS[Skills.AGILITY] + " " + Skills.SKILL_NAME[Skills.AGILITY] + ", " + + REQUIREMENTS[Skills.RANGE] + " " + Skills.SKILL_NAME[Skills.RANGE] + ", ", + "and " + + REQUIREMENTS[Skills.STRENGTH] + " " + Skills.SKILL_NAME[Skills.STRENGTH] + " to use this shortcut." + ) + return@on true + } + + lock(player, 15) + submitWorldPulse(object : Pulse(2) { + var counter = 0 + override fun pulse() : Boolean { + when (counter++) { + 1 -> { + face(player, END_LOCATION) + // Audit: shows player climbing (probably a wall), need a cliff climb animation + animate(player, Animation(4455)) + } + 3 -> { + // Audit: shows grapple on rocks, but there is no rope + replaceScenery(rocks!!, rocks!!.id + 1, 10) + } + 8 -> { + teleport(player, END_LOCATION) + } + 9 -> { + sendMessage(player, "You successfully grapple the rock and climb the cliffside.") + unlock(player) + return true + } + } + return false + } + }) + + return@on true + } + } + + private fun doesPlayerHaveRequiredItemsEquipped(player: Player): Boolean { + return isEquipped(player, Items.MITH_GRAPPLE_9419) && areAnyEquipped(player, *VALID_CROSSBOWS) + } + + private fun doesPlayerHaveRequiredLevels(player: Player): Boolean { + for ((skill, requiredLevel) in REQUIREMENTS) { + if (!hasLevelDyn(player, skill, requiredLevel)) { + return false + } + } + return true + } + + private fun isPlayerInRangeToGrapple(player: Player): Boolean { + return inBorders(player,START_LOCATION.x - 2, START_LOCATION.y - 2, START_LOCATION.x, START_LOCATION.y) + } +}