From 9a8f94df184ab3fa1e680d5c5d6c91e4ee7a331d Mon Sep 17 00:00:00 2001 From: Gary Tierney Date: Mon, 3 Sep 2018 22:40:11 +0100 Subject: [PATCH] Add runecrafting action unit tests --- .../runecrafting/src/{altar.kt => Altar.kt} | 2 + .../runecrafting/src/CreateTiaraAction.kt | 25 ++++ game/plugin/skills/runecrafting/src/Rune.kt | 66 ++++++++++ ...ing.plugin.kts => Runecrafting.plugin.kts} | 21 +++- .../runecrafting/src/RunecraftingAction.kt | 39 ++++++ .../src/{talisman.kt => Talisman.kt} | 10 +- .../runecrafting/src/TeleportToAltarAction.kt | 12 ++ .../runecrafting/src/{tiara.kt => Tiara.kt} | 6 +- game/plugin/skills/runecrafting/src/action.kt | 75 ----------- .../skills/runecrafting/src/constants.kt | 9 ++ game/plugin/skills/runecrafting/src/rune.kt | 36 ------ .../test/CreateTiaraActionTests.kt | 68 ++++++++++ .../test/RunecraftingActionTests.kt | 116 ++++++++++++++++++ 13 files changed, 364 insertions(+), 121 deletions(-) rename game/plugin/skills/runecrafting/src/{altar.kt => Altar.kt} (97%) create mode 100644 game/plugin/skills/runecrafting/src/CreateTiaraAction.kt create mode 100644 game/plugin/skills/runecrafting/src/Rune.kt rename game/plugin/skills/runecrafting/src/{runecrafting.plugin.kts => Runecrafting.plugin.kts} (80%) create mode 100644 game/plugin/skills/runecrafting/src/RunecraftingAction.kt rename game/plugin/skills/runecrafting/src/{talisman.kt => Talisman.kt} (88%) create mode 100644 game/plugin/skills/runecrafting/src/TeleportToAltarAction.kt rename game/plugin/skills/runecrafting/src/{tiara.kt => Tiara.kt} (86%) delete mode 100644 game/plugin/skills/runecrafting/src/action.kt create mode 100644 game/plugin/skills/runecrafting/src/constants.kt delete mode 100644 game/plugin/skills/runecrafting/src/rune.kt create mode 100644 game/plugin/skills/runecrafting/test/CreateTiaraActionTests.kt create mode 100644 game/plugin/skills/runecrafting/test/RunecraftingActionTests.kt diff --git a/game/plugin/skills/runecrafting/src/altar.kt b/game/plugin/skills/runecrafting/src/Altar.kt similarity index 97% rename from game/plugin/skills/runecrafting/src/altar.kt rename to game/plugin/skills/runecrafting/src/Altar.kt index 3895a26a..f336b2b1 100644 --- a/game/plugin/skills/runecrafting/src/altar.kt +++ b/game/plugin/skills/runecrafting/src/Altar.kt @@ -1,3 +1,5 @@ +package org.apollo.game.plugin.skill.runecrafting + import org.apollo.game.model.Position enum class Altar(val entranceId: Int, val craftingId: Int, val portalId: Int, val entrance: Position, val exit: Position, val center: Position) { diff --git a/game/plugin/skills/runecrafting/src/CreateTiaraAction.kt b/game/plugin/skills/runecrafting/src/CreateTiaraAction.kt new file mode 100644 index 00000000..f6bcc43f --- /dev/null +++ b/game/plugin/skills/runecrafting/src/CreateTiaraAction.kt @@ -0,0 +1,25 @@ +package org.apollo.game.plugin.skill.runecrafting + +import org.apollo.game.action.DistancedAction +import org.apollo.game.model.Position +import org.apollo.game.model.entity.Player +import org.apollo.game.plugin.api.runecraft + +class CreateTiaraAction(val player: Player, val position: Position, val tiara: Tiara, val altar: Altar) : DistancedAction(0, true, player, position, 2) { + override fun executeAction() { + if (tiara.altar != altar) { + player.sendMessage("You can't use that talisman on this altar.") + stop() + return + } + + if (player.inventory.contains(blankTiaraId)) { + player.inventory.remove(blankTiaraId) + player.inventory.add(tiara.id) + player.runecraft.experience += tiara.xp + player.playAnimation(runecraftingAnimation) + player.playGraphic(runecraftingGraphic) + stop() + } + } +} \ No newline at end of file diff --git a/game/plugin/skills/runecrafting/src/Rune.kt b/game/plugin/skills/runecrafting/src/Rune.kt new file mode 100644 index 00000000..9d2c3991 --- /dev/null +++ b/game/plugin/skills/runecrafting/src/Rune.kt @@ -0,0 +1,66 @@ +package org.apollo.game.plugin.skill.runecrafting + +import org.apollo.game.plugin.skill.runecrafting.Altar.* + + +interface Rune { + /** + * The item id of the rune. + */ + val id: Int + + /** + * The [Altar] this rune must be crafted at. + */ + val altar: Altar + + /** + * The runecrafting level required to craft runes of this type. + */ + val level: Int + + /** + * The amount of experience rewarded from crafting a single rune of this type. + */ + val xp: Double + + /** + * Get the multiplier that is applied to the number of runes the player crafts for their runecrafting level. + * + * [playerLevel] - The players current runecrafting level. + */ + fun getBonusMultiplier(playerLevel: Int) : Double +} + +enum class DefaultRune( + override val id: Int, + override val altar: Altar, + override val level: Int, + override val xp: Double +) : Rune { + AIR_RUNE(556, AIR_ALTAR, 1, 5.0), + MIND_RUNE(558, MIND_ALTAR, 1, 5.5), + WATER_RUNE(555, WATER_ALTAR, 5, 6.0), + EARTH_RUNE(557, EARTH_ALTAR, 9, 6.5), + FIRE_RUNE(554, FIRE_ALTAR, 14, 7.0), + BODY_RUNE(559, BODY_ALTAR, 20, 7.5), + COSMIC_RUNE(564, COSMIC_ALTAR, 27, 8.0), + CHAOS_RUNE(562, CHAOS_ALTAR, 35, 8.5), + NATURE_RUNE(561, NATURE_ALTAR, 44, 9.0), + LAW_RUNE(563, LAW_ALTAR, 54, 9.5), + DEATH_RUNE(560, DEATH_ALTAR, 65, 10.0); + + override fun getBonusMultiplier(playerLevel: Int): Double = when (this) { + DefaultRune.AIR_RUNE -> (Math.floor((playerLevel / 11.0)) + 1) + DefaultRune.MIND_RUNE -> (Math.floor((playerLevel / 14.0)) + 1) + DefaultRune.WATER_RUNE -> (Math.floor((playerLevel / 19.0)) + 1) + DefaultRune.EARTH_RUNE -> (Math.floor((playerLevel / 26.0)) + 1) + DefaultRune.FIRE_RUNE -> (Math.floor((playerLevel / 35.0)) + 1) + DefaultRune.BODY_RUNE -> (Math.floor((playerLevel / 46.0)) + 1) + DefaultRune.COSMIC_RUNE -> (Math.floor((playerLevel / 59.0)) + 1) + DefaultRune.CHAOS_RUNE -> (Math.floor((playerLevel / 74.0)) + 1) + DefaultRune.NATURE_RUNE -> (Math.floor((playerLevel / 91.0)) + 1) + DefaultRune.LAW_RUNE -> 1.0 + DefaultRune.DEATH_RUNE -> 1.0 + } +} diff --git a/game/plugin/skills/runecrafting/src/runecrafting.plugin.kts b/game/plugin/skills/runecrafting/src/Runecrafting.plugin.kts similarity index 80% rename from game/plugin/skills/runecrafting/src/runecrafting.plugin.kts rename to game/plugin/skills/runecrafting/src/Runecrafting.plugin.kts index ece21c98..b31dbc5b 100644 --- a/game/plugin/skills/runecrafting/src/runecrafting.plugin.kts +++ b/game/plugin/skills/runecrafting/src/Runecrafting.plugin.kts @@ -1,9 +1,22 @@ +package org.apollo.game.plugin.skill.runecrafting + import org.apollo.game.message.impl.* import org.apollo.game.model.entity.EquipmentConstants import org.apollo.game.model.event.impl.LoginEvent private val changeAltarObjectConfigId = 491 +internal val RUNES = mutableListOf() + +fun List.findById(id: Int) : Rune? { + return find { rune -> rune.id == id } +} + + +start { + RUNES.addAll(DefaultRune.values()) +} + on_player_event { LoginEvent::class } .then { val equippedHat = player.equipment.get(EquipmentConstants.HAT) @@ -20,7 +33,7 @@ on { ObjectActionMessage::class } val hat = it.equipment.get(EquipmentConstants.HAT) ?: return@then if (hat.id == tiara.id && tiara.altar.entranceId == id) { - it.startAction(TeleportAction(it, position, 2, tiara.altar.entrance)) + it.startAction(TeleportToAltarAction(it, position, 2, tiara.altar.entrance)) terminate() } } @@ -57,7 +70,7 @@ on { ItemOnObjectMessage::class } val talisman = Talisman.findById(id) ?: return@then val altar = Altar.findByEntranceId(objectId) ?: return@then - it.startAction(TeleportAction(it, position, 2, altar.entrance)) + it.startAction(TeleportToAltarAction(it, position, 2, altar.entrance)) terminate() } @@ -66,14 +79,14 @@ on { ObjectActionMessage::class } .then { val altar = Altar.findByPortalId(id) ?: return@then - it.startAction(TeleportAction(it, altar.entrance, 1, altar.exit)) + it.startAction(TeleportToAltarAction(it, altar.entrance, 1, altar.exit)) terminate() } on { ObjectActionMessage::class } .where { option == 1 } .then { - val rune = Rune.findByAltarId(id) ?: return@then + val rune = RUNES.findById(id) ?: return@then val craftingAltar = Altar.findByCraftingId(id) ?: return@then it.startAction(RunecraftingAction(it, rune, craftingAltar)) diff --git a/game/plugin/skills/runecrafting/src/RunecraftingAction.kt b/game/plugin/skills/runecrafting/src/RunecraftingAction.kt new file mode 100644 index 00000000..371a3554 --- /dev/null +++ b/game/plugin/skills/runecrafting/src/RunecraftingAction.kt @@ -0,0 +1,39 @@ +package org.apollo.game.plugin.skill.runecrafting + +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.Definitions +import org.apollo.game.plugin.api.runecraft +import org.apollo.util.LanguageUtil + +class RunecraftingAction(val player: Player, val rune: Rune, altar: Altar) : AsyncDistancedAction(0, true, player, altar.center, 3) { + override fun action(): ActionBlock = { + if (player.runecraft.current < rune.level) { + player.sendMessage("You need a runecrafting level of ${rune.level} to craft this rune.") + stop() + } + + if (!player.inventory.contains(runeEssenceId)) { + player.sendMessage("You need rune essence to craft runes.") + stop() + } + + player.turnTo(position) + player.playAnimation(runecraftingAnimation) + player.playGraphic(runecraftingGraphic) + + wait(1) + + val name = Definitions.item(rune.id).name; + val nameArticle = LanguageUtil.getIndefiniteArticle(name) + val essenceAmount = player.inventory.removeAll(runeEssenceId) + val runeAmount = essenceAmount * rune.getBonusMultiplier(player.runecraft.current) + val runesDescription = if (runeAmount > 1) "some ${name}s" else "$nameArticle $name" + + player.sendMessage("You craft the rune essence into $runesDescription") + player.inventory.add(rune.id, runeAmount.toInt()) + player.runecraft.experience += rune.xp * essenceAmount + stop() + } +} diff --git a/game/plugin/skills/runecrafting/src/talisman.kt b/game/plugin/skills/runecrafting/src/Talisman.kt similarity index 88% rename from game/plugin/skills/runecrafting/src/talisman.kt rename to game/plugin/skills/runecrafting/src/Talisman.kt index db81d9dc..bd4cc542 100644 --- a/game/plugin/skills/runecrafting/src/talisman.kt +++ b/game/plugin/skills/runecrafting/src/Talisman.kt @@ -1,3 +1,5 @@ +package org.apollo.game.plugin.skill.runecrafting + import org.apollo.game.model.Position import org.apollo.game.model.entity.Player @@ -22,13 +24,13 @@ enum class Talisman(val id: Int, val altar: Position) { fun sendProximityMessageTo(player: Player) { if (altar.isWithinDistance(player.position, 10)) { - player.sendMessage("Your talisman glows brightly."); + player.sendMessage("Your talisman glows brightly.") return } - var direction = if (player.position.y > altar.y) "North" else "South"; - direction += if (player.position.x > altar.x) "-East" else "-West"; + var direction = if (player.position.y > altar.y) "North" else "South" + direction += if (player.position.x > altar.x) "-East" else "-West" - player.sendMessage("The talisman pulls toward the $direction"); + player.sendMessage("The talisman pulls toward the $direction") } } \ No newline at end of file diff --git a/game/plugin/skills/runecrafting/src/TeleportToAltarAction.kt b/game/plugin/skills/runecrafting/src/TeleportToAltarAction.kt new file mode 100644 index 00000000..ec6ff9a8 --- /dev/null +++ b/game/plugin/skills/runecrafting/src/TeleportToAltarAction.kt @@ -0,0 +1,12 @@ +package org.apollo.game.plugin.skill.runecrafting + +import org.apollo.game.action.DistancedAction +import org.apollo.game.model.Position +import org.apollo.game.model.entity.Player + +class TeleportToAltarAction(val player: Player, val start: Position, val distance: Int, val end: Position) : DistancedAction(0, true, player, start, distance) { + override fun executeAction() { + player.teleport(end) + stop() + } +} \ No newline at end of file diff --git a/game/plugin/skills/runecrafting/src/tiara.kt b/game/plugin/skills/runecrafting/src/Tiara.kt similarity index 86% rename from game/plugin/skills/runecrafting/src/tiara.kt rename to game/plugin/skills/runecrafting/src/Tiara.kt index 549fe76b..d9e002c0 100644 --- a/game/plugin/skills/runecrafting/src/tiara.kt +++ b/game/plugin/skills/runecrafting/src/Tiara.kt @@ -1,5 +1,7 @@ -import Altar.* -import Talisman.* +package org.apollo.game.plugin.skill.runecrafting + +import org.apollo.game.plugin.skill.runecrafting.Altar.* +import org.apollo.game.plugin.skill.runecrafting.Talisman.* enum class Tiara(val id: Int, val altar: Altar, val talisman: Talisman, val configId: Int, val xp: Double) { AIR_TIARA(5527, AIR_ALTAR, AIR_TALISMAN, 0, 25.0), diff --git a/game/plugin/skills/runecrafting/src/action.kt b/game/plugin/skills/runecrafting/src/action.kt deleted file mode 100644 index 6beb4570..00000000 --- a/game/plugin/skills/runecrafting/src/action.kt +++ /dev/null @@ -1,75 +0,0 @@ -import org.apollo.game.action.ActionBlock -import org.apollo.game.action.AsyncDistancedAction -import org.apollo.game.action.DistancedAction -import org.apollo.game.model.Animation -import org.apollo.game.model.Graphic -import org.apollo.game.model.Position -import org.apollo.game.model.entity.Player -import org.apollo.game.plugin.api.Definitions -import org.apollo.game.plugin.api.runecraft -import org.apollo.util.LanguageUtil - -private val blankTiaraId = 5525 -private val runecraftingAnimation = Animation(791) -private val runecraftingGraphic = Graphic(186, 0, 100) -private val runeEssenceId = 1436 - -class TeleportAction(val player: Player, val start: Position, val distance: Int, val end: Position) : DistancedAction(0, true, player, start, distance) { - override fun executeAction() { - player.teleport(end) - stop() - } -} - -class CreateTiaraAction(val player: Player, val position: Position, val tiara: Tiara, val altar: Altar) : DistancedAction(0, true, player, position, 2) { - override fun executeAction() { - if (tiara.altar != altar) { - player.sendMessage("You can't use that talisman on this altar.") - stop() - return - } - - if (player.inventory.contains(blankTiaraId)) { - player.inventory.remove(blankTiaraId) - player.inventory.add(tiara.id) - player.runecraft.experience += tiara.xp - player.playAnimation(runecraftingAnimation) - player.playGraphic(runecraftingGraphic) - stop() - } - } -} - -class RunecraftingAction(val player: Player, val rune: Rune, altar: Altar) : AsyncDistancedAction(0, true, player, altar.center, 3) { - override fun action(): ActionBlock = { - if (player.runecraft.current < rune.level) { - player.sendMessage("You need a runecrafting level of ${rune.level} to craft this rune.") - stop() - } - - if (!player.inventory.contains(runeEssenceId)) { - player.sendMessage("You need rune essence to craft runes.") - stop() - } - - player.turnTo(position) - player.playAnimation(runecraftingAnimation) - player.playGraphic(runecraftingGraphic) - - wait(1) - - val name = Definitions.item(rune.id)?.name; - val nameArticle = LanguageUtil.getIndefiniteArticle(name) - val essenceAmount = player.inventory.removeAll(runeEssenceId) - val runeAmount = essenceAmount * rune.getBonus() - val runesDescription = if (runeAmount > 1) "some ${name}s" else "$nameArticle $name" - - player.sendMessage("You craft the rune essence into $runesDescription") - player.inventory.add(rune.id, runeAmount.toInt()) - player.runecraft.experience += rune.xp - stop() - } - -} - - diff --git a/game/plugin/skills/runecrafting/src/constants.kt b/game/plugin/skills/runecrafting/src/constants.kt new file mode 100644 index 00000000..73f77cf5 --- /dev/null +++ b/game/plugin/skills/runecrafting/src/constants.kt @@ -0,0 +1,9 @@ +package org.apollo.game.plugin.skill.runecrafting + +import org.apollo.game.model.Animation +import org.apollo.game.model.Graphic + +const val blankTiaraId = 5525 +val runecraftingAnimation = Animation(791) +val runecraftingGraphic = Graphic(186, 0, 100) +const val runeEssenceId = 1436 \ No newline at end of file diff --git a/game/plugin/skills/runecrafting/src/rune.kt b/game/plugin/skills/runecrafting/src/rune.kt deleted file mode 100644 index bc94e94a..00000000 --- a/game/plugin/skills/runecrafting/src/rune.kt +++ /dev/null @@ -1,36 +0,0 @@ -import Altar.* - -enum class Rune(val id: Int, val altar: Altar, val level: Int, val xp: Double) { - AIR_RUNE(556, AIR_ALTAR, 1, 5.0), - MIND_RUNE(558, MIND_ALTAR, 1, 5.5), - WATER_RUNE(555, WATER_ALTAR, 5, 6.0), - EARTH_RUNE(557, EARTH_ALTAR, 9, 6.5), - FIRE_RUNE(554, FIRE_ALTAR, 14, 7.0), - BODY_RUNE(559, BODY_ALTAR, 20, 7.5), - COSMIC_RUNE(564, COSMIC_ALTAR, 27, 8.0), - CHAOS_RUNE(562, CHAOS_ALTAR, 35, 8.5), - NATURE_RUNE(561, NATURE_ALTAR, 44, 9.0), - LAW_RUNE(563, LAW_ALTAR, 54, 9.5), - DEATH_RUNE(560, DEATH_ALTAR, 65, 10.0); - - companion object { - private val RUNES = Rune.values() - - fun findById(id: Int): Rune? = RUNES.find { rune -> rune.id == id } - fun findByAltarId(id: Int): Rune? = RUNES.find { rune -> rune.altar.craftingId == id } - } - - fun getBonus(): Double = when (this) { - Rune.AIR_RUNE -> (Math.floor((level / 11.0)) + 1) - Rune.MIND_RUNE -> (Math.floor((level / 14.0)) + 1) - Rune.WATER_RUNE -> (Math.floor((level / 19.0)) + 1) - Rune.EARTH_RUNE -> (Math.floor((level / 26.0)) + 1) - Rune.FIRE_RUNE -> (Math.floor((level / 35.0)) + 1) - Rune.BODY_RUNE -> (Math.floor((level / 46.0)) + 1) - Rune.COSMIC_RUNE -> (Math.floor((level / 59.0)) + 1) - Rune.CHAOS_RUNE -> (Math.floor((level / 74.0)) + 1) - Rune.NATURE_RUNE -> (Math.floor((level / 91.0)) + 1) - Rune.LAW_RUNE -> 1.0 - Rune.DEATH_RUNE -> 1.0 - } -} diff --git a/game/plugin/skills/runecrafting/test/CreateTiaraActionTests.kt b/game/plugin/skills/runecrafting/test/CreateTiaraActionTests.kt new file mode 100644 index 00000000..98af45f2 --- /dev/null +++ b/game/plugin/skills/runecrafting/test/CreateTiaraActionTests.kt @@ -0,0 +1,68 @@ +package org.apollo.game.plugin.skill.runecrafting + +import org.apollo.cache.def.ItemDefinition +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.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.TestMock +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(ApolloTestingExtension::class) +class CreateTiaraActionTests { + + @TestMock + lateinit var world: World + + @TestMock + lateinit var player: Player + + @TestMock + lateinit var action: ActionCapture + + @Test + fun `A tiara should be rewarded after action completion`() { + player.inventory.add(blankTiaraId) + player.startAction(CreateTiaraAction(player, player.position, Tiara.AIR_TIARA, Altar.AIR_ALTAR)) + + after(action.complete(), "tiara added to inventory") { + assertEquals(1, player.inventory.getAmount(Tiara.AIR_TIARA.id)) + } + } + + @Test + fun `Tiaras can only be enchanted on compatible altars`() { + player.inventory.add(blankTiaraId) + player.startAction(CreateTiaraAction(player, player.position, Tiara.AIR_TIARA, Altar.BODY_ALTAR)) + + verifyAfter(action.complete(), "error message sent") { + player.sendMessage("You can't use that talisman on this altar.") + } + } + + @Test + fun `Experience is rewarded for enchanting tiaras`() { + player.inventory.add(blankTiaraId) + player.skillSet.setExperience(Skill.RUNECRAFT, 0.0) + player.startAction(CreateTiaraAction(player, player.position, Tiara.AIR_TIARA, Altar.AIR_ALTAR)) + + after(action.complete(), "experience gained") { + assertEquals(Tiara.AIR_TIARA.xp, player.skillSet.getExperience(Skill.RUNECRAFT)) + } + } + + companion object { + @ItemDefinitions + private val tiaras = Tiara.values() + .map { ItemDefinition(it.id).apply { name = "" } } + + @ItemDefinitions + private val blankTiara = listOf(ItemDefinition(blankTiaraId)) + } +} \ No newline at end of file diff --git a/game/plugin/skills/runecrafting/test/RunecraftingActionTests.kt b/game/plugin/skills/runecrafting/test/RunecraftingActionTests.kt new file mode 100644 index 00000000..4e01a44b --- /dev/null +++ b/game/plugin/skills/runecrafting/test/RunecraftingActionTests.kt @@ -0,0 +1,116 @@ +package org.apollo.game.plugin.skill.runecrafting + +import io.mockk.verify +import org.apollo.cache.def.ItemDefinition +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.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.TestMock +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(ApolloTestingExtension::class) +class RunecraftingActionTests { + + @TestMock + lateinit var player: Player + + @TestMock + lateinit var action: ActionCapture + + @BeforeEach + fun setupPlayer() { + player.position = TEST_ALTAR.center + player.inventory.add(runeEssenceId, 25) + + } + + @Test + fun `Bonus runes are rewarded depending on the multiplier returned by the rune type`() { + player.startAction(RunecraftingAction(player, `rune with 1xp and bonus multiplier of 2`, TEST_ALTAR)) + + after(action.complete()) { + assertEquals(50, player.inventory.getAmount(1)) + } + } + + @Test + fun `Experience does not stack with bonus multiplier`() { + player.skillSet.setExperience(Skill.RUNECRAFT, 0.0) + player.startAction(RunecraftingAction(player, `rune with 1xp and bonus multiplier of 2`, TEST_ALTAR)) + + after(action.complete()) { + assertEquals(25.0, player.skillSet.getExperience(Skill.RUNECRAFT)) + } + } + + @Test + fun `Experience is rewarded for each rune essence used`() { + player.skillSet.setExperience(Skill.RUNECRAFT, 0.0) + player.startAction(RunecraftingAction(player, `rune with 1xp and bonus multiplier of 1`, TEST_ALTAR)) + + after(action.complete()) { + assertEquals(25.0, player.skillSet.getExperience(Skill.RUNECRAFT)) + } + } + + @Test + fun `Cannot create runes that are too high of a level`() { + player.skillSet.setCurrentLevel(Skill.RUNECRAFT, 1) + player.startAction(RunecraftingAction(player, `rune with required level of 99`, TEST_ALTAR)) + + after(action.complete()) { + verify { player.sendMessage("You need a runecrafting level of 99 to craft this rune.") } + + assertEquals(25, player.inventory.getAmount(runeEssenceId)) + assertEquals(0, player.inventory.getAmount(1)) + } + } + + companion object { + val TEST_ALTAR = Altar.AIR_ALTAR + + val `rune with required level of 99` = object : Rune { + override val id = 1 + override val altar: Altar = TEST_ALTAR + override val level = 99 + override val xp = 1.0 + + override fun getBonusMultiplier(playerLevel: Int) = 1.0 + } + + val `rune with 1xp and bonus multiplier of 1` = object : Rune { + override val id = 1 + override val altar: Altar = TEST_ALTAR + override val level = 1 + override val xp = 1.0 + + override fun getBonusMultiplier(playerLevel: Int) = 1.0 + } + + val `rune with 1xp and bonus multiplier of 2` = object : Rune { + override val id = 1 + override val altar: Altar = TEST_ALTAR + override val level = 1 + override val xp = 1.0 + + override fun getBonusMultiplier(playerLevel: Int) = 2.0 + } + + @ItemDefinitions + private val runeEssence = listOf(ItemDefinition(runeEssenceId).apply { + isStackable = true + }) + + @ItemDefinitions + private val runes = listOf(ItemDefinition(1).apply { + name = "" + isStackable = true + }) + } +} \ No newline at end of file