Fix nitpicks in Mining plugin

Also adds equals() and hashcode() implementations to the various
Mining actions.
This commit is contained in:
Major
2018-03-28 16:50:43 +01:00
parent 173623b76b
commit 6941fc9de0
5 changed files with 257 additions and 214 deletions
+1
View File
@@ -3,6 +3,7 @@ plugin {
authors = [
"Graham",
"Mikey`",
"Major",
"WH:II:DOW",
"Requa",
"Clifton",
+10 -9
View File
@@ -1,12 +1,13 @@
package org.apollo.game.plugin.skills.mining
enum class Gem(val id: Int, val chance: Int) {
UNCUT_SAPPHIRE(1623, 0),
UNCUT_EMERALD(1605, 0),
UNCUT_RUBY(1619, 0),
UNCUT_DIAMOND(1617, 0)
enum class Gem(val id: Int) { // TODO add gem drop chances
UNCUT_SAPPHIRE(1623),
UNCUT_EMERALD(1605),
UNCUT_RUBY(1619),
UNCUT_DIAMOND(1617);
companion object {
private val GEMS = Gem.values().associateBy({ it.id }, { it })
fun lookup(id: Int): Gem? = GEMS[id]
}
}
val GEMS = Gem.values()
fun lookupGem(id: Int): Gem? = GEMS.find { it.id == id }
+87 -49
View File
@@ -12,17 +12,33 @@ import org.apollo.game.plugin.api.findObject
import org.apollo.game.plugin.api.mining
import org.apollo.game.plugin.api.rand
import org.apollo.game.plugin.skills.mining.Ore
import org.apollo.game.plugin.skills.mining.PICKAXES
import org.apollo.game.plugin.skills.mining.Pickaxe
import org.apollo.game.plugin.skills.mining.lookupOreRock
import org.apollo.net.message.Message
import java.util.Optional
import java.util.Objects
class MiningTarget(val objectId: Int, val position: Position, val ore: Ore) {
on { ObjectActionMessage::class }
.where { option == Actions.MINING }
.then { player ->
Ore.fromRock(id)?.let { ore ->
MiningAction.start(this, player, ore)
}
}
fun getObject(world: World): Optional<GameObject> {
on { ObjectActionMessage::class }
.where { option == Actions.PROSPECTING }
.then { player ->
val ore = Ore.fromRock(id)
if (ore != null) {
ProspectingAction.start(this, player, ore)
}
}
data class MiningTarget(val objectId: Int, val position: Position, val ore: Ore) {
fun getObject(world: World): GameObject? {
val region = world.regionRepository.fromPosition(position)
return region.findObject(position, objectId)
return region.findObject(position, objectId).orElse(null)
}
fun isSuccessful(mob: Player): Boolean {
@@ -41,27 +57,22 @@ class MiningAction(
) : AsyncDistancedAction<Player>(PULSES, true, player, target.position, ORE_SIZE) {
companion object {
private val PULSES = 0
private val ORE_SIZE = 1
fun pickaxeFor(player: Player): Pickaxe? {
return PICKAXES
.filter { it.level <= player.mining.current }
.filter { player.equipment.contains(it.id) || player.inventory.contains(it.id) }
.sortedByDescending { it.level }
.firstOrNull()
}
private const val PULSES = 0
private const val ORE_SIZE = 1
/**
* Starts a [MiningAction] for the specified [Player], terminating the [Message] that triggered it.
*/
fun start(message: ObjectActionMessage, player: Player, ore: Ore) {
val pickaxe = pickaxeFor(player)
if (pickaxe != null) {
val action = MiningAction(player, pickaxe, MiningTarget(message.id, message.position, ore))
player.startAction(action)
} else {
val pickaxe = Pickaxe.bestFor(player)
if (pickaxe == null) {
player.sendMessage("You do not have a pickaxe for which you have the level to use.")
} else {
val target = MiningTarget(message.id, message.position, ore)
val action = MiningAction(player, pickaxe, target)
player.startAction(action)
}
message.terminate()
@@ -83,7 +94,7 @@ class MiningAction(
wait(tool.pulses)
val obj = target.getObject(mob.world)
if (!obj.isPresent) {
if (obj == null) {
stop()
}
@@ -94,25 +105,46 @@ class MiningAction(
}
if (mob.inventory.add(target.ore.id)) {
val oreName = Definitions.item(target.ore.id)?.name?.toLowerCase()
val oreName = Definitions.item(target.ore.id)!!.name.toLowerCase()
mob.sendMessage("You manage to mine some $oreName")
mob.mining.experience += target.ore.exp
mob.world.expireObject(obj.get(), target.ore.objects[target.objectId]!!, target.ore.respawn)
mob.world.expireObject(obj!!, target.ore.objects[target.objectId]!!, target.ore.respawn)
stop()
}
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MiningAction
return mob == other.mob && target == other.target
}
override fun hashCode(): Int = Objects.hash(mob, target)
}
class ExpiredProspectingAction(
mob: Player,
position: Position
) : DistancedAction<Player>(PROSPECT_PULSES, true, mob, position, ORE_SIZE) {
) : DistancedAction<Player>(DELAY, true, mob, position, ORE_SIZE) {
companion object {
private val PROSPECT_PULSES = 0
private val ORE_SIZE = 1
private const val DELAY = 0
private const val ORE_SIZE = 1
/**
* Starts a [ExpiredProspectingAction] for the specified [Player], terminating the [Message] that triggered it.
*/
fun start(message: ObjectActionMessage, player: Player) {
val action = ExpiredProspectingAction(player, message.position)
player.startAction(action)
message.terminate()
}
}
override fun executeAction() {
@@ -120,17 +152,27 @@ class ExpiredProspectingAction(
stop()
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ExpiredProspectingAction
return mob == other.mob && position == other.position
}
override fun hashCode(): Int = Objects.hash(mob, position)
}
class ProspectingAction(
player: Player,
position: Position,
private val ore: Ore
) : AsyncDistancedAction<Player>(PROSPECT_PULSES, true, player, position, ORE_SIZE) {
) : AsyncDistancedAction<Player>(DELAY, true, player, position, ORE_SIZE) {
companion object {
private val PROSPECT_PULSES = 3
private val ORE_SIZE = 1
private const val DELAY = 3
private const val ORE_SIZE = 1
/**
* Starts a [MiningAction] for the specified [Player], terminating the [Message] that triggered it.
@@ -141,7 +183,6 @@ class ProspectingAction(
message.terminate()
}
}
override fun action(): ActionBlock = {
@@ -151,27 +192,24 @@ class ProspectingAction(
wait()
val oreName = Definitions.item(ore.id)?.name?.toLowerCase()
mob.sendMessage("This rock contains $oreName")
mob.sendMessage("This rock contains $oreName.")
stop()
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ProspectingAction
return mob == other.mob && position == other.position && ore == other.ore
}
override fun hashCode(): Int = Objects.hash(mob, position, ore)
}
on { ObjectActionMessage::class }
.where { option == 1 }
.then {
val ore = lookupOreRock(id)
if (ore != null) {
MiningAction.start(this, it, ore)
}
}
on { ObjectActionMessage::class }
.where { option == 2 }
.then {
val ore = lookupOreRock(id)
if (ore != null) { // TODO send expired action if rock is expired
ProspectingAction.start(this, it, ore)
}
}
private object Actions {
const val MINING = 1
const val PROSPECTING = 2
}
+36 -37
View File
@@ -1,13 +1,46 @@
package org.apollo.game.plugin.skills.mining
import com.google.common.collect.Maps.asMap
/*
Thanks to Mikey` <http://www.rune-server.org/members/mikey%60/> for helping
to find some of the item/object IDs, minimum levels and experiences.
Thanks to Clifton <http://www.rune-server.org/members/clifton/> for helping
to find some of the expired object IDs.
*/
/**
* Chance values thanks to: http://runescape.wikia.com/wiki/Talk:Mining#Mining_success_rate_formula
* Respawn times and xp thanks to: http://oldschoolrunescape.wikia.com/wiki/
*/
enum class Ore(
val objects: Map<Int, Int>,
val id: Int,
val level: Int,
val exp: Double,
val respawn: Int,
val chance: Double,
val chanceOffset: Boolean = false
) {
CLAY(CLAY_OBJECTS, id = 434, level = 1, exp = 5.0, respawn = 1, chance = 0.0085, chanceOffset = true),
COPPER(COPPER_OBJECTS, id = 436, level = 1, exp = 17.5, respawn = 4, chance = 0.0085, chanceOffset = true),
TIN(TIN_OBJECTS, id = 438, level = 1, exp = 17.5, respawn = 4, chance = 0.0085, chanceOffset = true),
IRON(IRON_OBJECTS, id = 440, level = 15, exp = 35.0, respawn = 9, chance = 0.0085, chanceOffset = true),
COAL(COAL_OBJECTS, id = 453, level = 30, exp = 50.0, respawn = 50, chance = 0.004),
GOLD(GOLD_OBJECTS, id = 444, level = 40, exp = 65.0, respawn = 100, chance = 0.003),
SILVER(SILVER_OBJECTS, id = 442, level = 20, exp = 40.0, respawn = 100, chance = 0.0085),
MITHRIL(MITHRIL_OBJECTS, id = 447, level = 55, exp = 80.0, respawn = 200, chance = 0.002),
ADAMANT(ADAMANT_OBJECTS, id = 449, level = 70, exp = 95.0, respawn = 800, chance = 0.001),
RUNITE(RUNITE_OBJECTS, id = 451, level = 85, exp = 125.0, respawn = 1_200, chance = 0.0008);
companion object {
private val ORE_ROCKS = Ore.values().flatMap { ore -> ore.objects.map { Pair(it.key, ore) } }.toMap()
private val EXPIRED_ORE = Ore.values().flatMap { ore -> ore.objects.map { Pair(it.value, ore) } }.toMap()
fun fromRock(id: Int): Ore? = ORE_ROCKS[id]
fun fromExpiredRock(id: Int): Ore? = EXPIRED_ORE[id]
}
}
// Maps from regular rock id to expired rock id.
val CLAY_OBJECTS = mapOf(
2108 to 450,
@@ -71,7 +104,7 @@ val COAL_OBJECTS = mapOf(
14852 to 14834
)
val SILVER_OBJECTS = mapOf (
val SILVER_OBJECTS = mapOf(
11948 to 11555,
11949 to 11556,
11950 to 11557,
@@ -119,37 +152,3 @@ val RUNITE_OBJECTS = mapOf(
14860 to 14833,
14861 to 14834
)
/**
* Chance values thanks to: http://runescape.wikia.com/wiki/Talk:Mining#Mining_success_rate_formula
* Respawn times and xp thanks to: http://oldschoolrunescape.wikia.com/wiki/
*/
enum class Ore(val id: Int, val objects: Map<Int, Int>, val level: Int, val exp: Double, val respawn: Int, val chance: Double, val chanceOffset: Boolean) {
CLAY(434, CLAY_OBJECTS, 1, 5.0, 1, 0.0085, true),
COPPER(436, COPPER_OBJECTS, 1, 17.5, 4, 0.0085, true),
TIN(438, TIN_OBJECTS, 1, 17.5, 4, 0.0085, true),
IRON(440, IRON_OBJECTS, 15, 35.0, 9, 0.0085, true),
COAL(453, COAL_OBJECTS, 30, 50.0, 50, 0.004, false),
GOLD(444, GOLD_OBJECTS, 40, 65.0, 100, 0.003, false),
SILVER(442, SILVER_OBJECTS, 20, 40.0, 100, 0.0085, false),
MITHRIL(447, MITHRIL_OBJECTS, 55, 80.0, 200, 0.002, false),
ADAMANT(449, ADAMANT_OBJECTS, 70, 95.0, 800, 0.001, false),
RUNITE(451, RUNITE_OBJECTS, 85, 125.0, 1200, 0.0008, false)
}
val ORES = enumValues<Ore>()
fun lookupOre(id: Int): Ore? = ORES.find { it.id == id }
fun lookupOreRock(id: Int): Ore? {
for (ore in enumValues<Ore>()) {
for (rock in ore.objects) {
if (rock.key == id) {
return ore
}
}
}
return null
}
+23 -19
View File
@@ -1,23 +1,27 @@
package org.apollo.game.plugin.skills.mining
import org.apollo.game.model.Animation;
import org.apollo.game.model.Animation
import org.apollo.game.model.entity.Player
import org.apollo.game.plugin.api.mining
enum class Pickaxe(val id: Int, val level: Int, val animation: Animation, val pulses: Int) {
RUNE(1275, 41, Animation(624), 3),
ADAMANT(1271, 31, Animation(628), 4),
MITHRIL(1273, 21, Animation(629), 5),
STEEL(1269, 1, Animation(627), 6),
ITRON(1267, 1, Animation(626), 7),
BRONZE(1265, 1, Animation(625), 8)
enum class Pickaxe(val id: Int, val level: Int, animation: Int, val pulses: Int) {
BRONZE(id = 1265, level = 1, animation = 625, pulses = 8),
ITRON(id = 1267, level = 1, animation = 626, pulses = 7),
STEEL(id = 1269, level = 1, animation = 627, pulses = 6),
MITHRIL(id = 1273, level = 21, animation = 629, pulses = 5),
ADAMANT(id = 1271, level = 31, animation = 628, pulses = 4),
RUNE(id = 1275, level = 41, animation = 624, pulses = 3);
val animation = Animation(animation)
companion object {
private val PICKAXES = Pickaxe.values().sortedByDescending { it.level }
fun bestFor(player: Player): Pickaxe? {
return PICKAXES.asSequence()
.filter { it.level <= player.mining.current }
.filter { player.equipment.contains(it.id) || player.inventory.contains(it.id) }
.firstOrNull()
}
}
}
val PICKAXES = Pickaxe.values()
fun getPickaxes(): Array<Pickaxe> {
return PICKAXES
}
fun lookupPickaxe(id: Int): Pickaxe? = PICKAXES.find { it.id == id }