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.