mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-06 16:51:37 +00:00
Add tests for fishing plugin
This commit is contained in:
@@ -1,128 +0,0 @@
|
|||||||
|
|
||||||
import Fishing_plugin.FishingAction
|
|
||||||
import org.apollo.game.action.ActionBlock
|
|
||||||
import org.apollo.game.action.AsyncDistancedAction
|
|
||||||
import org.apollo.game.message.impl.NpcActionMessage
|
|
||||||
import org.apollo.game.model.Position
|
|
||||||
import org.apollo.game.model.entity.Player
|
|
||||||
import org.apollo.game.plugin.api.fishing
|
|
||||||
import org.apollo.game.plugin.api.rand
|
|
||||||
import org.apollo.game.plugin.skills.fishing.FishingSpot
|
|
||||||
import org.apollo.game.plugin.skills.fishing.FishingTool
|
|
||||||
import java.util.Objects
|
|
||||||
|
|
||||||
// TODO: moving fishing spots, seaweed and caskets, evil bob
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Intercepts the [NpcActionMessage] and starts a [FishingAction] if the npc
|
|
||||||
*/
|
|
||||||
on { NpcActionMessage::class }
|
|
||||||
.where { option == 1 || option == 3 }
|
|
||||||
.then { player ->
|
|
||||||
val entity = player.world.npcRepository[index]
|
|
||||||
val spot = FishingSpot.lookup(entity.id) ?: return@then
|
|
||||||
|
|
||||||
val option = spot.option(option)
|
|
||||||
player.startAction(FishingAction(player, entity.position, option))
|
|
||||||
|
|
||||||
terminate()
|
|
||||||
}
|
|
||||||
|
|
||||||
class FishingAction(player: Player, position: Position, val option: FishingSpot.Option) :
|
|
||||||
AsyncDistancedAction<Player>(0, true, player, position, SPOT_DISTANCE) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The [FishingTool] used for the fishing spot.
|
|
||||||
*/
|
|
||||||
private val tool = option.tool
|
|
||||||
|
|
||||||
override fun action(): ActionBlock = {
|
|
||||||
if (!verify()) {
|
|
||||||
stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
mob.turnTo(position)
|
|
||||||
mob.sendMessage(tool.message)
|
|
||||||
|
|
||||||
while (isRunning) {
|
|
||||||
mob.playAnimation(tool.animation)
|
|
||||||
wait(FISHING_DELAY)
|
|
||||||
|
|
||||||
val level = mob.fishing.current
|
|
||||||
val fish = option.sample(level)
|
|
||||||
|
|
||||||
if (successfulCatch(level, fish.level)) {
|
|
||||||
if (tool.bait != -1) {
|
|
||||||
mob.inventory.remove(tool.bait)
|
|
||||||
}
|
|
||||||
|
|
||||||
mob.inventory.add(fish.id)
|
|
||||||
mob.sendMessage(fish.catchMessage)
|
|
||||||
mob.fishing.experience += fish.experience
|
|
||||||
|
|
||||||
if (mob.inventory.freeSlots() == 0) {
|
|
||||||
mob.inventory.forceCapacityExceeded()
|
|
||||||
|
|
||||||
mob.stopAnimation()
|
|
||||||
stop()
|
|
||||||
} else if (!hasBait(mob, tool.bait)) {
|
|
||||||
mob.sendMessage("You need more ${tool.baitName} to fish at this spot.")
|
|
||||||
|
|
||||||
mob.stopAnimation()
|
|
||||||
stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies that the player can gather fish from the [FishingSpot] they clicked.
|
|
||||||
*/
|
|
||||||
private fun verify(): Boolean {
|
|
||||||
val current = mob.fishing.current
|
|
||||||
|
|
||||||
when {
|
|
||||||
current < option.level -> mob.sendMessage("You need a fishing level of ${option.level} to fish at this spot.")
|
|
||||||
!hasTool(mob, tool) -> mob.sendMessage("You need a ${tool.formattedName} to fish at this spot.")
|
|
||||||
!hasBait(mob, tool.bait) -> mob.sendMessage("You need some ${tool.baitName} to fish at this spot.")
|
|
||||||
mob.inventory.freeSlots() == 0 -> mob.inventory.forceCapacityExceeded()
|
|
||||||
else -> return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (javaClass != other?.javaClass) return false
|
|
||||||
|
|
||||||
other as FishingAction
|
|
||||||
return option == other.option && position == other.position && mob == other.mob
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int = Objects.hash(option, position, mob)
|
|
||||||
|
|
||||||
private companion object {
|
|
||||||
private const val SPOT_DISTANCE = 1
|
|
||||||
private const val FISHING_DELAY = 4
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether or not the catch was successful.
|
|
||||||
* TODO: We need to identify the correct algorithm for this
|
|
||||||
*/
|
|
||||||
private fun successfulCatch(level: Int, req: Int): Boolean = minOf(level - req + 5, 40) > rand(100)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether or not the [Player] has (or does not need) bait.
|
|
||||||
*/
|
|
||||||
private fun hasBait(player: Player, bait: Int): Boolean = bait == -1 || player.inventory.contains(bait)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether or not the player has the required tool to fish at the spot.
|
|
||||||
*/
|
|
||||||
private fun hasTool(player: Player, tool: FishingTool): Boolean = player.equipment.contains(tool.id) ||
|
|
||||||
player.inventory.contains(tool.id)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package org.apollo.game.plugin.skills.fishing
|
||||||
|
|
||||||
|
import org.apollo.game.plugin.api.Definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A fish that can be gathered using the fishing skill.
|
||||||
|
*/
|
||||||
|
enum class Fish(val id: Int, val level: Int, val experience: Double, catchSuffix: String? = null) {
|
||||||
|
SHRIMPS(id = 317, level = 1, experience = 10.0, catchSuffix = "some shrimp."),
|
||||||
|
SARDINE(id = 327, level = 5, experience = 20.0),
|
||||||
|
MACKEREL(id = 353, level = 16, experience = 20.0),
|
||||||
|
HERRING(id = 345, level = 10, experience = 30.0),
|
||||||
|
ANCHOVIES(id = 321, level = 15, experience = 40.0, catchSuffix = "some anchovies."),
|
||||||
|
TROUT(id = 335, level = 20, experience = 50.0),
|
||||||
|
COD(id = 341, level = 23, experience = 45.0),
|
||||||
|
PIKE(id = 349, level = 25, experience = 60.0),
|
||||||
|
SALMON(id = 331, level = 30, experience = 70.0),
|
||||||
|
TUNA(id = 359, level = 35, experience = 80.0),
|
||||||
|
LOBSTER(id = 377, level = 40, experience = 90.0),
|
||||||
|
BASS(id = 363, level = 46, experience = 100.0),
|
||||||
|
SWORDFISH(id = 371, level = 50, experience = 100.0),
|
||||||
|
SHARK(id = 383, level = 76, experience = 110.0, catchSuffix = "a shark!");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this fish, formatted so it can be inserted into a message.
|
||||||
|
*/
|
||||||
|
val catchMessage by lazy { "You catch ${catchSuffix ?: "a $catchName."}" }
|
||||||
|
|
||||||
|
private val catchName by lazy { Definitions.item(id).name.toLowerCase().removePrefix("raw ") }
|
||||||
|
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package org.apollo.game.plugin.skills.fishing
|
||||||
|
|
||||||
|
import org.apollo.game.message.impl.NpcActionMessage
|
||||||
|
|
||||||
|
// TODO: moving fishing spots, seaweed and caskets, evil bob
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercepts the [NpcActionMessage] and starts a [FishingAction] if the npc
|
||||||
|
*/
|
||||||
|
on { NpcActionMessage::class }
|
||||||
|
.where { option == 1 || option == 3 }
|
||||||
|
.then { player ->
|
||||||
|
val entity = player.world.npcRepository[index]
|
||||||
|
val option = FishingSpot.lookup(entity.id)?.option(option) ?: return@then
|
||||||
|
|
||||||
|
val target = FishingTarget(entity.position, option)
|
||||||
|
player.startAction(FishingAction(player, target))
|
||||||
|
|
||||||
|
terminate()
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package org.apollo.game.plugin.skills.fishing
|
||||||
|
|
||||||
|
import org.apollo.game.action.ActionBlock
|
||||||
|
import org.apollo.game.action.AsyncDistancedAction
|
||||||
|
import org.apollo.game.model.entity.Player
|
||||||
|
import org.apollo.game.plugin.api.fishing
|
||||||
|
import java.util.Objects
|
||||||
|
|
||||||
|
class FishingAction(
|
||||||
|
player: Player,
|
||||||
|
private val target: FishingTarget
|
||||||
|
) : AsyncDistancedAction<Player>(0, true, player, target.position, SPOT_DISTANCE) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [FishingTool] used for the fishing spot.
|
||||||
|
*/
|
||||||
|
private val tool = target.option.tool
|
||||||
|
|
||||||
|
override fun action(): ActionBlock = {
|
||||||
|
if (!target.verify(mob)) {
|
||||||
|
stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
mob.turnTo(position)
|
||||||
|
mob.sendMessage(tool.message)
|
||||||
|
|
||||||
|
while (isRunning) {
|
||||||
|
mob.playAnimation(tool.animation)
|
||||||
|
wait(FISHING_DELAY)
|
||||||
|
|
||||||
|
val level = mob.fishing.current
|
||||||
|
val fish = target.option.sample(level)
|
||||||
|
|
||||||
|
if (target.isSuccessful(mob, fish.level)) {
|
||||||
|
if (tool.bait != -1) {
|
||||||
|
mob.inventory.remove(tool.bait)
|
||||||
|
}
|
||||||
|
|
||||||
|
mob.inventory.add(fish.id)
|
||||||
|
mob.sendMessage(fish.catchMessage)
|
||||||
|
mob.fishing.experience += fish.experience
|
||||||
|
|
||||||
|
if (mob.inventory.freeSlots() == 0) {
|
||||||
|
mob.inventory.forceCapacityExceeded()
|
||||||
|
|
||||||
|
mob.stopAnimation()
|
||||||
|
stop()
|
||||||
|
} else if (!hasBait(mob, tool.bait)) {
|
||||||
|
mob.sendMessage("You need more ${tool.baitName} to fish at this spot.")
|
||||||
|
|
||||||
|
mob.stopAnimation()
|
||||||
|
stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other is FishingAction) {
|
||||||
|
return position == other.position && target == other.target && mob == other.mob
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int = Objects.hash(target, position, mob)
|
||||||
|
|
||||||
|
internal companion object {
|
||||||
|
private const val SPOT_DISTANCE = 1
|
||||||
|
private const val FISHING_DELAY = 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the [Player] has (or does not need) bait.
|
||||||
|
*/
|
||||||
|
internal fun hasBait(player: Player, bait: Int): Boolean {
|
||||||
|
return bait == -1 || bait in player.inventory
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the player has the required tool to fish at the spot.
|
||||||
|
*/
|
||||||
|
internal fun hasTool(player: Player, tool: FishingTool): Boolean {
|
||||||
|
return tool.id in player.equipment || tool.id in player.inventory
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+24
-64
@@ -1,76 +1,36 @@
|
|||||||
package org.apollo.game.plugin.skills.fishing
|
package org.apollo.game.plugin.skills.fishing
|
||||||
|
|
||||||
import org.apollo.game.model.Animation
|
|
||||||
import org.apollo.game.plugin.api.Definitions
|
|
||||||
import org.apollo.game.plugin.api.rand
|
import org.apollo.game.plugin.api.rand
|
||||||
import org.apollo.game.plugin.skills.fishing.Fish.*
|
import org.apollo.game.plugin.skills.fishing.Fish.*
|
||||||
import org.apollo.game.plugin.skills.fishing.FishingTool.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A fish that can be gathered using the fishing skill.
|
|
||||||
*/
|
|
||||||
enum class Fish(val id: Int, val level: Int, val experience: Double, catchSuffix: String? = null) {
|
|
||||||
SHRIMPS(id = 317, level = 1, experience = 10.0, catchSuffix = "some shrimp."),
|
|
||||||
SARDINE(id = 327, level = 5, experience = 20.0),
|
|
||||||
MACKEREL(id = 353, level = 16, experience = 20.0),
|
|
||||||
HERRING(id = 345, level = 10, experience = 30.0),
|
|
||||||
ANCHOVIES(id = 321, level = 15, experience = 40.0, catchSuffix = "some anchovies."),
|
|
||||||
TROUT(id = 335, level = 20, experience = 50.0),
|
|
||||||
COD(id = 341, level = 23, experience = 45.0),
|
|
||||||
PIKE(id = 349, level = 25, experience = 60.0),
|
|
||||||
SALMON(id = 331, level = 30, experience = 70.0),
|
|
||||||
TUNA(id = 359, level = 35, experience = 80.0),
|
|
||||||
LOBSTER(id = 377, level = 40, experience = 90.0),
|
|
||||||
BASS(id = 363, level = 46, experience = 100.0),
|
|
||||||
SWORDFISH(id = 371, level = 50, experience = 100.0),
|
|
||||||
SHARK(id = 383, level = 76, experience = 110.0, catchSuffix = "a shark!");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of this fish, formatted so it can be inserted into a message.
|
|
||||||
*/
|
|
||||||
val catchMessage by lazy { "You catch ${catchSuffix ?: "a ${catchName()}."}" }
|
|
||||||
|
|
||||||
private fun catchName() = Definitions.item(id).name.toLowerCase().removePrefix("raw ")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A tool used to gather [Fish] from a [FishingSpot].
|
|
||||||
*/
|
|
||||||
enum class FishingTool(
|
|
||||||
val message: String,
|
|
||||||
val id: Int,
|
|
||||||
animation: Int,
|
|
||||||
val bait: Int = -1,
|
|
||||||
val baitName: String? = null
|
|
||||||
) {
|
|
||||||
LOBSTER_CAGE("You attempt to catch a lobster...", id = 301, animation = 619),
|
|
||||||
SMALL_NET("You cast out your net...", id = 303, animation = 620),
|
|
||||||
BIG_NET("You cast out your net...", id = 305, animation = 620),
|
|
||||||
HARPOON("You start harpooning fish...", id = 311, animation = 618),
|
|
||||||
FISHING_ROD("You attempt to catch a fish...", id = 307, animation = 622, bait = 313, baitName = "feathers"),
|
|
||||||
FLY_FISHING_ROD("You attempt to catch a fish...", id = 309, animation = 622, bait = 314, baitName = "fishing bait");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The [Animation] played when fishing with this tool.
|
|
||||||
*/
|
|
||||||
val animation: Animation = Animation(animation)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of this tool, formatted so it can be inserted into a message.
|
|
||||||
*/
|
|
||||||
val formattedName by lazy { Definitions.item(id).name.toLowerCase() }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A spot that can be fished from.
|
* A spot that can be fished from.
|
||||||
*/
|
*/
|
||||||
enum class FishingSpot(val npc: Int, private val first: Option, private val second: Option) {
|
enum class FishingSpot(val npc: Int, private val first: Option, private val second: Option) {
|
||||||
ROD(309, Option.of(FLY_FISHING_ROD, TROUT, SALMON), Option.of(FISHING_ROD, PIKE)),
|
|
||||||
CAGE_HARPOON(312, Option.of(LOBSTER_CAGE, LOBSTER), Option.of(HARPOON, TUNA, SWORDFISH)),
|
ROD(
|
||||||
NET_HARPOON(313, Option.of(BIG_NET, MACKEREL, COD), Option.of(HARPOON, BASS, SHARK)),
|
npc = 309,
|
||||||
NET_ROD(316, Option.of(SMALL_NET, SHRIMPS, ANCHOVIES), Option.of(FISHING_ROD, SARDINE, HERRING));
|
first = Option.of(tool = FishingTool.FLY_FISHING_ROD, primary = TROUT, secondary = SALMON),
|
||||||
|
second = Option.of(tool = FishingTool.FISHING_ROD, primary = PIKE)
|
||||||
|
),
|
||||||
|
|
||||||
|
CAGE_HARPOON(
|
||||||
|
npc = 312,
|
||||||
|
first = Option.of(tool = FishingTool.LOBSTER_CAGE, primary = LOBSTER),
|
||||||
|
second = Option.of(tool = FishingTool.HARPOON, primary = TUNA, secondary = SWORDFISH)
|
||||||
|
),
|
||||||
|
|
||||||
|
NET_HARPOON(
|
||||||
|
npc = 313,
|
||||||
|
first = Option.of(tool = FishingTool.BIG_NET, primary = MACKEREL, secondary = COD),
|
||||||
|
second = Option.of(tool = FishingTool.HARPOON, primary = BASS, secondary = SHARK)
|
||||||
|
),
|
||||||
|
|
||||||
|
NET_ROD(
|
||||||
|
npc = 316,
|
||||||
|
first = Option.of(tool = FishingTool.SMALL_NET, primary = SHRIMPS, secondary = ANCHOVIES),
|
||||||
|
second = Option.of(tool = FishingTool.FISHING_ROD, primary = SARDINE, secondary = HERRING)
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the [FishingSpot.Option] associated with the specified action id.
|
* Returns the [FishingSpot.Option] associated with the specified action id.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package org.apollo.game.plugin.skills.fishing
|
||||||
|
|
||||||
|
import org.apollo.game.model.Position
|
||||||
|
import org.apollo.game.model.entity.Player
|
||||||
|
import org.apollo.game.plugin.api.fishing
|
||||||
|
import org.apollo.game.plugin.api.rand
|
||||||
|
import org.apollo.game.plugin.skills.fishing.FishingAction.Companion.hasBait
|
||||||
|
import org.apollo.game.plugin.skills.fishing.FishingAction.Companion.hasTool
|
||||||
|
|
||||||
|
data class FishingTarget(val position: Position, val option: FishingSpot.Option) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not the catch was successful.
|
||||||
|
* TODO: We need to identify the correct algorithm for this
|
||||||
|
*/
|
||||||
|
fun isSuccessful(player: Player, req: Int): Boolean {
|
||||||
|
return minOf(player.fishing.current - req + 5, 40) > rand(100)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the [Player] can gather fish from their chosen [FishingSpot.Option].
|
||||||
|
*/
|
||||||
|
fun verify(player: Player): Boolean {
|
||||||
|
val current = player.fishing.current
|
||||||
|
val required = option.level
|
||||||
|
val tool = option.tool
|
||||||
|
|
||||||
|
when {
|
||||||
|
current < required -> player.sendMessage("You need a fishing level of $required to fish at this spot.")
|
||||||
|
hasTool(player, tool) -> player.sendMessage("You need a ${tool.formattedName} to fish at this spot.")
|
||||||
|
hasBait(player, tool.bait) -> player.sendMessage("You need some ${tool.baitName} to fish at this spot.")
|
||||||
|
player.inventory.freeSlots() == 0 -> player.inventory.forceCapacityExceeded()
|
||||||
|
else -> return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package org.apollo.game.plugin.skills.fishing
|
||||||
|
|
||||||
|
import org.apollo.game.model.Animation
|
||||||
|
import org.apollo.game.plugin.api.Definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tool used to gather [Fish] from a [FishingSpot].
|
||||||
|
*/
|
||||||
|
enum class FishingTool(
|
||||||
|
val message: String,
|
||||||
|
val id: Int,
|
||||||
|
animation: Int,
|
||||||
|
val bait: Int = -1,
|
||||||
|
val baitName: String? = null
|
||||||
|
) {
|
||||||
|
LOBSTER_CAGE("You attempt to catch a lobster...", id = 301, animation = 619),
|
||||||
|
SMALL_NET("You cast out your net...", id = 303, animation = 620),
|
||||||
|
BIG_NET("You cast out your net...", id = 305, animation = 620),
|
||||||
|
HARPOON("You start harpooning fish...", id = 311, animation = 618),
|
||||||
|
FISHING_ROD("You attempt to catch a fish...", id = 307, animation = 622, bait = 313, baitName = "feathers"),
|
||||||
|
FLY_FISHING_ROD("You attempt to catch a fish...", id = 309, animation = 622, bait = 314, baitName = "fishing bait");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The [Animation] played when fishing with this tool.
|
||||||
|
*/
|
||||||
|
val animation: Animation = Animation(animation)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this tool, formatted so it can be inserted into a message.
|
||||||
|
*/
|
||||||
|
val formattedName by lazy { Definitions.item(id).name.toLowerCase() }
|
||||||
|
|
||||||
|
}
|
||||||
+2
-3
@@ -1,7 +1,6 @@
|
|||||||
import org.apollo.game.model.Direction
|
package org.apollo.game.plugin.skills.fishing
|
||||||
import org.apollo.game.model.Position
|
import org.apollo.game.model.Position
|
||||||
import org.apollo.game.plugin.entity.spawn.spawnNpc
|
import org.apollo.game.plugin.entity.spawn.spawnNpc
|
||||||
import org.apollo.game.plugin.skills.fishing.FishingSpot
|
|
||||||
import org.apollo.game.plugin.skills.fishing.FishingSpot.CAGE_HARPOON
|
import org.apollo.game.plugin.skills.fishing.FishingSpot.CAGE_HARPOON
|
||||||
import org.apollo.game.plugin.skills.fishing.FishingSpot.NET_HARPOON
|
import org.apollo.game.plugin.skills.fishing.FishingSpot.NET_HARPOON
|
||||||
import org.apollo.game.plugin.skills.fishing.FishingSpot.NET_ROD
|
import org.apollo.game.plugin.skills.fishing.FishingSpot.NET_ROD
|
||||||
@@ -177,5 +176,5 @@ NET_ROD at Position(3103, 3092)
|
|||||||
* Registers the [FishingSpot] at the specified position.
|
* Registers the [FishingSpot] at the specified position.
|
||||||
*/
|
*/
|
||||||
infix fun FishingSpot.at(position: Position) {
|
infix fun FishingSpot.at(position: Position) {
|
||||||
spawnNpc("", position.x, position.y, position.height, id = npc, facing = Direction.NORTH)
|
spawnNpc("", position, id = npc)
|
||||||
}
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
package org.apollo.game.plugin.skills.fishing
|
||||||
|
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.spyk
|
||||||
|
import io.mockk.verify
|
||||||
|
import org.apollo.cache.def.ItemDefinition
|
||||||
|
import org.apollo.cache.def.NpcDefinition
|
||||||
|
import org.apollo.game.model.World
|
||||||
|
import org.apollo.game.model.entity.Player
|
||||||
|
import org.apollo.game.model.entity.Skill
|
||||||
|
import org.apollo.game.plugin.testing.assertions.after
|
||||||
|
import org.apollo.game.plugin.testing.assertions.contains
|
||||||
|
import org.apollo.game.plugin.testing.assertions.startsWith
|
||||||
|
import org.apollo.game.plugin.testing.assertions.verifyAfter
|
||||||
|
import org.apollo.game.plugin.testing.junit.ApolloTestingExtension
|
||||||
|
import org.apollo.game.plugin.testing.junit.api.ActionCapture
|
||||||
|
import org.apollo.game.plugin.testing.junit.api.annotations.ItemDefinitions
|
||||||
|
import org.apollo.game.plugin.testing.junit.api.annotations.NpcDefinitions
|
||||||
|
import org.apollo.game.plugin.testing.junit.api.annotations.TestMock
|
||||||
|
import org.apollo.game.plugin.testing.junit.api.interactions.spawnNpc
|
||||||
|
import org.apollo.game.plugin.testing.junit.api.interactions.spawnObject
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertTrue
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
|
|
||||||
|
@ExtendWith(ApolloTestingExtension::class)
|
||||||
|
class FishingActionTests {
|
||||||
|
|
||||||
|
@TestMock
|
||||||
|
lateinit var world: World
|
||||||
|
|
||||||
|
@TestMock
|
||||||
|
lateinit var player: Player
|
||||||
|
|
||||||
|
@TestMock
|
||||||
|
lateinit var action: ActionCapture
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Attempting to fish at a spot we don't have the skill to should send the player a message`() {
|
||||||
|
val obj = world.spawnObject(1, player.position)
|
||||||
|
|
||||||
|
val option = spyk(FishingSpot.CAGE_HARPOON.option(1))
|
||||||
|
val target = FishingTarget(obj.position, option)
|
||||||
|
|
||||||
|
player.startAction(FishingAction(player, target))
|
||||||
|
|
||||||
|
every { option.level } returns Int.MAX_VALUE
|
||||||
|
|
||||||
|
verifyAfter(action.complete()) {
|
||||||
|
player.sendMessage(contains("need a fishing level of ${Int.MAX_VALUE}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Fishing at a spot we have the skill to should eventually reward fish and experience`() {
|
||||||
|
val option = spyk(FishingSpot.CAGE_HARPOON.option(1))
|
||||||
|
val obj = world.spawnNpc(FishingSpot.CAGE_HARPOON.npc, player.position)
|
||||||
|
|
||||||
|
val target = spyk(FishingTarget(obj.position, option))
|
||||||
|
every { target.isSuccessful(player, any()) } returns true
|
||||||
|
every { target.verify(player) } returns true
|
||||||
|
|
||||||
|
player.skillSet.setCurrentLevel(Skill.FISHING, option.level)
|
||||||
|
player.startAction(FishingAction(player, target))
|
||||||
|
|
||||||
|
verifyAfter(action.ticks(1)) {
|
||||||
|
player.sendMessage(startsWith("You attempt to catch a lobster"))
|
||||||
|
}
|
||||||
|
|
||||||
|
after(action.ticks(4)) {
|
||||||
|
verify { player.sendMessage(startsWith("You catch a <fish_type>.")) }
|
||||||
|
|
||||||
|
assertTrue(player.inventory.contains(Fish.LOBSTER.id))
|
||||||
|
assertEquals(player.skillSet.getExperience(Skill.FISHING), Fish.LOBSTER.experience)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
@ItemDefinitions
|
||||||
|
private val fish = Fish.values()
|
||||||
|
.map { ItemDefinition(it.id).apply { name = "<fish_type>" } }
|
||||||
|
|
||||||
|
@ItemDefinitions
|
||||||
|
private val tools = FishingTool.values()
|
||||||
|
.map { ItemDefinition(it.id).apply { name = "<fish_tool>" } }
|
||||||
|
|
||||||
|
@NpcDefinitions
|
||||||
|
private val spots = FishingSpot.values()
|
||||||
|
.map { NpcDefinition(it.npc).apply { name = "<fishing_spot>" } }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user