diff --git a/Server/src/main/content/global/skill/cooking/dairy/DairyChurnPulse.java b/Server/src/main/content/global/skill/cooking/dairy/DairyChurnPulse.java index 9b774e607..f93e436cb 100644 --- a/Server/src/main/content/global/skill/cooking/dairy/DairyChurnPulse.java +++ b/Server/src/main/content/global/skill/cooking/dairy/DairyChurnPulse.java @@ -1,5 +1,8 @@ package content.global.skill.cooking.dairy; +import content.region.fremennik.rellekka.handlers.RellekkaUtils; +import content.region.fremennik.rellekka.handlers.RellekkaZone; +import core.game.event.ResourceProducedEvent; import core.game.node.entity.player.Player; import core.game.node.entity.player.link.diary.DiaryType; import core.game.node.entity.skill.SkillPulse; @@ -11,6 +14,9 @@ import core.game.world.update.flag.context.Animation; import core.tools.StringUtils; import org.rs09.consts.Items; +import static core.api.ContentAPIKt.location; +import static core.api.ContentAPIKt.sendMessage; + /** * Represents the skill pulse used to make a dairy product. * @author 'Vexia @@ -106,14 +112,9 @@ public final class DairyChurnPulse extends SkillPulse { } } player.getPacketDispatch().sendMessage("You make " + (StringUtils.isPlusN(dairy.getProduct().getName().toLowerCase()) ? "an" : "a") + " " + dairy.getProduct().getName().toLowerCase() + "."); + player.dispatch(new ResourceProducedEvent(dairy.getProduct().getId(), amount, node, BUCKET_OF_MILK.getId())); player.getSkills().addExperience(Skills.COOKING, dairy.getExperience(), true); - - // Seers village diary - if (player.getLocation().withinDistance(new Location(2730, 3578, 0)) - && !player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).isComplete(0,8)) { - player.getAchievementDiaryManager().getDiary(DiaryType.SEERS_VILLAGE).updateTask(player,0,8,true); - } - break; + break; } } diff --git a/Server/src/main/content/global/skill/gather/fishing/FishingListener.kt b/Server/src/main/content/global/skill/gather/fishing/FishingListener.kt index 947b1f389..bf6309c71 100644 --- a/Server/src/main/content/global/skill/gather/fishing/FishingListener.kt +++ b/Server/src/main/content/global/skill/gather/fishing/FishingListener.kt @@ -9,9 +9,9 @@ import content.global.skill.skillcapeperks.SkillcapePerks.Companion.isActive import content.global.skill.summoning.familiar.Forager import core.api.* import core.game.event.ResourceProducedEvent +import core.game.interaction.Clocks import core.game.interaction.IntType import core.game.interaction.InteractionListener -import core.game.interaction.Clocks import core.game.node.Node import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player @@ -42,6 +42,7 @@ class FishingListener : InteractionListener{ val npc = node as? NPC ?: return clearScripts(player) val spot = FishingSpot.forId(npc.id) ?: return clearScripts(player) val op = spot.getOptionByName(getUsedOption(player)) ?: return clearScripts(player) + var forager: Forager? = null if (player.familiarManager.hasFamiliar() && player.familiarManager.familiar is Forager) { @@ -58,7 +59,20 @@ class FishingListener : InteractionListener{ val dest = player.location.transform(player.direction) Pathfinder.find(it, dest).walk(it) } - sendMessage(player, "You attempt to catch some fish...") + when (op.option) { + "cage" -> if (spot.name == "CAGE_HARPOON") { + sendMessage(player, "You attempt to catch a lobster.") + } else sendMessage(player, "You attempt to catch a crayfish.") + "harpoon" -> sendMessage(player, "You start harpooning fish.") + "net" -> sendMessage(player, "You cast out your net...") + in arrayOf("bait", "lure") -> { + sendMessage(player, "You cast out your line...") + sendMessage(player, "You attempt to catch a fish.") + } + else -> { // Probably not authentic, but covers unknown cases. + sendMessage(player, "You attempt to catch some fish...") + } + } } if (clockReady(player, Clocks.SKILLING)) { @@ -72,11 +86,15 @@ class FishingListener : InteractionListener{ val bigFishId = Fish.getBigFish(fish) val bigFishChance = if (GameWorld.settings?.isDevMode == true) 10 else 5000 if (bigFishId != null && RandomFunction.roll(bigFishChance)) { - sendMessage(player, "You catch an enormous" + getItemName(fish!!.id).lowercase().replace("raw", "") + "!") + sendMessage(player, "You catch an enormous" + getItemName(fish.id).lowercase().replace("raw", "") + "!") addItemOrDrop(player, bigFishId, 1) } else { - var msg = if (fish == Fish.ANCHOVIE || fish == Fish.SHRIMP) "You catch some" else "You catch a" - msg += getItemName(fish!!.id).lowercase().replace("raw", "").replace("big", "") + var msg = when (fish) { + in arrayOf(Fish.ANCHOVIE, Fish.SHRIMP, Fish.SEAWEED) -> "You catch some " + in arrayOf(Fish.OYSTER) -> "You catch an " + else -> "You catch a " + } + msg += getItemName(fish.id).lowercase().replace("raw ", "").replace("big ", "") msg += if (fish == Fish.SHARK) "!" else "." sendMessage(player, msg) addItemOrDrop(player, item.id, item.amount) @@ -109,20 +127,29 @@ class FishingListener : InteractionListener{ private fun checkRequirements(player: Player, option: FishingOption, node: Node) : Boolean { if (!inInventory(player, option.tool) && !hasBarbTail(player, option)) { - player.dialogueInterpreter.sendDialogue("You need a " + getItemName(option.tool).lowercase() + " to catch these fish.") + // The fly fishing rod & net dialogue is confirmed from videos. Others are assumptions based upon this. + var msg = "You need a " + msg += if (getItemName(option.tool).contains("net", true)) "net to " else "${getItemName(option.tool).lowercase()} to " + msg += if (option.option in arrayOf("lure", "bait")) "${option.option} these fish." else "catch these fish." + sendDialogue(player, msg) return false } if (!option.hasBait(player)) { - player.dialogueInterpreter.sendDialogue("You don't have any " + option.getBaitName().lowercase() + "s left.") + var msg = "You don't have any " + option.getBaitName().lowercase() + msg += if (option.getBaitName() == getItemName(Items.FISHING_BAIT_313)) " left." else "s left." + sendDialogue(player, msg) return false } - if (player.skills.getLevel(Skills.FISHING) < option!!.level) { - val f = option!!.fish[option!!.fish.size - 1] - player.dialogueInterpreter.sendDialogue("You need a fishing level of " + f.level + " to catch " + (if (f == Fish.SHRIMP || f == Fish.ANCHOVIE) "" else "a") + " " + getItemName(f.id).lowercase() + ".".trim { it <= ' ' }) + if (!hasLevelDyn(player, Skills.FISHING, option.level)) { + sendDialogue(player, "You need a Fishing level of at least ${option.level} to ${option.option} these fish.") return false } - if (player.inventory.freeSlots() == 0) { - player.dialogueInterpreter.sendDialogue("You don't have enough space in your inventory.") + if (freeSlots(player) == 0) { + if (option.fish.contains(Fish.LOBSTER)) { + sendDialogue(player, "You can't carry any more lobsters.") + } else { + sendDialogue(player, "You can't carry any more fish.") + } return false } return node.isActive && node.location.withinDistance(player.location, 1) diff --git a/Server/src/main/content/global/skill/gather/fishing/FishingPulse.kt b/Server/src/main/content/global/skill/gather/fishing/FishingPulse.kt index b779ed9c0..ea254e311 100644 --- a/Server/src/main/content/global/skill/gather/fishing/FishingPulse.kt +++ b/Server/src/main/content/global/skill/gather/fishing/FishingPulse.kt @@ -1,31 +1,29 @@ package content.global.skill.gather.fishing -import core.game.event.ResourceProducedEvent import content.data.skill.SkillingPets -import core.game.node.entity.npc.NPC -import core.game.node.entity.player.Player -import core.game.node.entity.player.link.skillertasks.SkillTasks -import core.game.node.entity.skill.SkillPulse -import core.game.node.entity.skill.Skills import content.global.skill.fishing.Fish import content.global.skill.fishing.FishingOption import content.global.skill.skillcapeperks.SkillcapePerks import content.global.skill.skillcapeperks.SkillcapePerks.Companion.isActive import content.global.skill.summoning.familiar.Forager -import core.api.addItem -import core.api.getItemName -import core.api.inEquipment -import core.api.inInventory +import core.api.* +import core.game.event.ResourceProducedEvent +import core.game.node.entity.npc.NPC +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.skillertasks.SkillTasks +import core.game.node.entity.skill.SkillPulse +import core.game.node.entity.skill.Skills import core.game.node.item.Item +import core.game.system.command.sets.STATS_BASE +import core.game.system.command.sets.STATS_FISH import core.game.system.task.Pulse +import core.game.world.GameWorld.Pulser import core.game.world.map.Location import core.game.world.map.path.Pathfinder import core.game.world.update.flag.context.Animation import core.tools.RandomFunction -import core.game.system.command.sets.STATS_BASE -import core.game.system.command.sets.STATS_FISH -import core.game.world.GameWorld.Pulser import core.tools.colorize +import org.rs09.consts.Items /** * Handles a fishing pulse. @@ -58,24 +56,32 @@ class FishingPulse(player: Player?, npc: NPC, private val option: FishingOption? } player.debug(inInventory(player, option.tool).toString()) if (!inInventory(player, option.tool) && !hasBarbTail()) { - - player.dialogueInterpreter.sendDialogue("You need a " + getItemName(option.tool).lowercase() + " to catch these fish.") + // The fly fishing rod & net dialogue is confirmed from videos. Others are assumptions based upon this. + var msg = "You need a " + msg += if (getItemName(option.tool).contains("net", true)) "net to " else "${getItemName(option.tool).lowercase()} to " + msg += if (option.option in arrayOf("lure", "bait")) "${option.option} these fish." else "catch these fish." + sendDialogue(player, msg) stop() return false } if (!option.hasBait(player)) { - player.dialogueInterpreter.sendDialogue("You don't have any " + option.getBaitName().lowercase() + "s left.") + var msg = "You don't have any " + option.getBaitName().lowercase() + msg += if (option.getBaitName() == getItemName(Items.FISHING_BAIT_313)) " left." else "s left." + sendDialogue(player, msg) stop() return false } - if (player.skills.getLevel(Skills.FISHING) < option!!.level) { - val f = option!!.fish[option!!.fish.size - 1] - player.dialogueInterpreter.sendDialogue("You need a fishing level of " + f.level + " to catch " + (if (f == Fish.SHRIMP || f == Fish.ANCHOVIE) "" else "a") + " " + getItemName(f.id).lowercase() + ".".trim { it <= ' ' }) + if (!hasLevelDyn(player, Skills.FISHING, option.level)) { + sendDialogue(player, "You need a Fishing level of at least ${option.level} to ${option.option} these fish.") stop() return false } - if (player.inventory.freeSlots() == 0) { - player.dialogueInterpreter.sendDialogue("You don't have enough space in your inventory.") + if (freeSlots(player) == 0) { + if (option.fish.contains(Fish.LOBSTER)) { + sendDialogue(player, "You can't carry any more lobsters.") + } else { + sendDialogue(player, "You can't carry any more fish.") + } stop() return false } @@ -240,15 +246,23 @@ class FishingPulse(player: Player?, npc: NPC, private val option: FishingOption? override fun message(type: Int) { when (type) { - 0 -> player.packetDispatch.sendMessage(option!!.getStartMessage()) + 0 -> sendMessage(player, option!!.getStartMessage()) 2 -> { - player.packetDispatch.sendMessage( - if (fish == Fish.ANCHOVIE || fish == Fish.SHRIMP) "You catch some " + getItemName(fish!!.id).lowercase() - .replace("raw", "") - .trim { it <= ' ' } + "." else "You catch a " + getItemName(fish!!.id).lowercase() - .replace("raw", "").trim { it <= ' ' } + ".") + var msg = when (fish) { + in arrayOf(Fish.ANCHOVIE, Fish.SHRIMP, Fish.SEAWEED) -> "You catch some " + in arrayOf(Fish.OYSTER) -> "You catch an " + else -> "You catch a " + } + msg += getItemName(fish!!.id).lowercase().replace("raw ", "").replace("big ", "") + msg += if (fish == Fish.SHARK) "!" else "." + sendMessage(player, msg) + if (player.inventory.freeSlots() == 0) { - player.dialogueInterpreter.sendDialogue("You don't have enough space in your inventory.") + if (fish == Fish.LOBSTER) { + sendDialogue(player, "You can't carry any more lobsters.") + } else { + sendDialogue(player, "You can't carry any more fish.") + } stop() } } diff --git a/Server/src/main/content/global/skill/herblore/GrindItemPlugin.kt b/Server/src/main/content/global/skill/herblore/GrindItemPlugin.kt index 3d7184c06..ec9cd70c4 100644 --- a/Server/src/main/content/global/skill/herblore/GrindItemPlugin.kt +++ b/Server/src/main/content/global/skill/herblore/GrindItemPlugin.kt @@ -1,9 +1,12 @@ package content.global.skill.herblore +import core.api.addItem +import core.api.amountInInventory +import core.api.removeItem +import core.game.dialogue.SkillDialogueHandler import core.game.interaction.NodeUsageEvent import core.game.interaction.UseWithHandler import core.game.node.entity.skill.SkillPulse -import content.global.skill.herblore.GrindingItem import core.game.node.item.Item import core.game.world.update.flag.context.Animation import core.net.packet.PacketRepository @@ -11,7 +14,9 @@ import core.net.packet.context.ChildPositionContext import core.net.packet.out.RepositionChild import core.plugin.Initializable import core.plugin.Plugin -import core.game.dialogue.SkillDialogueHandler +import org.rs09.consts.Items +import kotlin.math.ceil +import kotlin.math.roundToInt /** * plugin used to handle the grinding of an item. @@ -30,14 +35,19 @@ class GrindItemPlugin : UseWithHandler(233) { override fun handle(event: NodeUsageEvent): Boolean { val grind = GrindingItem.forItem(if (event.usedItem.id == 233) event.baseItem else event.usedItem) - val handler = object : SkillDialogueHandler(event.player,SkillDialogue.ONE_OPTION,grind.product){ + val handler = object : SkillDialogueHandler(event.player,SkillDialogue.ONE_OPTION,grind.product) { override fun create(amount: Int, index: Int) { - player.pulseManager.run(object : SkillPulse(player,event.usedItem){ + player.pulseManager.run(object : SkillPulse(player,event.usedItem) { var amt = 0 init { amt = amount - if(amt > player.inventory.getAmount(node)){ - amt = player.inventory.getAmount(node) + if(amt > amountInInventory(player, node.id)) { + amt = amountInInventory(player, node.id) + } + if (node.id == FISHING_BAIT) { + if(amt > (amountInInventory(player, node.id) / 10)) { + amt = ceil(amountInInventory(player, node.id).toDouble() / 10).roundToInt() + } } super.setDelay(2) } @@ -50,8 +60,20 @@ class GrindItemPlugin : UseWithHandler(233) { } override fun reward(): Boolean { - if(player.inventory.remove(node)){ - player.inventory.add(GrindingItem.forItem(node).product) + if (node.id == Items.FISHING_BAIT_313) { + var quantity = 0 + quantity = if (amountInInventory(player, FISHING_BAIT) >= 10) { + 10 + } else { + amountInInventory(player, FISHING_BAIT) + } + if (removeItem(player, Item(node.id, quantity))) { + addItem(player, GrindingItem.forItem(node).product.id, quantity) + } + } else { + if (removeItem(player, Item(node.id, 1))) { + addItem(player, GrindingItem.forItem(node).product.id) + } } amt-- return amt <= 0 @@ -61,7 +83,7 @@ class GrindItemPlugin : UseWithHandler(233) { } override fun getAll(index: Int): Int { - return player.inventory.getAmount(event.usedItem) + return amountInInventory(player, event.usedItem.id) } } handler.open() @@ -74,5 +96,6 @@ class GrindItemPlugin : UseWithHandler(233) { * Represents the animation to use. */ private val ANIMATION = Animation(364) + private const val FISHING_BAIT = Items.FISHING_BAIT_313 } } diff --git a/Server/src/main/content/global/skill/herblore/GrindingItem.java b/Server/src/main/content/global/skill/herblore/GrindingItem.java index 7f8db39df..83b1f3efe 100644 --- a/Server/src/main/content/global/skill/herblore/GrindingItem.java +++ b/Server/src/main/content/global/skill/herblore/GrindingItem.java @@ -8,21 +8,21 @@ import core.game.node.item.Item; * @author Vexia */ public enum GrindingItem { - UNICORN_HORN(new Item[] { new Item(237) },new Item(235)), - KEBBIT_TEETH(new Item[] { new Item(10109) }, new Item(10111)), - BIRDS_NEST(new Item[] { new Item(5070), new Item(5071), new Item(5072), new Item(5073), new Item(5074), new Item(5075) }, new Item(6693)), - GOAT_HORN(new Item[] { new Item(9735) }, new Item(9736)), - MUD_RUNE(new Item[] { new Item(4698) }, new Item(9594)), - ASHES(new Item[] { new Item(592) }, new Item(8865)), - POISON_KARAMBWAN(new Item[] { new Item(3146) }, new Item(3152)), - FISHING_BAIT(new Item[] { new Item(313) }, new Item(12129)), - SEAWEED(new Item[] { new Item(401) }, new Item(6683)), - BAT_BONES(new Item[] { new Item(530) }, new Item(2391)), - CHARCOAL(new Item[] { new Item(973) }, new Item(704)), - ASTRAL_RUNE_SHARDS(new Item[] { new Item(11156) }, new Item(11155)), - GARLIC(new Item[] { new Item(1550) }, new Item(4668)), - DRAGON_SCALE(new Item[] { new Item(243) }, new Item(241)), - ANCHOVIES(new Item[] { new Item(319) }, new Item(11266)), + UNICORN_HORN(new Item[] { new Item(Items.UNICORN_HORN_237) }, new Item(Items.UNICORN_HORN_DUST_235)), + KEBBIT_TEETH(new Item[] { new Item(Items.KEBBIT_TEETH_10109) }, new Item(Items.KEBBIT_TEETH_DUST_10111)), + BIRDS_NEST(new Item[] { new Item(Items.BIRDS_NEST_5075) }, new Item(Items.CRUSHED_NEST_6693)), + GOAT_HORN(new Item[] { new Item(Items.DESERT_GOAT_HORN_9735) }, new Item(Items.GOAT_HORN_DUST_9736)), + MUD_RUNE(new Item[] { new Item(Items.MUD_RUNE_4698) }, new Item(Items.GROUND_MUD_RUNES_9594)), + ASHES(new Item[] { new Item(Items.ASHES_592) }, new Item(Items.GROUND_ASHES_8865)), + POISON_KARAMBWAN(new Item[] { new Item(Items.POISON_KARAMBWAN_3146) }, new Item(Items.KARAMBWAN_PASTE_3152)), + FISHING_BAIT(new Item[] { new Item(Items.FISHING_BAIT_313) }, new Item(Items.GROUND_FISHING_BAIT_12129)), + SEAWEED(new Item[] { new Item(Items.SEAWEED_401) }, new Item(Items.GROUND_SEAWEED_6683)), + BAT_BONES(new Item[] { new Item(Items.BAT_BONES_530) }, new Item(Items.GROUND_BAT_BONES_2391)), + CHARCOAL(new Item[] { new Item(Items.CHARCOAL_973) }, new Item(Items.GROUND_CHARCOAL_704)), + ASTRAL_RUNE_SHARDS(new Item[] { new Item(Items.ASTRAL_RUNE_SHARDS_11156) }, new Item(Items.GROUND_ASTRAL_RUNE_11155)), + GARLIC(new Item[] { new Item(Items.GARLIC_1550) }, new Item(Items.GARLIC_POWDER_4668)), + DRAGON_SCALE(new Item[] { new Item(Items.BLUE_DRAGON_SCALE_243) }, new Item(Items.DRAGON_SCALE_DUST_241)), + ANCHOVIES(new Item[] { new Item(Items.ANCHOVIES_319) }, new Item(Items.ANCHOVY_PASTE_11266)), CHOCOLATE_BAR(new Item[] {new Item(Items.CHOCOLATE_BAR_1973)}, new Item(Items.CHOCOLATE_DUST_1975)), GUAM_LEAF(new Item[] { new Item(Items.CLEAN_GUAM_249) }, new Item(Items.GROUND_GUAM_6681)); diff --git a/Server/src/main/content/global/skill/thieving/StallThiefPulse.java b/Server/src/main/content/global/skill/thieving/StallThiefPulse.java index 4734385c3..7cb9b2dd8 100644 --- a/Server/src/main/content/global/skill/thieving/StallThiefPulse.java +++ b/Server/src/main/content/global/skill/thieving/StallThiefPulse.java @@ -1,5 +1,6 @@ package content.global.skill.thieving; +import core.game.event.ResourceProducedEvent; import core.game.node.entity.skill.SkillPulse; import core.game.node.entity.skill.Skills; import core.game.node.entity.npc.NPC; @@ -119,6 +120,7 @@ public final class StallThiefPulse extends SkillPulse { return true; } player.getPacketDispatch().sendMessage("You steal " + (StringUtils.isPlusN(item.getName()) ? "an" : "a") + " " + item.getName().toLowerCase() + " from the " + stall.name().toLowerCase().replace('_',' ') + "."); + player.dispatch(new ResourceProducedEvent(item.getId(), item.getAmount(), node, 0)); } return true; } diff --git a/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt b/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt index e460ba6b0..e6367c387 100644 --- a/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt +++ b/Server/src/main/content/region/fremennik/diary/FremennikAchievementDiary.kt @@ -1,16 +1,9 @@ package content.region.fremennik.diary -import core.game.node.entity.player.Player -import core.game.node.entity.player.link.diary.DiaryType -import core.game.world.map.zone.ZoneBorders -import org.rs09.consts.Items -import org.rs09.consts.NPCs -import org.rs09.consts.Scenery -import content.minigame.barbassault.CaptainCainDialogue -import content.region.fremennik.rellekka.dialogue.HuntingExpertRellekkaDialogue import content.global.handlers.iface.FairyRing -import content.global.skill.cooking.dairy.DairyChurnDialogue +import content.minigame.barbassault.CaptainCainDialogue import content.region.fremennik.jatizso.dialogue.TowerGuardDialogue +import content.region.fremennik.rellekka.dialogue.HuntingExpertRellekkaDialogue import content.region.fremennik.rellekka.quest.thefremenniktrials.ChieftanBrundt import core.api.inBorders import core.api.inEquipment @@ -18,9 +11,12 @@ import core.game.diary.AreaDiaryTask import core.game.diary.DiaryEventHookBase import core.game.diary.DiaryLevel import core.game.event.* +import core.game.node.entity.player.Player import core.game.node.entity.player.link.SpellBookManager +import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.skill.Skills -import org.rs09.consts.Components +import core.game.world.map.zone.ZoneBorders +import org.rs09.consts.* class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { companion object { @@ -166,16 +162,6 @@ class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { ) } } - - is DairyChurnDialogue -> { - if (event.optionId == 12) { - finishTask( - player, - DiaryLevel.MEDIUM, - MediumTasks.MAKE_CHEESE_WITH_CHURN - ) - } - } } } @@ -183,10 +169,22 @@ class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { when (player.viewport.region.id) { 10553 -> if (event.source.id in FISHING_SPOTS) { finishTask( - player, - DiaryLevel.EASY, + player, + DiaryLevel.EASY, EasyTasks.PIER_CATCH_FISH ) + } else if (event.itemId == Items.CHEESE_1985) { + finishTask( + player, + DiaryLevel.MEDIUM, + MediumTasks.MAKE_CHEESE_WITH_CHURN + ) + } else if (event.source.id == Scenery.FISH_STALL_4277) { + finishTask( + player, + DiaryLevel.MEDIUM, + MediumTasks.STEAL_FISH_FROM_STALL + ) } /* After Royal trouble quest @@ -298,14 +296,6 @@ class FremennikAchievementDiary : DiaryEventHookBase(DiaryType.FREMENNIK) { override fun onInteracted(player: Player, event: InteractionEvent) { when (player.viewport.region.id) { - 10553 -> if (event.target.id == Scenery.FISH_STALL_4277 && event.option == "steal-from" && player.questRepository.isComplete("Fremennik Trials")) { - finishTask( - player, - DiaryLevel.MEDIUM, - MediumTasks.STEAL_FISH_FROM_STALL - ) - } - 10811 -> if (event.target.id == Scenery.COLLAPSED_TRAP_19233 && inBorders(player, RELLEKKA_HUNTING_AREA) && event.option == "dismantle") { finishTask( player, diff --git a/Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchivementDiary.kt b/Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchievementDiary.kt similarity index 92% rename from Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchivementDiary.kt rename to Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchievementDiary.kt index 015578c9c..75dfde368 100644 --- a/Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchivementDiary.kt +++ b/Server/src/main/content/region/kandarin/seers/diary/SeersVillageAchievementDiary.kt @@ -1,12 +1,5 @@ package content.region.kandarin.seers.diary -import core.game.node.entity.player.Player -import core.game.node.entity.player.link.diary.DiaryType -import core.game.node.item.Item -import core.game.world.map.Location -import core.game.world.map.zone.ZoneBorders -import org.rs09.consts.Items -import org.rs09.consts.NPCs import content.global.handlers.iface.FairyRing import content.global.handlers.item.withnpc.PoisonChaliceOnKingArthurDialogue import core.api.inBorders @@ -14,8 +7,15 @@ import core.api.inEquipment import core.game.diary.DiaryEventHookBase import core.game.diary.DiaryLevel import core.game.event.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.diary.DiaryType +import core.game.node.item.Item +import core.game.world.map.Location +import core.game.world.map.zone.ZoneBorders +import org.rs09.consts.Items +import org.rs09.consts.NPCs -class SeersVillageAchivementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) { +class SeersVillageAchievementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) { companion object { private const val ATTRIBUTE_CUT_YEW_COUNT = "diary:seers:cut-yew" private const val ATTRIBUTE_BASS_CAUGHT = "diary:seers:bass-caught" @@ -47,6 +47,10 @@ class SeersVillageAchivementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) NPCs.AIR_ELEMENTAL_1021, NPCs.WATER_ELEMENTAL_1022 ) + private val CHURN_PRODUCT = arrayOf( + Items.CHEESE_1985, Items.POT_OF_CREAM_2130, Items.PAT_OF_BUTTER_6697 + ) + object EasyTasks { const val PICK_5_FLAX = 0 const val WALK_CLOCKWISE_AROUND_MYSTERIOUS_STATUE = 1 @@ -94,6 +98,14 @@ class SeersVillageAchivementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) override fun onResourceProduced(player: Player, event: ResourceProducedEvent) { when (player.viewport.region.id) { + 10807 -> if (event.itemId in CHURN_PRODUCT) { + finishTask( + player, + DiaryLevel.EASY, + EasyTasks.SINCLAIR_MANSION_USE_CHURN + ) + } + 10806 -> if (event.itemId == Items.YEW_LOGS_1515) { progressIncrementalTask( player, @@ -263,8 +275,8 @@ class SeersVillageAchivementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) if (inBorders(player, SEERS_BANK_AREA)) { if (event.itemId == Items.MAGIC_SHORTBOW_861 && event.isHigh) { finishTask( - player, - DiaryLevel.HARD, + player, + DiaryLevel.HARD, HardTasks.HIGH_ALCH_MAGIC_SHORTBOW_INSIDE_BANK ) } @@ -274,10 +286,20 @@ class SeersVillageAchivementDiary : DiaryEventHookBase(DiaryType.SEERS_VILLAGE) override fun onFairyRingDialed(player: Player, event: FairyRingDialEvent) { if (event.fairyRing == FairyRing.ALS) { finishTask( - player, - DiaryLevel.HARD, + player, + DiaryLevel.HARD, HardTasks.DIAL_FAIRY_RING_MCGRUBORS_WOOD ) } } + + override fun onItemPurchasedFromShop(player: Player, event: ItemShopPurchaseEvent) { + if (event.itemId == Items.CANDLE_36 && player.viewport.region.id == 11061) { + finishTask( + player, + DiaryLevel.EASY, + EasyTasks.BUY_CANDLE + ) + } + } } \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/CandleMakerDialogue.java b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/CandleMakerDialogue.java index a9d3369cf..003add8ff 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/CandleMakerDialogue.java +++ b/Server/src/main/content/region/kandarin/seers/quest/merlinsquest/CandleMakerDialogue.java @@ -58,7 +58,7 @@ public final class CandleMakerDialogue extends DialoguePlugin { NPC npc = node.asNpc(); Quest quest = player.getQuestRepository().getQuest("Merlin's Crystal"); if (quest.getStage(player) > 60) { - Shops.openId(player, 198); + Shops.openId(player, 56); } else { npc.openShop(player); } @@ -175,7 +175,7 @@ public final class CandleMakerDialogue extends DialoguePlugin { case 30: end(); if (quest.getStage(player) > 60) { - Shops.openId(player, 198); + Shops.openId(player, 56); } else { npc.openShop(player); } diff --git a/Server/src/main/content/region/kandarin/catherby/dialogue/CandleSellerPlugin.java b/Server/src/main/content/region/misthalin/lumbridge/dialogue/CandleSellerDialogue.java similarity index 96% rename from Server/src/main/content/region/kandarin/catherby/dialogue/CandleSellerPlugin.java rename to Server/src/main/content/region/misthalin/lumbridge/dialogue/CandleSellerDialogue.java index 878052d7c..f2497754b 100644 --- a/Server/src/main/content/region/kandarin/catherby/dialogue/CandleSellerPlugin.java +++ b/Server/src/main/content/region/misthalin/lumbridge/dialogue/CandleSellerDialogue.java @@ -1,4 +1,4 @@ -package content.region.kandarin.catherby.dialogue; +package content.region.misthalin.lumbridge.dialogue; import core.game.dialogue.DialoguePlugin; import core.game.dialogue.FacialExpression; @@ -13,7 +13,7 @@ import core.game.node.item.Item; * @version 1.0 */ @Initializable -public final class CandleSellerPlugin extends DialoguePlugin { +public final class CandleSellerDialogue extends DialoguePlugin { /** * Represents the coins item. @@ -28,7 +28,7 @@ public final class CandleSellerPlugin extends DialoguePlugin { /** * Constructs a new {@code CandleSellerPlugin} {@code Object}. */ - public CandleSellerPlugin() { + public CandleSellerDialogue() { /** * empty. */ @@ -38,13 +38,13 @@ public final class CandleSellerPlugin extends DialoguePlugin { * Constructs a new {@code CandleSellerPlugin} {@code Object}. * @param player the player. */ - public CandleSellerPlugin(Player player) { + public CandleSellerDialogue(Player player) { super(player); } @Override public DialoguePlugin newInstance(Player player) { - return new CandleSellerPlugin(player); + return new CandleSellerDialogue(player); } @Override diff --git a/Server/src/main/core/game/shops/Shop.kt b/Server/src/main/core/game/shops/Shop.kt index 801c80a4c..d19a4c2ec 100644 --- a/Server/src/main/core/game/shops/Shop.kt +++ b/Server/src/main/core/game/shops/Shop.kt @@ -1,24 +1,22 @@ package core.game.shops +import core.ServerConstants import core.api.* +import core.game.component.Component +import core.game.container.* +import core.game.container.Container import core.game.event.ItemShopPurchaseEvent import core.game.event.ItemShopSellEvent -import core.game.component.Component -import core.game.container.Container -import core.game.container.ContainerEvent -import core.game.container.ContainerListener -import core.game.container.ContainerType import core.game.node.entity.player.Player import core.game.node.item.Item +import core.game.shops.Shops.Companion.logShop +import core.game.system.config.ItemConfigParser +import core.game.world.GameWorld import core.net.packet.PacketRepository import core.net.packet.context.ContainerContext import core.net.packet.out.ContainerPacket import org.rs09.consts.Components import org.rs09.consts.Items -import core.ServerConstants -import core.game.shops.Shops.Companion.logShop -import core.game.system.config.ItemConfigParser -import core.game.world.GameWorld import java.lang.Integer.max import java.lang.Integer.min import kotlin.math.ceil @@ -78,8 +76,8 @@ class Shop(val title: String, val stock: Array, val general: Boolean = } val settings = IfaceSettingsBuilder() - .enableOptions(0..9) - .build() + .enableOptions(0..9) + .build() player.packetDispatch.sendIfaceSettings(settings, if (main) 23 else 24, Components.SHOP_TEMPLATE_620, 0, cont.capacity()) player.packetDispatch.sendRunScript(150, "IviiiIsssssssss", "", "", "", "", "Buy X", "Buy 10", "Buy 5", "Buy 1", "Value", -1, 0, 4, 10, 92, (620 shl 16) or if (main) 23 else 24) @@ -196,21 +194,21 @@ class Shop(val title: String, val stock: Array, val general: Boolean = var (isPlayerStock, shopSlot) = getStockSlot(shopItemId) val stockAmt = - if(isPlayerStock) - 0 - else{ - if(shopSlot != -1) stock[shopSlot].amount - else 0 - } - val currentAmt = - if(isPlayerStock) playerStock.getAmount(shopItemId) - else { - if(shopSlot != -1) shopCont[shopSlot].amount - else { - isPlayerStock = true + if(isPlayerStock) 0 + else{ + if(shopSlot != -1) stock[shopSlot].amount + else 0 + } + val currentAmt = + if(isPlayerStock) playerStock.getAmount(shopItemId) + else { + if(shopSlot != -1) shopCont[shopSlot].amount + else { + isPlayerStock = true + 0 + } } - } val price = when(currency) { @@ -240,9 +238,9 @@ class Shop(val title: String, val stock: Array, val general: Boolean = val price: Int = ceil(item.definition.value * mod.toDouble() / 100.0).toInt() -/* if(player.getVarp(532) == 6529){ - price = 3 * price / 2 - }*/ + /* if(player.getVarp(532) == 6529){ + price = 3 * price / 2 + }*/ return max(price, 1) } @@ -300,7 +298,7 @@ class Shop(val title: String, val stock: Array, val general: Boolean = while(amt-- > 1) cost.amount += getGPCost(Item(item.id, 1), if (isMainStock) stock[slot].amount else playerStock[slot].amount, --inStockAmt) } else { - cost.amount = cost.amount * item.amount + cost.amount = cost.amount * item.amount } if(inInventory(player, cost.id, cost.amount)) @@ -338,7 +336,8 @@ class Shop(val title: String, val stock: Array, val general: Boolean = } else { - sendMessage(player, "You don't have enough ${cost.name.toLowerCase()} to buy that many.") + sendMessage(player, "You don't have enough ${cost.name.lowercase()} to buy that many.") + return TransactionStatus.Failure("Not enough money in inventory") } player.dispatch(ItemShopPurchaseEvent(item.id, item.amount, cost)) @@ -457,4 +456,4 @@ class Shop(val title: String, val stock: Array, val general: Boolean = class Success : TransactionStatus() class Failure(val reason: String) : TransactionStatus() } -} +} \ No newline at end of file diff --git a/Server/src/main/core/game/shops/Shops.kt b/Server/src/main/core/game/shops/Shops.kt index 230f5e0b3..94408357e 100644 --- a/Server/src/main/core/game/shops/Shops.kt +++ b/Server/src/main/core/game/shops/Shops.kt @@ -1,23 +1,25 @@ package core.game.shops +import content.global.skill.crafting.TanningProduct +import core.ServerConstants import core.api.* +import core.game.ge.GrandExchange +import core.game.interaction.IntType +import core.game.interaction.InteractionListener +import core.game.interaction.InterfaceListener import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player -import content.global.skill.crafting.TanningProduct +import core.game.system.command.Privilege +import core.tools.END_DIALOGUE +import core.tools.Log +import core.tools.secondsToTicks import org.json.simple.JSONArray import org.json.simple.JSONObject import org.json.simple.parser.JSONParser import org.rs09.consts.Components import org.rs09.consts.Items import org.rs09.consts.NPCs -import core.ServerConstants -import core.game.interaction.InteractionListener -import core.game.interaction.IntType -import core.game.interaction.InterfaceListener -import core.game.system.command.Privilege import java.io.FileReader -import core.tools.* -import core.game.ge.* /** * The "controller" class for shops. Handles opening shops from various NPC interactions and updating stock, etc. @@ -154,6 +156,15 @@ class Shops : StartupListener, TickListener, InteractionListener, InterfaceListe } return@on true } + + on(NPCs.CANDLE_MAKER_562, IntType.NPC, "trade") { player, node -> + if (getQuestStage(player, "Merlin's Crystal") > 60) { + openId(player, 56) + } else { + shopsByNpc[node.id]?.openFor(player) + } + return@on true + } } override fun defineInterfaceListeners() { @@ -179,7 +190,7 @@ class Shops : StartupListener, TickListener, InteractionListener, InterfaceListe when(opcode) { - OP_VALUE -> sendMessage(player, "${getItemName(if (isMainStock) shop.stock[slot].itemId else shop.playerStock[slot].id)}: This item currently costs ${price.amount} ${price.name.toLowerCase()}.") + OP_VALUE -> sendMessage(player, "${getItemName(if (isMainStock) shop.stock[slot].itemId else shop.playerStock[slot].id)}: This item currently costs ${price.amount} ${price.name.lowercase()}.") OP_BUY_1 -> shop.buy(player, slot, 1) OP_BUY_5 -> shop.buy(player, slot, 5) OP_BUY_10 -> shop.buy(player, slot, 10) diff --git a/Server/src/test/kotlin/ShopTests.kt b/Server/src/test/kotlin/ShopTests.kt index 218280204..025fd13f1 100644 --- a/Server/src/test/kotlin/ShopTests.kt +++ b/Server/src/test/kotlin/ShopTests.kt @@ -1,11 +1,12 @@ + import core.game.node.entity.player.link.IronmanMode import core.game.node.item.Item +import core.game.shops.Shop +import core.game.shops.Shops import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.rs09.consts.Items -import core.game.shops.Shop -import core.game.shops.Shops import kotlin.math.min import kotlin.math.roundToInt @@ -228,7 +229,7 @@ class ShopTests { } @Test fun shouldAllowStandardPlayerToBuy() { - testPlayer.inventory.add(Item(995, 100000)) + testPlayer.inventory.add(Item(995, 125000)) testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer)) testPlayer.setAttribute("shop-main", true) val status = general.buy(testPlayer, 0, 1) @@ -236,7 +237,7 @@ class ShopTests { } @Test fun shouldAllowStandardPlayerToBuyOverstock() { - testPlayer.inventory.add(Item(995, 100000)) + testPlayer.inventory.add(Item(995, 125000)) testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer)) testPlayer.setAttribute("shop-main", true) general.getContainer(testPlayer).add(Item(4151, 100)) @@ -245,7 +246,7 @@ class ShopTests { } @Test fun shouldAllowStandardPlayerToBuyPlayerStock() { - testPlayer.inventory.add(Item(995, 100000)) + testPlayer.inventory.add(Item(995, 125000)) testPlayer.setAttribute("shop-cont", general.getContainer(testPlayer)) testPlayer.setAttribute("shop-main", false) general.playerStock.add(Item(4151, 100))