From e38a17a1140068108784aab5c219deebbb0c67b0 Mon Sep 17 00:00:00 2001 From: DesecratedTree <52549792+DesecratedTree@users.noreply.github.com> Date: Sat, 20 Jan 2024 04:15:48 -0600 Subject: [PATCH 1/3] lost city push #1 --- .../content/areas/entrana/entrana.plugin.kts | 68 +++++++ .../areas/lumbridge/lostcity_shed.plugin.kts | 67 ++++++ .../areas/lumbridge/lostcity_tree.plugin.kts | 29 +++ .../content/areas/lumbridge/shamus.plugin.kts | 144 +++++++++++++ .../areas/lumbridge/warrior.plugin.kts | 190 ++++++++++++++++++ .../areas/portsarim/charter.plugin.kts | 71 ++++++- .../plugins/content/quests/impl/LostCity.kt | 128 ++++++++++++ .../content/quests/quest_tab.plugin.kts | 4 +- 8 files changed, 696 insertions(+), 5 deletions(-) create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_tree.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/shamus.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/warrior.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/impl/LostCity.kt diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts new file mode 100644 index 000000000..728d1ef34 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts @@ -0,0 +1,68 @@ +package gg.rsmod.plugins.content.areas.entrana + +import gg.rsmod.plugins.content.areas.portsarim.CharterType +import gg.rsmod.plugins.content.areas.portsarim.Ports +import gg.rsmod.plugins.content.quests.advanceToNextStage +import gg.rsmod.plugins.content.quests.getCurrentStage +import gg.rsmod.plugins.content.quests.impl.LostCity +import gg.rsmod.plugins.content.skills.woodcutting.AxeType + + +val ladder = Objs.LADDER_2408 + +val dungeonTile = Tile(2822, 9774, 0) + +on_obj_option(ladder, "climb-down") { + player.moveTo(dungeonTile) + if (player.getCurrentStage(LostCity) == LostCity.ENTRANA_ARRIVAL) player.advanceToNextStage(LostCity) +} + +on_item_on_item(Items.KNIFE, Items.DRAMEN_BRANCH) { + player.inventory.remove(Items.DRAMEN_BRANCH, amount = 1) + player.inventory.add(Items.DRAMEN_STAFF) + if (player.getCurrentStage(LostCity) == LostCity.CREATE_DRAMEN_STAFF) player.advanceToNextStage(LostCity) + +} + +on_obj_option(Objs.DRAMEN_TREE, "chop down") { + when (player.getCurrentStage(LostCity)) { + LostCity.ENTRANA_ARRIVAL -> { + player.queue { + world.spawn(Npc(Npcs.TREE_SPIRIT, Tile(2860, 9737, 0), world = world)) + on_npc_death(Npcs.TREE_SPIRIT) { + player.advanceToNextStage(LostCity) //sets stage 3 + } + } + } + else -> { + player.queue { + if (player.skills.getMaxLevel(Skills.WOODCUTTING) >= 36) { + if (player.inventory.hasFreeSpace()) { + chopDramenTree(this) + } else { + messageBox("Your inventory is too full to hold any more logs.") + } + } else { + messageBox("You need a Woodcutting level of 36 to chop this tree.") + } + } + } + } +} + +suspend fun chopDramenTree(it: QueueTask) { + val player = it.player + val axe = AxeType.values.reversed().firstOrNull { + player.skills + .getMaxLevel(Skills.WOODCUTTING) >= it.level && (player.equipment.contains(it.item) || player.inventory.contains( + it.item + )) + }!! + val axeAnimation = axe.animation + player.animate(axeAnimation, idleOnly = true) + player.filterableMessage("You swing your hatchet at the dramen tree.") + player.animate(axeAnimation, idleOnly = true) + it.wait(5) + player.inventory.add(Items.DRAMEN_BRANCH, amount = 1, assureFullInsertion = true) + player.animate(-1) +} diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts new file mode 100644 index 000000000..bdc217c48 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts @@ -0,0 +1,67 @@ +package gg.rsmod.plugins.content.areas.lumbridge + +import gg.rsmod.plugins.content.magic.TeleportType +import gg.rsmod.plugins.content.magic.teleport +import gg.rsmod.plugins.content.quests.advanceToNextStage +import gg.rsmod.plugins.content.quests.buildQuestFinish +import gg.rsmod.plugins.content.quests.getCurrentStage +import gg.rsmod.plugins.content.quests.impl.LostCity + +val inShed = listOf( + Tile(3202, 3168), + Tile(3202, 3169), + Tile(3203, 3168), + Tile(3203, 3169), + Tile(3204, 3168) + +) +val zanarisTile = Tile(2452, 4471) +val teleportTile = Tile(3202, 3169) + +on_obj_option(Objs.DOOR_2406, "open"){ + if (player.hasEquipped(intArrayOf(Items.DRAMEN_STAFF)) && player.getCurrentStage(LostCity) >= LostCity.CREATE_DRAMEN_STAFF) { + player.queue{ + handleDoor(player) + player.lock() + player.walkTo(teleportTile) + player.unlock() + wait(2) + zanarisTeleport(player) + } + } + else { + handleDoor(player) + } +} + +fun zanarisTeleport (player: Player) { + if (player.tile in inShed) { + player.lock() + player.message("The world starts to shimmer...") + player.teleport(zanarisTile, type = TeleportType.SCROLL) + player.unlock() + if (player.getCurrentStage(LostCity) == LostCity.ENTER_ZANARIS) { + player.advanceToNextStage(LostCity) + player.buildQuestFinish(LostCity, Items.DRAMEN_STAFF, rewards = arrayOf("3 quest points", "Access to Zanaris")) + } + } +} + +fun handleDoor(player: Player) { //TODO: Fix door + val openDoor = DynamicObject(id = 2406, type = 0, rot = 1, tile = Tile(x = 3202, z = 3169)) + val door = DynamicObject(id = 2406, type = 0, rot = 2, tile = Tile(x = 3201, z = 3169)) + player.queue { + val x = if (player.tile.x == 3201) 3202 else 3201 + val z = 3169 + world.remove(door) + world.remove(openDoor) + world.spawn(openDoor) + player.playSound(Sfx.DOOR_OPEN) + player.walkTo(tile = Tile(x = x, z = z), detectCollision = false) + wait(3) + world.remove(openDoor) + world.remove(door) + player.playSound(Sfx.DOOR_CLOSE) + world.spawn(door) + } +} \ No newline at end of file diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_tree.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_tree.plugin.kts new file mode 100644 index 000000000..bb88a8b62 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_tree.plugin.kts @@ -0,0 +1,29 @@ +package gg.rsmod.plugins.content.areas.lumbridge + +import gg.rsmod.plugins.content.quests.advanceToNextStage +import gg.rsmod.plugins.content.quests.getCurrentStage +import gg.rsmod.plugins.content.quests.impl.LostCity + +val shamusTile = Tile(3139, 3211) + +on_obj_option(Objs.TREE_2409, "chop") { + when (player.getCurrentStage(LostCity)) { + LostCity.FINDING_SHAMUS -> { + player.queue{ + world.spawn(TileGraphic(shamusTile, id = 74, height = 0)) + world.spawn(Npc(Npcs.SHAMUS, shamusTile, world = world)) + chatNpc( + "Hey! Yer big elephant!", + "Don't go chopping down me house, now!", npc = Npcs.SHAMUS) + player.advanceToNextStage(LostCity) // should set stage to 2 + } + } + else -> { + player.queue { + chatNpc( + "Hey! Yer big elephant!", + "Don't go chopping down me house, now!", npc = Npcs.SHAMUS) + } + } + } +} \ No newline at end of file diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/shamus.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/shamus.plugin.kts new file mode 100644 index 000000000..468300c87 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/shamus.plugin.kts @@ -0,0 +1,144 @@ +package gg.rsmod.plugins.content.areas.lumbridge + +import gg.rsmod.game.model.attr.INTERACTING_PLAYER_ATTR +import gg.rsmod.plugins.content.combat.createProjectile +import gg.rsmod.plugins.content.combat.strategy.MagicCombatStrategy +import gg.rsmod.plugins.content.quests.advanceToNextStage +import gg.rsmod.plugins.content.quests.getCurrentStage +import gg.rsmod.plugins.content.quests.impl.LostCity +import java.lang.ref.WeakReference + +val lostCity = LostCity + +on_npc_option(npc = Npcs.SHAMUS, option = "talk-to") { + player.queue { + when (player.getCurrentStage(lostCity)) { + LostCity.NOT_STARTED -> {} + LostCity.FINDING_SHAMUS -> foundShamus(this) + LostCity.ENTRANA_ARRIVAL -> postEntrana(this) + LostCity.CHOP_DRAMEN_BRANCH -> postEntrana(this) + LostCity.CREATE_DRAMEN_STAFF -> postEntrana(this) + LostCity.ENTER_ZANARIS -> postEntrana(this) + LostCity.QUEST_COMPLETE -> shamusTeleport(this) + } + } +} + +suspend fun foundShamus(it: QueueTask) { + it.chatNpc( + "Ah, yer big elephant! Yer've caught me! What", + "would an elephant like yer be wanting wid ol'", + "Shamus, then?") + it.chatPlayer("I want to find Zanaris.") + it.chatNpc( + "Zanaris, is it now? Well, well, well... You'll be needing", + "that funny little shed out there in the swamp, so you", + "will.") + it.chatPlayer( + "Shed? I thought Zanaris was a city.") + it.chatNpc("Aye, that it is!") + when(it.options( + "How does it fit in a shed, then?", + "I've been in that shed and I didn't see a city.")) { + 1 -> { + it.chatPlayer("How does it fit in a shed, then?") + it.chatNpc("Ah, yer stupid elephant! The city isn't IN the shed! The", + "doorway to the shed is a portal to Zanaris, so it is.") + it.chatPlayer("So, I just walk into the shed and end up in Zanaris?") + it.chatNpc( + "Oh, was I forgetting to say? Ya need to be carrying a", + "dramen staff to be getting there! Otherwise, yer'll just", + "be ending up in the shed.") + it.chatPlayer("Where could I get such a staff?") + it.chatNpc( + "Dramen staves are crafted from branches of the", + "dramen tree, so they are. I hear there's a dramen tree", + "in a cave over on the island of Entrana.") + it.chatNpc( + "There would probably be a good place for an elephant", + "like yer to look, I reckon") + it.chatNpc("The monks are running a ship from Port Sarim to", + "Entrana, so I hear.") + shamusTeleport(it) + } + 2 -> { + it.chatPlayer("I've been in that shed and I didn't see a city.") + it.chatNpc("Ah, yer stupid elephant! The city isn't IN the shed! The", + "doorway to the shed is a portal to Zanaris, so it is.") + it.chatPlayer("So, I just walk into the shed and end up in Zanaris?") + it.chatNpc( + "Oh, was I forgetting to say? Ya need to be carrying a", + "dramen staff to be getting there! Otherwise, yer'll just", + "be ending up in the shed.") + it.chatPlayer("Where could I get such a staff?") + it.chatNpc( + "Dramen staves are crafted from branches of the", + "dramen tree, so they are. I hear there's a dramen tree", + "in a cave over on the island of Entrana.") + it.chatNpc( + "There would probably be a good place for an elephant", + "like yer to look, I reckon") + it.chatNpc("The monks are running a ship from Port Sarim to", + "Entrana, so I hear.") + shamusTeleport(it) + } + } +} + +suspend fun postEntrana(it: QueueTask) { + it.chatNpc( + "Ah, yer big elephant! Yer've caught me! What", + "would an elephant like yer be wanting wid ol'", + "Shamus, then?") + when (it.options("I'm not sure.", "How do I get to Zanaris again?")) { + 1 -> { + it.chatPlayer("I'm not sure.") + it.chatNpc( + "Yer stupid elephant! I'll tell yer again! Yer need to", + "be entering the shed in the middle of the swamp while", + "holding a dramenwood staff! Yer can make the Dramen") + it.chatNpc( + "staff from a tree branch, and there's a Dramen", + "tree on Entrana! Now leave me alone yer great", + "elephant!") + } + 2 -> { + it.chatPlayer("How do I get to Zanaris again?") + } + } +} + +suspend fun shamusTeleport(it: QueueTask) { + val portSarimTile = Tile(3041, 3247, 0) + it.player.advanceToNextStage(LostCity) + it.chatNpc("Did yer need a teleport over to Port Sarim?") + when(it.options( + "Yes, please a teleport would be useful.", + "No, thanks, I'll get there on my own.", + title = " What do you say? ")) { + 1 -> { + it.chatPlayer("Yes, please, a teleport would be useful.") + it.chatNpc("Right yer are. Hold on!") + portSarimTeleport(it.player, "Avach Sarimporto!", targetTile = portSarimTile) + } + } +} + +fun portSarimTeleport(player: Player, dialogue: String = "", targetTile: Tile) { + val npc = player.getInteractingNpc() + npc.attr[INTERACTING_PLAYER_ATTR] = WeakReference(player) + val p = npc.getInteractingPlayer() + npc.queue { + npc.facePawn(npc.getInteractingPlayer()) + npc.forceChat(dialogue) + npc.graphic(108) + val projectile = npc.createProjectile(p, 109, ProjectileType.MAGIC) + p.world.spawn(projectile) + p.playSound(Sfx.CURSE_CAST_AND_FIRE) + wait(MagicCombatStrategy.getHitDelay(npc.tile, p.tile) + 1) + p.moveTo(targetTile) + wait(1) + p.graphic(110) + p.playSound(Sfx.CURSE_HIT) + } +} diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/warrior.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/warrior.plugin.kts new file mode 100644 index 000000000..02e5f3183 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/warrior.plugin.kts @@ -0,0 +1,190 @@ +package gg.rsmod.plugins.content.areas.lumbridge + +import gg.rsmod.plugins.content.quests.getCurrentStage +import gg.rsmod.plugins.content.quests.impl.LostCity +import gg.rsmod.plugins.content.quests.startQuest + +val lostCity = LostCity + +on_npc_option(npc = Npcs.WARRIOR, option = "talk-to") { + player.queue { + when (player.getCurrentStage(lostCity)) { + LostCity.NOT_STARTED -> beforeLostCity(this) + LostCity.FINDING_SHAMUS -> findingShamus(this) + LostCity.ENTRANA_ARRIVAL -> afterShamus(this) + LostCity.CHOP_DRAMEN_BRANCH, LostCity.CREATE_DRAMEN_STAFF, LostCity.ENTER_ZANARIS -> afterShamus(this) + LostCity.QUEST_COMPLETE -> afterLostCity(this) + } + } +} + +suspend fun beforeLostCity(it: QueueTask) { + it.chatNpc("Hello there, traveler", facialExpression = FacialExpression.CALM_TALK) + when(it.options("What are you camped out here for?", "Do you know any good adventures I can go on?")) { + 1 -> { + it.chatPlayer("What are you camped out here for?") + it.chatNpc( + "We're looking for Zanaris...GAH! I mean we're not", + "here for any particular reason at all.") + lookingForZanaris(it) + } + 2 -> { + it.chatPlayer("Do you know any good adventures I can go on?") + it.chatNpc( + "Well we're on an adventure right now. Mind you, this", + "is OUR adventure and we don't want to share it - find", + "your own!") + when(it.options("Please tell me.", "I don't think you've found a good adventure at all!")){ + 1 -> { + it.chatPlayer("Please tell me.") + it.chatNpc("No.") + it.chatPlayer("Please?") + it.chatNpc("No!") + it.chatPlayer("PLEEEEEEEEEEEEEEEEEEEEEEASE???") + it.chatNpc("NO!") + } + 2 -> { + it.chatPlayer("I don't think you've found a good adventure at all!") + it.chatNpc( + "Hah! Adventurers of our calibre don't just hang around", + "in forests for fun, whelp!") + it.chatPlayer("Oh really?") + it.chatPlayer("Why are you camped out here?") + it.chatNpc( + "We're looking for Zanaris...GAH! I mean we're not", + "here for any particular reason at all.") + lookingForZanaris(it) + } + } + } + } +} + +suspend fun lookingForZanaris(it: QueueTask) { + when (it.options("Who's Zanaris?", "What's Zanaris?", "What makes you think its out here?")) { + 1 -> { + it.chatPlayer("Who's Zanaris?") + it.chatNpc( + "Ahahahahaha! Zanaris isn't a person! It's a magical hidden", + "city filled with treasures and rich... uh, nothing. It's", + "nothing.") + when (it.options("If it's hidden, how are you planning to find it?", "There's no such thing.")) { + 1 -> { + lookingforShamus(it) + } + 2 -> { + it.chatPlayer("There's no such thing!") + it.chatNpc( + "When we've found Zanaris, you'll... GAH! I mean, we're", + "not here for any particular reason at all") + lookingForZanaris(it) + } + } + } + 2 -> { + it.chatPlayer("What's Zanaris?") + it.chatNpc( + "I don't think we want other people competing with us", + "to find it. Forget I said anything.") + } + 3 -> { + it.chatPlayer("What makes you think it's out here?") + it.chatNpc( + "Don't you know of the legends that tell of the magical", + "city, hidden in the swam...") + it.chatNpc("Uh, no, you're right, we're wasting our time here.") + lookingforShamus(it) + } + } +} + +suspend fun lookingforShamus(it: QueueTask) { + it.chatPlayer("If it's hidden, how are you planning to find it?") + it.chatNpc( + "Well, we don't want to tell anyone else about that,", + "because we don't want anyone else sharing in all the", + "glory and treasure" + ) + when(it.options("Please tell me.", "Looks like you don't know either.")){ + 1 -> { + it.chatPlayer("Please tell me.") + it.chatNpc("No.") + it.chatPlayer("Please?") + it.chatNpc("No!") + it.chatPlayer("PLEEEEEEEEEEEEEEEEEEEEEEASE???") + it.chatNpc("NO!") + } + 2 -> { + it.chatPlayer( + "Well, it looks to me like YOU don't know EITHER", + "seeing as you're all just sat around here.") + it.chatNpc( + "Of course we know! We just haven't figured out which", + "tree the stupid leprechaun's hiding in yet! GAH!", + "I didn't mean to tell you that! Look, just forget", + "I said anything okay?") + it.chatPlayer("So a leprechaun knows where Zanaris is, eh?") + it.chatNpc( + "Ye... uh, no. No, not at all. And even if he did - ", + "which he doesn't - he DEFINITELY ISN'T hiding in", + "some tree around here. Nope, definitely not.", + "Honestly.") + when(it.options("Yes.", "No.", title = " Start Lost City? ")) { + 1 -> { + if(it.player.skills.getMaxLevel(Skills.CRAFTING) >= 31 && it.player.skills.getMaxLevel(Skills.WOODCUTTING) > 36){ + it.chatPlayer("Thanks for the help!") + it.chatNpc( + "Help? What help? I didn't help! Please Don't say I", + "did, I'll get in trouble!") + it.player.startQuest(LostCity) + } else { + it.messageBox("You don't have the skill levels to start this quest...") + if (it.player.skills.getMaxLevel(Skills.CRAFTING) < 31) { + it.messageBox("You need 31 crafting.") + } + if (it.player.skills.getMaxLevel(Skills.WOODCUTTING) < 36) { + it.messageBox("You need 36 woodcutting.") + } + } + } + 2 -> { + it.chatPlayer("No.") + } + } + } + } + +} +suspend fun findingShamus(it: QueueTask) { + it.chatPlayer( + "So let me get this straight. I need to search the", + "trees around here for a leprechaun. Then he will", + "tell me where this 'Zanaris' is?") + it.chatNpc( + "What? How did you know that Uh... I mean, no, no", + "you're very wrong. Very wrong, and not right at", + "all, and I definitely didn't tell you about that", + "at all.") +} + +suspend fun afterShamus(it: QueueTask) { + it.chatPlayer("Have you found anything yet?") + it.chatNpc( + "We're still searching for Zanaris... GAH! I mean we're", + "not doing anything here at all.") + it.chatPlayer("I haven't found it yet either.") +} + +suspend fun afterLostCity(it: QueueTask) { + it.chatPlayer( + "Hey, thanks for all the information. It REALLY helped", + "me out in finding the lost city of Zanaris and all.") + it.chatNpc( + "Oh, please don't say that anymore! If the rest of my", + "party knew I'd helped you they'd probably throw me", + "out and make me walk home by myself!") + it.chatNpc( + "So anyway, what have you found out? Where is the", + "fabled Zanaris? Is it all the legends say it is?") + it.chatPlayer("You know... I think I'll keep that to myself.") +} diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/portsarim/charter.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/portsarim/charter.plugin.kts index ce3d0a403..273104507 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/portsarim/charter.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/portsarim/charter.plugin.kts @@ -69,10 +69,65 @@ suspend fun chooseAgainDialogue(it: QueueTask, port: Ports, destination: Destina } } } +arrayOf(Npcs.MONK_OF_ENTRANA_658, Npcs.MONK_OF_ENTRANA_2730, Npcs.MONK_OF_ENTRANA_2731).forEach { monk -> + on_npc_option(monk, "Travel") { + player.queue { + setSail(player, CharterType.ENTRANA_TO_PORT_SARIM, Ports.ENTRANA_MONKS, 0) + } + } +} + +arrayOf(Npcs.MONK_OF_ENTRANA_658, Npcs.MONK_OF_ENTRANA_2730, Npcs.MONK_OF_ENTRANA_2731).forEach { monk -> + on_npc_option(monk, "Talk") { + player.queue { + chatNpc("Do you wish to leave holy Entrana?") + when (options("Yes, I'm ready to go.", "Not just yet.")) { + 1 -> { + chatPlayer("Yes, I'm ready to go.") + chatNpc("Okay, let's board...") + player.queue{ + } + } + 2 -> { + chatPlayer("Not just yet.") + } + } + } + } +} arrayOf(Npcs.MONK_OF_ENTRANA, Npcs.MONK_OF_ENTRANA_2729, Npcs.MONK_OF_ENTRANA_2728).forEach { monk -> - on_npc_option(monk, "Travel") {//TODO add money check and dialogue - setSail(player, CharterType.PORT_SARIM_TO_ENTRANA, Ports.ENTRANA_MONKS, 0) + on_npc_option(monk, "Travel") { + player.queue{ + chatNpc( + "Do you seek passage to holy Entrana? If so, you must", + "leave your weaponry and armour behind. This is", + "Saradomin's will.") + when (options("No, not right now.", "Yes, okay, I'm ready to go.")) { + 1 -> { + chatPlayer("No, not right now.") + } + 2 -> { + chatPlayer("Yes, okay, I'm ready to go.") + chatNpc("Very well. One moment please.") + messageBox("The monk quickly searches you") + if (!hasRestrictedEquipment(player)) { + chatNpc("All is satisfactory. You may board the boat now.") + setSail(player, CharterType.PORT_SARIM_TO_ENTRANA, Ports.ENTRANA_MONKS, 0) + } + else { + chatNpc( + "NO WEAPONS OR ARMOUR are permitted on holy Entrana", + "AT ALL. We will not allow you to travel there in", + "breach of mighty Saradomin's edict.") + chatNpc( + "Do not try to deceive us again. Come back when", + "you have laid down your Zamorakian instruments", + "of death.") + } + } + } + } } } @@ -91,7 +146,6 @@ arrayOf(Npcs.CAPTAIN_TOBIAS, Npcs.SEAMAN_LORRIS, Npcs.SEAMAN_THRESNOR).forEach { } } - on_npc_option(Npcs.CUSTOMS_OFFICER, "Talk-to") { player.queue { karamjaDialogue(this, leaving = true) @@ -340,4 +394,15 @@ create_shop( items[24] = ShopItem(Items.TYRAS_HELM, 25) items[25] = ShopItem(Items.RAW_RABBIT, 20) items[26] = ShopItem(Items.EYE_PATCH, 5) +} + +fun hasRestrictedEquipment(player: Player): Boolean { + val restrictedItems: IntArray = intArrayOf( + Items.BRONZE_SWORD, + ) + val hasProhibitedItemInInventory = player.inventory.hasItems(restrictedItems) + val hasProhibitedItemEquipped = player.equipment.hasItems(restrictedItems) + + return hasProhibitedItemInInventory || hasProhibitedItemEquipped + } \ No newline at end of file diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/impl/LostCity.kt b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/impl/LostCity.kt new file mode 100644 index 000000000..56f98a683 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/impl/LostCity.kt @@ -0,0 +1,128 @@ +package gg.rsmod.plugins.content.quests.impl + +import gg.rsmod.game.model.attr.gaveHarlowBeer +import gg.rsmod.game.model.attr.killedCountDraynor +import gg.rsmod.game.model.entity.Player +import gg.rsmod.plugins.api.Skills +import gg.rsmod.plugins.api.cfg.Items +import gg.rsmod.plugins.api.cfg.SkillRequirement +import gg.rsmod.plugins.api.ext.getVarp +import gg.rsmod.plugins.api.ext.setVarp +import gg.rsmod.plugins.content.quests.* + +object LostCity : Quest( + name = "Lost City", + startPoint = "Talk to warrior adventurer in the Lumbridge Swamp.", + requirements = listOf( + SkillRequirement(Skills.CRAFTING, level = 31), + SkillRequirement(Skills.WOODCUTTING, level = 36), + ), + requiredItems = "None.", + combat = "Must be able to kill a level 63 Tree spirit.", + rewards = "Access to Zanaris
Ability to wield dragon longswords and dragon daggers" + + "
Ability to craft cosmic runes
Access to Chaeldar, the slayer master (requires level 75 combat)", + pointReward = 3, + questId = 147, + spriteId = 0, + slot = 68, + stages = 6 +) { + init { + addQuest(this) + } + + //QuestStages + val NOT_STARTED: Int = 0 + val FINDING_SHAMUS: Int = 1 + val ENTRANA_ARRIVAL: Int = 2 + val CHOP_DRAMEN_BRANCH: Int = 3 + val CREATE_DRAMEN_STAFF: Int = 4 + val ENTER_ZANARIS: Int = 5 + val QUEST_COMPLETE: Int = 6 + + + override fun getObjective(player: Player, stage: Int): QuestStage = when (stage) { + 1 -> QuestStage ( + objectives = listOf( + "The warrior in Lumbridge Swamp said I am to find a", + "leprechaun in the area by trying to chop down trees?", + "", + ) + ) + + 2 -> { + if (player.attr.has(gaveHarlowBeer) && !player.attr.has(killedCountDraynor)) { + QuestStage( + objectives = listOf( + striked("I talked to Morgan in Draynor Village. He told me that the"), + striked("Locals are being attacked by a terrifying vampyre."), + striked("I have spoken to Dr Harlow. He seemed terribly drunk, and"), + striked("he kept asking for drinks."), + "", + "${red("Dr Harlow")} told me that, to succeed, I'll need the following:", + striked("A stake to kill the vampyre once I've finished fighting it."), + striked("A stake hammer to drive the stake deep into the"), + striked("vampyre's chest."), + "Some ${red("garlic")} to weaken the ${red("vampire")}", + "", + "When I'm ready, I should go to ${red("Draynor Manor")}, north of", + "Draynor, to kill the ${red("vampyre")} that's living in the basement.", + "Dr Harlow reminded me again and again to be prepared for", + "a tough fight." + ) + ) + } + if (player.attr.has(gaveHarlowBeer) && player.attr.has(killedCountDraynor)) { + QuestStage( + objectives = listOf( + striked("I talked to Morgan in Draynor Village. He told me that the"), + striked("Locals are being attacked by a terrifying vampyre."), + striked("I have spoken to Dr Harlow. He seemed terribly drunk, and"), + striked("he kept asking for drinks."), + "", + "I killed the vampyre! I should tell ${red("Morgan")} that his village is", + "safe once again.", + ) + ) + } else { + QuestStage( + objectives = listOf( + striked("I talked to Morgan in Draynor Village. He told me that the"), + striked("Locals are being attacked by a terrifying vampyre."), + striked("I have spoken to Dr Harlow. He seemed terribly drunk, and"), + striked("he kept asking for drinks."), + "", + "I need to buy ${red("Dr Harlow")} a drink and ask him", + "how to kill the vampyre.", + ) + ) + } + } + + else -> QuestStage( + objectives = listOf( + striked("I talked to Morgan in Draynor Village. He told me that the"), + striked("Locals are being attacked by a terrifying vampyre."), + striked("I have spoken to Dr Harlow. He seemed terribly drunk, and"), + striked("he kept asking for drinks."), + "", + "I have killed the vampyre, Count Draynor.", + "Draynor Village is now safe!", + questCompleteText + ) + ) + } + + override fun finishQuest(player: Player) { + player.advanceToNextStage(this) + player.setVarp(QUEST_POINT_VARP, player.getVarp(QUEST_POINT_VARP).plus(pointReward)) + player.buildQuestFinish(this, + item = Items.DRAMEN_STAFF, + rewards = arrayOf( + "3 Quest Points", + "Access to Zanaris", + "The ability to wield a dragon longsword or dagger with level 60 attack." + ) + ) + } +} \ No newline at end of file diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/quest_tab.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/quest_tab.plugin.kts index ba59786f7..d1e9d807c 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/quest_tab.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/quest_tab.plugin.kts @@ -146,8 +146,8 @@ on_login { player.setVarp(175, 12) // slot 67 player.setVarp(139, 75) - // slot 68 - player.setVarp(147, 6) + // slot 68 - Lost City + // Done. // slot 69 player.setVarbit(532, 11) // slot 70 From 5aa8ec07213e9a6362189cf8ead61cdcc578add9 Mon Sep 17 00:00:00 2001 From: DesecratedTree <52549792+DesecratedTree@users.noreply.github.com> Date: Sat, 20 Jan 2024 04:23:12 -0600 Subject: [PATCH 2/3] lost city push 2 --- .../gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts | 2 -- .../plugins/content/areas/lumbridge/lostcity_shed.plugin.kts | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts index 728d1ef34..d1395f5d9 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts @@ -1,7 +1,5 @@ package gg.rsmod.plugins.content.areas.entrana -import gg.rsmod.plugins.content.areas.portsarim.CharterType -import gg.rsmod.plugins.content.areas.portsarim.Ports import gg.rsmod.plugins.content.quests.advanceToNextStage import gg.rsmod.plugins.content.quests.getCurrentStage import gg.rsmod.plugins.content.quests.impl.LostCity diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts index bdc217c48..eaf8efd10 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts @@ -41,8 +41,7 @@ fun zanarisTeleport (player: Player) { player.teleport(zanarisTile, type = TeleportType.SCROLL) player.unlock() if (player.getCurrentStage(LostCity) == LostCity.ENTER_ZANARIS) { - player.advanceToNextStage(LostCity) - player.buildQuestFinish(LostCity, Items.DRAMEN_STAFF, rewards = arrayOf("3 quest points", "Access to Zanaris")) + LostCity.finishQuest(player) } } } From 9cb2b18f086f89cd538d99b48dfad467aae5732c Mon Sep 17 00:00:00 2001 From: DesecratedTree <52549792+DesecratedTree@users.noreply.github.com> Date: Sun, 28 Jan 2024 02:29:48 -0600 Subject: [PATCH 3/3] lost city push 3 --- data/cfg/doors/double-doors.json | 10 + .../gg/rsmod/plugins/api/ext/PlayerExt.kt | 107 ++++++++++- .../content/areas/entrana/entrana.plugin.kts | 125 ++++++++++--- .../content/areas/lumbridge/archer.plugin.kts | 52 +++++ .../areas/lumbridge/lostcity_shed.plugin.kts | 113 ++++++++--- .../areas/lumbridge/lostcity_tree.plugin.kts | 2 +- .../content/areas/lumbridge/monk.plugin.kts | 42 +++++ .../content/areas/lumbridge/shamus.plugin.kts | 23 ++- .../areas/lumbridge/warrior.plugin.kts | 4 +- .../content/areas/lumbridge/wizard.plugin.kts | 45 +++++ .../areas/portsarim/charter.plugin.kts | 56 +++--- .../content/areas/zanaris/zanaris.plugin.kts | 56 ++++++ .../dragondagger/dragon_dagger.plugin.kts | 2 +- .../plugins/content/magic/TeleportType.kt | 1 + .../undeads/tree_spirit_lv_101.plugin.kts | 70 +++++++ .../undeads/zombie_lvl_13.plugin.kts | 6 +- .../undeads/zombie_lvl_18.plugin.kts | 42 ++--- .../undeads/zombie_lvl_24.plugin.kts | 42 ++--- .../undeads/zombie_lvl_25.plugin.kts | 103 ++++++++++ .../undeads/zombie_lvl_30.plugin.kts | 42 ++--- .../undeads/zombie_lvl_44.plugin.kts | 42 ++--- .../undeads/zombie_lvl_53.plugin.kts | 42 ++--- .../plugins/content/quests/impl/LostCity.kt | 177 +++++++++++------- .../kotlin/gg/rsmod/game/fs/def/ItemDef.kt | 2 + .../gg/rsmod/game/model/attr/Attributes.kt | 6 +- .../game/model/container/ItemContainer.kt | 23 ++- 26 files changed, 965 insertions(+), 270 deletions(-) create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/archer.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/monk.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/wizard.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/zanaris/zanaris.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/tree_spirit_lv_101.plugin.kts create mode 100644 game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_25.plugin.kts diff --git a/data/cfg/doors/double-doors.json b/data/cfg/doors/double-doors.json index 6ae0150c7..8e56ca21d 100644 --- a/data/cfg/doors/double-doors.json +++ b/data/cfg/doors/double-doors.json @@ -148,5 +148,15 @@ "left": 1596, "right": 1597 } + }, + { + "opened": { + "left": 12046, + "right": 12048 + }, + "closed": { + "left": 12047, + "right": 12045 + } } ] \ No newline at end of file diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/api/ext/PlayerExt.kt b/game/plugins/src/main/kotlin/gg/rsmod/plugins/api/ext/PlayerExt.kt index 579b62d46..53c22055b 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/api/ext/PlayerExt.kt +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/api/ext/PlayerExt.kt @@ -1099,4 +1099,109 @@ fun Player.refreshBonuses() { bonusName = StringBuilder(bonusName).append("%").toString() setComponentText(667, 31 + i, bonusName)//31 to 48 is bonuses } -} \ No newline at end of file +} + +private val entranaPermittedItems: List = listOf( + Items.PENANCE_GLOVES, Items.PENANCE_GLOVES_10554, Items.ICE_GLOVES, Items.GLOVES_OF_SILENCE, + Items.SPINACH_ROLL, Items.BREAD, Items.CHOCOLATE_SLICE, Items.BAGUETTE, + Items.KEBAB, Items.STEW, Items.SPICY_STEW, Items.CABBAGE, Items.ONION, Items.SPICY_SAUCE, Items.CHILLI_CON_CARNE, + Items.SCRAMBLED_EGG, Items.EVIL_TURNIP, Items._23_EVIL_TURNIP, Items._13_EVIL_TURNIP, Items.TUNA_AND_CORN, + Items.POT_OF_CREAM, Items.DWELLBERRIES, Items.PEACH, Items.ROLL, Items.CHOCOLATE_BAR, + Items.ANCHOVIES, Items.STUFFED_SNAKE, Items.UGTHANKI_MEAT, Items.SHRIMPS, Items.SARDINE, Items.HERRING, Items.MACKEREL, + Items.COD, Items.TROUT, Items.CAVE_EEL, Items.CAVE_EEL_O, Items.PIKE, Items.SALMON, Items.TUNA, Items.FURY_SHARK, Items.LAVA_EEL, + Items.LOBSTER, Items.BASS, Items.SHARK, Items.SHARK_6969, Items.SEA_TURTLE, Items.MANTA_RAY, Items.ROCKTAIL, Items.CRAB_MEAT, + Items.FROG_MASK, Items.FROG_MASK_10721, Items.GNOME_SCARF, Items.GNOME_SCARF_22215, Items.GNOME_SCARF_22216, + Items.GNOME_SCARF_22217, Items.GNOME_SCARF_22218, +) + +fun Player.hasEntranaRestrictedEquipment(): Boolean { + val allItemsList = (inventory.sequence() + equipment.sequence()) + .filterNot { item -> + exceptionList(item) || excludedNames(this, item) || + item.getDef(world.definitions).equipSlot < 0 + } + .toList() + + return allItemsList.any() +} + +private fun exceptionList(item: Item): Boolean { + return item.id in entranaPermittedItems +} + +private fun excludedNames(player: Player, item: Item): Boolean { + val name = item.getName(player.world.definitions) + if (name.startsWith("Ring of ")) { + return true + } + if (name.startsWith("Amulet of ")) { + return true + } + if (name.startsWith("Ancient ceremonial")) { + return true + } + if (name.contains(" ring")) { + return true + } + if (name.contains(" amulet")) { + return true + } + if (name.contains(" necklace")) { + return true + } + if (name.contains(" pendant")) { + return true + } + if (name.contains(" bracelet")) { + return true + } + if (name.endsWith(" cloak")) { + return true + } + if (name.endsWith(" dragon mask")) { + return true + } + if (name.endsWith(" bolts")) { + return true + } + if (name.endsWith(" bolts (e)")) { + return true + } + if (name.endsWith(" afro")) { + return true + } + if (name.lowercase().contains("arrow")) { + return true + } + if (name.endsWith(" (p)")) { + return true + } + if (name.endsWith(" (p+)")) { + return true + } + if (name.endsWith(" (p++)")) { + return true + } + if (name.endsWith(" partyhat")) { + return true + } + if (name.endsWith(" of lightness")) { + return true + } + if (name.contains("cavalier")) { + return true + } + if (name.contains("book")) { + return true + } + if (name.contains(" cape")) { + return true + } + if (name.contains("beret")) { + return true + } + if (name.startsWith("Ghostly")) { + return true + } + return false +} diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts index d1395f5d9..a632e950d 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/entrana/entrana.plugin.kts @@ -1,38 +1,85 @@ package gg.rsmod.plugins.content.areas.entrana +import gg.rsmod.game.model.attr.HAS_SPAWNED_TREE_SPIRIT import gg.rsmod.plugins.content.quests.advanceToNextStage import gg.rsmod.plugins.content.quests.getCurrentStage import gg.rsmod.plugins.content.quests.impl.LostCity import gg.rsmod.plugins.content.skills.woodcutting.AxeType - +import gg.rsmod.game.model.Tile +import gg.rsmod.game.model.queue.QueueTask +import gg.rsmod.plugins.content.magic.TeleportType +import gg.rsmod.plugins.content.magic.teleport +import gg.rsmod.plugins.content.quests.finishedQuest val ladder = Objs.LADDER_2408 - val dungeonTile = Tile(2822, 9774, 0) -on_obj_option(ladder, "climb-down") { +suspend fun monkDialogue(it: QueueTask) { + it.chatNpc( + "Be careful going in there! You are unarmed, and there", + "is much evilness lurking down there! The evilness seems", + "to block off our contact with our gods,", + npc = Npcs.CAVE_MONK) + it.chatNpc( + "so our prayers seem to have less effect down there. Oh,", + "also, you wont be able to come back this way - This", + "ladder only goes one way", + npc = Npcs.CAVE_MONK) + it.chatNpc( + "The only exit from the caves below is a portal which is", + "guarded by greater demons!", + npc = Npcs.CAVE_MONK) + when(it.options( + "I don't think I'm strong enough to enter then.", + "Well, that is a risk I will have to take.")) { + 1 -> { + it.chatPlayer("I don't think I'm strong enough to enter then.") + } + 2 -> { + it.chatPlayer("Well, that is a risk I will have to take.") + dungeonEntrance(it.player) + } + } +} + +fun dungeonEntrance(player: Player) { player.moveTo(dungeonTile) - if (player.getCurrentStage(LostCity) == LostCity.ENTRANA_ARRIVAL) player.advanceToNextStage(LostCity) } -on_item_on_item(Items.KNIFE, Items.DRAMEN_BRANCH) { - player.inventory.remove(Items.DRAMEN_BRANCH, amount = 1) - player.inventory.add(Items.DRAMEN_STAFF) - if (player.getCurrentStage(LostCity) == LostCity.CREATE_DRAMEN_STAFF) player.advanceToNextStage(LostCity) +on_obj_option(ladder, "climb-down") { + val currentStage = player.getCurrentStage(LostCity) + if (currentStage == LostCity.ENTRANA_DUNGEON) { + player.queue{ + monkDialogue(this) + } + } + if (currentStage > LostCity.ENTRANA_DUNGEON) { + dungeonEntrance(player) + } + else { + player.message("Nothing interesting happens.") + } +} +on_item_on_item(Items.KNIFE, Items.DRAMEN_BRANCH) { + player.queue { + player.lock() + player.animate(1248) + wait(8) + player.inventory.remove(Items.DRAMEN_BRANCH, amount = 1) + player.inventory.add(Items.DRAMEN_STAFF) + messageBox("You carve the branch into a staff.") + player.unlock() + } } on_obj_option(Objs.DRAMEN_TREE, "chop down") { when (player.getCurrentStage(LostCity)) { - LostCity.ENTRANA_ARRIVAL -> { - player.queue { - world.spawn(Npc(Npcs.TREE_SPIRIT, Tile(2860, 9737, 0), world = world)) - on_npc_death(Npcs.TREE_SPIRIT) { - player.advanceToNextStage(LostCity) //sets stage 3 - } - } + LostCity.ENTRANA_DUNGEON -> { + world.spawn(Npc(Npcs.TREE_SPIRIT, Tile(2860, 9737, 0), world = world)) + player.attr.set(HAS_SPAWNED_TREE_SPIRIT, value = 1) } - else -> { + LostCity.CUT_DRAMEN_TREE, LostCity.CREATE_DRAMEN_BRANCH, LostCity.QUEST_COMPLETE -> { player.queue { if (player.skills.getMaxLevel(Skills.WOODCUTTING) >= 36) { if (player.inventory.hasFreeSpace()) { @@ -45,22 +92,58 @@ on_obj_option(Objs.DRAMEN_TREE, "chop down") { } } } + else -> { + player.queue { + messageBox("The tree seems to have an ominous aura.
You do not feel like chopping it down.") + } + } } } suspend fun chopDramenTree(it: QueueTask) { val player = it.player val axe = AxeType.values.reversed().firstOrNull { - player.skills - .getMaxLevel(Skills.WOODCUTTING) >= it.level && (player.equipment.contains(it.item) || player.inventory.contains( - it.item - )) - }!! + player.skills.getMaxLevel(Skills.WOODCUTTING) >= it.level && (player.equipment.contains(it.item) || player.inventory.contains(it.item)) + } ?: return val axeAnimation = axe.animation + player.lock() player.animate(axeAnimation, idleOnly = true) player.filterableMessage("You swing your hatchet at the dramen tree.") player.animate(axeAnimation, idleOnly = true) it.wait(5) + if (player.getCurrentStage(LostCity) == LostCity.CUT_DRAMEN_TREE) { + player.advanceToNextStage(LostCity) + } player.inventory.add(Items.DRAMEN_BRANCH, amount = 1, assureFullInsertion = true) player.animate(-1) + player.unlock() +} + +on_obj_option(Objs.MAGIC_DOOR, "open") { + val obj = player.getInteractingGameObj() + player.lockingQueue(TaskPriority.STRONG) { + handleDoor(player, obj) + wait(2) + player.message("You feel the world around you dissolve...") + player.playSound(Sfx.FT_FAIRY_TELEPORT) + player.teleport(Tile(3237, 3773, 0), type = TeleportType.FAIRY) + } } + +suspend fun handleDoor(player: Player, obj: GameObject) { + val openDoor = DynamicObject(id = 20988, type = 0, rot = 1, tile = Tile(x = 2874, z = 9750)) + val door = DynamicObject(id = 2407, type = 0, rot = 0, tile = Tile(x = 2874, z = 9750)) + player.lockingQueue { + val x = 2874 + val z = 9750 + world.remove(obj) + world.spawn(openDoor) + player.playSound(Sfx.DOOR_OPEN) + player.walkTo(tile = Tile(x = x, z = z), detectCollision = false) + wait(3) + world.remove(openDoor) + player.playSound(Sfx.DOOR_CLOSE) + world.spawn(door) + } +} + diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/archer.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/archer.plugin.kts new file mode 100644 index 000000000..fc1098278 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/archer.plugin.kts @@ -0,0 +1,52 @@ +package gg.rsmod.plugins.content.areas.lumbridge + +import gg.rsmod.plugins.content.quests.getCurrentStage +import gg.rsmod.plugins.content.quests.impl.LostCity + +val lostCity = LostCity + +on_npc_option(npc = Npcs.ARCHER_649, option = "talk-to") { + player.queue { + when (player.getCurrentStage(lostCity)) { + LostCity.NOT_STARTED -> beforeLostCity(this) + LostCity.FINDING_SHAMUS -> findingShamus(this) + LostCity.FOUND_SHAMUS -> afterLostCity(this) + LostCity.ENTRANA_DUNGEON, LostCity.CUT_DRAMEN_TREE, LostCity.CREATE_DRAMEN_BRANCH -> afterLostCity(this) + LostCity.QUEST_COMPLETE -> afterLostCity(this) + } + } +} + +suspend fun beforeLostCity(it: QueueTask) { + it.chatPlayer("Why are you guys standing around here?") + it.chatNpc("(ahem)... 'Guys'?") + it.chatPlayer("Um... yeah, sorry about that.", + "Why are you all standing around out here?") + it.chatNpc("Well, that's really none of your business.") + +} + +suspend fun findingShamus(it: QueueTask) { + it.chatPlayer( + "So I hear there's a leprechaun around here who can show", + "me the way to Zanaris?") + it.chatNpc( + "... W-what? How did you...?", + "Wait a minute! How did you know about that?") + it.chatNpc( + "No. You're wrong. Now go away.") +} + +suspend fun afterLostCity(it: QueueTask) { + it.chatPlayer( + "So you didn't find the entrance to Zanaris yet, huh?") + it.chatNpc( + "Don't tell me a novice like YOU has found it!") + it.chatPlayer( + "Yep. Found it REALLY easily too.") + it.chatNpc( + "... I Cannot believe that someone like you could find", + "the portal when experienced adventurers such as", + "ourselves could not.") + it.chatPlayer("Believe what you want. Enjoy your little camp fire.") +} diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts index eaf8efd10..1aaa33979 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_shed.plugin.kts @@ -1,9 +1,12 @@ package gg.rsmod.plugins.content.areas.lumbridge +import gg.rsmod.game.model.collision.ObjectType import gg.rsmod.plugins.content.magic.TeleportType +import gg.rsmod.plugins.content.magic.prepareForTeleport import gg.rsmod.plugins.content.magic.teleport +import gg.rsmod.plugins.content.mechanics.doors.DoorStickState import gg.rsmod.plugins.content.quests.advanceToNextStage -import gg.rsmod.plugins.content.quests.buildQuestFinish +import gg.rsmod.plugins.content.quests.finishedQuest import gg.rsmod.plugins.content.quests.getCurrentStage import gg.rsmod.plugins.content.quests.impl.LostCity @@ -15,52 +18,114 @@ val inShed = listOf( Tile(3204, 3168) ) + val zanarisTile = Tile(2452, 4471) -val teleportTile = Tile(3202, 3169) +val shedTile = Tile(3202, 3169) -on_obj_option(Objs.DOOR_2406, "open"){ - if (player.hasEquipped(intArrayOf(Items.DRAMEN_STAFF)) && player.getCurrentStage(LostCity) >= LostCity.CREATE_DRAMEN_STAFF) { - player.queue{ - handleDoor(player) - player.lock() - player.walkTo(teleportTile) - player.unlock() + +on_obj_option(Objs.DOOR_2406, "open") { + val obj = player.getInteractingGameObj() + val currentStage = player.getCurrentStage(LostCity) + + // Specify the minimum quest stage and the item ID for the Dramen Staff + val minQuestStage = LostCity.CREATE_DRAMEN_BRANCH// Set your minimum quest stage here + val dramenStaffId = Items.DRAMEN_STAFF + + if (player.hasEquipped(intArrayOf(dramenStaffId)) && currentStage >= 5) { + player.queue { + handleDoor(player, obj) + if (player.tile.x == 3201) { + player.walkTo(shedTile) + } wait(2) zanarisTeleport(player) } - } - else { - handleDoor(player) + } else { + player.queue { + handleDoor(player, obj) + } } } fun zanarisTeleport (player: Player) { + val type = TeleportType.FAIRY if (player.tile in inShed) { - player.lock() - player.message("The world starts to shimmer...") - player.teleport(zanarisTile, type = TeleportType.SCROLL) - player.unlock() - if (player.getCurrentStage(LostCity) == LostCity.ENTER_ZANARIS) { - LostCity.finishQuest(player) + player.lockingQueue{ + player.message("The world starts to shimmer...") + player.playSound(Sfx.FT_FAIRY_TELEPORT) + player.prepareForTeleport() + player.animate(type.animation) + type.graphic?.let { + player.graphic(it) + } + wait(type.teleportDelay) + player.teleportTo(zanarisTile) + type.endAnimation?.let { + player.animate(it) + } + type.endGraphic?.let { + player.graphic(it) + } + type.endAnimation?.let { + val def = world.definitions.get(AnimDef::class.java, it) + wait(def.cycleLength) + } + player.animate(-1) + player.unlock() + wait(2) + if (player.getCurrentStage(LostCity) == LostCity.CREATE_DRAMEN_BRANCH) { + LostCity.finishQuest(player) + } } } } -fun handleDoor(player: Player) { //TODO: Fix door +fun shedTeleport (player: Player) { + val type = TeleportType.FAIRY + player.lockingQueue{ + player.message("The world starts to shimmer...") + player.playSound(Sfx.FT_FAIRY_TELEPORT) + player.prepareForTeleport() + player.animate(type.animation) + type.graphic?.let { + player.graphic(it) + } + wait(type.teleportDelay) + player.teleportTo(shedTile) + type.endAnimation?.let { + player.animate(it) + } + type.endGraphic?.let { + player.graphic(it) + } + type.endAnimation?.let { + val def = world.definitions.get(AnimDef::class.java, it) + wait(def.cycleLength) + } + player.animate(-1) + player.unlock() + wait(2) + } +} + +suspend fun handleDoor(player: Player, obj: GameObject) { val openDoor = DynamicObject(id = 2406, type = 0, rot = 1, tile = Tile(x = 3202, z = 3169)) val door = DynamicObject(id = 2406, type = 0, rot = 2, tile = Tile(x = 3201, z = 3169)) - player.queue { + player.lockingQueue { + if (player.tile in inShed) { + player.moveTo(Tile(3202, 3169, 0)) + } else { + player.moveTo(Tile(3201, 3169, 0)) + } val x = if (player.tile.x == 3201) 3202 else 3201 val z = 3169 - world.remove(door) - world.remove(openDoor) + world.remove(obj) world.spawn(openDoor) player.playSound(Sfx.DOOR_OPEN) player.walkTo(tile = Tile(x = x, z = z), detectCollision = false) wait(3) world.remove(openDoor) - world.remove(door) player.playSound(Sfx.DOOR_CLOSE) world.spawn(door) } -} \ No newline at end of file +} diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_tree.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_tree.plugin.kts index bb88a8b62..6a19fb38e 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_tree.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/lostcity_tree.plugin.kts @@ -11,11 +11,11 @@ on_obj_option(Objs.TREE_2409, "chop") { LostCity.FINDING_SHAMUS -> { player.queue{ world.spawn(TileGraphic(shamusTile, id = 74, height = 0)) + player.advanceToNextStage(LostCity) world.spawn(Npc(Npcs.SHAMUS, shamusTile, world = world)) chatNpc( "Hey! Yer big elephant!", "Don't go chopping down me house, now!", npc = Npcs.SHAMUS) - player.advanceToNextStage(LostCity) // should set stage to 2 } } else -> { diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/monk.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/monk.plugin.kts new file mode 100644 index 000000000..a1d02216c --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/monk.plugin.kts @@ -0,0 +1,42 @@ +package gg.rsmod.plugins.content.areas.lumbridge + +import gg.rsmod.plugins.content.quests.getCurrentStage +import gg.rsmod.plugins.content.quests.impl.LostCity + +val lostCity = LostCity + +on_npc_option(npc = Npcs.MONK_651, option = "talk-to") { + player.queue { + when (player.getCurrentStage(lostCity)) { + LostCity.NOT_STARTED -> beforeLostCity(this) + LostCity.FINDING_SHAMUS -> findingShamus(this) + LostCity.FOUND_SHAMUS -> afterLostCity(this) + LostCity.ENTRANA_DUNGEON, LostCity.CUT_DRAMEN_TREE, LostCity.CREATE_DRAMEN_BRANCH -> afterLostCity(this) + LostCity.QUEST_COMPLETE -> afterLostCity(this) + } + } +} + +suspend fun beforeLostCity(it: QueueTask) { + it.chatPlayer("Why are all of you standing around here?") + it.chatNpc("None of your business. Get lost.") + +} + +suspend fun findingShamus(it: QueueTask) { + it.chatPlayer( + "Have you found the tree with the leprechaun", + "yet?") + it.chatNpc( + "No, we've looked for ages but haven't.... hey!", + "Wait a minute! How did you know about that?") + it.chatPlayer( + "Thanks for the information!") + it.chatNpc( + "... You tricked me. I'm not talking to you anymore.") +} + +suspend fun afterLostCity(it: QueueTask) { + it.chatNpc( + "I already told you. I'm not talking to you anymore.") +} diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/shamus.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/shamus.plugin.kts index 468300c87..d965843e0 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/shamus.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/shamus.plugin.kts @@ -14,11 +14,11 @@ on_npc_option(npc = Npcs.SHAMUS, option = "talk-to") { player.queue { when (player.getCurrentStage(lostCity)) { LostCity.NOT_STARTED -> {} - LostCity.FINDING_SHAMUS -> foundShamus(this) - LostCity.ENTRANA_ARRIVAL -> postEntrana(this) - LostCity.CHOP_DRAMEN_BRANCH -> postEntrana(this) - LostCity.CREATE_DRAMEN_STAFF -> postEntrana(this) - LostCity.ENTER_ZANARIS -> postEntrana(this) + LostCity.FINDING_SHAMUS -> {} + LostCity.FOUND_SHAMUS -> foundShamus(this) + LostCity.ENTRANA_DUNGEON -> postEntrana(this) + LostCity.CUT_DRAMEN_TREE -> postEntrana(this) + LostCity.CREATE_DRAMEN_BRANCH -> postEntrana(this) LostCity.QUEST_COMPLETE -> shamusTeleport(this) } } @@ -86,6 +86,7 @@ suspend fun foundShamus(it: QueueTask) { } suspend fun postEntrana(it: QueueTask) { + val shamus = it.player.getInteractingNpc() it.chatNpc( "Ah, yer big elephant! Yer've caught me! What", "would an elephant like yer be wanting wid ol'", @@ -93,6 +94,14 @@ suspend fun postEntrana(it: QueueTask) { when (it.options("I'm not sure.", "How do I get to Zanaris again?")) { 1 -> { it.chatPlayer("I'm not sure.") + it.chatNpc( + "Ha! Look at yer! Look at the stupid elephant who tries to", + "go catching a leprechaun when he don't even be knowing", + "what he wants!") + world.remove(shamus) + } + 2 -> { + it.chatPlayer("How do I get to Zanaris again?") it.chatNpc( "Yer stupid elephant! I'll tell yer again! Yer need to", "be entering the shed in the middle of the swamp while", @@ -101,9 +110,7 @@ suspend fun postEntrana(it: QueueTask) { "staff from a tree branch, and there's a Dramen", "tree on Entrana! Now leave me alone yer great", "elephant!") - } - 2 -> { - it.chatPlayer("How do I get to Zanaris again?") + world.remove(shamus) } } } diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/warrior.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/warrior.plugin.kts index 02e5f3183..afb5eae9c 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/warrior.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/warrior.plugin.kts @@ -11,8 +11,8 @@ on_npc_option(npc = Npcs.WARRIOR, option = "talk-to") { when (player.getCurrentStage(lostCity)) { LostCity.NOT_STARTED -> beforeLostCity(this) LostCity.FINDING_SHAMUS -> findingShamus(this) - LostCity.ENTRANA_ARRIVAL -> afterShamus(this) - LostCity.CHOP_DRAMEN_BRANCH, LostCity.CREATE_DRAMEN_STAFF, LostCity.ENTER_ZANARIS -> afterShamus(this) + LostCity.FOUND_SHAMUS -> afterShamus(this) + LostCity.ENTRANA_DUNGEON, LostCity.CUT_DRAMEN_TREE, LostCity.CREATE_DRAMEN_BRANCH -> afterShamus(this) LostCity.QUEST_COMPLETE -> afterLostCity(this) } } diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/wizard.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/wizard.plugin.kts new file mode 100644 index 000000000..8d6e9b288 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/lumbridge/wizard.plugin.kts @@ -0,0 +1,45 @@ +package gg.rsmod.plugins.content.areas.lumbridge + +import gg.rsmod.plugins.content.quests.getCurrentStage +import gg.rsmod.plugins.content.quests.impl.LostCity + +val lostCity = LostCity + +on_npc_option(npc = Npcs.WIZARD_652, option = "talk-to") { + player.queue { + when (player.getCurrentStage(lostCity)) { + LostCity.NOT_STARTED -> beforeLostCity(this) + LostCity.FINDING_SHAMUS -> findingShamus(this) + LostCity.FOUND_SHAMUS -> afterLostCity(this) + LostCity.ENTRANA_DUNGEON, LostCity.CUT_DRAMEN_TREE, LostCity.CREATE_DRAMEN_BRANCH -> afterLostCity(this) + LostCity.QUEST_COMPLETE -> afterLostCity(this) + } + } +} + +suspend fun beforeLostCity(it: QueueTask) { + it.chatPlayer("Why are all of you standing around here?") + it.chatNpc( + "Hahaha, you dare talk to a mighty wizard such as myself?", + "I bet you can't even cast Air Strike yet, amateur!") + it.chatPlayer("... You're an idiot.") + +} + +suspend fun findingShamus(it: QueueTask) { + it.chatPlayer( + "Found that leprechaun yet?") + it.chatNpc( + "Hahaha! Go away, amateur! You're not worthy", + "of joining our great group!") + it.chatPlayer( + "... Right.") +} + +suspend fun afterLostCity(it: QueueTask) { + it.chatNpc( + "Hahaha, you're such an amateur!") + it.chatNpc( + "Go and play with some cabbage, amateur!") + it.chatPlayer("... Right.") +} diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/portsarim/charter.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/portsarim/charter.plugin.kts index 273104507..2803a106c 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/portsarim/charter.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/portsarim/charter.plugin.kts @@ -1,7 +1,6 @@ package gg.rsmod.plugins.content.areas.portsarim import gg.rsmod.plugins.content.mechanics.shops.CoinCurrency -import gg.rsmod.plugins.content.quests.Quest import gg.rsmod.plugins.content.quests.finishedQuest val CHARTER_SELECTION_INTERFACE = 95 @@ -77,27 +76,28 @@ arrayOf(Npcs.MONK_OF_ENTRANA_658, Npcs.MONK_OF_ENTRANA_2730, Npcs.MONK_OF_ENTRAN } } -arrayOf(Npcs.MONK_OF_ENTRANA_658, Npcs.MONK_OF_ENTRANA_2730, Npcs.MONK_OF_ENTRANA_2731).forEach { monk -> - on_npc_option(monk, "Talk") { - player.queue { - chatNpc("Do you wish to leave holy Entrana?") - when (options("Yes, I'm ready to go.", "Not just yet.")) { - 1 -> { - chatPlayer("Yes, I'm ready to go.") - chatNpc("Okay, let's board...") - player.queue{ - } - } - 2 -> { - chatPlayer("Not just yet.") - } - } +arrayOf(Npcs.MONK_OF_ENTRANA, Npcs.MONK_OF_ENTRANA_2729, Npcs.MONK_OF_ENTRANA_2728).forEach { monk -> + on_npc_option(monk, "Travel") { + player.queue{ + messageBox("The monk quickly searches you.") + if (player.hasEntranaRestrictedEquipment()) { + chatNpc( + "NO WEAPONS OR ARMOUR are permitted on holy Entrana", + "AT ALL. We will not allow you to travel there in", + "breach of mighty Saradomin's edict.") + chatNpc( + "Do not try to deceive us again. Come back when", + "you have laid down your Zamorakian instruments", + "of death.") + } else { + chatNpc("All is satisfactory. You may board the boat now.") + setSail(player, CharterType.PORT_SARIM_TO_ENTRANA, Ports.ENTRANA_MONKS, 0) } } } } arrayOf(Npcs.MONK_OF_ENTRANA, Npcs.MONK_OF_ENTRANA_2729, Npcs.MONK_OF_ENTRANA_2728).forEach { monk -> - on_npc_option(monk, "Travel") { + on_npc_option(monk, "talk-to") { player.queue{ chatNpc( "Do you seek passage to holy Entrana? If so, you must", @@ -110,12 +110,8 @@ arrayOf(Npcs.MONK_OF_ENTRANA, Npcs.MONK_OF_ENTRANA_2729, Npcs.MONK_OF_ENTRANA_27 2 -> { chatPlayer("Yes, okay, I'm ready to go.") chatNpc("Very well. One moment please.") - messageBox("The monk quickly searches you") - if (!hasRestrictedEquipment(player)) { - chatNpc("All is satisfactory. You may board the boat now.") - setSail(player, CharterType.PORT_SARIM_TO_ENTRANA, Ports.ENTRANA_MONKS, 0) - } - else { + messageBox("The monk quickly searches you.") + if (player.hasEntranaRestrictedEquipment()) { chatNpc( "NO WEAPONS OR ARMOUR are permitted on holy Entrana", "AT ALL. We will not allow you to travel there in", @@ -125,6 +121,10 @@ arrayOf(Npcs.MONK_OF_ENTRANA, Npcs.MONK_OF_ENTRANA_2729, Npcs.MONK_OF_ENTRANA_27 "you have laid down your Zamorakian instruments", "of death.") } + else { + chatNpc("All is satisfactory. You may board the boat now.") + setSail(player, CharterType.PORT_SARIM_TO_ENTRANA, Ports.ENTRANA_MONKS, 0) + } } } } @@ -396,13 +396,3 @@ create_shop( items[26] = ShopItem(Items.EYE_PATCH, 5) } -fun hasRestrictedEquipment(player: Player): Boolean { - val restrictedItems: IntArray = intArrayOf( - Items.BRONZE_SWORD, - ) - val hasProhibitedItemInInventory = player.inventory.hasItems(restrictedItems) - val hasProhibitedItemEquipped = player.equipment.hasItems(restrictedItems) - - return hasProhibitedItemInInventory || hasProhibitedItemEquipped - -} \ No newline at end of file diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/zanaris/zanaris.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/zanaris/zanaris.plugin.kts new file mode 100644 index 000000000..fbf272d6f --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/areas/zanaris/zanaris.plugin.kts @@ -0,0 +1,56 @@ +package gg.rsmod.plugins.content.areas.zanaris + +import gg.rsmod.plugins.content.magic.TeleportType +import gg.rsmod.plugins.content.magic.prepareForTeleport +import gg.rsmod.plugins.content.mechanics.shops.CoinCurrency + +on_obj_option(Objs.FAIRY_RING_12094, "use") { + player.lockingQueue(TaskPriority.STRONG) { + wait(2) + shedTeleport(player) + } +} + +fun shedTeleport (player: Player) { + val shedTile = Tile(3202, 3169) + val type = TeleportType.FAIRY + player.lockingQueue{ + player.message("The world starts to shimmer...") + player.playSound(Sfx.FT_FAIRY_TELEPORT) + player.prepareForTeleport() + player.animate(type.animation) + type.graphic?.let { + player.graphic(it) + } + wait(type.teleportDelay) + player.teleportTo(shedTile) + type.endAnimation?.let { + player.animate(it) + } + type.endGraphic?.let { + player.graphic(it) + } + type.endAnimation?.let { + val def = world.definitions.get(AnimDef::class.java, it) + wait(def.cycleLength) + } + player.animate(-1) + player.unlock() + wait(2) + } +} + +create_shop( + "Jukat's Sword Shop", + currency = CoinCurrency(), + purchasePolicy = PurchasePolicy.BUY_STOCK, + containsSamples = false +) +{ + items[0] = ShopItem(Items.DRAGON_DAGGER, 30) + items[1] = ShopItem(Items.DRAGON_LONGSWORD, 10) +} + +on_npc_option(Npcs.JUKAT, "trade") { + player.openShop("Jukat's Sword Shop") +} diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/combat/specialattack/weapons/dragondagger/dragon_dagger.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/combat/specialattack/weapons/dragondagger/dragon_dagger.plugin.kts index 0a37cffdf..c2b353070 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/combat/specialattack/weapons/dragondagger/dragon_dagger.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/combat/specialattack/weapons/dragondagger/dragon_dagger.plugin.kts @@ -9,7 +9,7 @@ val SPECIAL_REQUIREMENT = 25 SpecialAttacks.register(SPECIAL_REQUIREMENT, Items.DRAGON_DAGGER, Items.DRAGON_DAGGER_P, Items.DRAGON_DAGGER_P_5680, Items.DRAGON_DAGGER_P_5698, Items.CORRUPT_DRAGON_DAGGER, Items.C_DRAGON_DAGGER_DEG) { player.animate(id = 1062) player.graphic(id = 252, height = 92) - world.spawn(AreaSound(tile = player.tile, id = 2537, radius = 10, volume = 1)) + player.playSound(2537) for (i in 0 until 2) { val maxHit = MeleeCombatFormula.getMaxHit(player, target, specialAttackMultiplier = 1.15) diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/magic/TeleportType.kt b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/magic/TeleportType.kt index 37e6de6f4..16a622082 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/magic/TeleportType.kt +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/magic/TeleportType.kt @@ -30,4 +30,5 @@ enum class TeleportType(val teleportDelay: Int, val animation: Int, val endAnima RING_OF_KINSHIP(teleportDelay = 11, animation = 13652, graphic = Graphic(2602, 0), endAnimation = 13654, endGraphic = Graphic(2603, 0)), SCROLL(teleportDelay = 4, animation = 14293, graphic = Graphic(94, 0)), OBELISK(teleportDelay = 6, animation = 8939, graphic = Graphic(1690, 0), endAnimation = 8941), + FAIRY(teleportDelay = 6, animation = 3254, graphic = Graphic(2670, 0), endAnimation = 3255), } \ No newline at end of file diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/tree_spirit_lv_101.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/tree_spirit_lv_101.plugin.kts new file mode 100644 index 000000000..5a9e734c9 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/tree_spirit_lv_101.plugin.kts @@ -0,0 +1,70 @@ +package gg.rsmod.plugins.content.npcs.definitions.undeads + +import gg.rsmod.game.model.attr.HAS_SPAWNED_TREE_SPIRIT +import gg.rsmod.game.model.combat.StyleType +import gg.rsmod.plugins.content.drops.DropTableFactory +import gg.rsmod.plugins.content.quests.advanceToNextStage +import gg.rsmod.plugins.content.quests.getCurrentStage +import gg.rsmod.plugins.content.quests.impl.LostCity + +val treeSpirit = Npcs.TREE_SPIRIT + +val table = DropTableFactory +val treeSpiritTable = table.build { + guaranteed { + obj(Items.BONES) + } +} + +table.register(treeSpiritTable, treeSpirit) + +on_npc_pre_death(treeSpirit) { + val p = npc.damageMap.getMostDamage()!! as Player + p.playSound(Sfx.BANSHEE_DEATH) + when (p.getCurrentStage(LostCity)) { + LostCity.ENTRANA_DUNGEON -> { + p.queue { + p.attr.remove(HAS_SPAWNED_TREE_SPIRIT) + p.advanceToNextStage(LostCity) + messageBox("With the tree spirit defeated, you can now chop the tree.") + } + } + } +} + +on_npc_death(treeSpirit) { + table.getDrop(world, npc.damageMap.getMostDamage()!! as Player, npc.id, npc.tile) +} + +on_npc_spawn(treeSpirit) { + npc.forceChat("You must defeat me before touching the tree!") +} + +set_combat_def(treeSpirit) { + configs { + attackSpeed = 4 + respawnDelay = 0 + attackStyle = StyleType.CRUSH + } + stats { + hitpoints = 220 + attack = 90 + strength = 95 + defence = 80 + } + bonuses { + defenceStab = 5 + defenceSlash = 5 + defenceCrush = 5 + defenceMagic = 0 + defenceRanged = 5 + } + aggro { + radius = 4 + } + anims { + attack = 5532 + death = 5534 + block = 5533 + } +} \ No newline at end of file diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_13.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_13.plugin.kts index 3cd8ab7dd..5d0aef10d 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_13.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_13.plugin.kts @@ -14,9 +14,10 @@ val zombie = table.build { main { total(total = 128) - obj(Items.IRON_HATCHET, quantity = 1, slots = 1) + obj(Items.IRON_HATCHET, quantity = 1, slots = 3) obj(Items.BRONZE_LONGSWORD, quantity = 1, slots = 1) obj(Items.BRONZE_MED_HELM, quantity = 1, slots = 4) + obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 3) obj(Items.IRON_ARROW, quantity = 5, slots = 7) obj(Items.BODY_RUNE, quantity = 6, slots = 5) @@ -25,6 +26,9 @@ val zombie = table.build { obj(Items.IRON_ARROW, quantity = 8, slots = 4) obj(Items.STEEL_ARROW, quantity = 6, slots = 2) obj(Items.NATURE_RUNE, quantity = 6, slots = 1) + obj(Items.COSMIC_RUNE, quantity = 4, slots = 1) + obj(Items.FIRE_RUNE, quantity = 7, slots = 1) + table(Herbs.minorHerbTable, slots = 25) diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_18.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_18.plugin.kts index bc2889e9f..713f29c85 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_18.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_18.plugin.kts @@ -15,34 +15,34 @@ val zombie = table.build { main { total(total = 128) - obj(Items.IRON_MACE, quantity = 1, slots = 3) - obj(Items.IRON_DAGGER, quantity = 1, slots = 2) - obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 1) + obj(Items.IRON_HATCHET, quantity = 1, slots = 3) + obj(Items.BRONZE_LONGSWORD, quantity = 1, slots = 1) + obj(Items.BRONZE_MED_HELM, quantity = 1, slots = 4) + obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 3) - obj(Items.MITHRIL_ARROW, quantity = 1, slots = 3) - obj(Items.AIR_RUNE, quantity = 3, slots = 2) - obj(Items.BODY_RUNE, quantity = 3, slots = 3) - obj(Items.CHAOS_RUNE, quantity = 4, slots = 1) - obj(Items.COSMIC_RUNE, quantity = 2, slots = 1) + obj(Items.IRON_ARROW, quantity = 5, slots = 7) + obj(Items.BODY_RUNE, quantity = 6, slots = 5) + obj(Items.MIND_RUNE, quantity = 5, slots = 5) + obj(Items.AIR_RUNE, quantity = 13, slots = 4) + obj(Items.IRON_ARROW, quantity = 8, slots = 4) + obj(Items.STEEL_ARROW, quantity = 6, slots = 2) + obj(Items.NATURE_RUNE, quantity = 6, slots = 1) + obj(Items.COSMIC_RUNE, quantity = 4, slots = 1) obj(Items.FIRE_RUNE, quantity = 7, slots = 1) - table(Herbs.minorHerbTable, slots = 30) - obj(Items.COINS_995, quantity = 10, slots = 21) - obj(Items.COINS_995, quantity = 18, slots = 11) - obj(Items.COINS_995, quantity = 26, slots = 7) - obj(Items.COINS_995, quantity = 35, slots = 7) - obj(Items.COINS_995, quantity = 1, slots = 2) + table(Herbs.minorHerbTable, slots = 25) + obj(Items.COINS_995, quantity = 10, slots = 36) + obj(Items.COINS_995, quantity = 4, slots = 4) + obj(Items.COINS_995, quantity = 18, slots = 3) + obj(Items.COINS_995, quantity = 13, slots = 2) + obj(Items.COINS_995, quantity = 28, slots = 2) - nothing(slots = 3) - obj(Items.FISHING_BAIT, quantity = 7, slots = 26) - obj(Items.TINDERBOX_590, quantity = 1, slots = 2) - obj(Items.EYE_OF_NEWT, quantity = 1, slots = 1) - obj(Items.TIN_ORE, quantity = 1, slots = 1) - - table(Gems.gemTable, slots = 1) + nothing(slots = 8) + obj(Items.FISHING_BAIT, quantity = 5, slots = 5) + obj(Items.COPPER_ORE, quantity = 1, slots = 2) } table("Charms") { total(1000) diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_24.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_24.plugin.kts index 716bd8b5d..ace29c84c 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_24.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_24.plugin.kts @@ -15,34 +15,34 @@ val zombie = table.build { main { total(total = 128) - obj(Items.IRON_MACE, quantity = 1, slots = 3) - obj(Items.IRON_DAGGER, quantity = 1, slots = 2) - obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 1) + obj(Items.IRON_HATCHET, quantity = 1, slots = 3) + obj(Items.BRONZE_LONGSWORD, quantity = 1, slots = 1) + obj(Items.BRONZE_MED_HELM, quantity = 1, slots = 4) + obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 3) - obj(Items.MITHRIL_ARROW, quantity = 1, slots = 3) - obj(Items.AIR_RUNE, quantity = 3, slots = 2) - obj(Items.BODY_RUNE, quantity = 3, slots = 3) - obj(Items.CHAOS_RUNE, quantity = 4, slots = 1) - obj(Items.COSMIC_RUNE, quantity = 2, slots = 1) + obj(Items.IRON_ARROW, quantity = 5, slots = 7) + obj(Items.BODY_RUNE, quantity = 6, slots = 5) + obj(Items.MIND_RUNE, quantity = 5, slots = 5) + obj(Items.AIR_RUNE, quantity = 13, slots = 4) + obj(Items.IRON_ARROW, quantity = 8, slots = 4) + obj(Items.STEEL_ARROW, quantity = 6, slots = 2) + obj(Items.NATURE_RUNE, quantity = 6, slots = 1) + obj(Items.COSMIC_RUNE, quantity = 4, slots = 1) obj(Items.FIRE_RUNE, quantity = 7, slots = 1) - table(Herbs.minorHerbTable, slots = 30) - obj(Items.COINS_995, quantity = 10, slots = 21) - obj(Items.COINS_995, quantity = 18, slots = 11) - obj(Items.COINS_995, quantity = 26, slots = 7) - obj(Items.COINS_995, quantity = 35, slots = 7) - obj(Items.COINS_995, quantity = 1, slots = 2) + table(Herbs.minorHerbTable, slots = 25) + obj(Items.COINS_995, quantity = 10, slots = 36) + obj(Items.COINS_995, quantity = 4, slots = 4) + obj(Items.COINS_995, quantity = 18, slots = 3) + obj(Items.COINS_995, quantity = 13, slots = 2) + obj(Items.COINS_995, quantity = 28, slots = 2) - nothing(slots = 3) - obj(Items.FISHING_BAIT, quantity = 7, slots = 26) - obj(Items.TINDERBOX_590, quantity = 1, slots = 2) - obj(Items.EYE_OF_NEWT, quantity = 1, slots = 1) - obj(Items.TIN_ORE, quantity = 1, slots = 1) - - table(Gems.gemTable, slots = 1) + nothing(slots = 8) + obj(Items.FISHING_BAIT, quantity = 5, slots = 5) + obj(Items.COPPER_ORE, quantity = 1, slots = 2) } table("Charms") { total(1000) diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_25.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_25.plugin.kts new file mode 100644 index 000000000..f671d8b03 --- /dev/null +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_25.plugin.kts @@ -0,0 +1,103 @@ +package gg.rsmod.plugins.content.npcs.definitions.undeads + +import gg.rsmod.game.model.combat.SlayerAssignment +import gg.rsmod.plugins.content.drops.DropTableFactory +import gg.rsmod.plugins.content.drops.global.Gems +import gg.rsmod.plugins.content.drops.global.Herbs + +val ids = intArrayOf(Npcs.ZOMBIE_76) +val table = DropTableFactory +val zombie = table.build { + + guaranteed { + obj(Items.BONES) + } + main { + total(total = 128) + + obj(Items.IRON_HATCHET, quantity = 1, slots = 5) + obj(Items.BRONZE_LONGSWORD, quantity = 1, slots = 1) + obj(Items.BRONZE_MED_HELM, quantity = 1, slots = 4) + obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 3) + + obj(Items.IRON_ARROW, quantity = 5, slots = 7) + obj(Items.BODY_RUNE, quantity = 6, slots = 5) + obj(Items.MIND_RUNE, quantity = 5, slots = 5) + obj(Items.AIR_RUNE, quantity = 13, slots = 4) + obj(Items.IRON_ARROW, quantity = 8, slots = 4) + obj(Items.STEEL_ARROW, quantity = 6, slots = 2) + obj(Items.NATURE_RUNE, quantity = 6, slots = 1) + obj(Items.COSMIC_RUNE, quantity = 4, slots = 1) + obj(Items.FIRE_RUNE, quantity = 7, slots = 1) + + + table(Herbs.minorHerbTable, slots = 25) + + obj(Items.COINS_995, quantity = 10, slots = 36) + obj(Items.COINS_995, quantity = 4, slots = 4) + obj(Items.COINS_995, quantity = 18, slots = 3) + obj(Items.COINS_995, quantity = 13, slots = 2) + obj(Items.COINS_995, quantity = 28, slots = 2) + + + nothing(slots = 6) + obj(Items.FISHING_BAIT, quantity = 5, slots = 5) + obj(Items.COPPER_ORE, quantity = 1, slots = 2) + } + table("Charms") { + total(1000) + obj(Items.GOLD_CHARM, quantity = 1, slots = 30) + obj(Items.GREEN_CHARM, quantity = 1, slots = 17) + obj(Items.CRIMSON_CHARM, quantity = 1, slots = 14) + obj(Items.BLUE_CHARM, quantity = 1, slots = 2) + nothing(slots = 937) + } +} + +table.register(zombie, *ids) + +on_npc_pre_death(*ids) { + val p = npc.damageMap.getMostDamage()!! as Player + p.playSound(Sfx.ZOMBIE_DEATH) +} + +on_npc_death(*ids) { + table.getDrop(world, npc.damageMap.getMostDamage()!! as Player, npc.id, npc.tile) +} + +ids.forEach { + set_combat_def(it) { + configs { + attackSpeed = 5 + respawnDelay = 35 + } + stats { + hitpoints = 300 + attack = 19 + strength = 21 + defence = 16 + } + bonuses { + attackStab = 5 + attackCrush = 7 + defenceStab = 9 + defenceSlash = 8 + defenceCrush = 12 + defenceMagic = 10 + defenceRanged = 11 + } + anims { + attack = 5578 + block = 5579 + death = 5580 + } + aggro { + radius = 4 + } + slayer { + assignment = SlayerAssignment.ZOMBIE + level = 1 + experience = 30.0 + } + } +} \ No newline at end of file diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_30.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_30.plugin.kts index 24976b0d6..ba4b496bb 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_30.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_30.plugin.kts @@ -15,34 +15,34 @@ val zombie = table.build { main { total(total = 128) - obj(Items.IRON_MACE, quantity = 1, slots = 3) - obj(Items.IRON_DAGGER, quantity = 1, slots = 2) - obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 1) + obj(Items.IRON_HATCHET, quantity = 1, slots = 3) + obj(Items.BRONZE_LONGSWORD, quantity = 1, slots = 1) + obj(Items.BRONZE_MED_HELM, quantity = 1, slots = 4) + obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 3) - obj(Items.MITHRIL_ARROW, quantity = 1, slots = 3) - obj(Items.AIR_RUNE, quantity = 3, slots = 2) - obj(Items.BODY_RUNE, quantity = 3, slots = 3) - obj(Items.CHAOS_RUNE, quantity = 4, slots = 1) - obj(Items.COSMIC_RUNE, quantity = 2, slots = 1) + obj(Items.IRON_ARROW, quantity = 5, slots = 7) + obj(Items.BODY_RUNE, quantity = 6, slots = 5) + obj(Items.MIND_RUNE, quantity = 5, slots = 5) + obj(Items.AIR_RUNE, quantity = 13, slots = 4) + obj(Items.IRON_ARROW, quantity = 8, slots = 4) + obj(Items.STEEL_ARROW, quantity = 6, slots = 2) + obj(Items.NATURE_RUNE, quantity = 6, slots = 1) + obj(Items.COSMIC_RUNE, quantity = 4, slots = 1) obj(Items.FIRE_RUNE, quantity = 7, slots = 1) - table(Herbs.minorHerbTable, slots = 30) - obj(Items.COINS_995, quantity = 10, slots = 21) - obj(Items.COINS_995, quantity = 18, slots = 11) - obj(Items.COINS_995, quantity = 26, slots = 7) - obj(Items.COINS_995, quantity = 35, slots = 7) - obj(Items.COINS_995, quantity = 1, slots = 2) + table(Herbs.minorHerbTable, slots = 25) + obj(Items.COINS_995, quantity = 10, slots = 36) + obj(Items.COINS_995, quantity = 4, slots = 4) + obj(Items.COINS_995, quantity = 18, slots = 3) + obj(Items.COINS_995, quantity = 13, slots = 2) + obj(Items.COINS_995, quantity = 28, slots = 2) - nothing(slots = 3) - obj(Items.FISHING_BAIT, quantity = 7, slots = 26) - obj(Items.TINDERBOX_590, quantity = 1, slots = 2) - obj(Items.EYE_OF_NEWT, quantity = 1, slots = 1) - obj(Items.TIN_ORE, quantity = 1, slots = 1) - - table(Gems.gemTable, slots = 1) + nothing(slots = 8) + obj(Items.FISHING_BAIT, quantity = 5, slots = 5) + obj(Items.COPPER_ORE, quantity = 1, slots = 2) } table("Charms") { total(1000) diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_44.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_44.plugin.kts index 4c2b785d1..32719f760 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_44.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_44.plugin.kts @@ -15,34 +15,34 @@ val zombie = table.build { main { total(total = 128) - obj(Items.IRON_MACE, quantity = 1, slots = 3) - obj(Items.IRON_DAGGER, quantity = 1, slots = 2) - obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 1) + obj(Items.IRON_HATCHET, quantity = 1, slots = 3) + obj(Items.BRONZE_LONGSWORD, quantity = 1, slots = 1) + obj(Items.BRONZE_MED_HELM, quantity = 1, slots = 4) + obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 3) - obj(Items.MITHRIL_ARROW, quantity = 1, slots = 3) - obj(Items.AIR_RUNE, quantity = 3, slots = 2) - obj(Items.BODY_RUNE, quantity = 3, slots = 3) - obj(Items.CHAOS_RUNE, quantity = 4, slots = 1) - obj(Items.COSMIC_RUNE, quantity = 2, slots = 1) + obj(Items.IRON_ARROW, quantity = 5, slots = 7) + obj(Items.BODY_RUNE, quantity = 6, slots = 5) + obj(Items.MIND_RUNE, quantity = 5, slots = 5) + obj(Items.AIR_RUNE, quantity = 13, slots = 4) + obj(Items.IRON_ARROW, quantity = 8, slots = 4) + obj(Items.STEEL_ARROW, quantity = 6, slots = 2) + obj(Items.NATURE_RUNE, quantity = 6, slots = 1) + obj(Items.COSMIC_RUNE, quantity = 4, slots = 1) obj(Items.FIRE_RUNE, quantity = 7, slots = 1) - table(Herbs.minorHerbTable, slots = 30) - obj(Items.COINS_995, quantity = 10, slots = 21) - obj(Items.COINS_995, quantity = 18, slots = 11) - obj(Items.COINS_995, quantity = 26, slots = 7) - obj(Items.COINS_995, quantity = 35, slots = 7) - obj(Items.COINS_995, quantity = 1, slots = 2) + table(Herbs.minorHerbTable, slots = 25) + obj(Items.COINS_995, quantity = 10, slots = 36) + obj(Items.COINS_995, quantity = 4, slots = 4) + obj(Items.COINS_995, quantity = 18, slots = 3) + obj(Items.COINS_995, quantity = 13, slots = 2) + obj(Items.COINS_995, quantity = 28, slots = 2) - nothing(slots = 3) - obj(Items.FISHING_BAIT, quantity = 7, slots = 26) - obj(Items.TINDERBOX_590, quantity = 1, slots = 2) - obj(Items.EYE_OF_NEWT, quantity = 1, slots = 1) - obj(Items.TIN_ORE, quantity = 1, slots = 1) - - table(Gems.gemTable, slots = 1) + nothing(slots = 8) + obj(Items.FISHING_BAIT, quantity = 5, slots = 5) + obj(Items.COPPER_ORE, quantity = 1, slots = 2) } table("Charms") { total(1000) diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_53.plugin.kts b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_53.plugin.kts index 8d206b5f7..5ffa3473b 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_53.plugin.kts +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/npcs/definitions/undeads/zombie_lvl_53.plugin.kts @@ -15,34 +15,34 @@ val zombie = table.build { main { total(total = 128) - obj(Items.IRON_MACE, quantity = 1, slots = 3) - obj(Items.IRON_DAGGER, quantity = 1, slots = 2) - obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 1) + obj(Items.IRON_HATCHET, quantity = 1, slots = 3) + obj(Items.BRONZE_LONGSWORD, quantity = 1, slots = 1) + obj(Items.BRONZE_MED_HELM, quantity = 1, slots = 4) + obj(Items.BRONZE_KITESHIELD, quantity = 1, slots = 3) - obj(Items.MITHRIL_ARROW, quantity = 1, slots = 3) - obj(Items.AIR_RUNE, quantity = 3, slots = 2) - obj(Items.BODY_RUNE, quantity = 3, slots = 3) - obj(Items.CHAOS_RUNE, quantity = 4, slots = 1) - obj(Items.COSMIC_RUNE, quantity = 2, slots = 1) + obj(Items.IRON_ARROW, quantity = 5, slots = 7) + obj(Items.BODY_RUNE, quantity = 6, slots = 5) + obj(Items.MIND_RUNE, quantity = 5, slots = 5) + obj(Items.AIR_RUNE, quantity = 13, slots = 4) + obj(Items.IRON_ARROW, quantity = 8, slots = 4) + obj(Items.STEEL_ARROW, quantity = 6, slots = 2) + obj(Items.NATURE_RUNE, quantity = 6, slots = 1) + obj(Items.COSMIC_RUNE, quantity = 4, slots = 1) obj(Items.FIRE_RUNE, quantity = 7, slots = 1) - table(Herbs.minorHerbTable, slots = 30) - obj(Items.COINS_995, quantity = 10, slots = 21) - obj(Items.COINS_995, quantity = 18, slots = 11) - obj(Items.COINS_995, quantity = 26, slots = 7) - obj(Items.COINS_995, quantity = 35, slots = 7) - obj(Items.COINS_995, quantity = 1, slots = 2) + table(Herbs.minorHerbTable, slots = 25) + obj(Items.COINS_995, quantity = 10, slots = 36) + obj(Items.COINS_995, quantity = 4, slots = 4) + obj(Items.COINS_995, quantity = 18, slots = 3) + obj(Items.COINS_995, quantity = 13, slots = 2) + obj(Items.COINS_995, quantity = 28, slots = 2) - nothing(slots = 3) - obj(Items.FISHING_BAIT, quantity = 7, slots = 26) - obj(Items.TINDERBOX_590, quantity = 1, slots = 2) - obj(Items.EYE_OF_NEWT, quantity = 1, slots = 1) - obj(Items.TIN_ORE, quantity = 1, slots = 1) - - table(Gems.gemTable, slots = 1) + nothing(slots = 8) + obj(Items.FISHING_BAIT, quantity = 5, slots = 5) + obj(Items.COPPER_ORE, quantity = 1, slots = 2) } table("Charms") { total(1000) diff --git a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/impl/LostCity.kt b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/impl/LostCity.kt index 56f98a683..4af188fa1 100644 --- a/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/impl/LostCity.kt +++ b/game/plugins/src/main/kotlin/gg/rsmod/plugins/content/quests/impl/LostCity.kt @@ -19,11 +19,11 @@ object LostCity : Quest( ), requiredItems = "None.", combat = "Must be able to kill a level 63 Tree spirit.", - rewards = "Access to Zanaris
Ability to wield dragon longswords and dragon daggers" + - "
Ability to craft cosmic runes
Access to Chaeldar, the slayer master (requires level 75 combat)", + rewards = "Access to Zanaris, Ability to wield dragon longswords and dragon daggers" + + "
Ability to craft cosmic runes, Access to Chaeldar, the slayer master (requires level 75 combat)", pointReward = 3, questId = 147, - spriteId = 0, + spriteId = -1, slot = 68, stages = 6 ) { @@ -32,85 +32,122 @@ object LostCity : Quest( } //QuestStages - val NOT_STARTED: Int = 0 - val FINDING_SHAMUS: Int = 1 - val ENTRANA_ARRIVAL: Int = 2 - val CHOP_DRAMEN_BRANCH: Int = 3 - val CREATE_DRAMEN_STAFF: Int = 4 - val ENTER_ZANARIS: Int = 5 - val QUEST_COMPLETE: Int = 6 + const val NOT_STARTED: Int = 0 + const val FINDING_SHAMUS: Int = 1 + const val FOUND_SHAMUS: Int = 2 + const val ENTRANA_DUNGEON: Int = 3 + const val CUT_DRAMEN_TREE: Int = 4 + const val CREATE_DRAMEN_BRANCH: Int = 5 + const val QUEST_COMPLETE: Int = 6 override fun getObjective(player: Player, stage: Int): QuestStage = when (stage) { - 1 -> QuestStage ( - objectives = listOf( - "The warrior in Lumbridge Swamp said I am to find a", - "leprechaun in the area by trying to chop down trees?", - "", + 1 -> { + QuestStage ( + objectives = listOf( + "According to one of the adventurers in Lumbridge Swamp", + "the entrance to Zanaris is somewhere around there.", + "", + ) ) - ) + } 2 -> { - if (player.attr.has(gaveHarlowBeer) && !player.attr.has(killedCountDraynor)) { - QuestStage( + QuestStage ( objectives = listOf( - striked("I talked to Morgan in Draynor Village. He told me that the"), - striked("Locals are being attacked by a terrifying vampyre."), - striked("I have spoken to Dr Harlow. He seemed terribly drunk, and"), - striked("he kept asking for drinks."), - "", - "${red("Dr Harlow")} told me that, to succeed, I'll need the following:", - striked("A stake to kill the vampyre once I've finished fighting it."), - striked("A stake hammer to drive the stake deep into the"), - striked("vampyre's chest."), - "Some ${red("garlic")} to weaken the ${red("vampire")}", - "", - "When I'm ready, I should go to ${red("Draynor Manor")}, north of", - "Draynor, to kill the ${red("vampyre")} that's living in the basement.", - "Dr Harlow reminded me again and again to be prepared for", - "a tough fight." + striked("According to one of the adventurers in Lumbridge Swamp"), + striked("the entrance to Zanaris is somewhere around there."), + "", + "I found a Leprechaun hiding in a nearby tree.", + "He told me that the entrance to Zanaris is in the shed in", + "Lumbridge swamp but only if I am carrying a Dramen Staff.", ) - ) - } - if (player.attr.has(gaveHarlowBeer) && player.attr.has(killedCountDraynor)) { - QuestStage( + ) + } + + 3 -> { + QuestStage ( objectives = listOf( - striked("I talked to Morgan in Draynor Village. He told me that the"), - striked("Locals are being attacked by a terrifying vampyre."), - striked("I have spoken to Dr Harlow. He seemed terribly drunk, and"), - striked("he kept asking for drinks."), - "", - "I killed the vampyre! I should tell ${red("Morgan")} that his village is", - "safe once again.", + striked("According to one of the adventurers in Lumbridge Swamp"), + striked("the entrance to Zanaris is somewhere around there."), + "", + striked("I found a Leprechaun hiding in a nearby tree."), + striked("He told me that the entrance to Zanaris is in the shed in"), + striked("Lumbridge swamp but only if I am carrying a Dramen Staff."), + "", + "The Dramen Tree was guarded by a powerful Tree Spirit.", ) - ) - } else { - QuestStage( + ) + } + 4 -> { + QuestStage ( objectives = listOf( - striked("I talked to Morgan in Draynor Village. He told me that the"), - striked("Locals are being attacked by a terrifying vampyre."), - striked("I have spoken to Dr Harlow. He seemed terribly drunk, and"), - striked("he kept asking for drinks."), - "", - "I need to buy ${red("Dr Harlow")} a drink and ask him", - "how to kill the vampyre.", + striked("According to one of the adventurers in Lumbridge Swamp"), + striked("the entrance to Zanaris is somewhere around there."), + "", + striked("I found a Leprechaun hiding in a nearby tree."), + striked("He told me that the entrance to Zanaris is in the shed in"), + striked("Lumbridge swamp but only if I am carrying a Dramen Staff."), + "", + "The Dramen Tree was guarded by a powerful Tree Spirit.", + "I cut a branch from the tree and crafted a Dramen Staff." ) - ) - } + ) } - - else -> QuestStage( - objectives = listOf( - striked("I talked to Morgan in Draynor Village. He told me that the"), - striked("Locals are being attacked by a terrifying vampyre."), - striked("I have spoken to Dr Harlow. He seemed terribly drunk, and"), - striked("he kept asking for drinks."), - "", - "I have killed the vampyre, Count Draynor.", - "Draynor Village is now safe!", - questCompleteText + 5 -> { + QuestStage ( + objectives = listOf( + striked("According to one of the adventurers in Lumbridge Swamp"), + striked("the entrance to Zanaris is somewhere around there."), + "", + striked("I found a Leprechaun hiding in a nearby tree."), + striked("He told me that the entrance to Zanaris is in the shed in"), + striked("Lumbridge swamp but only if I am carrying a Dramen Staff."), + "", + striked("The Dramen Tree was guarded by a powerful Tree Spirit."), + "I cut a branch from the tree and crafted a Dramen Staff.", + ) ) - ) + } + 6 -> { + QuestStage ( + objectives = listOf( + striked("According to one of the adventurers in Lumbridge Swamp"), + striked("the entrance to Zanaris is somewhere around there."), + "", + striked("I found a Leprechaun hiding in a nearby tree."), + striked("He told me that the entrance to Zanaris is in the shed in"), + striked("Lumbridge swamp but only if I am carrying a Dramen Staff."), + "", + striked("The Dramen Tree was guarded by a powerful Tree Spirit."), + striked("I cut a branch from the tree and crafted a Dramen Staff."), + striked("With the mystical Dramen Staff in my possession I was"), + striked("able to enter Zanaris through the shed in Lumbridge"), + striked("swamp."), + "", + " QUEST COMPLETE! ", + ) + ) + } + else -> { + QuestStage ( + objectives = listOf( + "Legends tell of a magical lost city hidden in the swamps.", + "Many adventurers have tried to find this city, but it is", + "proving difficult. Can you unlock the secrets of the city", + "of Zanaris?", + "", + "I can start this quest by talking to a warrior in Lumbridge Swamp.", + "You will need to puzzle through the dialogues to start the quest.", + "Come back here to see when to look for the dramen branches.", + "", + "~~Requirements~~", + "31 Crafting", + "36 Woodcutting", + "", + ) + ) + } } override fun finishQuest(player: Player) { @@ -120,9 +157,7 @@ object LostCity : Quest( item = Items.DRAMEN_STAFF, rewards = arrayOf( "3 Quest Points", - "Access to Zanaris", - "The ability to wield a dragon longsword or dagger with level 60 attack." - ) + "Access to Zanaris") ) } } \ No newline at end of file diff --git a/game/src/main/kotlin/gg/rsmod/game/fs/def/ItemDef.kt b/game/src/main/kotlin/gg/rsmod/game/fs/def/ItemDef.kt index 9fc6464b1..c4aeb4d16 100644 --- a/game/src/main/kotlin/gg/rsmod/game/fs/def/ItemDef.kt +++ b/game/src/main/kotlin/gg/rsmod/game/fs/def/ItemDef.kt @@ -21,6 +21,8 @@ class ItemDef(override val id: Int) : Definition(id) { val groundMenu = Array(5) { null } val inventoryMenu = Array(5) { null } val equipmentMenu = Array(8) { null } + val realId: Int + get() = if (noted) noteTemplateId else id /** * The item can be traded through the grand exchange. */ diff --git a/game/src/main/kotlin/gg/rsmod/game/model/attr/Attributes.kt b/game/src/main/kotlin/gg/rsmod/game/model/attr/Attributes.kt index 579886117..8fed22df7 100644 --- a/game/src/main/kotlin/gg/rsmod/game/model/attr/Attributes.kt +++ b/game/src/main/kotlin/gg/rsmod/game/model/attr/Attributes.kt @@ -529,4 +529,8 @@ val LAST_MAP_BUILD_TIME = AttributeKey(persistenceKey = "last_map_build") /** * The last slot the player has selected for the random event gift interface */ -val RANDOM_EVENT_GIFT_SLOT = AttributeKey() \ No newline at end of file +val RANDOM_EVENT_GIFT_SLOT = AttributeKey() +/** + * The lost city attribute + */ +val HAS_SPAWNED_TREE_SPIRIT = AttributeKey() \ No newline at end of file diff --git a/game/src/main/kotlin/gg/rsmod/game/model/container/ItemContainer.kt b/game/src/main/kotlin/gg/rsmod/game/model/container/ItemContainer.kt index 36dbd20fb..58e469a02 100644 --- a/game/src/main/kotlin/gg/rsmod/game/model/container/ItemContainer.kt +++ b/game/src/main/kotlin/gg/rsmod/game/model/container/ItemContainer.kt @@ -13,6 +13,21 @@ import mu.KLogging * @author Tom */ class ItemContainer(val definitions: DefinitionSet, val key: ContainerKey) : Iterable { + fun toUnnotedOrSelf(item: Item): Item { + val unnoted = item.getDef(definitions).realId + return if (unnoted == -1) { + item + } else { + Item(unnoted, item.amount) + } + } + + fun sequence(): Sequence { + return iterator() + .asSequence() + .filterNotNull() + .map(::toUnnotedOrSelf) + } constructor(definitions: DefinitionSet, capacity: Int, stackType: ContainerStackType) : this(definitions, ContainerKey("", capacity, stackType)) @@ -31,7 +46,7 @@ class ItemContainer(val definitions: DefinitionSet, val key: ContainerKey) : Ite private val stackType = key.stackType - private val items = Array(capacity) { null } + val items = Array(capacity) { null } /** * A flag which indicates that the [items] has been modified since the last @@ -57,6 +72,12 @@ class ItemContainer(val definitions: DefinitionSet, val key: ContainerKey) : Ite } return true } + /** + Method to check a player's items' + */ + fun getItemIds(): IntArray { + return items.filterNotNull().map { it.id }.toIntArray() + } /** * Method to check if player has free slots.