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.
*
@@ -3,7 +3,6 @@ package rs09.game.node.entity.skill.gather.mining
import api.*
import api.events.ResourceProducedEvent
import core.cache.def.impl.ItemDefinition
import core.game.container.impl.EquipmentContainer
import core.game.content.dialogue.FacialExpression
import core.game.content.global.SkillingPets
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.mining.MiningNode
import core.game.node.item.ChanceItem
import core.game.node.item.Item
import core.game.node.scenery.Scenery
import core.game.node.scenery.SceneryBuilder
import core.game.system.task.Pulse
import core.game.world.map.Location
import core.game.world.update.flag.context.Animation
import core.tools.RandomFunction
import core.tools.StringUtils
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_ROCKS
import rs09.game.node.entity.skill.skillcapeperks.SkillcapePerks
import rs09.tools.stringtools.*
/**
* 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) {
private var resource: MiningNode? = null
private var isMiningEssence = false
private var isMiningGems = false
private var ticks = 0
protected var resetAnimation = true
private var resetAnimation = true
// Perfect Gold Ore in Witchhaven Dungeon (Family Crest)
private val perfectGoldOreLocations = listOf(
@@ -49,7 +49,7 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
fun message(type: Int) {
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() {
if (resetAnimation) {
player.animate(Animation(-1, Animator.Priority.HIGH))
animate(player, Animation(-1, Animator.Priority.HIGH))
}
super.stop()
message(1)
@@ -72,15 +72,14 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
override fun start() {
resource = MiningNode.forId(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) {
return
}
if (resource!!.id == 2099 &&
!perfectGoldOreLocations.contains(node.location) ) {
// Perfect Gold Ore Id's outside of Witchhaven
// are replaced with a normal gold rock.
// Perfect Gold Ore IDs outside Witchhaven are replaced with a normal gold rock.
resource = MiningNode.forId(2098)
}
if (resource!!.id == 2491) {
@@ -96,23 +95,27 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
}
fun checkRequirements(): Boolean {
if (player.skills.getLevel(Skills.MINING) < resource!!.getLevel()) {
player.packetDispatch.sendMessage("You need a mining level of " + resource!!.getLevel() + " to mine this rock.")
if (getDynLevel(player, Skills.MINING) < resource!!.level) {
sendMessage(player, "You need a mining level of ${resource!!.level} to mine this rock.")
return false
}
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
}
if (player.inventory.freeSlots() < 1) {
player.dialogueInterpreter.sendDialogue("Your inventory is too full to hold any more " + ItemDefinition.forId(resource!!.getReward()).name.toLowerCase() + ".")
if (freeSlots(player) == 0) {
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 true
}
fun animate() {
player.animate(SkillingTool.getPickaxe(player).animation)
animate(player, SkillingTool.getPickaxe(player).animation)
}
fun reward(): Boolean {
@@ -120,16 +123,16 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
return false
}
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
}
if (!checkReward()) {
return false
}
//actual reward calculations
var reward = resource!!.getReward()
var rewardAmount = 0
// Reward logic
var reward = resource!!.reward
var rewardAmount : Int
if (reward > 0) {
reward = calculateReward(reward) // calculate rewards
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))
SkillingPets.checkPetDrop(player, SkillingPets.GOLEM) // roll for pet
//add experience
val experience = resource!!.getExperience() * rewardAmount
player.skills.addExperience(Skills.MINING, experience, true)
// Reward mining experience
val experience = resource!!.experience * rewardAmount
rewardXP(player, Skills.MINING, experience)
//Handle bracelet of clay
// If player is wearing Bracelet of Clay, soften
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.charge > 28) bracelet.charge = 28
bracelet.charge--
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){
player.sendMessage("Your bracelet of clay crumbles to dust.")
player.equipment.remove(bracelet)
if(removeItem(player, 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) {
val gemName = ItemDefinition.forId(reward).name.toLowerCase()
player.sendMessage("You get " + (if (StringUtils.isPlusN(gemName)) "an" else "a") + " " + gemName + ".")
sendMessage(player, "You get ${prependArticle(rewardName)}.")
} 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) {
var chance = 282
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()
altered = true
}
val necklace = player.equipment[EquipmentContainer.SLOT_AMULET]
val necklace = getItemFromEquipment(player, EquipmentSlot.AMULET)
if (necklace != null && necklace.id in 1705..1713) {
chance = (chance / 1.5).toInt()
altered = true
}
if (RandomFunction.roll(chance)) {
val gem = GEM_REWARDS.random()
player.packetDispatch.sendMessage("You find a " + gem.name + "!")
if (!player.inventory.add(gem, player)) {
player.packetDispatch.sendMessage("You do not have enough space in your inventory, so you drop the gem on the floor.")
sendMessage(player,"You find a ${gem.name}!")
if (!addItem(player, gem.id)) {
sendMessage(player,"You do not have enough space in your inventory, so you drop the gem on the floor.")
}
}
}
//transform to depleted version
if (!isMiningEssence && resource!!.getRespawnRate() != 0) {
// Transform ore to depleted version
if (!isMiningEssence && resource!!.respawnRate != 0) {
SceneryBuilder.replace(node as Scenery, Scenery(resource!!.emptyId, node.getLocation(), node.type, node.rotation), resource!!.respawnDuration)
node.setActive(false)
return true
@@ -203,28 +210,28 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
private fun calculateRewardAmount(reward: Int): Int {
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) {
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) {
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) {
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) {
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 (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
}
}
@@ -237,8 +244,8 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul
if (resource == MiningNode.SANDSTONE || resource == MiningNode.GRANITE) {
val value = RandomFunction.randomize(if (resource == MiningNode.GRANITE) 3 else 4)
reward += value shl 1
player.skills.addExperience(Skills.MINING, value * 10.toDouble(), true)
} else if (isMiningEssence && player.skills.getLevel(Skills.MINING) >= 30) {
rewardXP(player, Skills.MINING, value * 10.toDouble())
} else if (isMiningEssence && getDynLevel(player, Skills.MINING) >= 30) {
reward = 7936
} else if (isMiningGems) {
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.
*/
private fun checkReward(): Boolean {
val skill = Skills.MINING
val level = 1 + player.skills.getLevel(skill) + player.familiarManager.getBoost(skill)
val hostRatio = Math.random() * (100.0 * resource!!.getRate())
val level = 1 + getDynLevel(player, Skills.MINING) + getFamiliarBoost(player, Skills.MINING)
val hostRatio = Math.random() * (100.0 * resource!!.rate)
var toolRatio = SkillingTool.getPickaxe(player).ratio
if(SkillcapePerks.isActive(SkillcapePerks.PRECISION_MINER,player)){
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
}
@@ -1,8 +1,8 @@
package rs09.game.node.entity.skill.gather.mining
import api.*
import core.game.node.entity.skill.gather.SkillingResource
import core.game.node.entity.skill.gather.mining.MiningNode
import core.game.node.item.Item
import core.game.system.task.Pulse
import rs09.game.interaction.InteractionListener
@@ -14,11 +14,13 @@ class ProspectListener : InteractionListener {
override fun defineListeners() {
on(SCENERY, "prospect") { player, node ->
val rock = SkillingResource.forId(node.id)
val rock = MiningNode.forId(node.asScenery().id)
if(rock == null) {
sendMessage(player, "There is no ore currently available in this rock.")
return@on true
}
/** Check if the rock contains gems */
if(MiningNode.forId(node.id).identifier == 13.toByte()) {
sendMessage(player,"You examine the rock for ores...")
@@ -29,14 +31,16 @@ class ProspectListener : InteractionListener {
return true
}
})
return@on true
}
/** If it doesn't contain gems */
else {
sendMessage(player,"You examine the rock for ores...")
/** Get the name of the rock's reward and sends a message to the player */
player.pulseManager.run(object : Pulse(3) {
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
}
})
@@ -44,4 +48,4 @@ class ProspectListener : InteractionListener {
return@on true
}
}
}
}
@@ -39,3 +39,22 @@ fun String.shuffle(): String{
}
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"
}
}