Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Essence Mining #424

Open
wants to merge 15 commits into
base: kotlin-experiments
Choose a base branch
from
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