Implemented custom satchels

These satchels are normally from creature creation. The custom versions can be crafted by using an enchantment spell on hides, and have a stackable inventory that only stores certain items.
- Plain: Level 1 enchant on Blue D hide. Carries anything but can only be emptied by using it on a bank booth.
- Green: Level 2 enchant on Green D hide. Carries any seed or herb. Harvesting farming plots with the satchel equipped returns noted produce.
- Red: Level 3 enchant on Red D hide. Carries summoning charms. Charms dropped by mobs are automatically added to the satchel.
- Gold: Level 4 enchant on Dagannoth hide. Carries ore. Smelting at the furnace will use ore in the satchel.
- Rune: Level 5 enchant on Suqah hide. Carries catalytic runes. Spells will use runes in the satchel.
- Black: Level 6 enchant on Black D hide. Placeholder, as I don't have a use for it yet.
This commit is contained in:
randy 2025-03-05 09:34:48 -07:00
parent 249c501184
commit 16da0ed93e
14 changed files with 301 additions and 21 deletions

View file

@ -93923,7 +93923,7 @@
},
{
"shop_price": "128",
"examine": "I can keep my grub in here.",
"examine": "I can keep my items in here, but I'll need a banker to get them out.",
"durability": null,
"name": "Plain satchel",
"weight": "0.1",
@ -93932,7 +93932,7 @@
"equipment_slot": "5"
},
{
"examine": "I can keep my grub in here.",
"examine": "I can keep my seeds and herbs in here.",
"durability": null,
"name": "Green satchel",
"weight": "0.1",
@ -93942,7 +93942,7 @@
},
{
"shop_price": "128",
"examine": "I can keep my grub in here.",
"examine": "I can keep my summoning charms in here.",
"durability": null,
"name": "Red satchel",
"weight": "0.1",
@ -93960,7 +93960,7 @@
"equipment_slot": "5"
},
{
"examine": "I can keep my grub in here.",
"examine": "I can keep my ores in here.",
"durability": null,
"name": "Gold satchel",
"weight": "0.1",
@ -93969,7 +93969,7 @@
"equipment_slot": "5"
},
{
"examine": "I can keep my grub in here.",
"examine": "I can keep my catalytic runes in here.",
"durability": null,
"name": "Rune satchel",
"weight": "0.1",

View file

@ -10,12 +10,14 @@ import org.rs09.consts.Sounds
class EnchantJewelleryTabListener : InteractionListener {
private val LVL_1_ENCHANT = mapOf(
Items.BLUE_DRAGONHIDE_1751 to Items.PLAIN_SATCHEL_10877,
Items.SAPPHIRE_RING_1637 to Items.RING_OF_RECOIL_2550,
Items.SAPPHIRE_NECKLACE_1656 to Items.GAMES_NECKLACE8_3853,
Items.SAPPHIRE_AMULET_1694 to Items.AMULET_OF_MAGIC_1727,
Items.SAPPHIRE_BRACELET_11072 to Items.BRACELET_OF_CLAY_11074
)
private val LVL_2_ENCHANT = mapOf(
Items.GREEN_DRAGONHIDE_1753 to Items.GREEN_SATCHEL_10878,
Items.EMERALD_RING_1639 to Items.RING_OF_DUELLING8_2552,
Items.EMERALD_NECKLACE_1658 to Items.BINDING_NECKLACE_5521,
Items.EMERALD_AMULET_1696 to Items.AMULET_OF_DEFENCE_1729,
@ -23,6 +25,7 @@ class EnchantJewelleryTabListener : InteractionListener {
)
private val LVL_3_ENCHANT = mapOf(
Items.RED_DRAGONHIDE_1749 to Items.RED_SATCHEL_10879,
Items.RUBY_RING_1641 to Items.RING_OF_FORGING_2568,
Items.RUBY_NECKLACE_1660 to Items.DIGSITE_PENDANT_5_11194,
Items.RUBY_AMULET_1698 to Items.AMULET_OF_STRENGTH_1725,
@ -30,6 +33,7 @@ class EnchantJewelleryTabListener : InteractionListener {
)
private val LVL_4_ENCHANT = mapOf(
Items.DAGANNOTH_HIDE_6155 to Items.GOLD_SATCHEL_10881,
Items.DIAMOND_RING_1643 to Items.RING_OF_LIFE_2570,
Items.DIAMOND_NECKLACE_1662 to Items.PHOENIX_NECKLACE_11090,
Items.DIAMOND_AMULET_1700 to Items.AMULET_OF_POWER_1731,
@ -37,6 +41,7 @@ class EnchantJewelleryTabListener : InteractionListener {
)
private val LVL_5_ENCHANT = mapOf(
Items.SUQAH_HIDE_9080 to Items.RUNE_SATCHEL_10882,
Items.DRAGONSTONE_RING_1645 to Items.RING_OF_WEALTH4_14646,
Items.DRAGON_NECKLACE_1664 to Items.SKILLS_NECKLACE4_11105,
Items.DRAGONSTONE_AMMY_1702 to Items.AMULET_OF_GLORY4_1712,
@ -44,6 +49,7 @@ class EnchantJewelleryTabListener : InteractionListener {
)
private val LVL_6_ENCHANT = mapOf(
Items.BLACK_DRAGONHIDE_1747 to Items.BLACK_SATCHEL_10880,
Items.ONYX_RING_6575 to Items.RING_OF_STONE_6583,
Items.ONYX_NECKLACE_6577 to Items.BERSERKER_NECKLACE_11128,
Items.ONYX_AMULET_6581 to Items.AMULET_OF_FURY_6585,

View file

@ -0,0 +1,179 @@
package content.global.handlers.item
import core.api.*
import core.game.container.Container
import content.global.skill.summoning.familiar.BurdenContainerListener
import core.game.node.Node
import core.game.node.entity.player.Player
//import core.game.node.entity.player.info.login.PlayerSaver
import core.game.node.item.Item
import core.game.interaction.InteractionListener
import core.game.interaction.IntType
import org.json.simple.JSONArray
import org.json.simple.JSONObject
import org.json.simple.parser.JSONParser
import org.rs09.consts.Items
import core.game.component.Component
import core.game.component.CloseEvent
import core.game.container.access.InterfaceContainer
import content.global.handlers.scenery.BankBoothListener
/**
* Listener for satchels from Creature Creation, repurposed for Snowscape
* They are repurposed as item pouches, using the summoning familiar inventory interface
* @author
*/
class SnowscapeSatchelListener : InteractionListener {
companion object {
val plainSatchelId = 10877
val greenSatchelId = 10878
val redSatchelId = 10879
val blackSatchelId = 10880
val goldSatchelId = 10881
val runeSatchelId = 10882
val satchelIds = intArrayOf(plainSatchelId,greenSatchelId,redSatchelId,blackSatchelId,goldSatchelId,runeSatchelId)
//val runeSatchelAllowed = intArrayOf(558,559,564,562,9075,561,563,560,565,566)
//val runesForbidden = intArrayOf(556,555,557,554,4695,4696,4698,4697,4694,4699)
private fun transferItem(player: Player, satchelId: Int, item: Item, amount: Int, withdraw: Boolean, asNote: Boolean = false) {
if (withdraw == false && !isAllowed(satchelId, unnote(item).getId())) {
player.sendMessage(item.getName() + " cannot be stored in the " + Item(satchelId).getName() + ".")
return
}
if (withdraw == true && asNote == false && satchelId == plainSatchelId) {
player.sendMessage("This satchel can only be emptied by a banker. Use it on a bank booth to get the items.")
return
}
val to = if (withdraw) player.getInventory() else getSatchel(player, satchelId)
val from = if (withdraw) getSatchel(player, satchelId) else player.getInventory()
val maximum = if (asNote) to.getMaximumAdd(note(item)) else to.getMaximumAdd(unnote(item))
if (maximum < 1 && withdraw == false) {
player.sendMessage("There is not enough space for the " + item.getName() + " in the satchel.")
return
}
val finalAmount = kotlin.comparisons.minOf(amount, from.getAmount(item), maximum)
val finalItem = Item(item.getId(), finalAmount)
if (finalAmount > 0 && from.remove(finalItem)) {
if (asNote) to.add(note(finalItem)) else to.add(unnote(finalItem))
}
}
private fun emptySatchel(player: Player, satchelId: Int, asNote: Boolean = false) {
if (asNote == false && satchelId == plainSatchelId) {
player.sendMessage("This satchel can only be emptied by a banker. Use it on a Bank Booth to get the items.")
return
}
val satchel = getSatchel(player, satchelId)
repeat(satchel.capacity()) { index ->
var item = satchel.get(index)
if (item != null) {
transferItem(player, satchelId, item, satchel.getAmount(item), true, asNote)
}
}
}
//Function to handle constructing the correct interfaces when the satchel is opened
private fun openSatchel(player: Player, node: Node) {
val satchelId = node.asItem().getId()
val satchel = getSatchel(player, satchelId)
if (satchel.getListeners().count() < 1) satchel.register(BurdenContainerListener(player))
player.getInterfaceManager().open(Component(671)).setCloseEvent(CloseEvent { player, component ->
player.getInterfaceManager().closeSingleTab()
removeAttribute(player, "openSatchel")
return@CloseEvent true
}
)
setAttribute(player, "openSatchel", satchelId)
satchel.shift()
player.getInterfaceManager().openSingleTab(Component(665))
InterfaceContainer.generateItems(player, player.getInventory().toArray(), arrayOf("Store-X","Store-All","Store-10","Store-5","Store-1"),665,0,7,4,93)
InterfaceContainer.generateItems(player, satchel.toArray(), arrayOf("Withdraw-X","Withdraw-All","Withdraw-10","Withdraw-5","Withdraw-1"),671,27,5,6,30)
}
// This is called by BurdenInterfacePlugin.java when the player interacts with the familiar interface and the "openSatchel" attribute exists
fun satchelInterfaceAction(player: Player, component: Component, opcode: Int, button: Int, slot: Int, itemId: Int) {
//player.sendMessage("Button:" + button.toString() + ". Opcode:" + opcode.toString())
val satchelId = getAttribute(player, "openSatchel", 0)
val withdraw = component.getId() == 671
val container = if (withdraw) getSatchel(player, satchelId) else player.getInventory()
val item = if (slot >= 0 && slot < container.capacity()) container.get(slot) else null
if (item == null && button != 29) return
when (opcode) {
155 -> if (button == 29) emptySatchel(player, satchelId) else transferItem(player, satchelId, item!!, 1, withdraw)
196 -> transferItem(player, satchelId, item!!, 5, withdraw)
124 -> transferItem(player, satchelId, item!!, 10, withdraw)
199 -> transferItem(player, satchelId, item!!, container.getAmount(item), withdraw)
234 -> sendInputDialogue(player, true, "Enter the amount:") { value -> transferItem(player, satchelId, item!!, value as Int, withdraw) }
9 -> player.sendMessage(item!!.getDefinition().getExamine())
}
}
fun getSatchel(player: Player, satchelId: Int): Container {
var satchel: Container? = null
when (satchelId) {
plainSatchelId -> satchel = player.plainSatchel
greenSatchelId -> satchel = player.greenSatchel
redSatchelId -> satchel = player.redSatchel
blackSatchelId -> satchel = player.blackSatchel
goldSatchelId -> satchel = player.goldSatchel
runeSatchelId -> satchel = player.runeSatchel
}
return satchel!!
}
// Checks if the item is allowed in the satchel. The NPCDropTables.java function calls this on the Red Satchel if the player has one
fun isAllowed(satchelId: Int, itemId: Int): Boolean {
when (satchelId) {
plainSatchelId -> return itemId !in satchelIds
greenSatchelId -> return (Item(itemId).getName().contains(" seed") || Item(itemId).getName().contains("Grimy") || Item(itemId).getName().contains("Clean "))
redSatchelId -> return itemId in intArrayOf(12158,12159,12160,12161,12162,12163,12164,12165,12166,12167,12168)
blackSatchelId -> return itemId in intArrayOf(995)
goldSatchelId -> return itemId in intArrayOf(436,438,440,442,444,446,447,449,451,453,668,2892)
runeSatchelId -> return itemId in intArrayOf(558,559,564,562,9075,561,563,560,565,566)
}
return false
}
}
override fun defineListeners() {
onUseAnyWith(IntType.ITEM, *satchelIds) { player, used, with ->
val satchelId = with.asItem().getId()
transferItem(player, satchelId, used.asItem(), player.getInventory().getAmount(used.asItem()),false)
return@onUseAnyWith true
}
on(satchelIds, IntType.ITEM, "inspect","operate") { player, node ->
openSatchel(player, node)
return@on true
}
on(satchelIds, IntType.ITEM, "empty") { player, node ->
emptySatchel(player, node.asItem().getId())
return@on true
}
// BankBoothListener values are public but BankChestListener values are not, so rather than edit the BankChestListener file I have copied the IDs here. 12309 is the Culinomancer's chest.
val bankChests = intArrayOf(3194,4483,10562,14382,16695,16696,21301,27662,27663)
val bankUseWiths = intArrayOf(*BankBoothListener.BANK_BOOTHS, 12309, *bankChests)
onUseWith(IntType.SCENERY, satchelIds, *bankUseWiths) { player, used, with ->
emptySatchel(player, used.asItem().getId(), true)
return@onUseWith true
}
}
}

View file

@ -83,14 +83,16 @@ class CropHarvester : OptionHandler() {
return true
}
val necklace = getItemFromEquipment(player, EquipmentSlot.NECK)
var amulet = false
var noted = false
if (necklace != null && (necklace.name.lowercase().contains("amulet of farming") || necklace.name.lowercase().contains("amulet of nature"))) {
amulet = true
}
noted = true
} else if (inEquipment(player,10878,1)) {
noted = true
}
val sendHarvestMessages = if (fPatch.type == PatchType.FLOWER_PATCH) false else true
if (sendHarvestMessages && firstHarvest) {
sendMessage(player, "You begin to harvest the $patchName.")
if (amulet) {
if (noted) {
sendMessage(player, "The leprechaun exchanges your produce for banknotes.")
}
firstHarvest = false
@ -100,7 +102,7 @@ class CropHarvester : OptionHandler() {
// TODO: If a flower patch is being harvested, delay the clearing of the
// patch until after the animation has played - https://youtu.be/lg4GktlVNUY?t=75
delay = 2
if (amulet) {
if (noted) {
addItem(player, note(reward).id)
} else {
addItem(player, reward.id)

View file

@ -62,7 +62,12 @@ abstract class SpellListener(val bookName: String) : Listener {
}
fun removeRunes(player: Player,removeAttr: Boolean = true){
/* Snowscape modification: remove runes from the inventory or rune satchel
player.inventory.remove(*player.getAttribute("spell:runes",ArrayList<Item>()).toTypedArray())
*/
player.getAttribute("spell:runes",ArrayList<Item>()).toTypedArray().forEach { rune ->
if (!player.inventory.remove(rune)) player.runeSatchel.remove(rune)
}
if(removeAttr) {
player.removeAttribute("spell:runes")
player.removeAttribute("tablet-spell")

View file

@ -6,6 +6,7 @@ import core.game.node.entity.combat.spell.CombinationRune
import core.game.node.entity.combat.spell.MagicStaff
import core.game.node.entity.combat.spell.Runes
import core.game.node.item.Item
import core.api.*
object SpellUtils {
fun usingStaff(p: Player, rune: Int): Boolean {
@ -20,15 +21,16 @@ object SpellUtils {
return false
}
// Snowscape modifications: check the runeStachel container for the base runes if the player is carrying one
fun hasRune(p:Player,rune:Item):Boolean{
val removeItems = p.getAttribute("spell:runes",ArrayList<Item>())
if(usingStaff(p,rune.id)) return true
if(p.inventory.containsItem(rune)){
if(p.inventory.containsItem(rune) || (inEquipmentOrInventory(p, 10882) && p.runeSatchel.containsItem(rune))){
removeItems.add(rune)
p.setAttribute("spell:runes",removeItems)
}
val baseAmt = p.inventory.getAmount(rune.id)
val baseAmt = p.inventory.getAmount(rune.id) + (if (inEquipmentOrInventory(p, 10882)) p.runeSatchel.getAmount(rune.id) else 0)
var amtRemaining = rune.amount - baseAmt
val possibleComboRunes = CombinationRune.eligibleFor(Runes.forId(rune.id))
for (r in possibleComboRunes) {
@ -49,9 +51,9 @@ object SpellUtils {
fun hasRune(p: Player, item: Item, toRemove: MutableList<Item?>, message: Boolean): Boolean {
if (!usingStaff(p, item.id)) {
val hasBaseRune = p.inventory.contains(item.id, item.amount)
val hasBaseRune = p.inventory.contains(item.id, item.amount) || (inEquipmentOrInventory(p, 10882) && p.runeSatchel.contains(item.id, item.amount))
if (!hasBaseRune) {
val baseAmt = p.inventory.getAmount(item.id)
val baseAmt = p.inventory.getAmount(item.id) + (if (inEquipmentOrInventory(p, 10882)) p.runeSatchel.getAmount(item.id) else 0)
if (baseAmt > 0) {
toRemove.add(Item(item.id, p.inventory.getAmount(item.id)))
}

View file

@ -99,7 +99,8 @@ public class SmeltingPulse extends SkillPulse<Item> {
return false;
}
for (Item item : bar.getOres()) {
if (!player.getInventory().contains(item.getId(), item.getAmount())) {
//Snowscape modification: check gold satchel for ores as well, if carried
if (!player.getInventory().contains(item.getId(), item.getAmount()) && !(inEquipmentOrInventory(player, 10881, 1) && player.goldSatchel.contains(item.getId(), item.getAmount()))) {
player.getPacketDispatch().sendMessage("You do not have the required ores to make this bar.");
return false;
}
@ -128,7 +129,7 @@ public class SmeltingPulse extends SkillPulse<Item> {
player.getPacketDispatch().sendMessage("You place the required ores and attempt to create a bar of " + StringUtils.formatDisplayName(bar.toString().toLowerCase()) + ".");
}
for (Item i : bar.getOres()) {
if (!player.getInventory().remove(i)) {
if (!(player.getInventory().remove(i) || player.goldSatchel.remove(i))) {
return true;
}
}
@ -147,7 +148,8 @@ public class SmeltingPulse extends SkillPulse<Item> {
player.sendMessage("The magic of the Varrock armour enables you to smelt 2 bars at the same time.");
}
}
player.getInventory().add(new Item(bar.getProduct().getId(), amt));
//player.getInventory().add(new Item(bar.getProduct().getId(), amt));
addItemOrDrop(player, bar.getProduct().getId(), amt);
player.dispatch(new ResourceProducedEvent(bar.getProduct().getId(), 1, player, -1));
double xp = bar.getExperience() * amt;
// Goldsmith gauntlets

View file

@ -11,6 +11,8 @@ import core.plugin.Initializable;
import core.plugin.Plugin;
import kotlin.Unit;
import content.global.handlers.item.SnowscapeSatchelListener;
/**
* Handles the beast of burden interface.
* @author Emperor
@ -27,6 +29,10 @@ public final class BurdenInterfacePlugin extends ComponentPlugin {
@Override
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
if (getAttribute(player, "openSatchel", null) != null) {
SnowscapeSatchelListener.Companion.satchelInterfaceAction(player, component, opcode, button, slot, itemId);
return true;
}
if (!player.getFamiliarManager().hasFamiliar() || !player.getFamiliarManager().getFamiliar().isBurdenBeast()) {
return false;
}

View file

@ -113,6 +113,7 @@ class EnchantSpell : MagicSpell {
Items.SAPPHIRE_NECKLACE_1656 to Item(Items.GAMES_NECKLACE8_3853),
Items.SAPPHIRE_AMULET_1694 to Item(Items.AMULET_OF_MAGIC_1727),
Items.SAPPHIRE_BRACELET_11072 to Item(Items.BRACELET_OF_CLAY_11074),
Items.BLUE_DRAGONHIDE_1751 to Item(Items.PLAIN_SATCHEL_10877),
//Begin MTA-specific enchantments
Items.CUBE_6899 to Item(Items.ORB_6902),
Items.CYLINDER_6898 to Item(Items.ORB_6902),
@ -132,6 +133,7 @@ class EnchantSpell : MagicSpell {
Items.EMERALD_NECKLACE_1658 to Item(Items.BINDING_NECKLACE_5521),
Items.EMERALD_AMULET_1696 to Item(Items.AMULET_OF_DEFENCE_1729),
Items.EMERALD_BRACELET_11076 to Item(Items.CASTLEWAR_BRACE3_11079),
Items.GREEN_DRAGONHIDE_1753 to Item(Items.GREEN_SATCHEL_10878),
//Begin MTA-Specific Enchantments
Items.CUBE_6899 to Item(Items.ORB_6902),
Items.CYLINDER_6898 to Item(Items.ORB_6902),
@ -151,6 +153,7 @@ class EnchantSpell : MagicSpell {
Items.RUBY_NECKLACE_1660 to Item(Items.DIGSITE_PENDANT_5_11194),
Items.RUBY_AMULET_1698 to Item(Items.AMULET_OF_STRENGTH_1725),
Items.RUBY_BRACELET_11085 to Item(Items.INOCULATION_BRACE_11088),
Items.RED_DRAGONHIDE_1749 to Item(Items.RED_SATCHEL_10879),
//Begin MTA-Specific Enchantments
Items.CUBE_6899 to Item(Items.ORB_6902),
Items.CYLINDER_6898 to Item(Items.ORB_6902),
@ -169,6 +172,7 @@ class EnchantSpell : MagicSpell {
Items.DIAMOND_NECKLACE_1662 to Item(Items.PHOENIX_NECKLACE_11090),
Items.DIAMOND_AMULET_1700 to Item(Items.AMULET_OF_POWER_1731),
Items.DIAMOND_BRACELET_11092 to Item(Items.FORINTHRY_BRACE5_11095),
Items.DAGANNOTH_HIDE_6155 to Item(Items.GOLD_SATCHEL_10881),
//Begin MTA-Specific Enchantments
Items.CUBE_6899 to Item(Items.ORB_6902),
Items.CYLINDER_6898 to Item(Items.ORB_6902),
@ -188,6 +192,7 @@ class EnchantSpell : MagicSpell {
Items.DRAGON_NECKLACE_1664 to Item(Items.SKILLS_NECKLACE4_11105),
Items.DRAGONSTONE_AMMY_1702 to Item(Items.AMULET_OF_GLORY4_1712),
Items.DRAGON_BRACELET_11115 to Item(Items.COMBAT_BRACELET4_11118),
Items.SUQAH_HIDE_9080 to Item(Items.RUNE_SATCHEL_10882),
//Begin MTA-Specific Enchantments
Items.CUBE_6899 to Item(Items.ORB_6902),
Items.CYLINDER_6898 to Item(Items.ORB_6902),
@ -207,6 +212,7 @@ class EnchantSpell : MagicSpell {
Items.ONYX_NECKLACE_6577 to Item(Items.BERSERKER_NECKLACE_11128),
Items.ONYX_AMULET_6581 to Item(Items.AMULET_OF_FURY_6585),
Items.ONYX_BRACELET_11130 to Item(Items.REGEN_BRACELET_11133),
Items.BLACK_DRAGONHIDE_1747 to Item(Items.BLACK_SATCHEL_10880),
//Begin MTA-Specific Enchantments
Items.CUBE_6899 to Item(Items.ORB_6902),
Items.CYLINDER_6898 to Item(Items.ORB_6902),

View file

@ -21,6 +21,7 @@ import java.util.ArrayList;
import java.util.List;
import static core.api.ContentAPIKt.playGlobalAudio;
import static core.api.ContentAPIKt.inEquipmentOrInventory;
/**
* Represents a magic spell.
@ -243,7 +244,9 @@ public abstract class MagicSpell implements Plugin<SpellType> {
}
if (remove) {
toRemove.forEach(i -> {
p.getInventory().remove(i);
if (!p.getInventory().remove(i)){
p.runeSatchel.remove(i);
}
});
}
return true;
@ -277,7 +280,8 @@ public abstract class MagicSpell implements Plugin<SpellType> {
*/
public boolean hasRune(Player p, Item item, List<Item> toRemove, boolean message) {
if (!usingStaff(p, item.getId())) {
boolean hasBaseRune = p.getInventory().contains(item.getId(),item.getAmount());
// Snowscape modification: check the rune satchel for the base runes if the player is carrying one
boolean hasBaseRune = p.getInventory().contains(item.getId(),item.getAmount()) || (inEquipmentOrInventory(p, 10882,1) && p.runeSatchel.contains(item.getId(),item.getAmount()));
if(!hasBaseRune){
int baseAmt = p.getInventory().getAmount(item.getId());
if(baseAmt > 0){

View file

@ -27,6 +27,7 @@ import content.global.skill.summoning.familiar.BurdenBeast;
import content.global.skill.summoning.familiar.Forager;
import content.global.skill.summoning.SummoningPouch;
import content.global.skill.summoning.familiar.PackYakNPC;
import content.global.handlers.item.SnowscapeSatchelListener;
import java.util.ArrayList;
import java.util.List;
@ -104,6 +105,9 @@ public final class NPCDropTables {
if (handleBoneCrusher(player, item)) {
return;
}
if (handleSatchel(player, item)) {
return;
}
if (handleCurrency(player, item)) {
return;
}
@ -181,7 +185,7 @@ public final class NPCDropTables {
return true;
}
if (((BurdenBeast) player.getFamiliarManager().getFamiliar()).getContainer().add(item)) {
player.sendMessage("Your familiar picked up " + item.getAmount() + " " + item.getName() + ".");
player.sendMessage("Your familiar picked up <col=ffa07a>" + item.getAmount() + " " + item.getName() + ".</col>");
return true;
} else {
return false;
@ -266,6 +270,17 @@ public final class NPCDropTables {
player.getSkills().addExperience(Skills.PRAYER, item.getAmount() * bone.getExperience());
return true;
}
//Snowscape modification: loot certain items into the red satchel if carried
private boolean handleSatchel(Player player, Item item) {
if (inEquipmentOrInventory(player,10879,1)){
if (SnowscapeSatchelListener.Companion.isAllowed(10879,item.getId()) && player.redSatchel.add(item)) {
player.sendMessage("Your red satchel stashed <col=ffa07a>" + item.getAmount() + " " + item.getName() + ".</col>");
return true;
}
}
return false;
}
/**
* Snowscape custom: Automatically loot coins and tokkul if wearing a ring of wealth.
@ -278,7 +293,7 @@ public final class NPCDropTables {
Item ring = player.getEquipment().get(12);
if (ring != null && ring.getId() >= 14638 && ring.getId() <=14646) {
if (player.getInventory().add(item)) {
player.sendMessage("Your Ring collected " + item.getAmount() + " " + item.getName() + ".");
player.sendMessage("Your ring collected <col=ffa07a>" + item.getAmount() + " " + item.getName() + ".</col>");
return true;
}
}

View file

@ -311,6 +311,15 @@ public class Player extends Entity {
public byte[] opCounts = new byte[255];
public int invalidPacketCount = 0;
// Snowscape additions
// The satchel containers.
public final Container plainSatchel = new Container(6, ContainerType.ALWAYS_STACK);
public final Container greenSatchel = new Container(30, ContainerType.ALWAYS_STACK);
public final Container redSatchel = new Container(30, ContainerType.ALWAYS_STACK);
public final Container blackSatchel = new Container(30, ContainerType.ALWAYS_STACK);
public final Container goldSatchel = new Container(30, ContainerType.ALWAYS_STACK);
public final Container runeSatchel = new Container(30, ContainerType.ALWAYS_STACK);
/**
* Constructs a new {@code Player} {@code Object}.
* @param details The player's details.

View file

@ -74,6 +74,7 @@ class PlayerSaveParser(val player: Player) {
parseStatistics()
parseAchievements()
parsePouches()
parseSnowscapeData()
}
fun runContentHooks()
@ -358,4 +359,32 @@ class PlayerSaveParser(val player: Player) {
player.version = saveFile!!["version"].toString().toInt()
}
}
//Load the custom data added by snowscape
fun parseSnowscapeData() {
saveFile ?: return
if (!(saveFile!!.containsKey("snowscape_data"))) return
val snowscapeData = saveFile!!["snowscape_data"] as JSONObject
val plainSatchel = snowscapeData["plainSatchel"]
if (plainSatchel != null) player.plainSatchel.parse(plainSatchel as JSONArray)
val greenSatchel = snowscapeData["greenSatchel"]
if (greenSatchel != null) player.greenSatchel.parse(greenSatchel as JSONArray)
val redSatchel = snowscapeData["redSatchel"]
if (redSatchel != null) player.redSatchel.parse(redSatchel as JSONArray)
val blackSatchel = snowscapeData["blackSatchel"]
if (blackSatchel != null) player.blackSatchel.parse(blackSatchel as JSONArray)
val goldSatchel = snowscapeData["goldSatchel"]
if (goldSatchel != null) player.goldSatchel.parse(goldSatchel as JSONArray)
val runeSatchel = snowscapeData["runeSatchel"]
if (runeSatchel != null) player.runeSatchel.parse(runeSatchel as JSONArray)
}
}

View file

@ -55,6 +55,7 @@ class PlayerSaver (val player: Player){
saveStatManager(saveFile)
saveAttributes(saveFile)
savePouches(saveFile)
saveSnowscapeData(saveFile)
contentHooks.forEach { it.savePlayer(player, saveFile) }
return saveFile
}
@ -643,4 +644,18 @@ class PlayerSaver (val player: Player){
root.put("core_data",coreData)
}
// Function to save the custom data added by snowscape
fun saveSnowscapeData(root: JSONObject){
val snowscapeData = JSONObject()
snowscapeData.put("plainSatchel", saveContainer(player.plainSatchel))
snowscapeData.put("greenSatchel", saveContainer(player.greenSatchel))
snowscapeData.put("redSatchel", saveContainer(player.redSatchel))
snowscapeData.put("blackSatchel", saveContainer(player.blackSatchel))
snowscapeData.put("goldSatchel", saveContainer(player.goldSatchel))
snowscapeData.put("runeSatchel", saveContainer(player.runeSatchel))
root.put("snowscape_data",snowscapeData)
}
}