From 3e6415f0d23543e3ac5ec23c2d5a2802f90fecc6 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Sat, 16 Sep 2017 20:31:53 -0700 Subject: [PATCH 1/4] Initial commit on new woodcutting branch --- game/plugin/skills/woodcutting/build.gradle | 7 + game/plugin/skills/woodcutting/meta.toml | 9 + game/plugin/skills/woodcutting/src/axe.kt | 23 +++ game/plugin/skills/woodcutting/src/wood.kt | 85 +++++++++ .../woodcutting/src/woodcutting.plugin.kts | 163 ++++++++++++++++++ 5 files changed, 287 insertions(+) create mode 100644 game/plugin/skills/woodcutting/build.gradle create mode 100644 game/plugin/skills/woodcutting/meta.toml create mode 100644 game/plugin/skills/woodcutting/src/axe.kt create mode 100644 game/plugin/skills/woodcutting/src/wood.kt create mode 100644 game/plugin/skills/woodcutting/src/woodcutting.plugin.kts diff --git a/game/plugin/skills/woodcutting/build.gradle b/game/plugin/skills/woodcutting/build.gradle new file mode 100644 index 00000000..886112d7 --- /dev/null +++ b/game/plugin/skills/woodcutting/build.gradle @@ -0,0 +1,7 @@ +plugin { + name = "woodcutting_skill" + packageName = "org.apollo.game.plugin.skills.woodcutting" + authors = [ + "tlf30" + ] +} \ No newline at end of file diff --git a/game/plugin/skills/woodcutting/meta.toml b/game/plugin/skills/woodcutting/meta.toml new file mode 100644 index 00000000..c490c711 --- /dev/null +++ b/game/plugin/skills/woodcutting/meta.toml @@ -0,0 +1,9 @@ +name = "woodcutting-skill" +package = "org.apollo.game.plugin.skills.woodcutting" +authors = [ + "tlf30" + ] + +[config] +srcDir = "src/" +testDir = "test/" diff --git a/game/plugin/skills/woodcutting/src/axe.kt b/game/plugin/skills/woodcutting/src/axe.kt new file mode 100644 index 00000000..ae3e11a7 --- /dev/null +++ b/game/plugin/skills/woodcutting/src/axe.kt @@ -0,0 +1,23 @@ +package org.apollo.game.plugin.skills.mining + +import org.apollo.game.model.Animation; + +//Animation IDs: https://www.rune-server.ee/runescape-development/rs2-client/configuration/272373-emote-gfx-id-list.html +enum class Axe(val id: Int, val level: Int, val animation: Animation, val pulses: Int) { + RUNE(1359, 41, Animation(867), 3), + ADAMANT(1357, 31, Animation(869), 4), + MITHRIL(1355, 21, Animation(871), 5), + BLACK(1361, 11, Animation(873), 6), + STEEL(1353, 6, Animation(875), 6), + IRON(1349, 1, Animation(877), 7), + BRONZE(1351, 1, Animation(879), 8) +} + +val AXES = Axe.values() + +fun getAxes(): Array { + return AXES +} + +fun lookupPickaxe(id: Int): Axe? = AXES.find { it.id == id } + diff --git a/game/plugin/skills/woodcutting/src/wood.kt b/game/plugin/skills/woodcutting/src/wood.kt new file mode 100644 index 00000000..6201d8cd --- /dev/null +++ b/game/plugin/skills/woodcutting/src/wood.kt @@ -0,0 +1,85 @@ +package org.apollo.game.plugin.skills.mining + + +/** + * values thanks to: http://oldschoolrunescape.wikia.com/wiki/Woodcutting + */ +enum class Wood(val id: Int, val objects: IntArray, val stump: Int, val level: Int, val exp: Double, val chance: Double) { + NORMAL(1511, NORMAL_OBJECTS, NORMAL_STUMP, 1, 25.0, 100.0), + ACHEY(2862, ACHEY_OBJECTS, ACHEY_STUMP, 1, 25.0, 100.0), + OAK(1521, OAK_OBJECTS, OAK_STUMP, 15, 37.5, 0.125), + WILLOW(1519, WILLOW_OBJECTS, WILLOW_STUMP, 30, 67.5, 0.125), + TEAK(6333, TEAK_OBJECTS, TEAK_STUMP, 35, 85.0, 0.125), + MAPLE(1517, MAPLE_OBJECTS, MAPLE_STUMP, 45, 100.0, 0.125), + MAHOGANY(6332, MAHOGANY_OBJECTS, MAHOGANY_STUMP, 50, 125.0,0.125), + YEW(1515, YEW_OBJECTS, YEW_STUMP, 60, 175.0, 0.125), + MAGIC(1513, MAGIC_OBJECTS, MAGIC_STUMP, 75, 250.0, 0.125), +} + +val WOOD = Wood.values() + +fun lookupWood(id: Int): Wood? =WOOD.find { it.id == id } + +fun lookupTree(id: Int): Wood? { + for (wood in WOOD) { + for (tree in wood.objects) { + if (tree == id) { + return wood + } + } + } + return null +} + +val NORMAL_STUMP = 1342 +val ACHEY_STUMP = 3371 +val OAK_STUMP = 1342 +val WILLOW_STUMP = 1342 +val TEAK_STUMP = 1342 +val MAPLE_STUMP = 1342 +val MAHOGANY_STUMP = 1342 +val YEW_STUMP = 1342 +val MAGIC_STUMP = 1324 + +val NORMAL_OBJECTS = intArrayOf( + 1276, 1277, 1278, 1279, 1280, 1282, 1283, 1284, 1285, 1285, 1286, 1289, 1290, 1291, 1315, + 1316, 1318, 1330, 1331, 1332, 1365, 1383, 1384, 2409, 3033, 3034, 3035, 3036, 3881, 3882, + 3883, 5902, 5903, 5904, 10041 +) + +val ACHEY_OBJECTS = intArrayOf( + 2023 +) + +val OAK_OBJECTS = intArrayOf( + 1281, 3037 +) + +val WILLOW_OBJECTS = intArrayOf( + 5551, 5552, 5553 +) + +val TEAK_OBJECTS = intArrayOf( + 9036 +) + + +val MAPLE_OBJECTS = intArrayOf( + 1307, 4674 +) + +val MAHOGANY_OBJECTS = intArrayOf( + 9034 +) + + +val YEW_OBJECTS = intArrayOf( + 1309 +) + +val MAGIC_OBJECTS = intArrayOf( + 1292, 1306 +) + + + diff --git a/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts new file mode 100644 index 00000000..8b5d0a48 --- /dev/null +++ b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts @@ -0,0 +1,163 @@ +import org.apollo.cache.def.ItemDefinition +import org.apollo.game.action.DistancedAction +import org.apollo.game.message.impl.ObjectActionMessage +import org.apollo.game.model.Position +import org.apollo.game.model.entity.Entity +import org.apollo.game.model.entity.EquipmentConstants +import org.apollo.game.model.entity.Player +import org.apollo.game.model.entity.Skill +import org.apollo.game.model.entity.obj.StaticGameObject +import org.apollo.game.plugin.skills.mining.* +import org.apollo.game.scheduling.ScheduledTask +import java.util.* + +class WoodcuttingAction(val player: Player, val objectID: Int, val p: Position, val wood: Wood) : DistancedAction(PULSES, true, player, p, TREE_SIZE) { + + companion object { + private val PULSES = 0 + private val TREE_SIZE = 1; + } + + private var counter: Int = 0 + private var started: Boolean = false + private val rand: Random = Random() + + override fun executeAction() { + System.out.println("Cutting " + wood.id + " @ " + p) + val level = mob.skillSet.getSkill(Skill.WOODCUTTING).currentLevel + val axe = findAxe() + + + //check that our pick can mine the wood + if (axe == null || level < axe.level) { + mob.sendMessage("You do not have a axe for which you have the level to use.") + stop() + return + } + + //check that we can mine the wood + if (level < wood.level) { + mob.sendMessage("You do not have the required level to mine this rock.") + stop() + return + } + + //start the process of cutting + if (started) { + if (counter == 0) { + //Check inv capacity + if (mob.inventory.freeSlots() == 0) { + mob.inventory.forceCapacityExceeded() + stop() + return + } + if (mob.inventory.add(wood.id)) { + //TODO: Use lookup from utils once it has a lookup function for IDs + val woodName = ItemDefinition.lookup(wood.id).name.toLowerCase(); + mob.sendMessage("You managed to cut some " + woodName + ".") + mob.skillSet.addExperience(Skill.WOODCUTTING, wood.exp) + + } else { + System.out.println("Failed to add wood to inv"); + stop(); + return; + } + + if (!cuttingSuccessful(wood.chance)) { + System.out.println("Chopping...") + cut(axe) + return //We did not cut down the tree... Keep going + } else { + //We cut down the tree + var treeEntity: StaticGameObject? = null + val region = mob.world.regionRepository.fromPosition(position) + val entities = region.getEntities(position) + for (entity: Entity in entities) { + if (entity is StaticGameObject) { + System.out.println("Entity at cutting location: " + entity.id + " with type: " + entity.entityType) + if (entity.id == objectID) { + treeEntity = entity + } + } + } + if (treeEntity == null) { //tree entity not found at location... + System.out.println("WARNING: Invalid cutting condition on tree"); + stop() + return + } + //Get ID of exipred wood + val expiredObjectID = wood.stump; + val expiredRockEntity = StaticGameObject(mob.world, expiredObjectID!!, position, treeEntity!!.type, treeEntity!!.orientation) + //Remove normal wood and replace with expired + System.out.println("Removing " + objectID + " addding " + expiredObjectID) + System.out.println("Adding tasks") + //add task to remove normal wood and replace with depleted + mob.world.schedule(object: ScheduledTask(0, true) { + override fun execute() { + System.out.println("running deplete task") + //Replace normal wood with expired wood + region.removeEntity(treeEntity); + region.addEntity(expiredRockEntity) + this.stop() //Makes task run once + } + }) + //add task to respawn normal wood + //respawn time: http://runescape.wikia.com/wiki/Trees + val respawn = ((30 * 1000) / 600) + ((rand.nextInt(150) * 1000) / 600) // between 30 sec and 3 min respawm + mob.world.schedule(object: ScheduledTask(respawn, false) { + override fun execute() { + System.out.println("running wood task") + //Replace expired wood with normal wood + region.removeEntity(expiredRockEntity) + region.addEntity(treeEntity); + this.stop() //Makes task run once + } + }) + stop() + return + } + } + counter -= 1 + } else { + started = true + cut(axe) + } + } + + private fun findAxe(): Axe? { + for (axe in getAxes()) { + if (axe!!.level > mob.skillSet.getSkill(Skill.WOODCUTTING).currentLevel) { + continue; + } + val weponSlot = mob.equipment.get(EquipmentConstants.WEAPON) + if (weponSlot != null && weponSlot.id == axe.id) { + return axe; + } else if (mob.inventory.contains(axe.id)) { + return axe; + } + } + return null; + } + + private fun cut(axe: Axe) { + mob.sendMessage("You swing your axe at the tree.") + mob.playAnimation(axe.animation) + counter = axe.pulses + mob.turnTo(position) + } + + private fun cuttingSuccessful(woodChance: Double): Boolean { + return rand.nextInt(100) <= woodChance * 100; + } +} + + +on {ObjectActionMessage::class} + .where {option == 1} + .then { + if (lookupTree(id) != null) { + it.startAction(WoodcuttingAction(it, id, this.position, lookupTree(id)!!)) + } else { + System.out.println("Unknown wood: " + id) + } + } From da7c7e10b45ca32557b4d699ec851ecc22f9c4b0 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Sat, 16 Sep 2017 21:26:29 -0700 Subject: [PATCH 2/4] Woodcutting now uses Async Action --- game/plugin/skills/woodcutting/build.gradle | 1 + game/plugin/skills/woodcutting/src/axe.kt | 2 +- game/plugin/skills/woodcutting/src/wood.kt | 2 +- .../woodcutting/src/woodcutting.plugin.kts | 218 +++++++----------- 4 files changed, 87 insertions(+), 136 deletions(-) diff --git a/game/plugin/skills/woodcutting/build.gradle b/game/plugin/skills/woodcutting/build.gradle index 886112d7..d52d61ca 100644 --- a/game/plugin/skills/woodcutting/build.gradle +++ b/game/plugin/skills/woodcutting/build.gradle @@ -4,4 +4,5 @@ plugin { authors = [ "tlf30" ] + dependencies = ["api"] } \ No newline at end of file diff --git a/game/plugin/skills/woodcutting/src/axe.kt b/game/plugin/skills/woodcutting/src/axe.kt index ae3e11a7..02ad7d36 100644 --- a/game/plugin/skills/woodcutting/src/axe.kt +++ b/game/plugin/skills/woodcutting/src/axe.kt @@ -1,4 +1,4 @@ -package org.apollo.game.plugin.skills.mining +package org.apollo.game.plugin.skills.woodcutting import org.apollo.game.model.Animation; diff --git a/game/plugin/skills/woodcutting/src/wood.kt b/game/plugin/skills/woodcutting/src/wood.kt index 6201d8cd..550b98ca 100644 --- a/game/plugin/skills/woodcutting/src/wood.kt +++ b/game/plugin/skills/woodcutting/src/wood.kt @@ -1,4 +1,4 @@ -package org.apollo.game.plugin.skills.mining +package org.apollo.game.plugin.skills.woodcutting /** diff --git a/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts index 8b5d0a48..9facda64 100644 --- a/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts +++ b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts @@ -1,163 +1,113 @@ import org.apollo.cache.def.ItemDefinition -import org.apollo.game.action.DistancedAction +import org.apollo.game.action.AsyncDistancedAction import org.apollo.game.message.impl.ObjectActionMessage import org.apollo.game.model.Position -import org.apollo.game.model.entity.Entity -import org.apollo.game.model.entity.EquipmentConstants +import org.apollo.game.model.World import org.apollo.game.model.entity.Player import org.apollo.game.model.entity.Skill -import org.apollo.game.model.entity.obj.StaticGameObject -import org.apollo.game.plugin.skills.mining.* +import org.apollo.game.model.entity.obj.GameObject +import org.apollo.game.plugin.skills.woodcutting.* +import org.apollo.game.plugins.api.Definitions +import org.apollo.game.plugins.api.woodcutting +import org.apollo.game.plugins.api.skills import org.apollo.game.scheduling.ScheduledTask import java.util.* -class WoodcuttingAction(val player: Player, val objectID: Int, val p: Position, val wood: Wood) : DistancedAction(PULSES, true, player, p, TREE_SIZE) { +class WoodcuttingTarget(val objectId: Int, val position: Position, val wood: Wood) { + + fun getObject(world: World): Optional { + val region = world.regionRepository.fromPosition(position) + val obj = region.findObject(position, objectId) + + return obj + } + + fun isSuccessful(mob: Player): Boolean { + return rand(100) <= wood.chance * 100 + } +} + +class WoodcuttingAction(val player: Player, val tool: Axe, val target: WoodcuttingTarget) : AsyncDistancedAction(PULSES, true, player, target.position, TREE_SIZE) { companion object { private val PULSES = 0 private val TREE_SIZE = 1; - } - private var counter: Int = 0 - private var started: Boolean = false - private val rand: Random = Random() - - override fun executeAction() { - System.out.println("Cutting " + wood.id + " @ " + p) - val level = mob.skillSet.getSkill(Skill.WOODCUTTING).currentLevel - val axe = findAxe() - - - //check that our pick can mine the wood - if (axe == null || level < axe.level) { - mob.sendMessage("You do not have a axe for which you have the level to use.") - stop() - return + fun axeFor(player: Player): Axe? { + return AXES + .filter { it.level <= player.skills.woodcutting.currentLevel } + .filter { player.equipment.contains(it.id) || player.inventory.contains(it.id) } + .sortedByDescending { it.level } + .firstOrNull() } - //check that we can mine the wood - if (level < wood.level) { - mob.sendMessage("You do not have the required level to mine this rock.") - stop() - return - } - - //start the process of cutting - if (started) { - if (counter == 0) { - //Check inv capacity - if (mob.inventory.freeSlots() == 0) { - mob.inventory.forceCapacityExceeded() - stop() - return - } - if (mob.inventory.add(wood.id)) { - //TODO: Use lookup from utils once it has a lookup function for IDs - val woodName = ItemDefinition.lookup(wood.id).name.toLowerCase(); - mob.sendMessage("You managed to cut some " + woodName + ".") - mob.skillSet.addExperience(Skill.WOODCUTTING, wood.exp) - - } else { - System.out.println("Failed to add wood to inv"); - stop(); - return; - } - - if (!cuttingSuccessful(wood.chance)) { - System.out.println("Chopping...") - cut(axe) - return //We did not cut down the tree... Keep going - } else { - //We cut down the tree - var treeEntity: StaticGameObject? = null - val region = mob.world.regionRepository.fromPosition(position) - val entities = region.getEntities(position) - for (entity: Entity in entities) { - if (entity is StaticGameObject) { - System.out.println("Entity at cutting location: " + entity.id + " with type: " + entity.entityType) - if (entity.id == objectID) { - treeEntity = entity - } - } - } - if (treeEntity == null) { //tree entity not found at location... - System.out.println("WARNING: Invalid cutting condition on tree"); - stop() - return - } - //Get ID of exipred wood - val expiredObjectID = wood.stump; - val expiredRockEntity = StaticGameObject(mob.world, expiredObjectID!!, position, treeEntity!!.type, treeEntity!!.orientation) - //Remove normal wood and replace with expired - System.out.println("Removing " + objectID + " addding " + expiredObjectID) - System.out.println("Adding tasks") - //add task to remove normal wood and replace with depleted - mob.world.schedule(object: ScheduledTask(0, true) { - override fun execute() { - System.out.println("running deplete task") - //Replace normal wood with expired wood - region.removeEntity(treeEntity); - region.addEntity(expiredRockEntity) - this.stop() //Makes task run once - } - }) - //add task to respawn normal wood - //respawn time: http://runescape.wikia.com/wiki/Trees - val respawn = ((30 * 1000) / 600) + ((rand.nextInt(150) * 1000) / 600) // between 30 sec and 3 min respawm - mob.world.schedule(object: ScheduledTask(respawn, false) { - override fun execute() { - System.out.println("running wood task") - //Replace expired wood with normal wood - region.removeEntity(expiredRockEntity) - region.addEntity(treeEntity); - this.stop() //Makes task run once - } - }) - stop() - return - } + /** + * Starts a [WoodcuttingAction] for the specified [Player], terminating the [Message] that triggered it. + */ + fun start(message: ObjectActionMessage, player: Player, wood: Wood) { + val axe = axeFor(player) + if (axe != null) { + val action = WoodcuttingAction(player, axe, WoodcuttingTarget(message.id, message.position, wood)) + player.startAction(action) + } else { + player.sendMessage("You do not have a axe for which you have the level to use.") } - counter -= 1 - } else { - started = true - cut(axe) + + message.terminate() } } - private fun findAxe(): Axe? { - for (axe in getAxes()) { - if (axe!!.level > mob.skillSet.getSkill(Skill.WOODCUTTING).currentLevel) { - continue; - } - val weponSlot = mob.equipment.get(EquipmentConstants.WEAPON) - if (weponSlot != null && weponSlot.id == axe.id) { - return axe; - } else if (mob.inventory.contains(axe.id)) { - return axe; - } - } - return null; - } - private fun cut(axe: Axe) { - mob.sendMessage("You swing your axe at the tree.") - mob.playAnimation(axe.animation) - counter = axe.pulses + + override fun start() { mob.turnTo(position) + + val level = mob.skills.woodcutting.currentLevel + + if (level < target.wood.level) { + mob.sendMessage("You do not have the required level to cut down this tree.") + stop() + } } - private fun cuttingSuccessful(woodChance: Double): Boolean { - return rand.nextInt(100) <= woodChance * 100; + override suspend fun executeActionAsync() { + mob.sendMessage("You swing your axe at the tree.") + mob.playAnimation(tool.animation) + + wait(tool.pulses) + // + + val obj = target.getObject(mob.world) + if (!obj.isPresent) { + stop() + return + } + + if (mob.inventory.freeSlots() == 0) { + mob.inventory.forceCapacityExceeded() + stop() + return + } + if (mob.inventory.add(target.wood.id)) { + //TODO: Use lookup from utils once it has a lookup function for IDs + val woodName = ItemDefinition.lookup(target.wood.id).name.toLowerCase(); + mob.sendMessage("You managed to cut some $woodName.") + mob.skillSet.addExperience(Skill.WOODCUTTING, target.wood.exp) + } + + if (target.isSuccessful(mob)) { + //respawn time: http://runescape.wikia.com/wiki/Trees + val respawn = ((30 * 1000) / 600) + ((rand(150) * 1000) / 600) // between 30 sec and 3 min respawm + mob.world.expireObject(obj.get(), target.wood.stump, respawn) + } } } - -on {ObjectActionMessage::class} - .where {option == 1} +on { ObjectActionMessage::class } + .where { option == 1 } .then { - if (lookupTree(id) != null) { - it.startAction(WoodcuttingAction(it, id, this.position, lookupTree(id)!!)) - } else { - System.out.println("Unknown wood: " + id) + val wood = lookupTree(id) + if (wood != null) { + WoodcuttingAction.start(this, it, wood) } } From 75a9b828b25a18e6c027330a9c3c748174f64ba9 Mon Sep 17 00:00:00 2001 From: Trevor Flynn Date: Sat, 16 Sep 2017 21:48:45 -0700 Subject: [PATCH 3/4] Fix all issues. Wood cutting now works. --- game/plugin/skills/woodcutting/build.gradle | 2 +- game/plugin/skills/woodcutting/meta.toml | 9 -- game/plugin/skills/woodcutting/src/axe.kt | 18 +-- game/plugin/skills/woodcutting/src/wood.kt | 121 ++++++++---------- .../woodcutting/src/woodcutting.plugin.kts | 82 ++++++------ 5 files changed, 109 insertions(+), 123 deletions(-) delete mode 100644 game/plugin/skills/woodcutting/meta.toml diff --git a/game/plugin/skills/woodcutting/build.gradle b/game/plugin/skills/woodcutting/build.gradle index d52d61ca..0c154fb3 100644 --- a/game/plugin/skills/woodcutting/build.gradle +++ b/game/plugin/skills/woodcutting/build.gradle @@ -2,7 +2,7 @@ plugin { name = "woodcutting_skill" packageName = "org.apollo.game.plugin.skills.woodcutting" authors = [ - "tlf30" + "tlf30" ] dependencies = ["api"] } \ No newline at end of file diff --git a/game/plugin/skills/woodcutting/meta.toml b/game/plugin/skills/woodcutting/meta.toml deleted file mode 100644 index c490c711..00000000 --- a/game/plugin/skills/woodcutting/meta.toml +++ /dev/null @@ -1,9 +0,0 @@ -name = "woodcutting-skill" -package = "org.apollo.game.plugin.skills.woodcutting" -authors = [ - "tlf30" - ] - -[config] -srcDir = "src/" -testDir = "test/" diff --git a/game/plugin/skills/woodcutting/src/axe.kt b/game/plugin/skills/woodcutting/src/axe.kt index 02ad7d36..d7d23e81 100644 --- a/game/plugin/skills/woodcutting/src/axe.kt +++ b/game/plugin/skills/woodcutting/src/axe.kt @@ -2,7 +2,7 @@ package org.apollo.game.plugin.skills.woodcutting import org.apollo.game.model.Animation; -//Animation IDs: https://www.rune-server.ee/runescape-development/rs2-client/configuration/272373-emote-gfx-id-list.html +//Animation IDs thanks to Deadly A G S at rune-server.ee enum class Axe(val id: Int, val level: Int, val animation: Animation, val pulses: Int) { RUNE(1359, 41, Animation(867), 3), ADAMANT(1357, 31, Animation(869), 4), @@ -10,14 +10,14 @@ enum class Axe(val id: Int, val level: Int, val animation: Animation, val pulses BLACK(1361, 11, Animation(873), 6), STEEL(1353, 6, Animation(875), 6), IRON(1349, 1, Animation(877), 7), - BRONZE(1351, 1, Animation(879), 8) + BRONZE(1351, 1, Animation(879), 8); + + companion object { + private val AXES = Axe.values() + fun getAxes(): Array { + return AXES + } + } } -val AXES = Axe.values() - -fun getAxes(): Array { - return AXES -} - -fun lookupPickaxe(id: Int): Axe? = AXES.find { it.id == id } diff --git a/game/plugin/skills/woodcutting/src/wood.kt b/game/plugin/skills/woodcutting/src/wood.kt index 550b98ca..71c910ad 100644 --- a/game/plugin/skills/woodcutting/src/wood.kt +++ b/game/plugin/skills/woodcutting/src/wood.kt @@ -1,85 +1,72 @@ package org.apollo.game.plugin.skills.woodcutting +private val NORMAL_STUMP = 1342 +private val ACHEY_STUMP = 3371 +private val OAK_STUMP = 1342 +private val WILLOW_STUMP = 1342 +private val TEAK_STUMP = 1342 +private val MAPLE_STUMP = 1342 +private val MAHOGANY_STUMP = 1342 +private val YEW_STUMP = 1342 +private val MAGIC_STUMP = 1324 + +private val NORMAL_OBJECTS = hashSetOf( + 1276, 1277, 1278, 1279, 1280, 1282, 1283, 1284, 1285, 1285, 1286, 1289, 1290, 1291, 1315, + 1316, 1318, 1330, 1331, 1332, 1365, 1383, 1384, 2409, 3033, 3034, 3035, 3036, 3881, 3882, + 3883, 5902, 5903, 5904, 10041 +) + +private val ACHEY_OBJECTS = hashSetOf( + 2023 +) + +private val OAK_OBJECTS = hashSetOf( + 1281, 3037 +) + +private val WILLOW_OBJECTS = hashSetOf( + 5551, 5552, 5553 +) + +private val TEAK_OBJECTS = hashSetOf( + 9036 +) + + +private val MAPLE_OBJECTS = hashSetOf( + 1307, 4674 +) + +private val MAHOGANY_OBJECTS = hashSetOf( + 9034 +) + +private val YEW_OBJECTS = hashSetOf( + 1309 +) + +private val MAGIC_OBJECTS = hashSetOf( + 1292, 1306 +) /** * values thanks to: http://oldschoolrunescape.wikia.com/wiki/Woodcutting */ -enum class Wood(val id: Int, val objects: IntArray, val stump: Int, val level: Int, val exp: Double, val chance: Double) { +enum class Tree(val id: Int, val objects: HashSet, val stump: Int, val level: Int, val exp: Double, val chance: Double) { NORMAL(1511, NORMAL_OBJECTS, NORMAL_STUMP, 1, 25.0, 100.0), ACHEY(2862, ACHEY_OBJECTS, ACHEY_STUMP, 1, 25.0, 100.0), OAK(1521, OAK_OBJECTS, OAK_STUMP, 15, 37.5, 0.125), WILLOW(1519, WILLOW_OBJECTS, WILLOW_STUMP, 30, 67.5, 0.125), TEAK(6333, TEAK_OBJECTS, TEAK_STUMP, 35, 85.0, 0.125), MAPLE(1517, MAPLE_OBJECTS, MAPLE_STUMP, 45, 100.0, 0.125), - MAHOGANY(6332, MAHOGANY_OBJECTS, MAHOGANY_STUMP, 50, 125.0,0.125), + MAHOGANY(6332, MAHOGANY_OBJECTS, MAHOGANY_STUMP, 50, 125.0, 0.125), YEW(1515, YEW_OBJECTS, YEW_STUMP, 60, 175.0, 0.125), - MAGIC(1513, MAGIC_OBJECTS, MAGIC_STUMP, 75, 250.0, 0.125), -} + MAGIC(1513, MAGIC_OBJECTS, MAGIC_STUMP, 75, 250.0, 0.125); -val WOOD = Wood.values() - -fun lookupWood(id: Int): Wood? =WOOD.find { it.id == id } - -fun lookupTree(id: Int): Wood? { - for (wood in WOOD) { - for (tree in wood.objects) { - if (tree == id) { - return wood - } - } + companion object { + private val TREES = Tree.values().flatMap { tree -> tree.objects.map { Pair(it, tree) } }.toMap() + fun lookup(id: Int): Tree? = TREES[id] } - return null } -val NORMAL_STUMP = 1342 -val ACHEY_STUMP = 3371 -val OAK_STUMP = 1342 -val WILLOW_STUMP = 1342 -val TEAK_STUMP = 1342 -val MAPLE_STUMP = 1342 -val MAHOGANY_STUMP = 1342 -val YEW_STUMP = 1342 -val MAGIC_STUMP = 1324 - -val NORMAL_OBJECTS = intArrayOf( - 1276, 1277, 1278, 1279, 1280, 1282, 1283, 1284, 1285, 1285, 1286, 1289, 1290, 1291, 1315, - 1316, 1318, 1330, 1331, 1332, 1365, 1383, 1384, 2409, 3033, 3034, 3035, 3036, 3881, 3882, - 3883, 5902, 5903, 5904, 10041 -) - -val ACHEY_OBJECTS = intArrayOf( - 2023 -) - -val OAK_OBJECTS = intArrayOf( - 1281, 3037 -) - -val WILLOW_OBJECTS = intArrayOf( - 5551, 5552, 5553 -) - -val TEAK_OBJECTS = intArrayOf( - 9036 -) - - -val MAPLE_OBJECTS = intArrayOf( - 1307, 4674 -) - -val MAHOGANY_OBJECTS = intArrayOf( - 9034 -) - - -val YEW_OBJECTS = intArrayOf( - 1309 -) - -val MAGIC_OBJECTS = intArrayOf( - 1292, 1306 -) - - diff --git a/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts index 9facda64..ab8aee86 100644 --- a/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts +++ b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts @@ -1,4 +1,5 @@ import org.apollo.cache.def.ItemDefinition +import org.apollo.game.GameConstants import org.apollo.game.action.AsyncDistancedAction import org.apollo.game.message.impl.ObjectActionMessage import org.apollo.game.model.Position @@ -7,34 +8,41 @@ import org.apollo.game.model.entity.Player import org.apollo.game.model.entity.Skill import org.apollo.game.model.entity.obj.GameObject import org.apollo.game.plugin.skills.woodcutting.* -import org.apollo.game.plugins.api.Definitions import org.apollo.game.plugins.api.woodcutting import org.apollo.game.plugins.api.skills -import org.apollo.game.scheduling.ScheduledTask import java.util.* +import java.util.concurrent.TimeUnit -class WoodcuttingTarget(val objectId: Int, val position: Position, val wood: Wood) { +class WoodcuttingTarget(val objectId: Int, val position: Position, val tree: Tree) { + /** + * Get the tree object in the world + */ fun getObject(world: World): Optional { val region = world.regionRepository.fromPosition(position) - val obj = region.findObject(position, objectId) - - return obj + return region.findObject(position, objectId) } - fun isSuccessful(mob: Player): Boolean { - return rand(100) <= wood.chance * 100 + /** + * Check if the tree was cut down + */ + fun isCutDown(mob: Player): Boolean { + return rand(100) <= tree.chance * 100 } } -class WoodcuttingAction(val player: Player, val tool: Axe, val target: WoodcuttingTarget) : AsyncDistancedAction(PULSES, true, player, target.position, TREE_SIZE) { +class WoodcuttingAction(val player: Player, val tool: Axe, val target: WoodcuttingTarget) : AsyncDistancedAction(DELAY, true, player, target.position, TREE_SIZE) { companion object { - private val PULSES = 0 - private val TREE_SIZE = 1; + private val DELAY = 0 + private val TREE_SIZE = 2 + private val MINIMUM_RESPAWN_TIME = 30L //In seconds - fun axeFor(player: Player): Axe? { - return AXES + /** + * Find the highest level axe the player has + */ + private fun axeFor(player: Player): Axe? { + return getAxes() .filter { it.level <= player.skills.woodcutting.currentLevel } .filter { player.equipment.contains(it.id) || player.inventory.contains(it.id) } .sortedByDescending { it.level } @@ -44,27 +52,30 @@ class WoodcuttingAction(val player: Player, val tool: Axe, val target: Woodcutti /** * Starts a [WoodcuttingAction] for the specified [Player], terminating the [Message] that triggered it. */ - fun start(message: ObjectActionMessage, player: Player, wood: Wood) { + fun start(message: ObjectActionMessage, player: Player, wood: Tree) { val axe = axeFor(player) if (axe != null) { + //Check that the player had room in their inventory + if (player.inventory.freeSlots() == 0) { + player.inventory.forceCapacityExceeded() + return + } val action = WoodcuttingAction(player, axe, WoodcuttingTarget(message.id, message.position, wood)) player.startAction(action) } else { - player.sendMessage("You do not have a axe for which you have the level to use.") + player.sendMessage("You do not have an axe for which you have the level to use.") } message.terminate() } } - - override fun start() { mob.turnTo(position) val level = mob.skills.woodcutting.currentLevel - if (level < target.wood.level) { + if (level < target.tree.level) { mob.sendMessage("You do not have the required level to cut down this tree.") stop() } @@ -75,39 +86,36 @@ class WoodcuttingAction(val player: Player, val tool: Axe, val target: Woodcutti mob.playAnimation(tool.animation) wait(tool.pulses) - // + //Check that the object exists in the world val obj = target.getObject(mob.world) if (!obj.isPresent) { stop() return } - if (mob.inventory.freeSlots() == 0) { - mob.inventory.forceCapacityExceeded() - stop() - return - } - if (mob.inventory.add(target.wood.id)) { + if (mob.inventory.add(target.tree.id)) { //TODO: Use lookup from utils once it has a lookup function for IDs - val woodName = ItemDefinition.lookup(target.wood.id).name.toLowerCase(); - mob.sendMessage("You managed to cut some $woodName.") - mob.skillSet.addExperience(Skill.WOODCUTTING, target.wood.exp) + val logName = ItemDefinition.lookup(target.tree.id).name.toLowerCase(); + mob.sendMessage("You managed to cut some $logName.") + mob.skillSet.addExperience(Skill.WOODCUTTING, target.tree.exp) } - if (target.isSuccessful(mob)) { + //Check if the tree was cut down. If it was, we stop the task. + if (target.isCutDown(mob)) { //respawn time: http://runescape.wikia.com/wiki/Trees - val respawn = ((30 * 1000) / 600) + ((rand(150) * 1000) / 600) // between 30 sec and 3 min respawm - mob.world.expireObject(obj.get(), target.wood.stump, respawn) + val respawn = TimeUnit.SECONDS.toMillis(MINIMUM_RESPAWN_TIME + rand(150)) / GameConstants.PULSE_DELAY + mob.world.expireObject(obj.get(), target.tree.stump, respawn.toInt()) + stop() } } } on { ObjectActionMessage::class } - .where { option == 1 } - .then { - val wood = lookupTree(id) - if (wood != null) { - WoodcuttingAction.start(this, it, wood) - } + .where { option == 1 } + .then { + val tree = Tree.lookup(id) + if (tree != null) { + WoodcuttingAction.start(this, it, tree) } + } From 2cd160feb3c2cbed73e0226f5f457e6204427c8e Mon Sep 17 00:00:00 2001 From: Gary Tierney Date: Tue, 19 Sep 2017 19:01:30 +0100 Subject: [PATCH 4/4] Refactor woodcutting to use coroutines --- .../woodcutting/src/woodcutting.plugin.kts | 54 +++++++++---------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts index ab8aee86..eb769d49 100644 --- a/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts +++ b/game/plugin/skills/woodcutting/src/woodcutting.plugin.kts @@ -1,5 +1,6 @@ import org.apollo.cache.def.ItemDefinition import org.apollo.game.GameConstants +import org.apollo.game.action.ActionBlock import org.apollo.game.action.AsyncDistancedAction import org.apollo.game.message.impl.ObjectActionMessage import org.apollo.game.model.Position @@ -8,8 +9,7 @@ import org.apollo.game.model.entity.Player import org.apollo.game.model.entity.Skill import org.apollo.game.model.entity.obj.GameObject import org.apollo.game.plugin.skills.woodcutting.* -import org.apollo.game.plugins.api.woodcutting -import org.apollo.game.plugins.api.skills +import org.apollo.game.plugins.api.* import java.util.* import java.util.concurrent.TimeUnit @@ -42,7 +42,7 @@ class WoodcuttingAction(val player: Player, val tool: Axe, val target: Woodcutti * Find the highest level axe the player has */ private fun axeFor(player: Player): Axe? { - return getAxes() + return Axe.getAxes() .filter { it.level <= player.skills.woodcutting.currentLevel } .filter { player.equipment.contains(it.id) || player.inventory.contains(it.id) } .sortedByDescending { it.level } @@ -55,11 +55,11 @@ class WoodcuttingAction(val player: Player, val tool: Axe, val target: Woodcutti fun start(message: ObjectActionMessage, player: Player, wood: Tree) { val axe = axeFor(player) if (axe != null) { - //Check that the player had room in their inventory if (player.inventory.freeSlots() == 0) { player.inventory.forceCapacityExceeded() return } + val action = WoodcuttingAction(player, axe, WoodcuttingTarget(message.id, message.position, wood)) player.startAction(action) } else { @@ -70,43 +70,39 @@ class WoodcuttingAction(val player: Player, val tool: Axe, val target: Woodcutti } } - override fun start() { + override fun action(): ActionBlock = { mob.turnTo(position) val level = mob.skills.woodcutting.currentLevel - if (level < target.tree.level) { mob.sendMessage("You do not have the required level to cut down this tree.") stop() } - } - override suspend fun executeActionAsync() { - mob.sendMessage("You swing your axe at the tree.") - mob.playAnimation(tool.animation) + while (isRunning) { + mob.sendMessage("You swing your axe at the tree.") + mob.playAnimation(tool.animation) - wait(tool.pulses) + wait(tool.pulses) - //Check that the object exists in the world - val obj = target.getObject(mob.world) - if (!obj.isPresent) { - stop() - return - } + //Check that the object exists in the world + val obj = target.getObject(mob.world) + if (!obj.isPresent) { + stop() + } - if (mob.inventory.add(target.tree.id)) { - //TODO: Use lookup from utils once it has a lookup function for IDs - val logName = ItemDefinition.lookup(target.tree.id).name.toLowerCase(); - mob.sendMessage("You managed to cut some $logName.") - mob.skillSet.addExperience(Skill.WOODCUTTING, target.tree.exp) - } + if (mob.inventory.add(target.tree.id)) { + val logName = Definitions.item(target.tree.id)?.name?.toLowerCase(); + mob.sendMessage("You managed to cut some $logName.") + mob.skills.addExperience(Skill.WOODCUTTING, target.tree.exp) + } - //Check if the tree was cut down. If it was, we stop the task. - if (target.isCutDown(mob)) { - //respawn time: http://runescape.wikia.com/wiki/Trees - val respawn = TimeUnit.SECONDS.toMillis(MINIMUM_RESPAWN_TIME + rand(150)) / GameConstants.PULSE_DELAY - mob.world.expireObject(obj.get(), target.tree.stump, respawn.toInt()) - stop() + if (target.isCutDown(mob)) { + //respawn time: http://runescape.wikia.com/wiki/Trees + val respawn = TimeUnit.SECONDS.toMillis(MINIMUM_RESPAWN_TIME + rand(150)) / GameConstants.PULSE_DELAY + mob.world.expireObject(obj.get(), target.tree.stump, respawn.toInt()) + stop() + } } } }