diff --git a/Server/build.gradle b/Server/build.gradle index 9f11df2fc..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.1.jar") + implementation files("libs/ConstLib-1.2.jar") implementation files("libs/PrimitiveExtensions-1.0.jar") } diff --git a/Server/libs/ConstLib-1.1.jar b/Server/libs/ConstLib-1.2.jar similarity index 97% rename from Server/libs/ConstLib-1.1.jar rename to Server/libs/ConstLib-1.2.jar index 8e0af0c6e..e8679d136 100644 Binary files a/Server/libs/ConstLib-1.1.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/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..6c368f65a 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 gold 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 gold 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.GOLD_BAR_2357, 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.GOLD_BAR_2357, 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 gold 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/interaction/item/StarRingListener.kt b/Server/src/main/kotlin/rs09/game/interaction/item/StarRingListener.kt new file mode 100644 index 000000000..4bf1e3d36 --- /dev/null +++ b/Server/src/main/kotlin/rs09/game/interaction/item/StarRingListener.kt @@ -0,0 +1,78 @@ +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 + +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 } + + 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) + } + } +} \ No newline at end of file