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

Port Herblore plugin to Kotlin #396

Merged
merged 1 commit into from Apr 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions game/plugin/skills/herblore/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugin {
name = "herblore_skill"
authors = [
"Chivvon",
"Chris Fletcher",
"Major"
]

dependencies = ["api"]
}
39 changes: 39 additions & 0 deletions game/plugin/skills/herblore/src/CrushIngredientAction.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import org.apollo.game.action.ActionBlock
import org.apollo.game.action.AsyncAction
import org.apollo.game.model.Animation
import org.apollo.game.model.entity.Player
import java.util.Objects

class CrushIngredientAction(
player: Player,
private val ingredient: CrushableIngredient
) : AsyncAction<Player>(0, true, player) {

override fun action(): ActionBlock = {
mob.playAnimation(GRINDING_ANIM)
wait(pulses = 1)

val inventory = mob.inventory
if (inventory.remove(ingredient.uncrushed)) {
inventory.add(ingredient.id)

mob.sendMessage("You carefully grind the ${ingredient.uncrushedName} to dust.")
}

stop()
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as CrushIngredientAction
return mob == other.mob && ingredient == other.ingredient
}

override fun hashCode(): Int = Objects.hash(mob, ingredient)

private companion object {
private val GRINDING_ANIM = Animation(364)
}
}
34 changes: 34 additions & 0 deletions game/plugin/skills/herblore/src/Herb.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import org.apollo.game.plugin.api.Definitions

enum class Herb(
val identified: Int,
val unidentified: Int,
val level: Int,
val experience: Double
) {
GUAM_LEAF(identified = 249, unidentified = 199, level = 1, experience = 2.5),
MARRENTILL(identified = 251, unidentified = 201, level = 5, experience = 3.8),
TARROMIN(identified = 253, unidentified = 203, level = 11, experience = 5.0),
HARRALANDER(identified = 255, unidentified = 205, level = 20, experience = 6.3),
RANARR(identified = 257, unidentified = 207, level = 25, experience = 7.5),
TOADFLAX(identified = 2998, unidentified = 2998, level = 30, experience = 8.0),
IRIT_LEAF(identified = 259, unidentified = 209, level = 40, experience = 8.8),
AVANTOE(identified = 261, unidentified = 211, level = 48, experience = 10.0),
KWUARM(identified = 263, unidentified = 213, level = 54, experience = 11.3),
SNAPDRAGON(identified = 3000, unidentified = 3051, level = 59, experience = 11.8),
CADANTINE(identified = 265, unidentified = 215, level = 65, experience = 12.5),
LANTADYME(identified = 2481, unidentified = 2485, level = 67, experience = 13.1),
DWARF_WEED(identified = 267, unidentified = 217, level = 70, experience = 13.8),
TORSTOL(identified = 269, unidentified = 219, level = 75, experience = 15.0);

val identifiedName: String = Definitions.item(identified)!!.name

companion object {
private val identified = Herb.values().map(Herb::identified).toHashSet()
private val herbs = Herb.values().associateBy(Herb::unidentified)

operator fun get(id: Int): Herb? = herbs[id]
internal fun Int.isUnidentified(): Boolean = this in herbs
internal fun Int.isIdentified(): Boolean = this in identified
}
}
49 changes: 49 additions & 0 deletions game/plugin/skills/herblore/src/IdentifyHerbAction.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

import org.apollo.game.action.ActionBlock
import org.apollo.game.action.AsyncAction
import org.apollo.game.model.entity.Player
import org.apollo.game.plugin.api.herblore
import org.apollo.util.LanguageUtil
import java.util.Objects

class IdentifyHerbAction(
player: Player,
private val slot: Int,
private val herb: Herb
) : AsyncAction<Player>(0, true, player) {

override fun action(): ActionBlock = {
if (mob.herblore.current < herb.level) {
mob.sendMessage("You need a Herblore level of ${herb.level} to clean this herb.")
stop()
}

val inventory = mob.inventory

if (inventory.removeSlot(slot, 1) > 0) {
inventory.add(herb.identified)
mob.herblore.experience += herb.experience

val name = herb.identifiedName
val article = LanguageUtil.getIndefiniteArticle(name)

mob.sendMessage("You identify the herb as $article $name.")
}

stop()
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as IdentifyHerbAction
return mob == other.mob && herb == other.herb && slot == other.slot
}

override fun hashCode(): Int = Objects.hash(mob, herb, slot)

companion object {
const val IDENTIFY_OPTION = 1
}
}
60 changes: 60 additions & 0 deletions game/plugin/skills/herblore/src/Ingredient.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import CrushableIngredient.Companion.isCrushable
import NormalIngredient.Companion.isNormalIngredient
import org.apollo.game.plugin.api.Definitions

/**
* A secondary ingredient in a potion.
*/
interface Ingredient {
val id: Int

companion object {
internal fun Int.isIngredient(): Boolean = isNormalIngredient() || isCrushable()
}
}

