Skip to content
Open
58 changes: 32 additions & 26 deletions game/plugin/skills/mining/src/MiningAction.kt
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
import java.util.*

import org.apollo.game.action.ActionBlock
import org.apollo.game.action.AsyncDistancedAction
import org.apollo.game.message.impl.ObjectActionMessage
import org.apollo.game.model.entity.Player
import org.apollo.game.plugin.api.*
import org.apollo.game.plugin.api.rand
import org.apollo.game.plugin.skills.mining.Ore
import org.apollo.game.plugin.skills.mining.Pickaxe
import org.apollo.net.message.Message
import java.util.Objects

class MiningAction(
player: Player,
private val tool: Pickaxe,
private val tool: Pickaxe?,
private val target: MiningTarget
) : AsyncDistancedAction<Player>(PULSES, true, player, target.position, ORE_SIZE) {
) : AsyncDistancedAction<Player>(PULSES, true, player, target.position, target.ore.objectSize) {

companion object {
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 = 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)
val target = MiningTarget(message.id, message.position, ore)
val action = MiningAction(player, pickaxe, target)

player.startAction(action)
}
player.startAction(action)

message.terminate()
}
Expand All @@ -40,33 +36,43 @@ class MiningAction(
override fun action(): ActionBlock = {
mob.turnTo(position)

if (tool == null) {
mob.sendMessage("You do not have a pickaxe for which you have the level to use.")
stop()
}

if (!target.skillRequirementsMet(mob)) {
mob.sendMessage("You do not have the required level to mine this rock.")
stop()
}

mob.sendMessage("You swing your pick at the rock.")
mob.playAnimation(tool.animation)

wait(tool.pulses)
while (isRunning) {
mob.playAnimation(tool.animation)

if (!target.isValid(mob.world)) {
stop()
}

val successChance = rand(100)
wait(tool.pulses)

if (target.isSuccessful(mob, successChance)) {
if (mob.inventory.freeSlots() == 0) {
mob.inventory.forceCapacityExceeded()
if (!target.isValid(mob.world)) {
stop()
}

if (target.reward(mob)) {
mob.sendMessage("You manage to mine some ${target.oreName()}")
target.deplete(mob.world)
val successChance = rand(100)

stop()
if (target.isSuccessful(mob, successChance)) {
if (mob.inventory.freeSlots() == 0) {
mob.inventory.forceCapacityExceeded()
stop()
}

if (target.reward(mob)) {
mob.sendMessage("You manage to mine some ${target.oreName(mob)}")

if (target.ore.respawn != -1) {
target.deplete(mob.world)
stop()
}
}
}
}
}
Expand Down
17 changes: 14 additions & 3 deletions game/plugin/skills/mining/src/MiningTarget.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import org.apollo.game.plugin.api.findObject
import org.apollo.game.plugin.api.mining
import org.apollo.game.plugin.api.replaceObject
import org.apollo.game.plugin.skills.mining.Ore
import org.apollo.game.plugin.skills.mining.PURE_ESSENCE
import org.apollo.game.plugin.skills.mining.RUNE_ESSENCE

data class MiningTarget(val objectId: Int, val position: Position, val ore: Ore) {

Expand Down Expand Up @@ -35,13 +37,22 @@ data class MiningTarget(val objectId: Int, val position: Position, val ore: Ore)
/**
* Get the normalized name of the [Ore] represented by this target.
*/
fun oreName() = Definitions.item(ore.id).name.toLowerCase()
fun oreName(mob: Player) = Definitions.item(oreReward(mob)).name.toLowerCase()

/**
* Get the item id for the [Ore].
*/
fun oreReward(mob: Player): Int = when (ore) {
Ore.ESSENCE -> if (mob.isMembers && mob.mining.current >= 30) PURE_ESSENCE else RUNE_ESSENCE
else -> ore.id
}

/**
* Reward a [player] with experience and ore if they have the inventory capacity to take a new ore.
*/
fun reward(player: Player): Boolean {
val hasInventorySpace = player.inventory.add(ore.id)
val itemId = oreReward(player)
val hasInventorySpace = player.inventory.add(itemId)

if (hasInventorySpace) {
player.mining.experience += ore.exp
Expand All @@ -54,5 +65,5 @@ data class MiningTarget(val objectId: Int, val position: Position, val ore: Ore)
* Check if the [mob] has met the skill requirements to mine te [Ore] represented by
* this [MiningTarget].
*/
fun skillRequirementsMet(mob: Player) = mob.mining.current < ore.level
fun skillRequirementsMet(mob: Player) = mob.mining.current >= ore.level
}
12 changes: 11 additions & 1 deletion game/plugin/skills/mining/src/Ore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ enum class Ore(
val exp: Double,
val respawn: Int,
val chance: Double,
val chanceOffset: Double = 0.0
val chanceOffset: Double = 0.0,
val prospectName: String? = null,
val objectSize: Int = 1
) {
ESSENCE(ESSENCE_OBJECTS, id = -1, level = 1, exp = 5.0, respawn = -1, chance = 0.0085, chanceOffset = 0.45, prospectName = "Rune Stone essence", objectSize = 7),
CLAY(CLAY_OBJECTS, id = 434, level = 1, exp = 5.0, respawn = 1, chance = 0.0085, chanceOffset = 0.45),
COPPER(COPPER_OBJECTS, id = 436, level = 1, exp = 17.5, respawn = 4, chance = 0.0085, chanceOffset = 0.45),
TIN(TIN_OBJECTS, id = 438, level = 1, exp = 17.5, respawn = 4, chance = 0.0085, chanceOffset = 0.45),
Expand All @@ -39,6 +42,9 @@ enum class Ore(
}
}

const val RUNE_ESSENCE = 1436
const val PURE_ESSENCE = 7936

// Maps from regular rock id to expired rock id.

val CLAY_OBJECTS = mapOf(
Expand Down Expand Up @@ -150,4 +156,8 @@ val RUNITE_OBJECTS = mapOf(
14859 to 14832,
14860 to 14833,
14861 to 14834
)

val ESSENCE_OBJECTS = mapOf(
2491 to -1
)
8 changes: 4 additions & 4 deletions game/plugin/skills/mining/src/ProspectingAction.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import java.util.Objects

import org.apollo.game.action.ActionBlock
import org.apollo.game.action.AsyncDistancedAction
import org.apollo.game.message.impl.ObjectActionMessage
Expand All @@ -7,16 +7,16 @@ import org.apollo.game.model.entity.Player
import org.apollo.game.plugin.api.Definitions
import org.apollo.game.plugin.skills.mining.Ore
import org.apollo.net.message.Message
import java.util.Objects

class ProspectingAction(
player: Player,
position: Position,
private val ore: Ore
) : AsyncDistancedAction<Player>(DELAY, true, player, position, ORE_SIZE) {
) : AsyncDistancedAction<Player>(DELAY, true, player, position, ore.objectSize) {

companion object {
private const val DELAY = 3
private const val ORE_SIZE = 1

/**
* Starts a [MiningAction] for the specified [Player], terminating the [Message] that triggered it.
Expand All @@ -35,7 +35,7 @@ class ProspectingAction(

wait()

val oreName = Definitions.item(ore.id)?.name?.toLowerCase()
val oreName = ore.prospectName ?: Definitions.item(ore.id).name?.toLowerCase()
mob.sendMessage("This rock contains $oreName.")

stop()
Expand Down
6 changes: 4 additions & 2 deletions game/plugin/skills/mining/test/TestData.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import java.util.stream.Stream

import org.apollo.game.plugin.skills.mining.Ore
import org.junit.jupiter.api.extension.ExtensionContext
import org.junit.jupiter.params.provider.Arguments
import org.junit.jupiter.params.provider.ArgumentsProvider
import java.util.stream.Stream

data class MiningTestData(val rockId: Int, val expiredRockId: Int, val ore: Ore)

fun miningTestData(): Collection<MiningTestData> = Ore.values()
.flatMap { ore -> ore.objects.map { MiningTestData(it.key, it.value, ore) } }
.filter { it.id != -1 }
.flatMap { ore -> ore.objects.filter { it.value != -1 }.map { MiningTestData(it.key, it.value, ore) } }
.toList()

class MiningTestDataProvider : ArgumentsProvider {
Expand Down