Authenticity improvements to runecrafting pouches. Due to changes in degrade counters, they will degrade within the next 1 or 2 fills after this update; this is a one-time event. Resolve (or prevent) this by repairing via the dark mage

This commit is contained in:
Player Name 2024-11-14 11:56:16 +00:00 committed by Ryan
parent 1da53c448d
commit 7a6adda997
3 changed files with 107 additions and 96 deletions

View file

@ -1,5 +1,6 @@
package content.global.skill.runecrafting package content.global.skill.runecrafting
import core.api.*
import core.game.container.Container import core.game.container.Container
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills import core.game.node.entity.skill.Skills
@ -7,109 +8,131 @@ import core.game.node.item.Item
import org.json.simple.JSONArray import org.json.simple.JSONArray
import org.json.simple.JSONObject import org.json.simple.JSONObject
import org.rs09.consts.Items import org.rs09.consts.Items
import core.tools.colorize
/** /**
* A class for managing rune pouches. * A class for managing rune pouches.
* @param player the player this manager instance belongs to. * @param player the player this manager instance belongs to.
* @author Ceikry * @author Ceikry, Player Name
*/ */
class PouchManager(val player: Player) { class PouchManager(val player: Player) {
val pouches = mapOf( val pouches = mapOf(
Items.SMALL_POUCH_5509 to RCPouch(3,1), Items.SMALL_POUCH_5509 to RCPouch(3, 3, 1),
Items.MEDIUM_POUCH_5510 to RCPouch(6,25), Items.MEDIUM_POUCH_5510 to RCPouch(6, 264, 25),
Items.LARGE_POUCH_5512 to RCPouch(9,50), Items.LARGE_POUCH_5512 to RCPouch(9, 186, 50),
Items.GIANT_POUCH_5514 to RCPouch(12,75) Items.GIANT_POUCH_5514 to RCPouch(12,140, 75)
) )
/** /**
* Method to add essence to a pouch * Method to add essence to a pouch
* @param pouchId the id of the pouch we are adding to * @param itemId the item ID of the pouch we are adding to
* @param amount the amount of essence to add * @param amount the amount of essence to add
* @param essence the ID of the essence item we are trying to add * @param essence the ID of the essence item we are trying to add
* @author Ceikry * @author Ceikry, Player Name
*/ */
fun addToPouch(pouchId: Int, amount: Int, essence: Int){ fun addToPouch(itemId: Int, amount: Int, essence: Int) {
if(!checkRequirement(pouchId)){ val pouchId = if (isDecayedPouch(itemId)) itemId - 1 else itemId
player.sendMessage(colorize("%RYou lack the required level to use this pouch.")) if (!checkRequirement(pouchId)) {
sendMessage(player, "You lack the required level to use this pouch.")
return return
} }
var amt = amount var amt = amount
val pouch = pouches[pouchId] val pouch = pouches[pouchId]
val otherEssence = when(essence){ val otherEssence = when(essence) {
Items.RUNE_ESSENCE_1436 -> Items.PURE_ESSENCE_7936 Items.RUNE_ESSENCE_1436 -> Items.PURE_ESSENCE_7936
Items.PURE_ESSENCE_7936 -> Items.RUNE_ESSENCE_1436 Items.PURE_ESSENCE_7936 -> Items.RUNE_ESSENCE_1436
else -> 0 else -> 0
} }
pouch ?: return pouch ?: return
if(amount > pouch.container.freeSlots()){ if (amount > pouch.container.freeSlots()) {
amt = pouch.container.freeSlots() amt = pouch.container.freeSlots()
} }
if(amt == 0){ if (amt == pouch.container.freeSlots()) {
player.sendMessage("This pouch is already full.") sendMessage(player, "Your pouch is full.") //https://www.youtube.com/watch?v=wbYtRwODKTo
} }
if(pouch.container.contains(otherEssence,1)){ if (pouch.container.contains(otherEssence,1)) {
player.sendMessage("You can only store one type of essence in each pouch.") sendMessage(player, "You can only store one type of essence in each pouch.")
return return
} }
player.inventory.remove(Item(essence,amt))
pouch.container.add(Item(essence,amt))
}
var disappeared = false
if (itemId != Items.SMALL_POUCH_5509) {
pouch.charges -= amt
}
if (pouch.charges <= 0) {
pouch.currentCap -= when (pouchId) {
Items.MEDIUM_POUCH_5510 -> 1
Items.LARGE_POUCH_5512 -> 2
Items.GIANT_POUCH_5514 -> 3
else /*small pouch*/ -> 0
}
if (pouch.currentCap <= 0) {
// The pouch will disappear: https://runescape.wiki/w/Runecrafting_pouches?oldid=708494, https://oldschool.runescape.wiki/w/Essence_pouch
// "Degraded pouches will continue to degrade and lose essence capacity until they disappear or are repaired." implies that this is the end result of a gradual decay process
if (removeItem(player, itemId)) {
disappeared = true
sendMessage(player, "Your pouch has degraded completely.")
// Reset the pouch for when the player obtains a new one
pouch.currentCap = pouch.capacity
pouch.charges = pouch.maxCharges
pouch.remakeContainer()
}
} else {
if (!isDecayedPouch(itemId)) {
val slot = player.inventory.getSlot(Item(itemId))
replaceSlot(player, slot, Item(itemId + 1))
}
sendMessage(player, "Your pouch has decayed through use.") //https://www.youtube.com/watch?v=FUcPYrgPUlQ
pouch.charges = 9 * pouch.currentCap //implied by multiple contemporaneous sources, quantified only by https://oldschool.runescape.wiki/w/Large_pouch
pouch.remakeContainer()
if (amt > pouch.currentCap) {
amt = pouch.currentCap
}
}
}
val essItem = Item(essence, amt)
if (!disappeared && removeItem(player, essItem)) {
pouch.container.add(essItem)
}
}
/** /**
* Method to withdraw rune essence from a pouch. * Method to withdraw rune essence from a pouch.
* @param pouchId the item ID of the pouch to withdraw from * @param itemId the item ID of the pouch to withdraw from
* @author Ceikry * @author Ceikry, Player Name
*/ */
fun withdrawFromPouch(pouchId: Int){ fun withdrawFromPouch(itemId: Int) {
val pouchId = if (isDecayedPouch(itemId)) itemId - 1 else itemId
val pouch = pouches[pouchId] val pouch = pouches[pouchId]
pouch ?: return pouch ?: return
val playerFree = player.inventory.freeSlots() val playerFree = freeSlots(player)
var amount = pouch.currentCap - pouch.container.freeSlots() var amount = pouch.currentCap - pouch.container.freeSlots()
if (amount > playerFree) amount = playerFree if (amount > playerFree) {
player.debug("$amount") amount = playerFree
if(amount == 0) return } else {
val essence = Item(pouch.container.get(0).id,amount) sendMessage(player, "Your pouch has no essence left in it.") //https://www.youtube.com/watch?v=wbYtRwODKTo
pouch.container.remove(essence) if (amount == 0) {
pouch.container.shift() return
player.inventory.add(essence)
if(pouch.charges-- <= 0){
pouch.currentCap -= when(pouchId){
5510 -> 1
5512 -> 2
5514 -> 3
else -> 0
}
if(pouch.currentCap <= 0){
player.inventory.remove(Item(pouchId))
player.inventory.add(Item(pouchId + 1))
player.sendMessage(colorize("%RYour ${Item(pouchId).name} has degraded completely."))
}
pouch.remakeContainer()
pouch.charges = 10
if(pouchId != 5509) {
player.sendMessage(colorize("%RYour ${Item(pouchId).name.toLowerCase()} has degraded slightly from use."))
} }
} }
val essence = Item(pouch.container.get(0).id, amount)
pouch.container.remove(essence)
pouch.container.shift()
addItem(player, essence.id, essence.amount)
} }
/** /**
* Method to save pouches to a root JSONObject * Method to save pouches to a root JSONObject
* @param root the JSONObject we are adding the "pouches" JSONArray to * @param root the JSONObject we are adding the "pouches" JSONArray to
* @author Ceikry * @author Ceikry
*/ */
fun save(root: JSONObject){ fun save(root: JSONObject) {
val pouches = JSONArray() val pouches = JSONArray()
for(i in this.pouches){ for(i in this.pouches) {
val pouch = JSONObject() val pouch = JSONObject()
pouch.put("id",i.key.toString()) pouch.put("id",i.key.toString())
val items = JSONArray() val items = JSONArray()
for(item in i.value.container.toArray()){ for(item in i.value.container.toArray()) {
item ?: continue item ?: continue
val it = JSONObject() val it = JSONObject()
it.put("itemId",item.id.toString()) it.put("itemId",item.id.toString())
@ -124,14 +147,13 @@ class PouchManager(val player: Player) {
root.put("pouches",pouches) root.put("pouches",pouches)
} }
/** /**
* Method to parse save data from a JSONArray * Method to parse save data from a JSONArray
* @param data the JSONArray that contains the data to parse * @param data the JSONArray that contains the data to parse
* @author Ceikry * @author Ceikry
*/ */
fun parse(data: JSONArray){ fun parse(data: JSONArray) {
for(e in data){ for (e in data){
val pouch = e as JSONObject val pouch = e as JSONObject
val id = pouch["id"].toString().toInt() val id = pouch["id"].toString().toInt()
val p = pouches[id] val p = pouches[id]
@ -141,7 +163,7 @@ class PouchManager(val player: Player) {
p.charges = charges p.charges = charges
p.currentCap = currentCap p.currentCap = currentCap
p.remakeContainer() p.remakeContainer()
for(i in pouch["container"] as JSONArray){ for (i in pouch["container"] as JSONArray) {
val it = i as JSONObject val it = i as JSONObject
it["itemId"] ?: continue it["itemId"] ?: continue
val item = it["itemId"].toString().toInt() val item = it["itemId"].toString().toInt()
@ -151,33 +173,31 @@ class PouchManager(val player: Player) {
} }
} }
/** /**
* Method for checking the level requirement for a given pouch. * Method for checking the level requirement for a given pouch.
* @param pouchId the item ID of the pouch to check * @param pouchId the item ID of the pouch to check
* @author Ceikry * @author Ceikry
*/ */
fun checkRequirement(pouchId: Int): Boolean{ fun checkRequirement(pouchId: Int): Boolean {
val p = pouches[pouchId] val p = pouches[pouchId]
p ?: return false p ?: return false
return player.skills.getLevel(Skills.RUNECRAFTING) >= p.levelRequirement return player.skills.getLevel(Skills.RUNECRAFTING) >= p.levelRequirement
} }
/** /**
* Method for sending the player a message about how much space is left in a pouch * Method for sending the player a message about how much space is left in a pouch
* @param pouchId the item ID of the pouch to check * @param itemId the item ID of the pouch to check
* @author Ceikry * @author Ceikry, Player Name
*/ */
fun checkAmount(pouchId: Int){ fun checkAmount(itemId: Int) {
val pouchId = if (isDecayedPouch(itemId)) itemId - 1 else itemId
val p = pouches[pouchId] val p = pouches[pouchId]
p ?: return p ?: return
player.sendMessage("This pouch has space for ${p.container.freeSlots()} more essence.") player.sendMessage("This pouch has space for ${p.container.freeSlots()} more essence.")
} }
fun isDecayedPouch(pouchId: Int): Boolean {
fun isDecayedPouch(pouchId: Int): Boolean{ if (pouchId == Items.MEDIUM_POUCH_5510) return false
if(pouchId == 5510) return false
return pouches[pouchId - 1] != null return pouches[pouchId - 1] != null
} }
@ -185,11 +205,11 @@ class PouchManager(val player: Player) {
* A class that represents a runecrafting pouch. * A class that represents a runecrafting pouch.
* @author Ceikry * @author Ceikry
*/ */
class RCPouch(val capacity: Int, val levelRequirement: Int){ class RCPouch(val capacity: Int, val maxCharges: Int, val levelRequirement: Int) {
var container = Container(capacity) var container = Container(capacity)
var currentCap = capacity var currentCap = capacity
var charges = 10 var charges = maxCharges
fun remakeContainer(){ fun remakeContainer() {
this.container = Container(currentCap) this.container = Container(currentCap)
} }
} }

View file

@ -11,7 +11,7 @@ import core.tools.colorize
/** /**
* Handles the rune pouches. * Handles the rune pouches.
* @author Ceikry * @author Ceikry, Player Name
*/ */
class RunePouchPlugin : OptionHandler() { class RunePouchPlugin : OptionHandler() {
@Throws(Throwable::class) @Throws(Throwable::class)
@ -37,21 +37,11 @@ class RunePouchPlugin : OptionHandler() {
if(preferenceFlag == 0) rEssAmt else pEssAmt if(preferenceFlag == 0) rEssAmt else pEssAmt
) )
when (option) {
if(player.pouchManager.isDecayedPouch(node.id)){ "fill" -> player.pouchManager.addToPouch(node.id, essence.amount, essence.id)
player.debug("E2") "empty" -> player.pouchManager.withdrawFromPouch(node.id)
when(option) { //Handling for IF the pouch has already completely decayed "check" -> player.pouchManager.checkAmount(node.id)
"drop" -> player.dialogueInterpreter.open(9878,Item(node.id)) "drop" -> player.dialogueInterpreter.open(9878,Item(node.id))
else -> player.sendMessage(colorize("%RThis pouch has completely decayed and needs to be repaired."))
}
} else {
player.debug("E")
when (option) { //Normal handling
"fill" -> player.pouchManager.addToPouch(node.id, essence.amount, essence.id)
"empty" -> player.pouchManager.withdrawFromPouch(node.id)
"check" -> player.pouchManager.checkAmount(node.id)
"drop" -> player.dialogueInterpreter.open(9878,Item(node.id))
}
} }
return true return true
} }

View file

@ -4,6 +4,7 @@ import core.game.dialogue.DialoguePlugin;
import core.game.node.entity.npc.NPC; import core.game.node.entity.npc.NPC;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.item.Item; import core.game.node.item.Item;
import org.rs09.consts.Items;
/** /**
* Handles the dark mages dialogue. * Handles the dark mages dialogue.
@ -140,18 +141,18 @@ public final class DarkMageDialogue extends DialoguePlugin {
private boolean repair() { private boolean repair() {
player.pouchManager.getPouches().forEach((id, pouch) -> { player.pouchManager.getPouches().forEach((id, pouch) -> {
pouch.setCurrentCap(pouch.getCapacity()); pouch.setCurrentCap(pouch.getCapacity());
pouch.setCharges(10); pouch.setCharges(pouch.getMaxCharges());
Item essence = null; Item essItem = null;
if(!pouch.getContainer().isEmpty()){ if (!pouch.getContainer().isEmpty()) {
int ess = pouch.getContainer().get(0).getId(); int essence = pouch.getContainer().get(0).getId();
int amount = pouch.getContainer().getAmount(ess); int amount = pouch.getContainer().getAmount(essence);
essence = new Item(ess,amount); essItem = new Item(essence, amount);
} }
pouch.remakeContainer(); pouch.remakeContainer();
if(essence != null){ if (essItem != null) {
pouch.getContainer().add(essence); pouch.getContainer().add(essItem);
} }
if(id != 5509) { if (id != Items.SMALL_POUCH_5509) {
if (player.getInventory().contains(id + 1, 1)) { if (player.getInventory().contains(id + 1, 1)) {
player.getInventory().remove(new Item(id + 1, 1)); player.getInventory().remove(new Item(id + 1, 1));
player.getInventory().add(new Item(id, 1)); player.getInventory().add(new Item(id, 1));