diff --git a/.gitignore b/.gitignore index 50416bde6..4daf3c49b 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,5 @@ gradle .idea .idea/ Server/worldprops/ -Management-Server/managementprops/ \ No newline at end of file +Management-Server/managementprops/ +/Development-Client/ \ No newline at end of file diff --git a/Management-Server/src/main/java/ms/net/IoEventHandler.java b/Management-Server/src/main/java/ms/net/IoEventHandler.java index 3139ae044..907ad9bbf 100644 --- a/Management-Server/src/main/java/ms/net/IoEventHandler.java +++ b/Management-Server/src/main/java/ms/net/IoEventHandler.java @@ -1,6 +1,7 @@ package ms.net; import ms.world.WorldDatabase; +import ms09.MSLogger; import java.io.IOException; import java.nio.ByteBuffer; @@ -69,6 +70,7 @@ public final class IoEventHandler { if(session.getGameServer() != null){ WorldDatabase.unRegister(session.getGameServer()); } + session.disconnect(); key.cancel(); return; } diff --git a/Server/build.gradle b/Server/build.gradle index 505344a91..cc0a72780 100644 --- a/Server/build.gradle +++ b/Server/build.gradle @@ -28,7 +28,7 @@ dependencies { implementation 'io.github.classgraph:classgraph:4.8.98' implementation 'org.jetbrains.kotlin:kotlin-reflect' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2' - implementation files("libs/ConstLib-1.0.jar") + implementation files("libs/ConstLib-1.2.jar") implementation files("libs/PrimitiveExtensions-1.0.jar") } diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index 4649bf719..d4b55bab4 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -7851,13 +7851,13 @@ }, { "minAmount": "10", - "weight": "25.0", + "weight": "12.5", "id": "886", - "maxAmount": "15" + "maxAmount": "10" }, { "minAmount": "1", - "weight": "50.0", + "weight": "25.0", "id": "1191", "maxAmount": "1" }, @@ -7869,79 +7869,73 @@ }, { "minAmount": "1", - "weight": "25.0", + "weight": "8.0", "id": "1309", "maxAmount": "1" }, { - "minAmount": "1", - "weight": "5.0", + "minAmount": "3", + "weight": "8.0", "id": "888", - "maxAmount": "1" + "maxAmount": "3" }, { "minAmount": "1", - "weight": "50.0", + "weight": "8.0", "id": "1207", "maxAmount": "1" }, { "minAmount": "1", - "weight": "25.0", + "weight": "8.0", "id": "1119", "maxAmount": "1" }, - { - "minAmount": "1", - "weight": "5.0", - "id": "890", - "maxAmount": "5" - }, { "minAmount": "7", - "weight": "50.0", + "weight": "25.0", "id": "555", "maxAmount": "7" }, { "minAmount": "15", - "weight": "50.0", + "weight": "8.0", "id": "554", "maxAmount": "15" }, { "minAmount": "2", - "weight": "50.0", + "weight": "8.0", "id": "564", "maxAmount": "2" }, { "minAmount": "2", - "weight": "25.0", + "weight": "8.0", "id": "563", "maxAmount": "3" }, { "minAmount": "6", - "weight": "25.0", + "weight": "8.0", "id": "561", "maxAmount": "6" }, { "minAmount": "3", - "weight": "50.0", + "weight": "8.0", "id": "558", "maxAmount": "3" }, { "minAmount": "2", - "weight": "5.0", + "weight": "8.0", "id": "560", "maxAmount": "2" }, { "minAmount": "2", - "weight": "5.0", + "weight": "8.0", "id": "562", "maxAmount": "2" }, @@ -7965,141 +7959,117 @@ }, { "minAmount": "1", - "weight": "5.0", + "weight": "8.0", "id": "207", "maxAmount": "1" }, { "minAmount": "1", - "weight": "5.0", + "weight": "25.0", "id": "205", "maxAmount": "1" }, { "minAmount": "1", - "weight": "5.0", + "weight": "8.0", "id": "209", "maxAmount": "1" }, { "minAmount": "1", - "weight": "5.0", + "weight": "8.0", "id": "211", "maxAmount": "1" }, { "minAmount": "1", - "weight": "5.0", + "weight": "8.0", "id": "213", "maxAmount": "1" }, { "minAmount": "1", - "weight": "5.0", + "weight": "8.0", "id": "217", "maxAmount": "1" }, { "minAmount": "1", - "weight": "5.0", + "weight": "8.0", "id": "215", "maxAmount": "1" }, { "minAmount": "1", - "weight": "5.0", + "weight": "8.0", "id": "2485", "maxAmount": "1" }, { "minAmount": "1", - "weight": "50.0", + "weight": "25.0", "id": "5322", "maxAmount": "3" }, { "minAmount": "1", "weight": "25.0", - "id": "5306", - "maxAmount": "3" - }, - { - "minAmount": "1", - "weight": "50.0", "id": "5318", "maxAmount": "4" }, { "minAmount": "4", - "weight": "50.0", + "weight": "25.0", "id": "5319", "maxAmount": "4" }, { "minAmount": "8", - "weight": "50.0", + "weight": "25.0", "id": "5319", "maxAmount": "8" }, { "minAmount": "2", - "weight": "50.0", + "weight": "25.0", "id": "5323", "maxAmount": "2" }, { "minAmount": "4", - "weight": "50.0", + "weight": "25.0", "id": "5324", "maxAmount": "4" }, - { - "minAmount": "2", - "weight": "25.0", - "id": "5307", - "maxAmount": "3" - }, { "minAmount": "1", - "weight": "5.0", + "weight": "8.0", "id": "5100", "maxAmount": "1" }, { "minAmount": "3", - "weight": "5.0", + "weight": "8.0", "id": "5320", "maxAmount": "3" }, { "minAmount": "1", - "weight": "25.0", - "id": "5302", - "maxAmount": "1" - }, - { - "minAmount": "2", - "weight": "5.0", + "weight": "8.0", "id": "5321", - "maxAmount": "2" - }, - { - "minAmount": "3", - "weight": "25.0", - "id": "5308", - "maxAmount": "3" + "maxAmount": "4" }, { "minAmount": "8", "weight": "50.0", "id": "995", - "maxAmount": "8" + "maxAmount": "80" }, { - "minAmount": "15", - "weight": "50.0", + "minAmount": "80", + "weight": "8.0", "id": "995", - "maxAmount": "15" + "maxAmount": "300" }, { "minAmount": "1", @@ -8115,7 +8085,7 @@ }, { "minAmount": "1", - "weight": "25.0", + "weight": "8.0", "id": "1446", "maxAmount": "1" }, @@ -8134,14 +8104,14 @@ { "minAmount": "1", "weight": "5.0", - "id": "2353", + "id": "31", "maxAmount": "1" }, { - "minAmount": "1", - "weight": "5.0", - "id": "31", - "maxAmount": "1" + "minAmount": "15", + "weight": "12.5", + "id": "886", + "maxAmount": "15" } ] }, diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json index 7ffc459ac..3e93b4770 100644 --- a/Server/data/configs/item_configs.json +++ b/Server/data/configs/item_configs.json @@ -139147,35 +139147,25 @@ }, { "id": "14651", - "examine": "Passed down from the super egg defending bunny knights.", + "examine": "Mysterious blueprints written in an alien language.", "destroy": "true", - "destroy_message": " WARNING: This item CAN NOT be re-obtained.", - "requirements": "{0,40}", + "destroy_message": " WARNING: You will have to reobtain this item the hard way.", + "requirements": "", "durability": null, - "weight": "0.4", - "attack_speed": "4", - "weapon_interface": "12", - "render_anim": "326", - "equipment_slot": "3", - "fun_weapon": "true", - "name": "Eggscalibur", - "archery_ticket_price": "0", - "bonuses": "-100,-100,-50,0,0,0,0,0,0,0,0,-10,0,0,0" + "weight": "0.1", + "name": "Ancient Blueprints", + "archery_ticket_price": "0" }, { - "name": "Super Egg", + "name": "Ring of the Star Sprite", "id": "14652", - "examine": "SUPER. EGG. SUPER. EGG.", + "examine": "A stardust-infused dragonstone ring.", "destroy": "true", - "destroy_message": "You dare destroy I?! THE ALL MIGHTY AND POWERFUL SUPER EGG?!", + "destroy_message": "You can get another by bringing the materials along with the blueprint to a Star Sprite.", "durability": null, - "weight": "0.4", - "attack_speed": "4", - "weapon_interface": "12", - "render_anim": "182", - "equipment_slot": "3", - "fun_weapon": "true", + "weight": "0.1", + "equipment_slot": "12", "archery_ticket_price": "0", - "bonuses": "-100,-100,-50,0,0,0,0,0,0,0,0,-10,0,0,0" + "bonuses": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" } ] \ No newline at end of file diff --git a/Server/libs/ConstLib-1.0.jar b/Server/libs/ConstLib-1.2.jar similarity index 71% rename from Server/libs/ConstLib-1.0.jar rename to Server/libs/ConstLib-1.2.jar index ae01341e3..e8679d136 100644 Binary files a/Server/libs/ConstLib-1.0.jar and b/Server/libs/ConstLib-1.2.jar differ diff --git a/Server/src/main/java/core/game/node/entity/player/link/TeleportManager.java b/Server/src/main/java/core/game/node/entity/player/link/TeleportManager.java index bed9736b9..d3933cfe2 100644 --- a/Server/src/main/java/core/game/node/entity/player/link/TeleportManager.java +++ b/Server/src/main/java/core/game/node/entity/player/link/TeleportManager.java @@ -668,25 +668,7 @@ public class TeleportManager { @Override public void start() { - player = ((Player) entity); - if (TutorialSession.getExtension(player).getStage() < TutorialSession.MAX_STAGE) { - stop(); - return; - } - if (player.getSavedData().getGlobalData().getMinigameTeleportDelay() > System.currentTimeMillis()) { - long milliseconds = player.getSavedData().getGlobalData().getMinigameTeleportDelay() - System.currentTimeMillis(); - int minutes = (int) Math.round(milliseconds / 60000); - if (minutes > 30) { - player.getSavedData().getGlobalData().setMinigameTeleportDelay(System.currentTimeMillis() + 600000); - milliseconds = player.getSavedData().getGlobalData().getMinigameTeleportDelay() - System.currentTimeMillis(); - minutes = (int) Math.round(milliseconds / 60000); - } - if (minutes != 0) { - player.getPacketDispatch().sendMessage("You need to wait another " + minutes + " " + (minutes == 1 ? "minute" : "minutes") + " to use the finder again."); - stop(); - return; - } - } + super.start(); } @@ -694,7 +676,7 @@ public class TeleportManager { public void stop() { super.stop(); entity.getAnimator().forceAnimation(new Animation(-1)); - player.graphics(new Graphics(-1)); + entity.graphics(new Graphics(-1)); } }; } diff --git a/Server/src/main/java/core/net/JS5Queue.java b/Server/src/main/java/core/net/JS5Queue.java index 7dbe80ce0..b08d1b10a 100644 --- a/Server/src/main/java/core/net/JS5Queue.java +++ b/Server/src/main/java/core/net/JS5Queue.java @@ -1,39 +1,66 @@ package core.net; -import core.game.system.task.TaskExecutor; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.atomic.AtomicBoolean; /** * Handles the JS5 queue for a session. - * @author Emperor + * @author Techdaan */ public final class JS5Queue { - /** - * The queued JS5 requests. - */ - private final Map queue = new HashMap<>(); + public static AtomicBoolean RUNNING = new AtomicBoolean(true); + + private static final Js5QueueHandler handler = new Js5QueueHandler(); + + private static class Js5QueueHandler extends Thread { + private final LinkedBlockingDeque requests = new LinkedBlockingDeque<>(); + + @Override + public void run() { + while (RUNNING.get()) { + try { + Js5Request request = requests.take(); + + JS5Queue queue = request.queue; + + if (queue.session.isActive()) { + queue.session.write(new int[]{request.index, request.archive, request.priority ? 1 : 0}); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + + static { + try { + handler.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static class Js5Request { + private final JS5Queue queue; + private final int index; + private final int archive; + private final boolean priority; + + public Js5Request(JS5Queue queue, int index, int archive, boolean priority) { + this.queue = queue; + this.index = index; + this.archive = archive; + this.priority = priority; + } + } /** * The I/O session. */ private final IoSession session; - /** - * If the queue has been scheduled for release. - */ - private boolean scheduledRelease; - - /** - * The lock object. - */ - private Lock lock = new ReentrantLock(); - /** * Constructs a new {@code JS5Queue} {@code Object}. * @param session The I/O session. @@ -44,53 +71,18 @@ public final class JS5Queue { /** * Queues a JS-5 request. + * Timers: + * 1000ms queue up files for this long + * 100ms release a file from the queue + * * @param container The container. * @param archive The archive. * @param highPriority If the request is high priority. + * */ public void queue(int container, int archive, boolean highPriority) { - try { - lock.tryLock(1000L, TimeUnit.MILLISECONDS); - } catch (Exception e){ - e.printStackTrace(); - lock.unlock(); - return; - } - int key = container << 16 | archive; - if (queue.containsKey(key)) { - // SystemLogger.logErr("Queue already contained request " + container - // + "," + archive + " > " + (container << 16 | archive) + "."); - } - queue.put(key, highPriority); - lock.unlock(); - release(); - } - - /** - * Releases the queue. - */ - public void release() { - lock.lock(); - if (!scheduledRelease) { - scheduledRelease = true; - TaskExecutor.getExecutor().schedule(new Runnable() { - @Override - public void run() { - lock.lock(); - for (Integer hash : queue.keySet()) { - try { - session.write(new int[] { hash >> 16 & 0xFF, hash & 0xFFFF, queue.get(hash) ? 1 : 0 }); - } catch (Throwable t) { - t.printStackTrace(); - } - } - queue.clear(); - scheduledRelease = false; - lock.unlock(); - } - }, 100, TimeUnit.MILLISECONDS); - } - lock.unlock(); + Js5Request request = new Js5Request(this, container, archive, highPriority); + handler.requests.add(request); } /** @@ -101,20 +93,5 @@ public final class JS5Queue { return session; } - /** - * Gets the scheduledRelease. - * @return the scheduledRelease - */ - public boolean isScheduledRelease() { - return scheduledRelease; - } - - /** - * Sets the scheduledRelease. - * @param scheduledRelease the scheduledRelease to set. - */ - public void setScheduledRelease(boolean scheduledRelease) { - this.scheduledRelease = scheduledRelease; - } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/content/activity/communityevents/SuperEggEaster2020.kt b/Server/src/main/kotlin/rs09/game/content/activity/communityevents/SuperEggEaster2020.kt deleted file mode 100644 index 4969f2885..000000000 --- a/Server/src/main/kotlin/rs09/game/content/activity/communityevents/SuperEggEaster2020.kt +++ /dev/null @@ -1,52 +0,0 @@ -package rs09.game.content.activity.communityevents - -import core.game.node.item.Item -import core.game.world.map.Location -import org.rs09.consts.Items -import rs09.game.interaction.InteractionListener -import rs09.game.system.config.GroundSpawnLoader - -class SuperEggEaster2020 : InteractionListener() { - override fun defineListeners() { - val egg = GroundSpawnLoader.GroundSpawn(-1,Item(14652,1),Location.create(2926, 3480, 0)).init() - - onDig(Location.create(2188, 3281, 0)){player -> - val hasKey = player.getAttribute("easter2020:key",false) - if(!hasKey){ - player.inventory.add(Item(Items.KEY_11039)) - player.dialogueInterpreter.sendDialogue("You dig and find an ancient key!") - player.setAttribute("/save:easter2020:key",true) - } else { - player.sendMessage("You dig and find nothing.") - } - } - - on(14652, ITEM,"unlock"){player, node -> - val item = node.asItem() - - if(player.inventory.contains(Items.KEY_11039,1)){ - player.dialogueInterpreter.sendDialogue("As you approach the egg you feel a great sense of unease.","You feel as though some ancient force lurks within the egg.","The key in your pocket begins to pull towards the egg...") - player.dialogueInterpreter.addAction { pl, _ -> - if(!pl.getAttribute("2020superegg",false)){ - pl.dialogueInterpreter.sendDialogue("However...","The egg does not recognize your essence.","You have been rejected.") - } else { - pl.dialogueInterpreter.sendDialogue("The egg recognizes your essence.","Visions of ancient Easterian knowledge fill your mind.","An ancient Easterian relic lurks within the egg.") - pl.dialogueInterpreter.addAction { p, _ -> - player.inventory.remove(Item(Items.KEY_11039)) - player.dialogueInterpreter.sendItemMessage(14651,"You pull from within the egg an ancient weapon.") - player.inventory.add(Item(14651)) - } - } - } - - } else { - player.dialogueInterpreter.sendDialogue("You approach the egg but you sense that it rejects you.") - } - - return@on true - } - - } -} - - diff --git a/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStarMiningPulse.kt b/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStarMiningPulse.kt index dac8fa0a3..b51717e83 100644 --- a/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStarMiningPulse.kt +++ b/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/ShootingStarMiningPulse.kt @@ -1,5 +1,6 @@ package rs09.game.content.global.worldevents.shootingstar +import api.ContentAPI import core.game.content.global.worldevents.shootingstar.ScoreboardManager import core.game.node.`object`.Scenery import core.game.node.entity.player.Player @@ -7,8 +8,11 @@ import core.game.node.entity.skill.SkillPulse import core.game.node.entity.skill.Skills import core.game.node.entity.skill.gather.SkillingTool import core.game.node.item.Item +import core.tools.RandomFunction +import org.rs09.consts.Items import rs09.game.world.GameWorld import rs09.game.world.repository.Repository +import rs09.tools.stringtools.colorize /** * The pulse used to handle mining shooting stars. @@ -71,9 +75,32 @@ class ShootingStarMiningPulse(player: Player?, node: Scenery?, val star: Shootin if (ShootingStarOptionHandler.getStarDust(player) < 200) { player.inventory.add(Item(ShootingStarOptionHandler.STAR_DUST, 1)) } + if(!ContentAPI.inInventory(player, Items.ANCIENT_BLUEPRINT_14651) && !ContentAPI.inBank(player, Items.ANCIENT_BLUEPRINT_14651)){ + rollBlueprint(player) + } return false } + fun rollBlueprint(player: Player){ + val chance = when(star.level){ + ShootingStarType.LEVEL_9 -> 250 + ShootingStarType.LEVEL_8 -> 500 + ShootingStarType.LEVEL_7 -> 750 + ShootingStarType.LEVEL_6 -> 1000 + ShootingStarType.LEVEL_5 -> 2000 + ShootingStarType.LEVEL_4 -> 3000 + ShootingStarType.LEVEL_3 -> 4000 + ShootingStarType.LEVEL_2 -> 5000 + ShootingStarType.LEVEL_1 -> 10000 + } + + if(RandomFunction.roll(chance)){ + ContentAPI.addItemOrDrop(player, Items.ANCIENT_BLUEPRINT_14651, 1) + ContentAPI.sendMessage(player, colorize("%RWhile mining the star you find an ancient-looking blueprint.")) + ContentAPI.sendNews("${player.username} found an Ancient Blueprint while mining a shooting star!") + } + } + override fun message(type: Int) { when (type) { 0 -> player.packetDispatch.sendMessage("You swing your pickaxe at the rock...") diff --git a/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/StarSpriteDialogue.kt b/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/StarSpriteDialogue.kt index 2944989b0..dfb237cb2 100644 --- a/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/StarSpriteDialogue.kt +++ b/Server/src/main/kotlin/rs09/game/content/global/worldevents/shootingstar/StarSpriteDialogue.kt @@ -1,9 +1,18 @@ package rs09.game.content.global.worldevents.shootingstar +import api.Container +import api.ContentAPI import core.game.content.dialogue.DialoguePlugin +import core.game.content.dialogue.FacialExpression import core.game.node.entity.npc.NPC import core.game.node.entity.player.Player import core.game.node.item.Item +import core.tools.RandomFunction +import org.rs09.consts.Items +import rs09.game.node.entity.state.newsys.states.ShootingStarState +import rs09.tools.END_DIALOGUE +import rs09.tools.secondsToTicks +import rs09.tools.stringtools.colorize import java.util.concurrent.TimeUnit /** @@ -55,6 +64,12 @@ class StarSpriteDialogue(player: Player? = null) : DialoguePlugin(player) { if (player.getSavedData().getGlobalData().getStarSpriteDelay() > System.currentTimeMillis() || !player.getInventory().contains(ShootingStarOptionHandler.STAR_DUST, 1)) { npc("Hello, strange creature.") stage = 0 + } else if (ContentAPI.inInventory(player, Items.ANCIENT_BLUEPRINT_14651) && !ContentAPI.getAttribute(player, "star-ring:bp-shown", false)) { + npcl(FacialExpression.NEUTRAL, "I see you got ahold of a blueprint of those silly old rings we used to make.") + stage = 1000 + } else if (ContentAPI.inInventory(player, Items.ANCIENT_BLUEPRINT_14651) && ContentAPI.getAttribute(player, "star-ring:bp-shown", false)) { + playerl(FacialExpression.HALF_ASKING, "So about those rings...") + stage = 2000 } else { npc("Thank you for helping me out of here.") stage = 50 @@ -166,6 +181,7 @@ class StarSpriteDialogue(player: Player? = null) : DialoguePlugin(player) { } 41 -> end() 50 -> { + val wearingRing = ContentAPI.inEquipment(player, Items.RING_OF_THE_STAR_SPRITE_14652) val dust = if (player.getInventory().getAmount(ShootingStarOptionHandler.STAR_DUST) > 200) 200 else player.getInventory().getAmount(ShootingStarOptionHandler.STAR_DUST) if (player.getInventory().remove(Item(ShootingStarOptionHandler.STAR_DUST, dust))) { val cosmicRunes = (Math.ceil(0.76 * dust) * AMPLIFIER).toInt() @@ -178,11 +194,61 @@ class StarSpriteDialogue(player: Player? = null) : DialoguePlugin(player) { player.getInventory().add(Item(COINS, coins), player) npc("I have rewarded you by making it so you can mine", "extra ore for the next 15 minutes. Also, have $cosmicRunes", "cosmic runes, $astralRunes astral runes, $goldOre gold ore and $coins", "coins.") player.getSavedData().getGlobalData().setStarSpriteDelay(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1)) - player.registerState("shooting-star").init() + player.registerState("shooting-star")?.init() + + if(wearingRing){ + val item = intArrayOf(Items.COSMIC_RUNE_564, Items.ASTRAL_RUNE_9075, Items.GOLD_ORE_445, Items.COINS_995).random() + val amount = when(item){ + Items.COSMIC_RUNE_564 -> cosmicRunes + Items.ASTRAL_RUNE_9075 -> astralRunes + Items.GOLD_ORE_445 -> goldOre + Items.COINS_995 -> coins + else -> 0 + } + rollForRingBonus(player, item, amount) + } + } + + if(!ContentAPI.inInventory(player, Items.ANCIENT_BLUEPRINT_14651) && !ContentAPI.inBank(player, Items.ANCIENT_BLUEPRINT_14651) && RandomFunction.roll(500)){ + ContentAPI.addItemOrDrop(player, Items.ANCIENT_BLUEPRINT_14651, 1) + ContentAPI.sendMessage(player, colorize("%RThe Star Sprite dropped what looks like some ancient piece of paper and you pick it up.")) + ContentAPI.sendNews("${player.username} found an Ancient Blueprint while mining a shooting star!") } stage = 52 } 52 -> end() + + //Inauthentic ring-based dialogue + 1000 -> playerl(FacialExpression.ASKING, "Oh, you mean this?").also { stage++ } + 1001 -> player.dialogueInterpreter.sendItemMessage(Items.ANCIENT_BLUEPRINT_14651, "You show the blueprint to the Star Sprite.").also { stage++ } + 1002 -> npcl(FacialExpression.ASKING, "Yeah, that's the one, alright!").also { stage++ } + 1003 -> npcl(FacialExpression.NEUTRAL, "I'll tell you what.. if you can get ahold of the resources needed to make one, I'm sure me or one of my kin would craft it for you.").also { stage++ } + 1004 -> playerl(FacialExpression.ASKING, "You'd just do that for me? For free?").also { stage++ } + 1005 -> npcl(FacialExpression.NEUTRAL, "I don't see why not. We used to make these for fun and hand them out to adventurers all the time.").also { stage++ } + 1006 -> playerl(FacialExpression.ASKING, "Well, thanks! So.. what do we need to make one?").also { stage++ } + 1007 -> npcl(FacialExpression.NEUTRAL, "Looking at the blueprint here...").also { stage++ } + 1008 -> npcl(FacialExpression.NEUTRAL, "Yes, it seems we need a ring mould, a silver bar, a cut dragonstone and 200 stardust. Oh, and make sure to bring this blueprint with you.").also { stage++ } + 1009 -> playerl(FacialExpression.FRIENDLY, "Thanks, I'll get right on it!").also { stage++ } + 1010 -> playerl(FacialExpression.ASKING, "So just to make sure I've got it right, I need a ring mould, a silver bar, a cut dragonstone and 200 stardust, as well as this blueprint?").also { stage++ } + 1011 -> npcl(FacialExpression.NEUTRAL, "Yeah, you've got it, human. Any of my kin should be able to do this for you.").also { stage++; ContentAPI.setAttribute(player, "/save:star-ring:bp-shown", true) } + 1012 -> playerl(FacialExpression.FRIENDLY, "Thanks!").also { stage = END_DIALOGUE } + + 2000 -> npcl(FacialExpression.NEUTRAL, "Yes, did you bring the components to make it, human?").also { stage++ } + 2001 -> if(ContentAPI.inInventory(player, Items.DRAGONSTONE_1615,1) && ContentAPI.inInventory(player, Items.RING_MOULD_1592, 1) && ContentAPI.inInventory(player, Items.STARDUST_13727, 200) && ContentAPI.inInventory(player, Items.SILVER_BAR_2355, 1)){ + playerl(FacialExpression.FRIENDLY, "Yes, I have them right here, friend.").also { stage++ } + } else { + playerl(FacialExpression.HALF_GUILTY, "I'm afraid not, what did I need again?").also { stage = 2100 } + } + 2002 -> npcl(FacialExpression.NEUTRAL, "Excellent, give me just a moment here...").also { stage++ } + 2003 -> sendDialogue("You watch as the Star Sprite casts some strange spell.").also { stage++ } + 2004 -> if(ContentAPI.removeItem(player, Items.SILVER_BAR_2355, Container.INVENTORY) && ContentAPI.removeItem(player, Items.DRAGONSTONE_1615, Container.INVENTORY) && ContentAPI.removeItem(player, Item(Items.STARDUST_13727, 200), Container.INVENTORY)){ + ContentAPI.addItem(player, Items.RING_OF_THE_STAR_SPRITE_14652) + player.dialogueInterpreter.sendItemMessage(Items.RING_OF_THE_STAR_SPRITE_14652, "The Star Sprite hands you a strange ring.").also { stage++ } + } else end() + 2005 -> npcl(FacialExpression.NEUTRAL, "There you go, I hope you enjoy it!").also { stage++ } + 2006 -> playerl(FacialExpression.FRIENDLY, "Thank you!").also { stage = END_DIALOGUE } + + 2100 -> npcl(FacialExpression.NEUTRAL, "A ring mould, a cut dragonstone, a silver bar and 200 stardust.").also { stage = END_DIALOGUE } } return true } @@ -191,4 +257,18 @@ class StarSpriteDialogue(player: Player? = null) : DialoguePlugin(player) { return intArrayOf(8091) } + fun rollForRingBonus(player: Player, bonusId: Int, bonusBaseAmt: Int){ + if(RandomFunction.roll(3)){ + val state = player.states["shooting-star"] as? ShootingStarState ?: return + state.ticksLeft += secondsToTicks(TimeUnit.MINUTES.toSeconds(5).toInt()) + ContentAPI.sendMessage(player, colorize("%RYour ring shines dimly as if imbued with energy.")) + } else if(RandomFunction.roll(5)){ + ContentAPI.addItem(player, bonusId, bonusBaseAmt) + ContentAPI.sendMessage(player, colorize("%RYour ring shines brightly as if surging with energy and then fades out.")) + } else if(RandomFunction.roll(25)){ + player.savedData.globalData.starSpriteDelay = 0L + ContentAPI.sendMessage(player, colorize("%RYour ring vibrates briefly as if surging with power, and then stops.")) + } + } + } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/ge/PlayerGrandExchange.kt b/Server/src/main/kotlin/rs09/game/ge/PlayerGrandExchange.kt index 867cf6cdc..a2c31eeb3 100644 --- a/Server/src/main/kotlin/rs09/game/ge/PlayerGrandExchange.kt +++ b/Server/src/main/kotlin/rs09/game/ge/PlayerGrandExchange.kt @@ -241,7 +241,7 @@ class PlayerGrandExchange(private val player: Player) { SystemLogger.logAlert("Check your logs, AVENGING ANGLE might have fucked up HARD and now " + player.name + "'s trade with index " + index + "is gone :(") continue } - OfferManager.setIndex(offer["offerUID"].toString().toInt().toLong(), index) + OfferManager.setIndex(offer["offerUID"].toString().toLong(), index) offers[index] = OfferManager.OFFER_MAPPING[offer["offerUID"].toString().toLong()] update(offers[index]) } diff --git a/Server/src/main/kotlin/rs09/game/interaction/item/ImplingJarListener.kt b/Server/src/main/kotlin/rs09/game/interaction/item/ImplingJarListener.kt new file mode 100644 index 000000000..d9ba9e9e6 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/interaction/item/ImplingJarListener.kt @@ -0,0 +1,266 @@ +package rs09.game.interaction.item + +import api.Container +import api.ContentAPI +import core.game.content.ttrail.ClueScrollPlugin +import org.rs09.consts.Items +import rs09.game.content.global.WeightBasedTable +import rs09.game.content.global.WeightedItem +import rs09.game.interaction.InteractionListener +import rs09.game.system.SystemLogger + +class ImplingJarListener : InteractionListener() { + + val JARS = ImplingLoot.values().map { it.jarId }.toIntArray() + + override fun defineListeners() { + on(JARS, ITEM, "loot"){player, node -> + val jar = node.asItem() + + val loot = ImplingLoot.forId(jar.id)?.roll()?.first() ?: return@on false + + if(ContentAPI.removeItem(player, jar, Container.INVENTORY)) { + ContentAPI.addItemOrDrop(player, loot.id, loot.amount) + ContentAPI.addItemOrDrop(player, Items.IMPLING_JAR_11260, 1) + } + + return@on true + } + } +} + + +enum class ImplingLoot(val jarId: Int, val table: WeightBasedTable){ + BABY_IMPLING(Items.BABY_IMPLING_JAR_11238, WeightBasedTable.create( + WeightedItem(Items.CHISEL_1755, 1, 1, 10.0), + WeightedItem(Items.THREAD_1734, 1, 1, 10.0), + WeightedItem(Items.NEEDLE_1733, 1, 1, 10.0), + WeightedItem(Items.KNIFE_946,1, 1, 10.0), + WeightedItem(Items.CHEESE_1985, 1, 1, 10.0), + WeightedItem(Items.HAMMER_2347, 1, 1, 10.0), + WeightedItem(0, 1, 1, 10.0), + WeightedItem(Items.BALL_OF_WOOL_1759, 1, 1, 10.0), + WeightedItem(Items.ANCHOVIES_319, 1, 1, 10.0), + WeightedItem(Items.SPICE_2007, 1, 1, 1.0), + WeightedItem(Items.FLAX_1779, 1, 1, 1.0), + WeightedItem(Items.MUD_PIE_7170, 1, 1, 1.0), + WeightedItem(Items.SEAWEED_401, 1, 1, 1.0), + WeightedItem(Items.AIR_TALISMAN_1438, 1, 1, 1.0), + WeightedItem(Items.SILVER_BAR_2355, 1, 1, 1.0), + WeightedItem(Items.SAPPHIRE_1607, 1, 1, 1.0), + WeightedItem(Items.HARD_LEATHER_1743, 1, 1, 1.0), + WeightedItem(Items.LOBSTER_379, 1, 1, 1.0), + WeightedItem(Items.SOFT_CLAY_1761, 1, 1, 1.0) + ).insertEasyClue(1.0)), + + YOUNG_IMPLING(Items.YOUNG_IMPLING_JAR_11240, WeightBasedTable.create( + WeightedItem(Items.STEEL_NAILS_1539, 5, 5, 10.0), + WeightedItem(Items.LOCKPICK_1523, 1, 1, 10.0), + WeightedItem(Items.PURE_ESSENCE_7936, 1, 1, 10.0), + WeightedItem(Items.TUNA_361, 1, 1, 10.0), + WeightedItem(Items.CHOCOLATE_SLICE_1901, 1, 1, 10.0), + WeightedItem(Items.STEEL_AXE_1353, 1, 1, 10.0), + WeightedItem(Items.MEAT_PIZZA_2293, 1, 1, 10.0), + WeightedItem(Items.COAL_453, 1, 1, 10.0), + WeightedItem(Items.BOW_STRING_1777, 1, 1, 10.0), + WeightedItem(Items.SNAPE_GRASS_231, 1, 1, 1.0), + WeightedItem(Items.SOFT_CLAY_1761, 1, 1, 1.0), + WeightedItem(Items.STUDDED_CHAPS_1097, 1, 1, 1.0), + WeightedItem(Items.STEEL_FULL_HELM_1157, 1, 1, 1.0), + WeightedItem(Items.OAK_PLANK_8778, 1, 1, 1.0), + WeightedItem(Items.DEFENCE_POTION3_133, 1, 1, 1.0), + WeightedItem(Items.MITHRIL_BAR_2359, 1, 1, 1.0), + WeightedItem(Items.YEW_LONGBOW_855, 1, 1, 1.0), + WeightedItem(Items.GARDEN_PIE_7178, 1, 1, 1.0), + WeightedItem(Items.JANGERBERRIES_247, 1, 1, 1.0) + ).insertEasyClue(2.0)), + + GOURMET_IMPLING(Items.GOURM_IMPLING_JAR_11242, WeightBasedTable.create( + WeightedItem(Items.TUNA_361, 1, 1, 20.0), + WeightedItem(Items.BASS_365, 1, 1, 10.0), + WeightedItem(Items.CURRY_2011, 1, 1, 10.0), + WeightedItem(Items.MEAT_PIE_2327, 1, 1, 10.0), + WeightedItem(Items.CHOCOLATE_CAKE_1897, 1, 1, 10.0), + WeightedItem(Items.FROG_SPAWN_5004, 1, 1, 10.0), + WeightedItem(Items.SPICE_2007, 1, 1, 10.0), + WeightedItem(Items.CURRY_LEAF_5970, 1, 1, 10.0), + WeightedItem(Items.UGTHANKI_KEBAB_1883, 1, 1, 1.0), + WeightedItem(Items.LOBSTER_380, 4, 4, 1.0), + WeightedItem(Items.SHARK_386, 3, 3, 1.0), + WeightedItem(Items.FISH_PIE_7188, 1, 1, 1.0), + WeightedItem(Items.CHEFS_DELIGHT4_5833, 1, 1, 1.0), + WeightedItem(Items.RAINBOW_FISH_10137, 5, 5, 1.0), + WeightedItem(Items.GARDEN_PIE_7179, 6, 6, 1.0), + WeightedItem(Items.SWORDFISH_374, 3, 3, 1.0), + WeightedItem(Items.STRAWBERRIES5_5406, 1, 1, 1.0), + WeightedItem(Items.COOKED_KARAMBWAN_3145, 2, 2, 1.0), + ).insertEasyClue(4.0)), + + EARTH_IMPLING(Items.EARTH_IMPLING_JAR_11244, WeightBasedTable.create( + WeightedItem(Items.FIRE_TALISMAN_1442, 1, 1, 10.0), + WeightedItem(Items.EARTH_TALISMAN_1440, 1, 1, 10.0), + WeightedItem(Items.EARTH_TIARA_5535, 1, 1, 10.0), + WeightedItem(Items.EARTH_RUNE_557, 32, 32, 10.0), + WeightedItem(Items.MITHRIL_ORE_447, 1, 1, 10.0), + WeightedItem(Items.BUCKET_OF_SAND_1784, 4, 4, 10.0), + WeightedItem(Items.UNICORN_HORN_237, 1, 1, 10.0), + WeightedItem(Items.COMPOST_6033, 6, 6, 10.0), + WeightedItem(Items.GOLD_ORE_444, 1, 1, 10.0), + WeightedItem(Items.STEEL_BAR_2353, 1, 1, 1.0), + WeightedItem(Items.MITHRIL_PICKAXE_1273, 1, 1, 1.0), + WeightedItem(Items.WILDBLOOD_SEED_5311, 2, 2, 1.0), + WeightedItem(Items.JANGERBERRY_SEED_5104, 2, 2, 1.0), + WeightedItem(Items.SUPERCOMPOST_6035, 2, 2, 1.0), + WeightedItem(Items.MITHRIL_ORE_448, 3, 3, 1.0), + WeightedItem(Items.HARRALANDER_SEED_5294, 2, 2, 1.0), + WeightedItem(Items.COAL_454, 6, 6, 1.0), + WeightedItem(Items.EMERALD_1606, 2, 2, 1.0), + WeightedItem(Items.RUBY_1603, 1, 1, 1.0) + ).insertMediumClue(1.0)), + + ESSENCE_IMPLING(Items.ESS_IMPLING_JAR_11246, WeightBasedTable.create( + WeightedItem(Items.PURE_ESSENCE_7937, 20, 20, 10.0), + WeightedItem(Items.WATER_RUNE_555, 30, 30, 10.0), + WeightedItem(Items.AIR_RUNE_556, 30, 30, 10.0), + WeightedItem(Items.FIRE_RUNE_554, 50, 50, 10.0), + WeightedItem(Items.MIND_RUNE_558, 25, 25, 10.0), + WeightedItem(Items.BODY_RUNE_559, 28, 28, 10.0), + WeightedItem(Items.CHAOS_RUNE_562, 4, 4, 10.0), + WeightedItem(Items.COSMIC_RUNE_564, 4, 4, 10.0), + WeightedItem(Items.MIND_TALISMAN_1448, 1, 1, 10.0), + WeightedItem(Items.PURE_ESSENCE_7937, 35, 35, 1.0), + WeightedItem(Items.LAVA_RUNE_4699, 4, 4, 1.0), + WeightedItem(Items.MUD_RUNE_4698, 4, 4, 1.0), + WeightedItem(Items.SMOKE_RUNE_4697, 4, 4, 1.0), + WeightedItem(Items.STEAM_RUNE_4694, 4, 4, 1.0), + WeightedItem(Items.DEATH_RUNE_560, 13, 13, 1.0), + WeightedItem(Items.LAW_RUNE_563, 13, 13, 1.0), + WeightedItem(Items.BLOOD_RUNE_565, 7, 7, 1.0), + WeightedItem(Items.SOUL_RUNE_566, 11, 11, 1.0), + WeightedItem(Items.NATURE_RUNE_561, 13, 13, 1.0) + ).insertMediumClue(2.0)), + + ECLECTIC_IMPLING(Items.ECLECTIC_IMPLING_JAR_11248, WeightBasedTable.create( + WeightedItem(Items.MITHRIL_PICKAXE_1273, 1, 1, 10.0), + WeightedItem(Items.CURRY_LEAF_5970, 1, 1, 10.0), + WeightedItem(Items.SNAPE_GRASS_231, 1, 1, 10.0), + WeightedItem(Items.AIR_RUNE_556, 30, 58, 10.0), + WeightedItem(Items.OAK_PLANK_8779, 4, 4, 10.0), + WeightedItem(Items.CANDLE_LANTERN_4527, 1, 1, 10.0), + WeightedItem(Items.GOLD_ORE_444, 1, 1, 10.0), + WeightedItem(Items.GOLD_BAR_2358, 5, 5, 10.0), + WeightedItem(Items.UNICORN_HORN_237, 1, 1, 10.0), + WeightedItem(Items.ADAMANT_KITESHIELD_1199, 1, 1, 1.0), + WeightedItem(Items.BLUE_DHIDE_CHAPS_2493, 1, 1, 1.0), + WeightedItem(Items.RED_SPIKY_VAMBS_10083, 1, 1, 1.0), + WeightedItem(Items.RUNE_DAGGER_1213, 1, 1, 1.0), + WeightedItem(Items.BATTLESTAFF_1391, 1, 1, 1.0), + WeightedItem(Items.ADAMANTITE_ORE_450, 10, 10, 1.0), + WeightedItem(Items.SLAYERS_RESPITE4_5842, 2, 2, 1.0), + WeightedItem(Items.WILD_PIE_7208, 1, 1, 1.0), + WeightedItem(Items.WATERMELON_SEED_5321, 3, 3, 1.0), + WeightedItem(Items.DIAMOND_1601, 1, 1, 1.0) + ).insertMediumClue(4.0)), + + NATURE_IMPLING(Items.NATURE_IMPLING_JAR_11250, WeightBasedTable.create( + WeightedItem(Items.LIMPWURT_SEED_5100, 1, 1, 10.0), + WeightedItem(Items.JANGERBERRY_SEED_5104, 1, 1, 10.0), + WeightedItem(Items.BELLADONNA_SEED_5281, 1, 1, 10.0), + WeightedItem(Items.HARRALANDER_SEED_5294, 1, 1, 10.0), + WeightedItem(Items.CACTUS_SPINE_6016, 1, 1, 10.0), + WeightedItem(Items.MAGIC_LOGS_1513, 1, 1, 10.0), + WeightedItem(Items.CLEAN_TARROMIN_254, 4, 4, 10.0), + WeightedItem(Items.COCONUT_5974, 1, 1, 10.0), + WeightedItem(Items.IRIT_SEED_5297, 1, 1, 10.0), + WeightedItem(Items.CURRY_TREE_SEED_5286, 1, 1, 1.0), + WeightedItem(Items.ORANGE_TREE_SEED_5285, 1, 1, 1.0), + WeightedItem(Items.CLEAN_SNAPDRAGON_3000, 1, 1, 1.0), + WeightedItem(Items.KWUARM_SEED_5299, 1, 1, 1.0), + WeightedItem(Items.AVANTOE_SEED_5298, 5, 5, 1.0), + WeightedItem(Items.WILLOW_SEED_5313, 1, 1, 1.0), + WeightedItem(Items.TORSTOL_SEED_5304, 1, 1, 1.0), + WeightedItem(Items.RANARR_SEED_5295, 1, 1, 1.0), + WeightedItem(Items.CLEAN_TORSTOL_270, 2, 2, 1.0), + WeightedItem(Items.DWARF_WEED_SEED_5303, 1, 1, 1.0) + ).insertHardClue(1.0)), + + MAGPIE_IMPLING(Items.MAGPIE_IMPLING_JAR_11252, WeightBasedTable.create( + WeightedItem(Items.BLACK_DRAGONHIDE_1748, 6, 6, 10.0), + WeightedItem(Items.DIAMOND_AMULET_1682, 3, 3, 5.0), + WeightedItem(Items.AMULET_OF_POWER_1732, 3, 3, 5.0), + WeightedItem(Items.RING_OF_FORGING_2569, 3, 3, 5.0), + WeightedItem(Items.SPLITBARK_GAUNTLETS_3391, 1, 1, 5.0), + WeightedItem(Items.MYSTIC_BOOTS_4097, 1, 1, 5.0), + WeightedItem(Items.MYSTIC_GLOVES_4095, 1, 1, 5.0), + WeightedItem(Items.RUNE_WARHAMMER_1347, 1, 1, 5.0), + WeightedItem(Items.RING_OF_LIFE_2571, 4, 4, 5.0), + WeightedItem(Items.RUNE_SQ_SHIELD_1185, 1, 1, 5.0), + WeightedItem(Items.DRAGON_DAGGER_1215, 1, 1, 5.0), + WeightedItem(Items.NATURE_TIARA_5541, 1, 1, 5.0), + WeightedItem(Items.RUNITE_BAR_2364, 2, 2, 5.0), + WeightedItem(Items.DIAMOND_1602, 4, 4, 5.0), + WeightedItem(Items.PINEAPPLE_SEED_5287, 1, 1, 5.0), + WeightedItem(Items.LOOP_HALF_OF_A_KEY_987, 1, 1, 5.0), + WeightedItem(Items.TOOTH_HALF_OF_A_KEY_985, 1, 1, 5.0), + WeightedItem(Items.SNAPDRAGON_SEED_5300, 1, 1, 5.0), + WeightedItem(Items.SINISTER_KEY_993, 1, 1, 5.0) + ).insertHardClue(2.0)), + + NINJA_IMPLING(Items.NINJA_IMPLING_JAR_11254, WeightBasedTable.create( + WeightedItem(Items.SNAKESKIN_BOOTS_6328, 1, 1, 1.65), + WeightedItem(Items.SPLITBARK_HELM_3385, 1, 1, 1.65), + WeightedItem(Items.MYSTIC_BOOTS_4098, 1, 1, 1.65), + WeightedItem(Items.RUNE_CHAINBODY_1113, 1, 1, 1.65), + WeightedItem(Items.MYSTIC_GLOVES_4095, 1, 1, 1.65), + WeightedItem(Items.OPAL_MACHETE_6313, 1, 1, 1.65), + WeightedItem(Items.RUNE_CLAWS_3101, 1, 1, 1.65), + WeightedItem(Items.RUNE_SCIMITAR_1333, 1, 1, 1.65), + WeightedItem(Items.DRAGON_DAGGERP_PLUS_5680, 1, 1, 1.65), + WeightedItem(Items.RUNE_ARROW_892, 70, 70, 1.65), + WeightedItem(Items.RUNE_DART_811, 70, 70, 1.65), + WeightedItem(Items.RUNE_KNIFE_868, 40, 40, 1.65), + WeightedItem(Items.RUNE_THROWNAXE_805, 50, 50, 1.65), + WeightedItem(Items.ONYX_BOLTS_9342, 2, 2, 1.65), + WeightedItem(Items.ONYX_BOLT_TIPS_9194, 4, 4, 1.65), + WeightedItem(Items.BLACK_DRAGONHIDE_1748, 10, 10, 1.65), + WeightedItem(Items.PRAYER_POTION3_140, 4, 4, 1.65), + WeightedItem(Items.WEAPON_POISON_PLUS_5938, 4, 4, 1.65), + WeightedItem(Items.DAGANNOTH_HIDE_6156, 3, 3, 1.65) + ).insertHardClue(1.0)), + + DRAGON_IMPLING(Items.DRAGON_IMPLING_JAR_11256, WeightBasedTable.create( + WeightedItem(Items.DRAGON_BOLT_TIPS_9193, 10, 30, 2.0), + WeightedItem(Items.DRAGON_BOLT_TIPS_9193, 36, 36, 2.0), + WeightedItem(Items.MYSTIC_ROBE_BOTTOM_4093, 1, 1, 2.0), + WeightedItem(Items.AMULET_OF_GLORY_1705, 3, 3, 2.0), + WeightedItem(Items.DRAGONSTONE_AMMY_1684, 2, 2, 2.0), + WeightedItem(Items.DRAGON_ARROW_11212, 100, 250, 2.0), + WeightedItem(Items.DRAGON_BOLTS_9341, 10, 40, 2.0), + WeightedItem(Items.DRAGON_LONGSWORD_1305, 1, 1, 2.0), + WeightedItem(Items.DRAGON_DAGGERP_PLUS_PLUS_5699, 3, 3, 2.0), + WeightedItem(Items.DRAGON_DART_11230, 100, 250, 2.0), + WeightedItem(Items.DRAGONSTONE_1616, 3, 3, 2.0), + WeightedItem(Items.DRAGON_DART_TIP_11232, 100, 350, 2.0), + WeightedItem(Items.DRAGON_ARROWTIPS_11237, 100, 350, 2.0), + WeightedItem(Items.BABYDRAGON_BONES_535, 1, 25, 2.0), + WeightedItem(Items.DRAGON_BONES_537, 1, 25, 2.0), + WeightedItem(Items.MAGIC_SEED_5316, 1, 1, 2.0), + WeightedItem(Items.SNAPDRAGON_SEED_5300, 6, 6, 2.0), + WeightedItem(Items.SUMMER_PIE_7219, 15, 15, 2.0) + ).insertHardClue(1.0)); + + companion object{ + + val jarMap = HashMap() + + init { + for(impling in values()){ + jarMap[impling.jarId] = impling.table + } + } + + fun forId(id: Int): WeightBasedTable?{ + return jarMap[id] + } + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/interaction/item/StarRingListener.kt b/Server/src/main/kotlin/rs09/game/interaction/item/StarRingListener.kt new file mode 100644 index 000000000..d59350e4f --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/interaction/item/StarRingListener.kt @@ -0,0 +1,85 @@ +package rs09.game.interaction.item + +import api.ContentAPI +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.TeleportManager +import core.game.node.entity.skill.Skills +import core.game.world.map.Location +import org.rs09.consts.Items +import rs09.game.content.dialogue.DialogueFile +import rs09.game.content.global.worldevents.WorldEvents +import rs09.game.content.global.worldevents.shootingstar.ShootingStar +import rs09.game.content.global.worldevents.shootingstar.ShootingStarEvent +import rs09.game.interaction.InteractionListener +import java.util.concurrent.TimeUnit + +class StarRingListener : InteractionListener(){ + + val RING = Items.RING_OF_THE_STAR_SPRITE_14652 + + override fun defineListeners() { + on(RING, ITEM, "rub", "operate"){player, node -> + val star = WorldEvents.get("shooting-stars") as? ShootingStarEvent + + if(star == null) ContentAPI.sendDialogue(player, "There is currently no active star.").also { return@on true } + + if(ContentAPI.getAttribute(player, "ring-next-tele", 0L) > System.currentTimeMillis()){ + ContentAPI.sendDialogue(player, "The ring is still recharging.") + return@on true + } + + val condition: (Player) -> Boolean = when(star?.star!!.location.toLowerCase()){ + "canifis bank" -> { p -> p.questRepository.isComplete("Priest in Peril")} + "crafting guild" -> {p -> ContentAPI.hasLevelStat(p, Skills.CRAFTING, 40) } + "south crandor mining site" -> {p -> p.questRepository.isComplete("Dragon Slayer")} + else -> {_ -> true} + } + + if(!condition.invoke(player) || player.skullManager.isWilderness){ + ContentAPI.sendDialogue(player, "Magical forces prevent your teleportation.") + return@on true + } + + val shouldWarn = when(star.star.location){ + "North Edgeville mining site", + "Southern wilderness mine", + "Pirates' Hideout mine", + "Lava Maze mining site", + "Mage Arena bank" -> true + else -> false + } + + ContentAPI.openDialogue(player, RingDialogue(shouldWarn, star.star)) + + return@on true + } + } + + internal class RingDialogue(val shouldWarn: Boolean, val star: ShootingStar) : DialogueFile(){ + override fun handle(componentID: Int, buttonID: Int) { + if(shouldWarn){ + when(stage) { + 0 -> dialogue("WARNING: That mining site is located in the wilderness.").also { stage++ } + 1 -> player!!.dialogueInterpreter.sendOptions("Continue?","Yes","No").also { stage++ } + 2 -> when(buttonID){ + 1 -> teleport(player!!, star).also { end() } + 2 -> end() + } + } + } else { + when(stage){ + 0 -> player!!.dialogueInterpreter.sendOptions("Teleport to the Star?", "Yes", "No").also { stage++ } + 1 -> when(buttonID){ + 1 -> teleport(player!!, star).also { end() } + 2 -> end() + } + } + } + } + + fun teleport(player: Player, star: ShootingStar){ + ContentAPI.teleport(player, star.crash_locations[star.location]!!.transform(0, -1, 0), TeleportManager.TeleportType.MINIGAME) + ContentAPI.setAttribute(player, "/save:ring-next-tele", System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1)) + } + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/interaction/item/withobject/AxeOnTree.kt b/Server/src/main/kotlin/rs09/game/interaction/item/withobject/AxeOnTree.kt new file mode 100644 index 000000000..9cec2668d --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/interaction/item/withobject/AxeOnTree.kt @@ -0,0 +1,21 @@ +package rs09.game.interaction.item.withobject + +import api.ContentAPI +import core.game.node.entity.skill.gather.SkillingTool +import core.game.node.entity.skill.gather.woodcutting.WoodcuttingNode +import core.game.node.entity.skill.gather.woodcutting.WoodcuttingSkillPulse +import org.rs09.consts.Items +import rs09.ServerConstants +import rs09.game.interaction.InteractionListener + +class AxeOnTree : InteractionListener(){ + val axes = intArrayOf(Items.BRONZE_AXE_1351, Items.MITHRIL_AXE_1355, Items.IRON_AXE_1349, Items.BLACK_AXE_1361, Items.STEEL_AXE_1353, Items.ADAMANT_AXE_1357, Items.RUNE_AXE_1359, Items.DRAGON_AXE_6739, Items.INFERNO_ADZE_13661) + val trees = WoodcuttingNode.values().map { it.id }.toIntArray() + + override fun defineListeners() { + onUseWith(SCENERY, axes, *trees){player, _, with -> + ContentAPI.submitIndividualPulse(player, WoodcuttingSkillPulse(player, with.asScenery())) + return@onUseWith true + } + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/interaction/item/withobject/SackOnHay.kt b/Server/src/main/kotlin/rs09/game/interaction/item/withobject/SackOnHay.kt new file mode 100644 index 000000000..0de84caa7 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/interaction/item/withobject/SackOnHay.kt @@ -0,0 +1,21 @@ +package rs09.game.interaction.item.withobject + +import api.Container +import api.ContentAPI +import org.rs09.consts.Items +import rs09.game.interaction.InteractionListener + +class SackOnHay : InteractionListener() { + val SACK = Items.EMPTY_SACK_5418 + val HAY = intArrayOf(36892, 36894, 36896, 300, 34593, 298, 299) + + override fun defineListeners() { + onUseWith(SCENERY, SACK, *HAY){player, used, _ -> + if(ContentAPI.removeItem(player, used.asItem(), Container.INVENTORY)){ + ContentAPI.addItem(player, Items.HAY_SACK_6057, 1) + ContentAPI.sendMessage(player, "You fill the sack with hay.") + } + return@onUseWith true + } + } +} \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/interaction/region/dungeons/brimhaven/BrimhavenUtils.kt b/Server/src/main/kotlin/rs09/game/interaction/region/dungeons/brimhaven/BrimhavenUtils.kt index 5c9869e88..97390d807 100644 --- a/Server/src/main/kotlin/rs09/game/interaction/region/dungeons/brimhaven/BrimhavenUtils.kt +++ b/Server/src/main/kotlin/rs09/game/interaction/region/dungeons/brimhaven/BrimhavenUtils.kt @@ -67,11 +67,15 @@ object BrimhavenUtils { } if (stage == 6) { player.achievementDiaryManager.finishTask(player, DiaryType.KARAMJA, 1, 15) - ContentAPI.clearLogoutListener(player, "steppingstone") } AgilityHandler.forceWalk(player, -1, l, l.transform(direction), Animation.create(769), 10, 0.0, null) return stage == 6 } + + override fun stop() { + ContentAPI.clearLogoutListener(player, "steppingstone") + super.stop() + } }) } diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Plantable.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Plantable.kt index 6efa31bee..cfeb444e9 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Plantable.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/farming/Plantable.kt @@ -63,7 +63,7 @@ enum class Plantable(val itemID: Int, val value: Int, val stages: Int, val plant MARRENTILL_SEED(5292,11,4,13.5,15.0,0.0,14,PatchType.HERB,Items.GRIMY_MARRENTILL_201), TARROMIN_SEED(5293,18,4,16.0,18.0,0.0,19,PatchType.HERB,Items.GRIMY_TARROMIN_203), HARRALANDER_SEED(5294,25,4,21.5,24.0,0.0,26,PatchType.HERB,Items.GRIMY_HARRALANDER_205), - GOUT_TUBER(5311,32,4,105.0,45.0,0.0,29,PatchType.HERB,Items.GOUTWEED_3261), + GOUT_TUBER(6311,32,4,105.0,45.0,0.0,29,PatchType.HERB,Items.GOUTWEED_3261), RANARR_SEED(5295,39,4,27.0,30.5,0.0,32,PatchType.HERB,Items.GRIMY_RANARR_207), TOADFLAX_SEED(5296,47,4,34.0,38.5,0.0,38,PatchType.HERB,Items.GRIMY_TOADFLAX_3049), IRIT_SEED(5297,54,4,43.0,48.5,0.0,44,PatchType.HERB,Items.GRIMY_IRIT_209), diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/gather/mining/MiningSkillPulse.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/gather/mining/MiningSkillPulse.kt index cb7695613..e8427ea64 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/gather/mining/MiningSkillPulse.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/gather/mining/MiningSkillPulse.kt @@ -1,5 +1,6 @@ package rs09.game.node.entity.skill.gather.mining +import api.ContentAPI import core.cache.def.impl.ItemDefinition import core.game.container.impl.EquipmentContainer import core.game.content.dialogue.FacialExpression @@ -173,16 +174,16 @@ class MiningSkillPulse(private val player: Player, private val node: Node) : Pul if (!isMiningEssence) { var chance = 282 var altered = false - if (Item(player.equipment.getId(12)).name.toLowerCase().contains("ring of wealth")) { + if (Item(player.equipment.getId(12)).name.toLowerCase().contains("ring of wealth") || ContentAPI.inEquipment(player, Items.RING_OF_THE_STAR_SPRITE_14652)) { chance = (chance / 1.5).toInt() altered = true } val necklace = player.equipment[EquipmentContainer.SLOT_AMULET] - if (necklace != null && necklace.id > 1705 && necklace.id < 1713) { + if (necklace != null && necklace.id in 1705..1713) { chance = (chance / 1.5).toInt() altered = true } - if (RandomFunction.random(chance) == chance / 2) { + if (RandomFunction.roll(chance)) { val gem = RandomFunction.rollChanceTable(true, *GEM_REWARDS)[0] player.packetDispatch.sendMessage("You find a " + gem.name + "!") if (!player.inventory.add(gem, player)) {