mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 00:38:21 +00:00
Add plugin for consumable food/drink
This commit is contained in:
@@ -20,7 +20,7 @@ abstract class KotlinPluginTest: KotlinPluginTestHelpers() {
|
||||
override lateinit var messageHandlers: MessageHandlerChainSet
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
open fun setup() {
|
||||
messageHandlers = MessageHandlerChainSet()
|
||||
world = PowerMockito.spy(World())
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
name = "consumables"
|
||||
package = "org.apollo.game.plugin.consumables"
|
||||
authors = [ "Gary Tierney" ]
|
||||
dependencies = []
|
||||
|
||||
[config]
|
||||
srcDir = "src/"
|
||||
testDir = "test/"
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.apollo.plugin.consumables
|
||||
|
||||
import org.apollo.game.model.entity.Player
|
||||
import org.apollo.game.model.entity.Skill
|
||||
|
||||
/**
|
||||
* An item that can be consumed to restore or buff stats.
|
||||
*/
|
||||
abstract class Consumable(val name: String, val id: Int, val sound: Int, val delay: Int, val replacement: Int?) {
|
||||
|
||||
abstract fun addEffect(player: Player)
|
||||
|
||||
fun consume(player: Player, slot: Int) {
|
||||
addEffect(player)
|
||||
player.inventory.reset(slot)
|
||||
|
||||
if (replacement != null) {
|
||||
player.inventory.add(replacement)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private val consumables = mutableMapOf<Int, Consumable>()
|
||||
|
||||
fun isConsumable(itemId: Int) = consumables.containsKey(itemId)
|
||||
fun lookupConsumable(itemId: Int): Consumable = consumables.get(itemId)!!
|
||||
fun consumable(consumable: Consumable) = consumables.put(consumable.id, consumable)
|
||||
|
||||
enum class FoodOrDrinkType(val action: String) {
|
||||
FOOD("eat"), DRINK("drink")
|
||||
}
|
||||
|
||||
class FoodOrDrink : Consumable {
|
||||
|
||||
companion object {
|
||||
const val EAT_FOOD_SOUND = 317
|
||||
}
|
||||
|
||||
val restoration: Int
|
||||
val type: FoodOrDrinkType
|
||||
|
||||
constructor(
|
||||
name: String,
|
||||
id: Int,
|
||||
delay: Int,
|
||||
type: FoodOrDrinkType,
|
||||
restoration: Int,
|
||||
replacement: Int? = null
|
||||
) : super(name, id, EAT_FOOD_SOUND, delay, replacement) {
|
||||
this.type = type
|
||||
this.restoration = restoration
|
||||
}
|
||||
|
||||
override fun addEffect(player: Player) {
|
||||
val hitpoints = player.skillSet.getSkill(Skill.HITPOINTS)
|
||||
val hitpointsLevel = hitpoints.currentLevel
|
||||
val newHitpointsLevel = Math.min(hitpointsLevel + restoration, hitpoints.maximumLevel)
|
||||
|
||||
player.sendMessage("You ${type.action} the $name.")
|
||||
if (newHitpointsLevel > hitpointsLevel) {
|
||||
player.sendMessage("It heals some health.")
|
||||
}
|
||||
|
||||
player.skillSet.setCurrentLevel(Skill.HITPOINTS, newHitpointsLevel)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a new type of [Consumable] food.
|
||||
*/
|
||||
fun food(name: String, id: Int, restoration: Int, replacement: Int? = null, delay: Int = 3) {
|
||||
consumable(FoodOrDrink(name, id, delay, FoodOrDrinkType.FOOD, restoration, replacement))
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a new type of [Consumable] drink.
|
||||
*/
|
||||
fun drink(name: String, id: Int, restoration: Int, replacement: Int? = null, delay: Int = 3) {
|
||||
consumable(FoodOrDrink(name, id, delay, FoodOrDrinkType.DRINK, restoration, replacement))
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import org.apollo.game.action.AsyncAction
|
||||
import org.apollo.game.message.impl.ItemOptionMessage
|
||||
import org.apollo.game.model.Animation
|
||||
import org.apollo.game.model.entity.Player
|
||||
import org.apollo.net.message.Message
|
||||
import org.apollo.plugin.consumables.*
|
||||
|
||||
on { ItemOptionMessage::class }
|
||||
.where { option == 1 && isConsumable(id) }
|
||||
.then {
|
||||
ConsumeAction.start(this, it, lookupConsumable(id), slot)
|
||||
}
|
||||
|
||||
class ConsumeAction(val consumable: Consumable, player: Player, val slot: Int) :
|
||||
AsyncAction<Player>(CONSUME_STARTUP_DELAY, true, player) {
|
||||
|
||||
companion object {
|
||||
const val CONSUME_ANIMATION_ID = 829
|
||||
const val CONSUME_STARTUP_DELAY = 2
|
||||
|
||||
/**
|
||||
* Starts a [ConsumeAction] for the specified [Player], terminating the [Message] that triggered it.
|
||||
*/
|
||||
fun start(message: Message, player: Player, consumable: Consumable, slot: Int) {
|
||||
player.startAction(ConsumeAction(consumable, player, slot))
|
||||
message.terminate()
|
||||
}
|
||||
}
|
||||
|
||||
suspend override fun executeActionAsync() {
|
||||
consumable.consume(mob, slot)
|
||||
mob.playAnimation(Animation(CONSUME_ANIMATION_ID))
|
||||
wait(consumable.delay)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import org.apollo.plugin.consumables.drink
|
||||
|
||||
//# Wine
|
||||
drink(name = "jug_of_wine", id = 1993, restoration = 11)
|
||||
|
||||
//# Hot Drinks
|
||||
drink(name = "nettle_tea", id = 4239, restoration = 3)
|
||||
drink(name = "nettle_tea", id = 4240, restoration = 3)
|
||||
|
||||
//# Gnome Cocktails
|
||||
drink(name = "fruit_blast", id = 2034, restoration = 9)
|
||||
drink(name = "fruit_blast", id = 2084, restoration = 9)
|
||||
drink(name = "pineapple_punch", id = 2036, restoration = 9)
|
||||
drink(name = "pineapple_punch", id = 2048, restoration = 9)
|
||||
drink(name = "wizard_blizzard", id = 2040, restoration = 5) // -4 attack, +5 strength also
|
||||
drink(name = "wizard_blizzard", id = 2054, restoration = 5) // -4 attack, +5 strength also
|
||||
drink(name = "short_green_guy", id = 2038, restoration = 5) // -4 attack, +5 strength also
|
||||
drink(name = "short_green_guy", id = 2080, restoration = 5) // -4 attack, +5 strength also
|
||||
drink(name = "drunk_dragon", id = 2032, restoration = 5) // -4 attack, +6 strength also
|
||||
drink(name = "drunk_dragon", id = 2092, restoration = 5) // -4 attack, +6 strength also
|
||||
drink(name = "chocolate_saturday", id = 2030, restoration = 7) // -4 attack, +6 strength also
|
||||
drink(name = "chocolate_saturday", id = 2074, restoration = 7) // -4 attack, +6 strength also
|
||||
drink(name = "blurberry_special", id = 2028, restoration = 7) // -4 attack, +6 strength also
|
||||
drink(name = "blurberry_special", id = 2064, restoration = 7) // -4 attack, +6 strength also
|
||||
@@ -0,0 +1,159 @@
|
||||
import org.apollo.plugin.consumables.food
|
||||
|
||||
food(name = "anchovies", id = 319, restoration = 1)
|
||||
food(name = "crab_meat", id = 7521, restoration = 2, replacement = 7523)
|
||||
food(name = "crab_meat", id = 7523, restoration = 2, replacement = 7524)
|
||||
food(name = "crab_meat", id = 7524, restoration = 2, replacement = 7525)
|
||||
food(name = "crab_meat", id = 7525, restoration = 2, replacement = 7526)
|
||||
food(name = "crab_meat", id = 7526, restoration = 2)
|
||||
food(name = "shrimp", id = 315, restoration = 3)
|
||||
food(name = "sardine", id = 325, restoration = 3)
|
||||
food(name = "cooked_meat", id = 2142, restoration = 3)
|
||||
food(name = "cooked_chicken", id = 2140, restoration = 3)
|
||||
food(name = "ugthanki_meat", id = 1861, restoration = 3)
|
||||
food(name = "karambwanji", id = 3151, restoration = 3)
|
||||
food(name = "cooked_rabbit", id = 3228, restoration = 5)
|
||||
food(name = "herring", id = 347, restoration = 6)
|
||||
food(name = "trout", id = 333, restoration = 7)
|
||||
food(name = "cod", id = 339, restoration = 7)
|
||||
food(name = "mackeral", id = 355, restoration = 7)
|
||||
food(name = "roast_rabbit", id = 7223, restoration = 7)
|
||||
food(name = "pike", id = 351, restoration = 8)
|
||||
food(name = "lean_snail_meat", id = 3371, restoration = 8)
|
||||
food(name = "salmon", id = 329, restoration = 9)
|
||||
food(name = "tuna", id = 361, restoration = 10)
|
||||
food(name = "lobster", id = 379, restoration = 12)
|
||||
food(name = "bass", id = 365, restoration = 13)
|
||||
food(name = "swordfish", id = 373, restoration = 14)
|
||||
food(name = "cooked_jubbly", id = 7568, restoration = 15)
|
||||
food(name = "monkfish", id = 7946, restoration = 16)
|
||||
food(name = "cooked_karambwan", id = 3144, restoration = 18, delay = 0)
|
||||
food(name = "shark", id = 385, restoration = 20)
|
||||
food(name = "sea_turtle", id = 397, restoration = 21)
|
||||
food(name = "manta_ray", id = 391, restoration = 22)
|
||||
|
||||
//# Breads/Wraps
|
||||
food(name = "bread", id = 2309, restoration = 5)
|
||||
food(name = "oomlie_wrap", id = 2343, restoration = 14)
|
||||
food(name = "ugthanki_kebab", id = 1883, restoration = 19)
|
||||
|
||||
//# Fruits
|
||||
food(name = "banana", id = 1963, restoration = 2)
|
||||
food(name = "sliced_banana", id = 3162, restoration = 2)
|
||||
food(name = "lemon", id = 2102, restoration = 2)
|
||||
food(name = "lemon_chunks", id = 2104, restoration = 2)
|
||||
food(name = "lemon_slices", id = 2106, restoration = 2)
|
||||
food(name = "lime", id = 2120, restoration = 2)
|
||||
food(name = "lime_chunks", id = 2122, restoration = 2)
|
||||
food(name = "lime_slices", id = 2124, restoration = 2)
|
||||
food(name = "strawberry", id = 5504, restoration = 5)
|
||||
food(name = "papaya_fruit", id = 5972, restoration = 8)
|
||||
food(name = "pineapple_chunks", id = 2116, restoration = 2)
|
||||
food(name = "pineapple_ring", id = 2118, restoration = 2)
|
||||
food(name = "orange", id = 2108, restoration = 2)
|
||||
food(name = "orange_rings", id = 2110, restoration = 2)
|
||||
food(name = "orange_slices", id = 2112, restoration = 2)
|
||||
|
||||
//# Pies
|
||||
//# TODO: pie special effects (e.g. fish pie raises fishing level)
|
||||
food(name = "redberry_pie", id = 2325, restoration = 5, replacement = 2333, delay = 1)
|
||||
food(name = "redberry_pie", id = 2333, restoration = 5, delay = 1)
|
||||
|
||||
food(name = "meat_pie", id = 2327, restoration = 6, replacement = 2331, delay = 1)
|
||||
food(name = "meat_pie", id = 2331, restoration = 6, delay = 1)
|
||||
|
||||
food(name = "apple_pie", id = 2323, restoration = 7, replacement = 2335, delay = 1)
|
||||
food(name = "apple_pie", id = 2335, restoration = 7, delay = 1)
|
||||
|
||||
food(name = "fish_pie", id = 7188, restoration = 6, replacement = 7190, delay = 1)
|
||||
food(name = "fish_pie", id = 7190, restoration = 6, delay = 1)
|
||||
|
||||
food(name = "admiral_pie", id = 7198, restoration = 8, replacement = 7200, delay = 1)
|
||||
food(name = "admiral_pie", id = 7200, restoration = 8, delay = 1)
|
||||
|
||||
food(name = "wild_pie", id = 7208, restoration = 11, replacement = 7210, delay = 1)
|
||||
food(name = "wild_pie", id = 7210, restoration = 11, delay = 1)
|
||||
|
||||
food(name = "summer_pie", id = 7218, restoration = 11, replacement = 7220, delay = 1)
|
||||
food(name = "summer_pie", id = 7220, restoration = 11, delay = 1)
|
||||
|
||||
//# Stews
|
||||
food(name = "stew", id = 2003, restoration = 11)
|
||||
food(name = "banana_stew", id = 4016, restoration = 11)
|
||||
food(name = "curry", id = 2011, restoration = 19)
|
||||
|
||||
//# Pizzas
|
||||
food(name = "plain_pizza", id = 2289, restoration = 7, replacement = 2291)
|
||||
food(name = "plain_pizza", id = 2291, restoration = 7)
|
||||
|
||||
food(name = "meat_pizza", id = 2293, restoration = 8, replacement = 2295)
|
||||
food(name = "meat_pizza", id = 2295, restoration = 8)
|
||||
|
||||
food(name = "anchovy_pizza", id = 2297, restoration = 9, replacement = 2299)
|
||||
food(name = "anchovy_pizza", id = 2299, restoration = 9)
|
||||
|
||||
food(name = "pineapple_pizza", id = 2301, restoration = 11, replacement = 2303)
|
||||
food(name = "pineapple_pizza", id = 2303, restoration = 11)
|
||||
|
||||
//# Cakes
|
||||
food(name = "fishcake", id = 7530, restoration = 11)
|
||||
|
||||
food(name = "cake", id = 1891, restoration = 4, replacement = 1893)
|
||||
food(name = "cake", id = 1893, restoration = 4, replacement = 1895)
|
||||
food(name = "cake", id = 1895, restoration = 4)
|
||||
|
||||
food(name = "chocolate_cake", id = 1897, restoration = 5, replacement = 1899)
|
||||
food(name = "chocolate_cake", id = 1899, restoration = 5, replacement = 1901)
|
||||
food(name = "chocolate_cake", id = 1901, restoration = 5)
|
||||
|
||||
//# Vegetables
|
||||
food(name = "potato", id = 1942, restoration = 1)
|
||||
food(name = "spinach_roll", id = 1969, restoration = 2)
|
||||
food(name = "baked_potato", id = 6701, restoration = 4)
|
||||
food(name = "sweetcorn", id = 5988, restoration = 10)
|
||||
food(name = "sweetcorn_bowl", id = 7088, restoration = 13)
|
||||
food(name = "potato_with_butter", id = 6703, restoration = 14)
|
||||
food(name = "chili_potato", id = 7054, restoration = 14)
|
||||
food(name = "potato_with_cheese", id = 6705, restoration = 16)
|
||||
food(name = "egg_potato", id = 7056, restoration = 16)
|
||||
food(name = "mushroom_potato", id = 7058, restoration = 20)
|
||||
food(name = "tuna_potato", id = 7060, restoration = 22)
|
||||
|
||||
//# Dairy
|
||||
food(name = "cheese", id = 1985, restoration = 2)
|
||||
food(name = "pot_of_cream", id = 2130, restoration = 1)
|
||||
|
||||
//# Gnome Food
|
||||
food(name = "toads_legs", id = 2152, restoration = 3)
|
||||
|
||||
//# Gnome Bowls
|
||||
food(name = "worm_hole", id = 2191, restoration = 12)
|
||||
food(name = "worm_hole", id = 2233, restoration = 12)
|
||||
food(name = "vegetable_ball", id = 2195, restoration = 12)
|
||||
food(name = "vegetable_ball", id = 2235, restoration = 12)
|
||||
food(name = "tangled_toads_legs", id = 2187, restoration = 15)
|
||||
food(name = "tangled_toads_legs", id = 2231, restoration = 15)
|
||||
food(name = "chocolate_bomb", id = 2185, restoration = 15)
|
||||
food(name = "chocolate_bomb", id = 2229, restoration = 15)
|
||||
|
||||
//# Gnome Crunchies
|
||||
food(name = "toad_crunchies", id = 2217, restoration = 7)
|
||||
food(name = "toad_crunchies", id = 2243, restoration = 7)
|
||||
food(name = "spicy_crunchies", id = 2213, restoration = 7)
|
||||
food(name = "spicy_crunchies", id = 2241, restoration = 7)
|
||||
food(name = "worm_crunchies", id = 2205, restoration = 8)
|
||||
food(name = "worm_crunchies", id = 2237, restoration = 8)
|
||||
food(name = "chocchip_crunchies", id = 2209, restoration = 7)
|
||||
food(name = "chocchip_crunchies", id = 2239, restoration = 7)
|
||||
|
||||
//# Gnome Battas
|
||||
food(name = "fruit_batta", id = 2225, restoration = 11)
|
||||
food(name = "fruit_batta", id = 2277, restoration = 11)
|
||||
food(name = "toad_batta", id = 2221, restoration = 11)
|
||||
food(name = "toad_batta", id = 2255, restoration = 11)
|
||||
food(name = "worm_batta", id = 2219, restoration = 11)
|
||||
food(name = "worm_batta", id = 2253, restoration = 11)
|
||||
food(name = "vegetable_batta", id = 2227, restoration = 11)
|
||||
food(name = "vegetable_batta", id = 2281, restoration = 11)
|
||||
food(name = "cheese_tom_batta", id = 2223, restoration = 11)
|
||||
food(name = "cheese_tom_batta", id = 2259, restoration = 11)
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.apollo.plugin.consumables
|
||||
|
||||
import org.apollo.game.message.impl.ItemOptionMessage
|
||||
import org.apollo.game.model.entity.Skill
|
||||
import org.apollo.game.plugin.testing.KotlinPluginTest
|
||||
import org.apollo.game.plugin.testing.mockito.KotlinMockitoExtensions.matches
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
|
||||
class FoodOrDrinkTests : KotlinPluginTest() {
|
||||
|
||||
companion object {
|
||||
const val TEST_FOOD_NAME = "test_food"
|
||||
const val TEST_FOOD_ID = 2000
|
||||
const val TEST_FOOD_RESTORATION = 5
|
||||
|
||||
const val TEST_DRINK_NAME = "test_drink"
|
||||
const val TEST_DRINK_ID = 2001
|
||||
const val TEST_DRINK_RESTORATION = 5
|
||||
|
||||
const val HP_LEVEL = 5
|
||||
const val MAX_HP_LEVEL = 10
|
||||
}
|
||||
|
||||
@Before override fun setup() {
|
||||
super.setup()
|
||||
|
||||
val skills = player.skillSet
|
||||
skills.setCurrentLevel(Skill.HITPOINTS, HP_LEVEL)
|
||||
skills.setMaximumLevel(Skill.HITPOINTS, MAX_HP_LEVEL)
|
||||
|
||||
food("test_food", TEST_FOOD_ID, TEST_FOOD_RESTORATION)
|
||||
drink("test_drink", TEST_DRINK_ID, TEST_DRINK_RESTORATION)
|
||||
}
|
||||
|
||||
@Test fun `Consuming food or drink should restore the players hitpoints`() {
|
||||
val expectedHpLevel = TEST_FOOD_RESTORATION + HP_LEVEL
|
||||
|
||||
player.notify(ItemOptionMessage(1, -1, TEST_FOOD_ID, 1))
|
||||
player.waitForActionCompletion()
|
||||
|
||||
val currentHpLevel = player.skillSet.getCurrentLevel(Skill.HITPOINTS)
|
||||
assertThat(currentHpLevel).isEqualTo(expectedHpLevel)
|
||||
}
|
||||
|
||||
@Test fun `A message should be sent notifying the player if the item restored hitpoints`() {
|
||||
player.notify(ItemOptionMessage(1, -1, TEST_FOOD_ID, 1))
|
||||
player.waitForActionCompletion()
|
||||
|
||||
verify(player).sendMessage(matches {
|
||||
assertThat(this).contains("heals some health")
|
||||
})
|
||||
}
|
||||
|
||||
@Test fun `A message should not be sent to the player if the item did not restore hitpoints`() {
|
||||
player.skillSet.setCurrentLevel(Skill.HITPOINTS, MAX_HP_LEVEL)
|
||||
player.notify(ItemOptionMessage(1, -1, TEST_FOOD_ID, 1))
|
||||
player.waitForActionCompletion()
|
||||
|
||||
verify(player, never()).sendMessage(matches {
|
||||
assertThat(this).contains("heals some health")
|
||||
})
|
||||
}
|
||||
|
||||
@Test fun `A message should be sent saying the player has drank an item when consuming a drink`() {
|
||||
player.notify(ItemOptionMessage(1, -1, TEST_DRINK_ID, 1))
|
||||
player.waitForActionCompletion()
|
||||
|
||||
verify(player).sendMessage(matches {
|
||||
assertThat(this).contains("You drink the ${TEST_DRINK_NAME}")
|
||||
})
|
||||
}
|
||||
|
||||
@Test fun `A message should be sent saying the player has eaten an item when consuming food`() {
|
||||
player.notify(ItemOptionMessage(1, -1, TEST_FOOD_ID, 1))
|
||||
player.waitForActionCompletion()
|
||||
|
||||
verify(player).sendMessage(matches {
|
||||
assertThat(this).contains("You eat the ${TEST_FOOD_NAME}")
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user