Refactored mining

Converted to content API
Corrected the prospecting text of gem rocks
Corrected the full-inventory text when mining gem rocks
This commit is contained in:
bushtail
2022-07-07 12:59:10 +00:00
committed by Ryan
parent 2f38f3dce0
commit 5e86ea2d04
4 changed files with 102 additions and 60 deletions
+13
View File
@@ -1513,6 +1513,19 @@ fun dumpBeastOfBurden(player: Player) {
} }
} }
/**
* Gets the player's familiar boost in the given skill
*
* @param player The player who owns the familiar.
* @param skill The skill to check boost of.
* @return The amount of skill boost gained from the player's familiar.
*
* @author bushtail
*/
fun getFamiliarBoost(player : Player, skill : Int) : Int {
return player.familiarManager.getBoost(skill)
}
/** /**
* Converts an item into its noted representation. * Converts an item into its noted representation.
* *
@@ -3,7 +3,6 @@ package rs09.game.node.entity.skill.gather.mining
import api.* import api.*
import api.events.ResourceProducedEvent import api.events.ResourceProducedEvent
import core.cache.def.impl.ItemDefinition import core.cache.def.impl.ItemDefinition
import core.game.container.impl.EquipmentContainer
import core.game.content.dialogue.FacialExpression import core.game.content.dialogue.FacialExpression
import core.game.content.global.SkillingPets import core.game.content.global.SkillingPets
import core.game.node.Node import core.game.node.Node
@@ -15,29 +14,30 @@ import core.game.node.entity.skill.Skills
import core.game.node.entity.skill.gather.SkillingTool import core.game.node.entity.skill.gather.SkillingTool
import core.game.node.entity.skill.gather.mining.MiningNode import core.game.node.entity.skill.gather.mining.MiningNode
import core.game.node.item.ChanceItem import core.game.node.item.ChanceItem
import core.game.node.item.Item
import core.game.node.scenery.Scenery import core.game.node.scenery.Scenery
import core.game.node.scenery.SceneryBuilder import core.game.node.scenery.SceneryBuilder
import core.game.system.task.Pulse import core.game.system.task.Pulse
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.update.flag.context.Animation import core.game.world.update.flag.context.Animation
import core.tools.RandomFunction import core.tools.RandomFunction
import core.tools.StringUtils
import org.rs09.consts.Items import org.rs09.consts.Items
import org.rs09.consts.NPCs
import rs09.game.node.entity.player.info.stats.STATS_BASE import rs09.game.node.entity.player.info.stats.STATS_BASE
import rs09.game.node.entity.player.info.stats.STATS_ROCKS import rs09.game.node.entity.player.info.stats.STATS_ROCKS
import rs09.game.node.entity.skill.skillcapeperks.SkillcapePerks import rs09.game.node.entity.skill.skillcapeperks.SkillcapePerks
import rs09.tools.stringtools.*
/** /**
* Mining skill pulse * Mining skill pulse
* @author ceik * @author Ceikry
* @author bushtail -> maintenance July 2022
*/ */
class MiningSkillPulse(private val player: Player, private val node: Node) : Pulse(1, player, node) { class MiningSkillPulse(private val player: Player, private val node: Node) : Pulse(1, player, node) {
private var resource: MiningNode? = null private var resource: MiningNode? = null
private var isMiningEssence = false private var isMiningEssence = false
private var isMiningGems = false private var isMiningGems = false
private var ticks = 0 private var ticks = 0
protected var resetAnimation = true private var resetAnimation = true
// Perfect Gold Ore in Witchhaven Dungeon (Family Crest) // Perfect Gold Ore in Witchhaven Dungeon (Family Crest)
private val perfectGoldOreLocations = listOf( private val perfectGoldOreLocations = listOf(
@@ -49,7 +49,7 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
fun message(type: Int) { fun message(type: Int) {
if (type == 0) { if (type == 0) {
player.packetDispatch.sendMessage("You swing your pickaxe at the rock...") sendMessage(player, "You swing your pickaxe at the rock...")
} }
} }
@@ -63,7 +63,7 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
override fun stop() { override fun stop() {
if (resetAnimation) { if (resetAnimation) {
player.animate(Animation(-1, Animator.Priority.HIGH)) animate(player, Animation(-1, Animator.Priority.HIGH))
} }
super.stop() super.stop()
message(1) message(1)
@@ -72,15 +72,14 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
override fun start() { override fun start() {
resource = MiningNode.forId(node.id) resource = MiningNode.forId(node.id)
if (MiningNode.isEmpty(node.id)) { if (MiningNode.isEmpty(node.id)) {
player.packetDispatch.sendMessage("This rock contains no ore.") sendMessage(player, "This rock contains no ore.")
} }
if (resource == null) { if (resource == null) {
return return
} }
if (resource!!.id == 2099 && if (resource!!.id == 2099 &&
!perfectGoldOreLocations.contains(node.location) ) { !perfectGoldOreLocations.contains(node.location) ) {
// Perfect Gold Ore Id's outside of Witchhaven // Perfect Gold Ore IDs outside Witchhaven are replaced with a normal gold rock.
// are replaced with a normal gold rock.
resource = MiningNode.forId(2098) resource = MiningNode.forId(2098)
} }
if (resource!!.id == 2491) { if (resource!!.id == 2491) {
@@ -96,23 +95,27 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
} }
fun checkRequirements(): Boolean { fun checkRequirements(): Boolean {
if (player.skills.getLevel(Skills.MINING) < resource!!.getLevel()) { if (getDynLevel(player, Skills.MINING) < resource!!.level) {
player.packetDispatch.sendMessage("You need a mining level of " + resource!!.getLevel() + " to mine this rock.") sendMessage(player, "You need a mining level of ${resource!!.level} to mine this rock.")
return false return false
} }
if (SkillingTool.getPickaxe(player) == null) { if (SkillingTool.getPickaxe(player) == null) {
player.packetDispatch.sendMessage("You do not have a pickaxe to use.") sendMessage(player, "You do not have a pickaxe to use.")
return false return false
} }
if (player.inventory.freeSlots() < 1) { if (freeSlots(player) == 0) {
player.dialogueInterpreter.sendDialogue("Your inventory is too full to hold any more " + ItemDefinition.forId(resource!!.getReward()).name.toLowerCase() + ".") if(resource!!.identifier == 13.toByte()) {
sendDialogue(player,"Your inventory is too full to hold any more gems.")
return false
}
sendDialogue(player,"Your inventory is too full to hold any more ${ItemDefinition.forId(resource!!.reward).name.lowercase()}.")
return false return false
} }
return true return true
} }
fun animate() { fun animate() {
player.animate(SkillingTool.getPickaxe(player).animation) animate(player, SkillingTool.getPickaxe(player).animation)
} }
fun reward(): Boolean { fun reward(): Boolean {
@@ -120,16 +123,16 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
return false return false
} }
if (node.id == 10041) { if (node.id == 10041) {
player.dialogueInterpreter.sendDialogues(2574, FacialExpression.FURIOUS, if (RandomFunction.random(2) == 1) "You'll blow my cover! I'm meant to be hidden!" else "Will you stop that?") sendNPCDialogue(player, NPCs.BANK_GUARD_2574,if (RandomFunction.random(2) == 1) "You'll blow my cover! I'm meant to be hidden!" else "Will you stop that?", FacialExpression.FURIOUS)
return true return true
} }
if (!checkReward()) { if (!checkReward()) {
return false return false
} }
//actual reward calculations // Reward logic
var reward = resource!!.getReward() var reward = resource!!.reward
var rewardAmount = 0 var rewardAmount : Int
if (reward > 0) { if (reward > 0) {
reward = calculateReward(reward) // calculate rewards reward = calculateReward(reward) // calculate rewards
rewardAmount = calculateRewardAmount(reward) // calculate amount rewardAmount = calculateRewardAmount(reward) // calculate amount
@@ -137,61 +140,65 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
player.dispatch(ResourceProducedEvent(reward, rewardAmount, node)) player.dispatch(ResourceProducedEvent(reward, rewardAmount, node))
SkillingPets.checkPetDrop(player, SkillingPets.GOLEM) // roll for pet SkillingPets.checkPetDrop(player, SkillingPets.GOLEM) // roll for pet
//add experience // Reward mining experience
val experience = resource!!.getExperience() * rewardAmount val experience = resource!!.experience * rewardAmount
player.skills.addExperience(Skills.MINING, experience, true) rewardXP(player, Skills.MINING, experience)
//Handle bracelet of clay // If player is wearing Bracelet of Clay, soften
if(reward == Items.CLAY_434){ if(reward == Items.CLAY_434){
val bracelet = player.equipment.get(EquipmentContainer.SLOT_HANDS) val bracelet = getItemFromEquipment(player, EquipmentSlot.HANDS)
if(bracelet != null && bracelet.id == Items.BRACELET_OF_CLAY_11074){ if(bracelet != null && bracelet.id == Items.BRACELET_OF_CLAY_11074){
if(bracelet.charge > 28) bracelet.charge = 28 if(bracelet.charge > 28) bracelet.charge = 28
bracelet.charge-- bracelet.charge--
reward = Items.SOFT_CLAY_1761 reward = Items.SOFT_CLAY_1761
player.sendMessage("Your bracelet of clay softens the clay for you.") sendMessage(player, "Your bracelet of clay softens the clay for you.")
if(bracelet.charge <= 0){ if(bracelet.charge <= 0){
player.sendMessage("Your bracelet of clay crumbles to dust.") if(removeItem(player, bracelet)) {
player.equipment.remove(bracelet) sendMessage(player, "Your bracelet of clay crumbles to dust.")
}
} }
} }
} }
val rewardName = getItemName(reward).lowercase()
//send the message for the resource reward // Send the message for the resource reward
if (isMiningGems) { if (isMiningGems) {
val gemName = ItemDefinition.forId(reward).name.toLowerCase() sendMessage(player, "You get ${prependArticle(rewardName)}.")
player.sendMessage("You get " + (if (StringUtils.isPlusN(gemName)) "an" else "a") + " " + gemName + ".")
} else { } else {
player.packetDispatch.sendMessage("You get some " + ItemDefinition.forId(reward).name.toLowerCase() + ".") sendMessage(player, "You get some ${rewardName.lowercase()}.")
} }
//give the reward
player.inventory.add(Item(reward, rewardAmount))
var rocksMined = player.getAttribute("$STATS_BASE:$STATS_ROCKS",0)
player.setAttribute("/save:$STATS_BASE:$STATS_ROCKS",++rocksMined)
//calculate bonus gem for mining // Give the mining reward, increment 'rocks mined' attribute
if(addItem(player, reward, rewardAmount)) {
var rocksMined = getAttribute(player, "$STATS_BASE:$STATS_ROCKS", 0)
setAttribute(player, "/save:$STATS_BASE:$STATS_ROCKS", ++rocksMined)
}
// Calculate bonus gem chance while mining
if (!isMiningEssence) { if (!isMiningEssence) {
var chance = 282 var chance = 282
var altered = false var altered = false
if (Item(player.equipment.getId(12)).name.toLowerCase().contains("ring of wealth") || inEquipment(player, Items.RING_OF_THE_STAR_SPRITE_14652)) { val ring = getItemFromEquipment(player, EquipmentSlot.RING)
if (ring != null && ring.name.lowercase().contains("ring of wealth") || inEquipment(player, Items.RING_OF_THE_STAR_SPRITE_14652)) {
chance = (chance / 1.5).toInt() chance = (chance / 1.5).toInt()
altered = true altered = true
} }
val necklace = player.equipment[EquipmentContainer.SLOT_AMULET] val necklace = getItemFromEquipment(player, EquipmentSlot.AMULET)
if (necklace != null && necklace.id in 1705..1713) { if (necklace != null && necklace.id in 1705..1713) {
chance = (chance / 1.5).toInt() chance = (chance / 1.5).toInt()
altered = true altered = true
} }
if (RandomFunction.roll(chance)) { if (RandomFunction.roll(chance)) {
val gem = GEM_REWARDS.random() val gem = GEM_REWARDS.random()
player.packetDispatch.sendMessage("You find a " + gem.name + "!") sendMessage(player,"You find a ${gem.name}!")
if (!player.inventory.add(gem, player)) { if (!addItem(player, gem.id)) {
player.packetDispatch.sendMessage("You do not have enough space in your inventory, so you drop the gem on the floor.") sendMessage(player,"You do not have enough space in your inventory, so you drop the gem on the floor.")
} }
} }
} }
//transform to depleted version // Transform ore to depleted version
if (!isMiningEssence && resource!!.getRespawnRate() != 0) { if (!isMiningEssence && resource!!.respawnRate != 0) {
SceneryBuilder.replace(node as Scenery, Scenery(resource!!.emptyId, node.getLocation(), node.type, node.rotation), resource!!.respawnDuration) SceneryBuilder.replace(node as Scenery, Scenery(resource!!.emptyId, node.getLocation(), node.type, node.rotation), resource!!.respawnDuration)
node.setActive(false) node.setActive(false)
return true return true
@@ -203,28 +210,28 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
private fun calculateRewardAmount(reward: Int): Int { private fun calculateRewardAmount(reward: Int): Int {
var amount = 1 var amount = 1
//checks for varrock armor from varrock diary and rolls chance at extra ore // If player is wearing Varrock armour from diary, roll chance at extra ore
if (!isMiningEssence && player.achievementDiaryManager.getDiary(DiaryType.VARROCK).level != -1) { if (!isMiningEssence && player.achievementDiaryManager.getDiary(DiaryType.VARROCK).level != -1) {
when (reward) { when (reward) {
Items.CLAY_434, Items.COPPER_ORE_436, Items.TIN_ORE_438, Items.LIMESTONE_3211, Items.BLURITE_ORE_668, Items.IRON_ORE_440, Items.ELEMENTAL_ORE_2892, Items.SILVER_ORE_442, Items.COAL_453 -> if (player.achievementDiaryManager.armour >= 0 && RandomFunction.random(100) <= 10) { Items.CLAY_434, Items.COPPER_ORE_436, Items.TIN_ORE_438, Items.LIMESTONE_3211, Items.BLURITE_ORE_668, Items.IRON_ORE_440, Items.ELEMENTAL_ORE_2892, Items.SILVER_ORE_442, Items.COAL_453 -> if (player.achievementDiaryManager.armour >= 0 && RandomFunction.random(100) <= 10) {
amount += 1 amount += 1
player.sendMessage("The Varrock armour allows you to mine an additional ore.") sendMessage(player,"The Varrock armour allows you to mine an additional ore.")
} }
Items.GOLD_ORE_444, Items.GRANITE_500G_6979, Items.GRANITE_2KG_6981, Items.GRANITE_5KG_6983, Items.MITHRIL_ORE_447 -> if (player.achievementDiaryManager.armour >= 1 && RandomFunction.random(100) <= 10) { Items.GOLD_ORE_444, Items.GRANITE_500G_6979, Items.GRANITE_2KG_6981, Items.GRANITE_5KG_6983, Items.MITHRIL_ORE_447 -> if (player.achievementDiaryManager.armour >= 1 && RandomFunction.random(100) <= 10) {
amount += 1 amount += 1
player.sendMessage("The Varrock armour allows you to mine an additional ore.") sendMessage(player, "The Varrock armour allows you to mine an additional ore.")
} }
Items.ADAMANTITE_ORE_449 -> if (player.achievementDiaryManager.armour >= 2 && RandomFunction.random(100) <= 10) { Items.ADAMANTITE_ORE_449 -> if (player.achievementDiaryManager.armour >= 2 && RandomFunction.random(100) <= 10) {
amount += 1 amount += 1
player.sendMessage("The Varrock armour allows you to mine an additional ore.") sendMessage(player, "The Varrock armour allows you to mine an additional ore.")
} }
} }
} }
//check for bonus ore from shooting star buff // If player has mining boost from Shooting Star, roll chance at extra ore
if (player.hasActiveState("shooting-star")) { if (player.hasActiveState("shooting-star")) {
if (RandomFunction.getRandom(5) == 3) { if (RandomFunction.getRandom(5) == 3) {
player.packetDispatch.sendMessage("...you manage to mine a second ore thanks to the Star Sprite.") sendMessage(player, "...you manage to mine a second ore thanks to the Star Sprite.")
amount += 1 amount += 1
} }
} }
@@ -237,8 +244,8 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
if (resource == MiningNode.SANDSTONE || resource == MiningNode.GRANITE) { if (resource == MiningNode.SANDSTONE || resource == MiningNode.GRANITE) {
val value = RandomFunction.randomize(if (resource == MiningNode.GRANITE) 3 else 4) val value = RandomFunction.randomize(if (resource == MiningNode.GRANITE) 3 else 4)
reward += value shl 1 reward += value shl 1
player.skills.addExperience(Skills.MINING, value * 10.toDouble(), true) rewardXP(player, Skills.MINING, value * 10.toDouble())
} else if (isMiningEssence && player.skills.getLevel(Skills.MINING) >= 30) { } else if (isMiningEssence && getDynLevel(player, Skills.MINING) >= 30) {
reward = 7936 reward = 7936
} else if (isMiningGems) { } else if (isMiningGems) {
reward = RandomFunction.rollWeightedChanceTable(MiningNode.gemRockGems).id reward = RandomFunction.rollWeightedChanceTable(MiningNode.gemRockGems).id
@@ -251,14 +258,13 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
* @return `True` if so. * @return `True` if so.
*/ */
private fun checkReward(): Boolean { private fun checkReward(): Boolean {
val skill = Skills.MINING val level = 1 + getDynLevel(player, Skills.MINING) + getFamiliarBoost(player, Skills.MINING)
val level = 1 + player.skills.getLevel(skill) + player.familiarManager.getBoost(skill) val hostRatio = Math.random() * (100.0 * resource!!.rate)
val hostRatio = Math.random() * (100.0 * resource!!.getRate())
var toolRatio = SkillingTool.getPickaxe(player).ratio var toolRatio = SkillingTool.getPickaxe(player).ratio
if(SkillcapePerks.isActive(SkillcapePerks.PRECISION_MINER,player)){ if(SkillcapePerks.isActive(SkillcapePerks.PRECISION_MINER,player)){
toolRatio += 0.075 toolRatio += 0.075
} }
val clientRatio = Math.random() * ((level - resource!!.getLevel()) * (1.0 + toolRatio)) val clientRatio = Math.random() * ((level - resource!!.level) * (1.0 + toolRatio))
return hostRatio < clientRatio return hostRatio < clientRatio
} }
@@ -1,8 +1,8 @@
package rs09.game.node.entity.skill.gather.mining package rs09.game.node.entity.skill.gather.mining
import api.* import api.*
import core.game.node.entity.skill.gather.SkillingResource
import core.game.node.entity.skill.gather.mining.MiningNode import core.game.node.entity.skill.gather.mining.MiningNode
import core.game.node.item.Item
import core.game.system.task.Pulse import core.game.system.task.Pulse
import rs09.game.interaction.InteractionListener import rs09.game.interaction.InteractionListener
@@ -14,11 +14,13 @@ class ProspectListener : InteractionListener {
override fun defineListeners() { override fun defineListeners() {
on(SCENERY, "prospect") { player, node -> on(SCENERY, "prospect") { player, node ->
val rock = SkillingResource.forId(node.id) val rock = MiningNode.forId(node.asScenery().id)
if(rock == null) { if(rock == null) {
sendMessage(player, "There is no ore currently available in this rock.") sendMessage(player, "There is no ore currently available in this rock.")
return@on true return@on true
} }
/** Check if the rock contains gems */ /** Check if the rock contains gems */
if(MiningNode.forId(node.id).identifier == 13.toByte()) { if(MiningNode.forId(node.id).identifier == 13.toByte()) {
sendMessage(player,"You examine the rock for ores...") sendMessage(player,"You examine the rock for ores...")
@@ -29,14 +31,16 @@ class ProspectListener : InteractionListener {
return true return true
} }
}) })
return@on true
} }
/** If it doesn't contain gems */ /** If it doesn't contain gems */
else { else {
sendMessage(player,"You examine the rock for ores...") sendMessage(player,"You examine the rock for ores...")
/** Get the name of the rock's reward and sends a message to the player */ /** Get the name of the rock's reward and sends a message to the player */
player.pulseManager.run(object : Pulse(3) { player.pulseManager.run(object : Pulse(3) {
override fun pulse(): Boolean { override fun pulse(): Boolean {
sendMessage(player, "This rock contains ${itemDefinition(rock.reward).name.toLowerCase()}.") sendMessage(player, "This rock contains ${Item(rock.reward).name.lowercase()}.")
return true return true
} }
}) })
@@ -39,3 +39,22 @@ fun String.shuffle(): String{
} }
return new return new
} }
/**
* Prepends 'a' or 'an' to a noun depending on whether it starts with a vowel.
* @author bushtail
* @param noun the noun to check grammar rules against.
* @return either 'a $noun' or 'an $noun' depending on the first letter.
*/
fun prependArticle(noun : String) : String {
if(noun == null) return noun
val exceptions = hashMapOf("unicorn" to "a", "herb" to "an", "hour" to "an")
if(exceptions.contains(noun.lowercase())) {
return "${exceptions[noun.lowercase()]} $noun"
}
return when(noun[0]) {
'a', 'e', 'i', 'o', 'u' -> "an $noun"
else -> "a $noun"
}
}