Merge branch 'in-pyre-need-implementation' into 'master'

Draft: Initial In Pyre Need

See merge request 2009scape/2009scape!1929
This commit is contained in:
Oven Bread 2025-11-30 03:00:15 +00:00
commit a372547c00
4 changed files with 502 additions and 0 deletions

View file

@ -12411,6 +12411,34 @@
"npc_id": "8545",
"loc_data": "{3122,3626,0,1,0}-"
},
{
"npc_id": "8557",
"loc_data": "{3497,5223,0,1,0}-{3504,5211,0,1,0}-{3514,5188,0,1,0}-{3514,5209,0,1,0}-{3526,5224,0,1,0}-"
},
{
"npc_id": "8559",
"loc_data": "{3460,5222,0,1,0}-{3469,5201,0,1,0}-{3470,5211,0,1,0}-{3474,5244,0,1,0}-{3482,5206,0,1,0}-{3484,5237,0,1,0}-{3494,5226,0,1,0}-{3495,5211,0,1,0}-{3501,5233,0,1,0}-{3508,5223,0,1,0}-{3526,5245,0,1,0}-{3536,5222,0,1,0}-"
},
{
"npc_id": "8561",
"loc_data": "{3466,5206,0,1,0}-{3516,5240,0,1,0}-{3530,5237,0,1,0}-{3546,5240,0,1,0}-"
},
{
"npc_id": "8563",
"loc_data": "{3462,5206,0,1,0}-{3464,5243,0,1,0}-{3469,5221,0,1,0}-{3483,5199,0,1,0}-{3483,5231,0,1,0}-{3497,5243,0,1,0}-{3506,5204,0,1,0}-{3516,5227,0,1,0}-"
},
{
"npc_id": "8565",
"loc_data": "{3461,5237,0,1,0}-{3465,5211,0,1,0}-{3477,5225,0,1,0}-{3498,5202,0,1,0}-{3525,5241,0,1,0}-"
},
{
"npc_id": "8567",
"loc_data": "{3479,5212,0,1,0}-{3492,5188,0,1,0}-{3494,5238,0,1,0}-{3496,5192,0,1,0}-{3504,5242,0,1,0}-{3513,5196,0,1,0}-{3534,5234,0,1,0}-{3547,5222,0,1,0}-{3547,5232,0,1,0}-"
},
{
"npc_id": "8579",
"loc_data": "{2292,3626,0,1,0}-"
},
{
"npc_id": "8590",
"loc_data": "{2743,3444,0,1,0}-"

View file

@ -0,0 +1,228 @@
package content.region.kandarin.pisc.quest.inpyreneed
import content.data.Quests
import core.api.getQuestStage
import core.api.hasLevelStat
import core.api.isQuestComplete
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.quest.Quest
import core.game.node.entity.skill.Skills
import core.plugin.Initializable
import org.rs09.consts.Items
@Initializable
class InPyreNeed : Quest(Quests.IN_PYRE_NEED,162, 161, 1, 1370, 5761, 0, 1, 30){
companion object {
val questName = Quests.IN_PYRE_NEED
const val attributeRegionInstance = "/save:quest:inpyreneed-regioninstance"
fun hasRequirements(player: Player): Boolean {
return arrayOf(
hasLevelStat(player, Skills.FLETCHING, 53),
hasLevelStat(player, Skills.CRAFTING, 52),
hasLevelStat(player, Skills.FIREMAKING, 55),
).all { it }
}
}
override fun drawJournal(player: Player, stage: Int) {
super.drawJournal(player, stage)
var line = 12
var stage = getStage(player)
var started = getQuestStage(player, questName) > 0
if (!started) {
line(player,"I can start this quest by speaking to the !!Priest of Guthix??", line++)
line(player,"near the cave south of the !!Piscatoris Fishing Colony??.", line++)
line++
line(player,"This quest has the following requirements:", line++)
line(player, "!!Level 53 Fletching??", line++, hasLevelStat(player, Skills.FLETCHING, 53))
line(player, "!!Level 52 Crafting??", line++, hasLevelStat(player, Skills.CRAFTING, 52))
line(player, "!!Level 55 Firemaking??", line++, hasLevelStat(player, Skills.FIREMAKING, 55))
} else {
line(player, "I spoke to the Priest of Guthix, near the cave south of the", line++, true)
line(player, "Piscatoris Fishing Colony. He wants me to enter a cave", line++, true)
line(player, "that is apparently the lair of the legendary phoenix, which", line++, true)
line(player, "was attacked and mortally wounded on its way back to its", line++, true)
line(player, "roost. I must complete a ritual, which he believes will", line++, true)
line(player, "ensure the phoenix's survival.", line++, true)
if (stage >= 2) {
line++
line(player, "I could !!enter the cave?? and try to figure it out for myself, or I", line++, true)
line(player, "should ask the !!Priest of Guthix?? for more information.", line++, true)
} else if (stage >= 1) {
line++
line(player, "I could !!enter the cave?? and try to figure it out for myself, or I", line++, false)
line(player, "should ask the !!Priest of Guthix?? for more information.", line++, false)
}
if (stage >= 3) {
line++
line(player, "I have gained some more information about the ritual.", line++, true)
line(player, "Apparently, there are !!five?? different !!aromatic trees?", line++, true)
line(player, "growing inside the !!phoenix's?? lair. I must gather !!twigs?? from", line++, true)
line(player, "each of these !!trees?? as I progress through the lair. These", line++, true)
line(player, "must then be !!fletched?? into !!weaving ribbon??, which in turn", line++, true)
line(player, "must be !!crafted?? into a large !!basket?? atop a !!funeral pyre?? in", line++, true)
line(player, "the !!phoenix's roost??. I must then !!light?? this !!completed??", line++, true)
line(player, "!!funeral pyre??, so that the !!phoenix?? can burn to, and be", line++, true)
line(player, "reborn from, ashes. !!If I leave the cave, I will have to??", line++, true)
line(player, "!!gather all the twigs again, as only fresh twigs are suitable??", line++, true)
line(player, "!!for the ritual??.", line++, true)
} else if (stage >= 2) {
line++
line(player, "I have gained some more information about the ritual.", line++, false)
line(player, "Apparently, there are !!five?? different !!aromatic trees?", line++, false)
line(player, "growing inside the !!phoenix's?? lair. I must gather !!twigs?? from", line++, false)
line(player, "each of these !!trees?? as I progress through the lair. These", line++, false)
line(player, "must then be !!fletched?? into !!weaving ribbon??, which in turn", line++, false)
line(player, "must be !!crafted?? into a large !!basket?? atop a !!funeral pyre?? in", line++, false)
line(player, "the !!phoenix's roost??. I must then !!light?? this !!completed??", line++, false)
line(player, "!!funeral pyre??, so that the !!phoenix?? can burn to, and be", line++, false)
line(player, "reborn from, ashes. !!If I leave the cave, I will have to??", line++, false)
line(player, "!!gather all the twigs again, as only fresh twigs are suitable??", line++, false)
line(player, "!!for the ritual??.", line++, false)
}
if (stage >= 3) {
line++
line(player, "I have entered the cave.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have gathered the cinnamon twigs.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have fletched the cinnamon twigs into weaving ribbon.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have gathered the sassafras twigs.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have fletched the sassafras twigs into weaving ribbon.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have gathered the ailanthus twigs.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have fletched the ailanthus twigs into weaving ribbon.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have gathered the cedar twigs.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have fletched the cedar twigs into weaving ribbon.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have gathered the mastic twigs.", line++, true)
}
if (stage >= 3) {
line++
line(player, "I have fletched the mastic twigs into weaving ribbon.", line++, true)
}
if (stage >= 5) {
line++
line(player, "I have gathered all the twigs, and made my way to the", line++, true)
line(player, "phoenix's roost. The phoenix is here. It is gravely", line++, true)
line(player, "wounded.", line++, true)
line(player, "I should look around for clues as to what to do next.", line++, true)
} else if (stage >= 4) {
line++
line(player, "I have gathered all the twigs, and made my way to the", line++, true)
line(player, "phoenix's roost. The phoenix is here. It is gravely", line++, true)
line(player, "wounded.", line++, true)
line(player, "I should look around for clues as to what to do next.", line++, false)
}
if (stage >= 6) {
line++
line(player, "I should hurry and !!fletch?? all of the !!twigs?? into !!weaving??.", line++, true)
line(player, "!!ribbons??, construct the !!funeral pyre?? and !!light?? it.", line++, true)
} else if (stage >= 5) {
line++
line(player, "I should hurry and !!fletch?? all of the !!twigs?? into !!weaving??.", line++, false)
line(player, "!!ribbons??, construct the !!funeral pyre?? and !!light?? it.", line++, false)
}
if (stage >= 7) {
line++
line(player, "I have constructed and lit the !!funeral pyre??. The !!phoenix??", line++, true)
line(player, "managed to limp over and throw itself into the fire.", line++, true)
line(player, "It burned to ashes, and in a flash of flame was reborn. I", line++, true)
line(player, "should speak to the !!phoenix?? and ensure all is okay before", line++, true)
line(player, "returning to the !!Priest of Guthix??.", line++, true)
} else if (stage >= 6) {
line++
line(player, "I have constructed and lit the !!funeral pyre??. The !!phoenix??", line++, false)
line(player, "managed to limp over and throw itself into the fire.", line++, false)
line(player, "It burned to ashes, and in a flash of flame was reborn. I", line++, false)
line(player, "should speak to the !!phoenix?? and ensure all is okay before", line++, false)
line(player, "returning to the !!Priest of Guthix??.", line++, false)
}
if (stage >= 8) {
line(player, "The !!reborn phoenix?? spoke to me, thanking me for helping", line++, true)
line(player, "her its time of need. As a reward, the !!phoenix?? gave me", line++, true)
line(player, "!!5 phoenix quills??, and also gave me permission to !!challenge??", line++, true)
line(player, "!!it to combat?? in its roost !!once per day, once my combat??", line++, true)
line(player, "!!skills are proven??. I should meet the !!Priest of Guthix?? at the", line++, true)
line(player, "entrance to the !!phoenix's lair?? to claim my !!reward?? from him,", line++, true)
line(player, "too.", line++, true)
} else if (stage >= 7) {
line(player, "The !!reborn phoenix?? spoke to me, thanking me for helping", line++, false)
line(player, "her its time of need. As a reward, the !!phoenix?? gave me", line++, false)
line(player, "!!5 phoenix quills??, and also gave me permission to !!challenge??", line++, false)
line(player, "!!it to combat?? in its roost !!once per day, once my combat??", line++, false)
line(player, "!!skills are proven??. I should meet the !!Priest of Guthix?? at the", line++, false)
line(player, "entrance to the !!phoenix's lair?? to claim my !!reward?? from him,", line++, false)
line(player, "too.", line++, false)
}
if (stage >= 100) {
line++
line(player, "I have spoken to the Priest of Guthix, who thanked and rewarded me", line++, true)
line(player, "for my help.", line++, true)
line++
line(player,"<col=FF0000>QUEST COMPLETE!</col>", line)
}
}
}
override fun reset(player: Player) {
}
override fun finish(player: Player) {
var ln = 10
super.finish(player)
player.packetDispatch.sendString("You have completed the In Pyre Need Quest!", 277, 4)
player.packetDispatch.sendItemZoomOnInterface(Items.PHOENIX_QUILL_14616, 240, 277, 5)
drawReward(player,"1 Quest Points", ln++)
drawReward(player,"14,400 Firemaking XP", ln++)
drawReward(player,"12,500 Fletching XP", ln++)
drawReward(player,"11,556 Crafting XP", ln++)
drawReward(player,"Access to the phoenix lair", ln)
drawReward(player,"once per day", ln)
player.skills.addExperience(Skills.FIREMAKING, 14400.0)
player.skills.addExperience(Skills.FLETCHING, 12500.0)
player.skills.addExperience(Skills.CRAFTING, 11556.0)
}
override fun newInstance(`object`: Any?): Quest {
return this
}
}

View file

@ -0,0 +1,89 @@
package content.region.kandarin.pisc.quest.inpyreneed
import core.api.*
import core.game.dialogue.DialogueFile
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.world.map.Location
import core.game.world.map.build.DynamicRegion
import core.tools.END_DIALOGUE
import org.rs09.consts.NPCs
import org.rs09.consts.Scenery
class InPyreNeedListeners: InteractionListener {
companion object {
// For region 13905
val entrancesLeft = arrayOf(
Location(20, 2), // SW entrance
Location(37, 2), // SE entrance
Location(5, 34), // NW entrance
Location(60, 40), // NE entrance
)
// For region 14161
val entrancesRight = arrayOf(
Location(26, 61), // NW entrance
Location(46, 40), // NE entrance egg
Location(15, 2), // SW entrance phoenix lair
)
// Trees are in order.
val trees = arrayOf(
Scenery.CINNAMON_TREE_41903,
Scenery.SASSAFRAS_TREE_41904,
Scenery.AILANTHUS_TREE_41905,
Scenery.CEDAR_TREE_41906,
Scenery.MASTIC_TREE_41907,
)
fun randomizeLayout(player: Player) {
}
}
override fun defineListeners() {
on(Scenery.CAVE_ENTRANCE_41900, IntType.SCENERY, "enter") { player, node ->
if (getQuestStage(player, InPyreNeed.questName) >= 100) {
// This is the weekly minigame.
}else if (getQuestStage(player, InPyreNeed.questName) >= 1) {
val regionInstance = DynamicRegion.create(13905)
//setAttribute(player, InPyreNeed.attributeRegionInstance, regionInstance)
teleport(player, regionInstance.baseLocation.transform(37,2, 0))
registerLogoutListener(player, "in-pyre-need-logout") {
player.location = Location.create(2294, 3626, 0)
player.locks.unlockTeleport()
}
// zone.register(getRegionBorders(regionInstance.id))
// Fade
} else {
openDialogue(player, object : DialogueFile() {
override fun handle(componentID: Int, buttonID: Int) {
when (stage) {
0 -> npcl("Hey, wait! I have something to as you if you're going down there.").also { stage++ }
1 -> playerl("Maybe I should see what he has to say before entering this dark, scary and unreasonably warm cave.").also {
stage = END_DIALOGUE
}
}
}
}, NPC(NPCs.PRIEST_OF_GUTHIX_8555))
}
return@on true
}
on(Scenery.CAVE_ENTRANCE_41902, IntType.SCENERY, "escape") { player, node ->
teleport(player, Location(2294, 3626, 0))
val regionInstance = getAttribute(player, InPyreNeed.attributeRegionInstance, null)
if (regionInstance != null) {
}
return@on true
}
}
}

View file

@ -0,0 +1,157 @@
package content.region.kandarin.pisc.quest.inpyreneed
import core.api.*
import core.game.dialogue.*
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.plugin.Initializable
import org.rs09.consts.NPCs
@Initializable
class PriestOfGuthixDialogue: InteractionListener {
override fun defineListeners() {
on(NPCs.PRIEST_OF_GUTHIX_8555, IntType.NPC, "talk-to") { player, node ->
DialogueLabeller.open(player, PriestOfGuthixDialogueFile (), node as NPC)
return@on true
}
}
// https://youtu.be/DZQqDsvxGM0
class PriestOfGuthixDialogueFile : DialogueLabeller() {
override fun addConversation() {
player(ChatAnim.FRIENDLY,"Hello there.")
exec { player, npc ->
if (getQuestStage(player, InPyreNeed.questName) in 1..6) {
loadLabel(player, "InPyreNeedAlreadyStarted")
} else if (InPyreNeed.hasRequirements(player)) {
loadLabel(player, "InPyreNeedStart")
} else {
loadLabel(player, "InPyreNeedRequirementsNotMet")
}
}
label("InPyreNeedRequirementsNotMet")
npc("Oh, isn't there anyone around here who is willing and able to help me?")
player("I'm willing to help.")
npc("Unfortunately, you are not able.")
line("You need 52 Crafting, 53 Fletching and 55 Firemaking to start this quest.")
label("InPyreNeedAlreadyStarted")
npc("@name! How is your quest to save the phoenix progressing?")
player("I'm a little unsure on what I have to do next. Could I ask you some questions?")
npc("What would you like to ask about?")
goto("InPyreNeedMoreInformation")
label("InPyreNeedStart")
npc("Please, adventurer, I beg you. You must help her!")
player("Woah, hold your unicorns! Help who?")
npc("I...I'm sorry. My emotions have run away with me. Allow me to explain.")
npc("This cave is a place of great significance. Do you know why?")
player("I can't say I do.")
npc("It is the roost of the legendary firebird, the phoenix!")
player("Really?")
player("But wait, how is this related to who I have to help?")
npc("It is related because it is the phoenix that is in need of your assistance.")
player("You're starting to confuse me.")
player("Perhaps you should take a deep breath and start from the beginning.")
npc("Okay...*sigh*")
npc("I have been studying the phoenix for some time now, out of curiosity and admiration.")
npc("While not truly immortal, the phoenix has the capacity to live forever if certain...conditions...are met.")
player("Conditions?")
npc("The phoenix has a natural lifespan of 500 years. There is a set ritual it must go through when its life is ending, in order for it to be reborn and live for another five centuries.")
npc("The end of the phoenix's current lifespan is nigh and it has returned to its roost to complete this ritual. I came here to witness this once in a lifetime event.")
player("So, the phoenix has returned to its roost and you came to watch it be reborn. I fail to see the problem.")
npc("The phoenix was gravely wounded on its way back to its roost. It barely managed to reach its lair.")
npc("It now rests there, slowly slipping from this world and soon it will be gone forever, incapable of completing its rebirth ritual owing to its wounds.")
player("A tragic tale, but what can I do about it?")
npc("I know the ritual that must be completed. To save the phoenix, you must go into the cave and perform it.")
npc("Completing the ritual before the phoenix takes its last breath will ensure its revival, and continue the potentially eternal life of this magnificent beast.")
player("If you know the ritual, why can't you venture forth and help the phoenix yourself?")
npc("Because I am an old man whose mind and fingers lack the necessary skill to complete the ritual...")
npc("...and whose body lacks the necessary heat-resistance.")
player("...")
npc("The task I ask of you will not take long, and you will be well rewarded for your efforts. Will you please complete the phoenix's ritual?")
options (
DialogueOption("StartYes", "Yes, I will help."),
DialogueOption("StartNo", "No, I have other things to do.")
)
label("StartYes")
exec { player, npc ->
if(getQuestStage(player, InPyreNeed.questName) == 0) {
setQuestStage(player, InPyreNeed.questName, 1)
}
}
npc("You'll help? Oh, praise be to Guthix! I knew I could trust you from the moment I saw you.")
npc("What is your name, adventurer?")
player("You can call me @name.")
npc("Well, @name, it's nice to meet you. No doubt you have questions about the task at hand.")
goto("InPyreNeedMoreInformation")
label("StartNo")
npc("Well, I can't force you. If you change your mind, hurry back. The phoenix's life could fade at any moment.")
label("InPyreNeedMoreInformation")
options (
DialogueOption("ThePhoenix", "The phoenix.", skipPlayer = true),
DialogueOption("TheRitual", "The ritual.", skipPlayer = true),
DialogueOption("ThePhoenixLair", "The phoenix lair.", skipPlayer = true),
DialogueOption("NoMoreQuestions", "No more questions", skipPlayer = true),
)
label("ThePhoenix")
player("Could you tell me about the phoenix?")
npc("The phoenix is an ancient creature - older than either of us can comprehend.")
npc("It is a large, powerful avian creature, surrounded by flames and covered in a fiery plumage. It also has strong magical abilities.")
npc("Every five hundred years, as it reaches the limits of its lifespan, it returns to its roost to complete a ritual and be reborn.")
npc("You see, while not truly immortal, the phoenix can be reborn any number of times, so long as it completes its rebirth ritual.")
npc("But, thanks to its wounds, the phoenix could soon be gone from this world forever.")
player("Thanks for the information. Now, back to my other questions.")
goto("InPyreNeedMoreInformation")
label("TheRitual")
player("Could you tell me about the phoenix's rebirth ritual?")
npc("The ritual is not that complicated, really; it just requires certain ingredients and a set of dexterous hands.")
npc("In order to be reborn, the phoenix must be burnt alive on a funeral pyre woven from the wood of five particular trees.")
npc("You must weave a basket from the fletched twigs of cinnamon, sassafras, ailanthus, cedar and mastic trees.")
npc("This basket must be placed on the base of the pyre in the phoenix's roost, and then it must be lit.")
npc("Usually, you would also need to best the phoenix in combat to weaken it, so that it can succumb to the flames.")
npc("This time, however, the phoenix is already weak and dying.")
npc("The phoenix will enter the pyre and be burnt to ashes. From these ashes, it will be reborn - young and strong again.")
/** First time */
player("Oh, I see. I need to search the four corners of the world for five trees. Well, I suppose I'd best get packing-")
npc("While I understand your concern, that won't be a problem at all.")
player("How so?")
npc("As I have said, the phoenix is an ancient creature with some limited power over life and death.")
npc("The trees you require are growing inside its very lair, and have been for millennia! The phoenix revives them from their own ashes each time they die.")
player("That's amazing. What a foresighted creature the phoenix is!")
/** Repeated instead of First time: npcl There are specimens of each tree growing inside the phoenix's lair, tended to by the phoenix's thralls in its absence and revived from the trees[sic] ashes whenever they die. */
npc("Each tree is on a separate level of the lair. You must collect the twigs before moving on. It's pointless to continue on to a deeper level without having the twigs from all the levels before it.")
npc("Only fresh twigs will suffice for the ritual. If you leave the lair at any time, you will have to go through and collect fresh twigs from every tree.")
npc("There are some other items required for the ritual that you cannot get from inside the lair.")
player("Oh? What would those be then?")
npc("Tools. Secateurs, to prune the trees and gather the twigs, a knife to fletch them and a tinderbox to light the pyre.")
npc("Given the circumstances, I'd be happy to give you the necessary tools for free. I brought a set to complete the ritual myself, but...I'm too old.")
goto("InPyreNeedMoreInformation")
label("ThePhoenixLair")
player("Could you tell me about the phoenix's lair?")
npc("The phoenix's lair is a lava-filled cave, guarded by its thralls.")
npc("You see, the phoenix has power over life and death that is not limited to itself. It has the ability to resurrect lesser creatures.")
npc("These revived creatures now roam the phoenix's lair, guarding it from interlopers during the phoenix's long absences.")
npc("They usually attack anyone who enters, weeding out the weaklings to ensure only the worthy reach the phoenix in its roost, deep inside the lair.")
npc("I have had a peek inside, however, and the creatures seem unusually passive at the moment.")
npc("Standing out here, I occasionally hear them cry out, as if in pain.")
player("Thanks for the information. Now, back to my other questions.")
goto("InPyreNeedMoreInformation")
label("NoMoreQuestions")
player("That's all the information I need for now.")
npc("Please, help the phoenix. Such a wondrous creature should not be taken from this world in this way.")
player("I'll try my best. I'll be back soon.")
}
}
}