diff --git a/Server/src/main/java/core/game/content/global/shop/CulinomancerShop.kt b/Server/src/main/java/core/game/content/global/shop/CulinomancerShop.kt new file mode 100644 index 000000000..4f7817092 --- /dev/null +++ b/Server/src/main/java/core/game/content/global/shop/CulinomancerShop.kt @@ -0,0 +1,147 @@ +package core.game.content.global.shop + +import api.LoginListener +import api.getAttribute +import api.setAttribute +import core.game.node.entity.player.Player +import core.game.node.item.Item +import core.game.system.task.Pulse +import org.rs09.consts.Items +import rs09.game.world.GameWorld +import java.lang.Integer.min +import kotlin.collections.HashMap + +object CulinomancerShop : LoginListener { + // Our shop mappings - shops are individualized due to the differing items based on player's QP. + // Maps player UID -> shop + private val foodShops = HashMap() + private val gearShops = HashMap() + + //Open methods for the shops - should check player's QP and whether they already have a container generated + @JvmStatic fun openShop(player: Player, food: Boolean) + { + getShop(player, food).open(player) + } + + //Retrieve a player's shop - should generate the shop if it does not exist. + fun getShop(player: Player, food: Boolean) : Shop + { + val uid = player.details.uid + val points = player.questRepository.points + val tier = (points / 18) + if(tier != getAttribute(player, "culino-tier", 0)) //If player tier has changed + { + foodShops.remove(uid) //Clear the previous shops, so they can regenerate with the new tier + gearShops.remove(uid) + } + return if(food) { + val shop = foodShops[uid] ?: Shop("Culinomancer's Chest Tier $tier", generateFoodStock(points),false) + foodShops[uid] = shop + shop + } else { + val shop = gearShops[uid] ?: Shop("Culinomancer's Chest Tier $tier", generateGearStock(points), false) + gearShops[uid] = shop + shop + } + } + + //Generate default food stock based on an amount of total QP. + private fun generateFoodStock(points: Int) : Array + { + val stock = Array(foodStock.size) { Item(0, 0) } + val maxQty = when(val qpTier = (points / 18) - 1) + { + 0,1,2,3,4 -> 1 + qpTier + else -> qpTier + (qpTier + (qpTier - 5)) //5 = 10, 6 = 13, 7 = 15, etc + } + for((index,item) in foodStock.withIndex()) + { + stock[index].id = item.id + stock[index].amount = if(item.id == Items.PIZZA_BASE_2283) 1 else maxQty + } + return stock + } + + //Generate default gear stock based on an amount of total QP. + private fun generateGearStock(points: Int): Array + { + val stock = Array(gearStock.size) { Item(0,0) } + val qpTier = (points/18) + for((index, item) in stock.withIndex()) item.id = gearStock[index] + + for(i in 0 until min(qpTier, 10)) + { + stock[i].amount = 30 + stock[i + 10].amount = 5 + } + return stock + } + + //Default gear shop stock + private val gearStock = arrayOf( + Items.GLOVES_7453, + Items.GLOVES_7454, + Items.GLOVES_7455, + Items.GLOVES_7456, + Items.GLOVES_7457, + Items.GLOVES_7458, + Items.GLOVES_7459, + Items.GLOVES_7460, + Items.GLOVES_7461, + Items.GLOVES_7462, + Items.WOODEN_SPOON_7433, + Items.EGG_WHISK_7435, + Items.SPORK_7437, + Items.SPATULA_7439, + Items.FRYING_PAN_7441, + Items.SKEWER_7443, + Items.ROLLING_PIN_7445, + Items.KITCHEN_KNIFE_7447, + Items.MEAT_TENDERISER_7449, + Items.CLEAVER_7451 + ) + + //Default food shop stock + private val foodStock = arrayOf( + Item(Items.CHOCOLATE_BAR_1973,1), + Item(Items.CHEESE_1985, 1), + Item(Items.TOMATO_1982, 1), + Item(Items.COOKING_APPLE_1955, 1), + Item(Items.GRAPES_1987, 1), + Item(Items.POT_OF_FLOUR_1933, 1), + Item(Items.PIZZA_BASE_2283, 1), + Item(Items.EGG_1944, 1), + Item(Items.BUCKET_OF_MILK_1927, 1), + Item(Items.POT_OF_CREAM_2130, 1), + Item(Items.PAT_OF_BUTTER_6697, 1), + Item(Items.SPICE_2007, 1), + Item(Items.PIE_DISH_2313, 1), + Item(Items.CAKE_TIN_1887, 1), + Item(Items.BOWL_1923, 1), + Item(Items.JUG_1935, 1), + Item(Items.EMPTY_POT_1931, 1), + Item(Items.EMPTY_CUP_1980, 1), + Item(Items.BUCKET_1925, 1) + ) + + //Enable the chest if the player has 18 quest points or more + override fun login(player: Player) { + if(player.questRepository.points >= 18){ + player.varpManager.get(678).setVarbit(0, 5).send(player) + setAttribute(player, "culino-tier", player.questRepository.points / 18) //Set this, so we can check if the player has gained a tier during server runtime + + //Restock pulse for this player (yes, this means the chest will only restock if the player has logged in. Shop system needs work in order to do otherwise.) + val restockPulse = object : Pulse(100){ //Run once a minute + override fun pulse(): Boolean { + getShop(player, false).restock() + getShop(player, true).restock() + return false + } + } + GameWorld.Pulser.submit(restockPulse) + //Stop the pulse if the player logs out (easy way to avoid a player having multiple restock pulses by relogging a bunch) + //Stopped pulses are cleared from the list on the next tick cycle + player.logoutListeners["culino-restock"] = {restockPulse.stop()} + } + } +} \ No newline at end of file diff --git a/Server/src/main/java/core/game/interaction/object/CulinoChestListener.kt b/Server/src/main/java/core/game/interaction/object/CulinoChestListener.kt new file mode 100644 index 000000000..0b615414c --- /dev/null +++ b/Server/src/main/java/core/game/interaction/object/CulinoChestListener.kt @@ -0,0 +1,36 @@ +package core.game.interaction.`object` + +import api.getUsedOption +import core.game.world.map.RegionManager.getObject +import core.game.content.global.shop.CulinomancerShop.openShop +import core.plugin.Initializable +import core.game.interaction.OptionHandler +import core.plugin.Plugin +import core.cache.def.impl.SceneryDefinition +import core.game.content.global.shop.CulinomancerShop +import core.game.node.scenery.SceneryBuilder +import core.game.node.entity.player.Player +import core.game.node.Node +import core.game.world.map.Location +import org.rs09.consts.Scenery +import rs09.game.interaction.InteractionListener + +/** + * Handles the culino chest options. + * @author Ceikry + */ +class CulinoChestListener : InteractionListener() { + val CULINO_CHEST = Scenery.CHEST_12309 + + override fun defineListeners() { + on(CULINO_CHEST, SCENERY, "buy-items","buy-food"){player, _ -> + openShop(player, food = getUsedOption(player).toLowerCase() == "buy-food") + return@on true + } + + on(CULINO_CHEST, SCENERY, "bank"){player, _ -> + player.bank.open() + return@on true + } + } +} \ No newline at end of file diff --git a/Server/src/main/java/core/game/interaction/object/CulinomancerChestPliugin.java b/Server/src/main/java/core/game/interaction/object/CulinomancerChestPliugin.java deleted file mode 100644 index fa25b5715..000000000 --- a/Server/src/main/java/core/game/interaction/object/CulinomancerChestPliugin.java +++ /dev/null @@ -1,48 +0,0 @@ -package core.game.interaction.object; - -import core.cache.def.impl.SceneryDefinition; -import core.game.interaction.OptionHandler; -import core.game.node.Node; -import core.game.node.entity.player.Player; -import core.game.node.scenery.Scenery; -import core.game.node.scenery.SceneryBuilder; -import core.game.world.map.Location; -import core.game.world.map.RegionManager; -import core.plugin.Initializable; -import core.plugin.Plugin; -import rs09.game.system.config.ShopParser; - -/** - * Handles the culinomancer chest. - * @author Vexia - */ -@Initializable -public final class CulinomancerChestPliugin extends OptionHandler { - - @Override - public Plugin newInstance(Object arg) throws Throwable { - SceneryDefinition.forId(12309).getHandlers().put("option:bank", this); - SceneryDefinition.forId(12309).getHandlers().put("option:buy-items", this); - SceneryDefinition.forId(12309).getHandlers().put("option:buy-food", this); - Scenery object = RegionManager.getObject(new Location(3219, 9623, 0)); - SceneryBuilder.replace(object, object.transform(object.getId(), 3)); - return this; - } - - @Override - public boolean handle(Player player, Node node, String option) { - switch (option) { - case "bank": - player.getBank().open(); - return true; - case "buy-items": - ShopParser.Companion.openUid(player, 178); - return true; - case "buy-food": - ShopParser.Companion.openUid(player, 177); - return true; - } - return true; - } - -} diff --git a/Server/src/main/kotlin/rs09/game/interaction/item/CulChestItems.kt b/Server/src/main/kotlin/rs09/game/interaction/item/CulChestItems.kt deleted file mode 100644 index 042674d99..000000000 --- a/Server/src/main/kotlin/rs09/game/interaction/item/CulChestItems.kt +++ /dev/null @@ -1,56 +0,0 @@ -package rs09.game.interaction.item - -import api.* -import core.game.node.Node -import core.game.node.entity.player.Player -import core.game.node.item.GroundItemManager -import core.game.node.item.Item -import org.rs09.consts.Items -import rs09.game.interaction.InteractionListener - -class CulChestItems: InteractionListener() { - - override fun defineListeners() { - - onEquip(Items.CLEAVER_7451){player, node -> - alchemize(player,node) - } - - onEquip(Items.MEAT_TENDERISER_7449){player, node -> - alchemize(player,node) - } - - onEquip(Items.GLOVES_7458){player, node -> - alchemize(player,node) - } - - onEquip(Items.GLOVES_7459){player, node -> - alchemize(player,node) - } - - onEquip(Items.GLOVES_7460){player, node -> - alchemize(player,node) - } - - onEquip(Items.GLOVES_7461){player,node -> - alchemize(player,node) - } - - onEquip(Items.GLOVES_7462){player, node -> - alchemize(player,node) - } - - } - - fun alchemize(player: Player, node: Node): Boolean{ - val amount = amountInInventory(player, node.id) + amountInEquipment(player, node.id) - val coins = amount * itemDefinition(node.id).value - - removeAll(player, node.id, api.Container.INVENTORY) - removeItem(player, node.id, api.Container.EQUIPMENT) - addItemOrDrop(player, 995, coins) - - sendDialogue(player, "The item instantly alchemized itself!") - return false //tell equip handler not to equip the gloves at all if they still even exist lel - } -} \ No newline at end of file