enum class CrushableIngredient(val uncrushed: Int, override val id: Int) : Ingredient {
UNICORN_HORN(uncrushed = 237, id = 235),
DRAGON_SCALE(uncrushed = 243, id = 241),
CHOCOLATE_BAR(uncrushed = 1973, id = 1975),
BIRDS_NEST(uncrushed = 5075, id = 6693);

val uncrushedName: String = Definitions.item(uncrushed)!!.name

companion object {
private const val PESTLE_AND_MORTAR = 233
private const val KNIFE = 5605

private val ingredients = CrushableIngredient.values().associateBy(CrushableIngredient::uncrushed)
operator fun get(id: Int): CrushableIngredient? = ingredients[id]

internal fun Int.isCrushable(): Boolean = this in ingredients
internal fun Int.isGrindingTool(): Boolean = this == KNIFE || this == PESTLE_AND_MORTAR
}
}

enum class NormalIngredient(override val id: Int) : Ingredient {
EYE_NEWT(id = 221),
RED_SPIDERS_EGGS(id = 223),
LIMPWURT_ROOT(id = 225),
SNAPE_GRASS(id = 231),
WHITE_BERRIES(id = 239),
WINE_ZAMORAK(id = 245),
JANGERBERRIES(id = 247),
TOADS_LEGS(id = 2152),
MORT_MYRE_FUNGI(id = 2970),
POTATO_CACTUS(id = 3138),
PHOENIX_FEATHER(id = 4621),
FROG_SPAWN(id = 5004),
PAPAYA_FRUIT(id = 5972),
POISON_IVY_BERRIES(id = 6018),
YEW_ROOTS(id = 6049),
MAGIC_ROOTS(id = 6051);

companion object {
private val ingredients = NormalIngredient.values().associateBy(NormalIngredient::id)
operator fun get(id: Int): NormalIngredient? = ingredients[id]

internal fun Int.isNormalIngredient(): Boolean = this in ingredients
}
}
50 changes: 50 additions & 0 deletions game/plugin/skills/herblore/src/MakeFinishedPotionAction.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import org.apollo.game.action.ActionBlock
import org.apollo.game.action.AsyncAction
import org.apollo.game.model.Animation
import org.apollo.game.model.entity.Player
import org.apollo.game.plugin.api.herblore
import java.util.Objects

class MakeFinishedPotionAction(
player: Player,
private val potion: FinishedPotion
) : AsyncAction<Player>(1, true, player) {

override fun action(): ActionBlock = {
val level = mob.herblore.current

if (level < potion.level) {
mob.sendMessage("You need a Herblore level of ${potion.level} to make this.")
stop()
}

val unfinished = potion.unfinished.id
val inventory = mob.inventory

if (inventory.contains(unfinished) && inventory.contains(potion.ingredient)) {
inventory.remove(unfinished)
inventory.remove(potion.ingredient)

mob.playAnimation(MIXING_ANIMATION)

inventory.add(potion.id)
mob.herblore.experience += potion.experience

mob.sendMessage("You mix the ${potion.ingredientName} into your potion.")
}
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as MakeFinishedPotionAction
return mob == other.mob && potion == other.potion
}

override fun hashCode(): Int = Objects.hash(mob, potion)

private companion object {
private val MIXING_ANIMATION = Animation(363)
}
}
47 changes: 47 additions & 0 deletions game/plugin/skills/herblore/src/MakeUnfinishedPotionAction.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import org.apollo.game.action.ActionBlock
import org.apollo.game.action.AsyncAction
import org.apollo.game.model.Animation
import org.apollo.game.model.entity.Player
import org.apollo.game.plugin.api.herblore
import java.util.Objects

class MakeUnfinishedPotionAction(
player: Player,
private val potion: UnfinishedPotion
) : AsyncAction<Player>(1, true, player) {

override fun action(): ActionBlock = {
val level = mob.herblore.current

if (level < potion.level) {
mob.sendMessage("You need a Herblore level of ${potion.level} to make this.")
stop()
}

val inventory = mob.inventory

if (inventory.contains(VIAL_OF_WATER) && inventory.contains(potion.herb)) {
inventory.remove(VIAL_OF_WATER)
inventory.remove(potion.herb)

mob.playAnimation(MIXING_ANIMATION)

inventory.add(potion.id)
mob.sendMessage("You put the ${potion.herbName} into the vial of water.")
}
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as MakeUnfinishedPotionAction
return mob == other.mob && potion == other.potion
}

override fun hashCode(): Int = Objects.hash(mob, potion)

private companion object {
private val MIXING_ANIMATION = Animation(363)
}
}
73 changes: 73 additions & 0 deletions game/plugin/skills/herblore/src/Potion.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import CrushableIngredient.CHOCOLATE_BAR
import CrushableIngredient.DRAGON_SCALE
import CrushableIngredient.UNICORN_HORN
import NormalIngredient.*
import UnfinishedPotion.*
import org.apollo.game.plugin.api.Definitions

const val VIAL_OF_WATER = 227

enum class UnfinishedPotion(val id: Int, herb: Herb, val level: Int) {
GUAM(id = 91, herb = Herb.GUAM_LEAF, level = 1),
MARRENTILL(id = 93, herb = Herb.MARRENTILL, level = 5),
TARROMIN(id = 95, herb = Herb.TARROMIN, level = 12),
HARRALANDER(id = 97, herb = Herb.HARRALANDER, level = 22),
RANARR(id = 99, herb = Herb.RANARR, level = 30),
TOADFLAX(id = 3002, herb = Herb.TOADFLAX, level = 34),
IRIT(id = 101, herb = Herb.IRIT_LEAF, level = 45),
AVANTOE(id = 103, herb = Herb.AVANTOE, level = 50),
KWUARM(id = 105, herb = Herb.KWUARM, level = 55),
SNAPDRAGON(id = 3004, herb = Herb.SNAPDRAGON, level = 63),
CADANTINE(id = 107, herb = Herb.CADANTINE, level = 66),
LANTADYME(id = 2483, herb = Herb.LANTADYME, level = 69),
DWARF_WEED(id = 109, herb = Herb.DWARF_WEED, level = 72),
TORSTOL(id = 111, herb = Herb.TORSTOL, level = 78);

val herb = herb.identified
val herbName: String = Definitions.item(herb.identified)!!.name

companion object {
private val ids = values().map(UnfinishedPotion::id).toHashSet()
private val potions = values().associateBy(UnfinishedPotion::herb)

operator fun get(id: Int) = potions[id]
internal fun Int.isUnfinished(): Boolean = this in ids
}
}

enum class FinishedPotion(
val id: Int,
val unfinished: UnfinishedPotion,
ingredient: Ingredient,
val level: Int,
val experience: Double
) {
ATTACK(id = 121, unfinished = GUAM, ingredient = EYE_NEWT, level = 1, experience = 25.0),
ANTIPOISON(id = 175, unfinished = MARRENTILL, ingredient = UNICORN_HORN, level = 5, experience = 37.5),
STRENGTH(id = 115, unfinished = TARROMIN, ingredient = LIMPWURT_ROOT, level = 12, experience = 50.0),
RESTORE(id = 127, unfinished = HARRALANDER, ingredient = RED_SPIDERS_EGGS, level = 18, experience = 62.5),
ENERGY(id = 3010, unfinished = HARRALANDER, ingredient = CHOCOLATE_BAR, level = 26, experience = 67.5),
DEFENCE(id = 133, unfinished = RANARR, ingredient = WHITE_BERRIES, level = 30, experience = 75.0),
AGILITY(id = 3034, unfinished = TOADFLAX, ingredient = TOADS_LEGS, level = 34, experience = 80.0),
PRAYER(id = 139, unfinished = RANARR, ingredient = SNAPE_GRASS, level = 38, experience = 87.5),
SUPER_ATTACK(id = 145, unfinished = IRIT, ingredient = EYE_NEWT, level = 45, experience = 100.0),
SUPER_ANTIPOISON(id = 181, unfinished = IRIT, ingredient = UNICORN_HORN, level = 48, experience = 106.3),
FISHING(id = 151, unfinished = AVANTOE, ingredient = SNAPE_GRASS, level = 50, experience = 112.5),
SUPER_ENERGY(id = 3018, unfinished = AVANTOE, ingredient = MORT_MYRE_FUNGI, level = 52, experience = 117.5),
SUPER_STRENGTH(id = 157, unfinished = KWUARM, ingredient = LIMPWURT_ROOT, level = 55, experience = 125.0),
WEAPON_POISON(id = 187, unfinished = KWUARM, ingredient = DRAGON_SCALE, level = 60, experience = 137.5),
SUPER_RESTORE(id = 3026, unfinished = SNAPDRAGON, ingredient = RED_SPIDERS_EGGS, level = 63, experience = 142.5),
SUPER_DEFENCE(id = 163, unfinished = CADANTINE, ingredient = WHITE_BERRIES, level = 66, experience = 150.0),
ANTIFIRE(id = 2428, unfinished = LANTADYME, ingredient = DRAGON_SCALE, level = 69, experience = 157.5),
RANGING(id = 169, unfinished = DWARF_WEED, ingredient = WINE_ZAMORAK, level = 72, experience = 162.5),
MAGIC(id = 3042, unfinished = LANTADYME, ingredient = POTATO_CACTUS, level = 76, experience = 172.5),
ZAMORAK_BREW(id = 189, unfinished = TORSTOL, ingredient = JANGERBERRIES, level = 78, experience = 175.0);

val ingredientName = Definitions.item(ingredient.id)!!.name.toLowerCase()
val ingredient = ingredient.id

companion object {
private val potions = FinishedPotion.values().associateBy { Pair(it.unfinished.id, it.ingredient) }
operator fun get(key: Pair<Int, Int>) = potions[key]
}
}
Loading