various suggested fixes 2

This commit is contained in:
Beck 2026-07-15 01:06:10 -07:00
parent d8c7b681bb
commit b22525e204
7 changed files with 140 additions and 65 deletions

View file

@ -4736,8 +4736,6 @@
"name": "Ghost's skull",
"examine": "Ooooh spooky!",
"archery_ticket_price": "0",
"destroy": "true",
"destroy_message": "If you get rid of the skull you'll have to search for it again.",
"durability": null,
"tradeable": "false"
},

View file

@ -30,15 +30,13 @@ class OldCroneDialogueFile : DialogueLabeller() {
override fun addConversation() {
label("anma_entry") {
exec { player, npc ->
when (getQuestStage(player, Quests.ANIMAL_MAGNETISM)) {
16, 17, 18 -> {
loadLabel(player, "about_the_farmers")
}
else -> {
loadLabel(player, "hello_old")
}
exec { player, npc ->
when (getQuestStage(player, Quests.ANIMAL_MAGNETISM)) {
16, 17, 18 -> {
loadLabel(player, "about_the_farmers")
}
else -> {
loadLabel(player, "hello_old")
}
}
}

View file

@ -32,22 +32,21 @@ class FatherAereckDefaultDialogue : InteractionListener {
class FatherAereckDefaultDialogueFile : DialogueLabeller() {
override fun addConversation() {
label("entry_logic")
//allows skipping the main dialogue while Restless Ghost quest is started
exec { player, npc ->
when (getQuestStage(player, Quests.THE_RESTLESS_GHOST)) {
0 -> {
loadLabel(player, "main_entry_transcript")
}
10, 20, 30, 40 -> {
//passthrough for mid-quest dialogue skip
open(player, FatherAereckQuestDialogueFile(), npc)
}
else -> {
loadLabel(player, "main_entry_transcript")
}
//allows skipping the main dialogue while Restless Ghost quest is started
exec { player, npc ->
when (getQuestStage(player, Quests.THE_RESTLESS_GHOST)) {
0 -> {
loadLabel(player, "main_entry_transcript")
}
10, 20, 30, 40 -> {
//passthrough for mid-quest dialogue skip
open(player, FatherAereckQuestDialogueFile(), npc)
}
else -> {
loadLabel(player, "main_entry_transcript")
}
}
}
label("main_entry_transcript") {
npc("Welcome to the church of holy Saradomin.")

View file

@ -33,18 +33,16 @@ class FatherUrhneyDefaultDialogueFile: DialogueLabeller() {
npc(FacialExpression.ANGRY, "Go away! I'm meditating!");
label("main_opts") {
exec {player, npc ->
when (getQuestStage(player, Quests.THE_RESTLESS_GHOST)) {
0 -> {
loadLabel(player, "pre_quest_opts")
}
10 -> {
loadLabel(player, "mid_quest_opts")
}
else -> {
loadLabel(player, "post_quest_opts")
}
exec { player, npc ->
when (getQuestStage(player, Quests.THE_RESTLESS_GHOST)) {
0 -> {
loadLabel(player, "pre_quest_opts")
}
10 -> {
loadLabel(player, "mid_quest_opts")
}
else -> {
loadLabel(player, "post_quest_opts")
}
}
}

View file

@ -3,6 +3,7 @@ package content.region.misthalin.lumbridge.quest.therestlessghost;
import content.data.Quests
import core.api.getQuestStage
import core.api.setQuestStage
import core.api.setVarbit
import core.game.dialogue.DialogueLabeller
import core.game.dialogue.DialogueOption
import core.game.dialogue.FacialExpression
@ -63,6 +64,9 @@ class FatherAereckQuestDialogueFile : DialogueLabeller() {
label("let_me_help") {
exec { player, npc ->
setQuestStage(player, Quests.THE_RESTLESS_GHOST, 10)
//ensures the varbits is set to default state
setVarbit(player, 2128, 0, true)
setVarbit(player, 2130, 0, true)
}
npc("Thank you. The problem is, there is a ghost in the", "church graveyard. I would like you to get rid of it.")

View file

@ -92,6 +92,11 @@ class RestlessGhost : Quest(Quests.THE_RESTLESS_GHOST, 25, 24, 1, 107, 0, 4, 5)
player.interfaceManager.closeChatbox()
player.packetDispatch.sendString("You have completed The Restless Ghost Quest!", 277, 2 + 2)
setVarp(player, 728, 31, true)
//post quest skeleton scenery and altar visually correct
setVarbit(player, 2128, 1, true)
setVarbit(player, 2130, 1, true)
//setVarp(player, 728, 31, true)
}
}

View file

@ -2,6 +2,7 @@ package content.region.misthalin.lumbridge.quest.therestlessghost;
import content.data.Quests
import core.api.*
import core.game.global.action.DropListener
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.Entity
@ -9,6 +10,7 @@ import core.game.node.entity.combat.CombatStyle
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.scenery.SceneryBuilder
import core.game.system.task.Pulse
import core.game.world.map.Direction
import core.game.world.map.Location
import core.game.world.map.RegionManager
@ -22,17 +24,20 @@ import org.rs09.consts.Sounds
/**
* Authenticity source Aug 18 2009
* https://www.youtube.com/watch?v=ikbX12Xywxs
* https://www.youtube.com/watch?v=gC3qR9tKJMI
* * Author Beck, Vexia
**/
class RestlessGhostListeners : InteractionListener {
companion object {
//This is not in the Animations consts
//This is not in the Animations consts, added in Constlib MR !22
private const val Animations_HUMAN_CLOSE_CHEST_535 = 535
private const val CLOSED_COFFIN = Scenery.COFFIN_2145
private const val INCOMPLETE_COFFIN_OPEN = Scenery.COFFIN_15052
private const val COMPLETE_COFFIN_OPEN = Scenery.COFFIN_15053
private const val ALTAR_WITH_SKULL = Scenery.ALTAR_15050
private const val ALTAR_NO_SKULL = Scenery.ALTAR_15051
private fun createRestlessGhostNPC() : NPC {
val restlessGhostNPC = NPC(NPCs.RESTLESS_GHOST_457, Location(3250, 3195, 0))
@ -45,14 +50,26 @@ class RestlessGhostListeners : InteractionListener {
return restlessGhostNPC
}
//removes the skeleton on ground, resets in ~2mins
private fun animSkeleAlive(player: Player, skeleScenery: core.game.node.scenery.Scenery) {
// TODO: find animation and maybe sfx of the skeleton coming alive, from a still scenery of a skeleton slumped on the ground against the wall and then rises to life
queueScript(player, 4) {_ ->
SceneryBuilder.remove(skeleScenery, 200)
return@queueScript stopExecuting(player)
//Scenery 15057 changes to 15060 hidden and plays animation, resets in ~2mins if player still doing quest, otherwise it stays at 15060 forever
private fun animSkeleAlive(player: Player) {
//set scenery to 15060 which hides the ground skeleton
setVarbit(player, 2128, 1, true)
// TODO: Scenery skeleton id 15057 turns into a hidden 15060 then with an animation, uses varbit 2128, client side only
// TODO: find animation and maybe sfx of the skeleton coming alive, from a still scenery 15057 (15060 is the post animation?) of a skeleton slumped on the ground against the wall and then rises to life
// TODO: convert to queuescript on Scenery objects when engine is capable to be attached to them.
// https://www.youtube.com/watch?v=gC3qR9tKJMI
// Use world pulse in the mean time, in the edge case where a player logs off in middle of the script
if (getQuestStage(player, Quests.THE_RESTLESS_GHOST) in 30..40) {
submitWorldPulse(object : Pulse(200) {
override fun pulse(): Boolean {
//resets the skeleton on the ground
setVarbit(player, 2128, 0, true)
return true
}
})
}
}
@ -106,8 +123,8 @@ class RestlessGhostListeners : InteractionListener {
toggleCoffinSceneryObj(player, node as core.game.node.scenery.Scenery)
if (!isQuestComplete(player, Quests.THE_RESTLESS_GHOST)) {
//is this from the center of the scenery/node object?
val ghostExists = RegionManager.getLocalNPCs(node.centerLocation).find { it.id == NPCs.RESTLESS_GHOST_457 }
//val ghostExists = RegionManager.getLocalNpcs(node.centerLocation).find { it.id == NPCs.RESTLESS_GHOST_457 }
//not within rendering distance or doesn't exist at all
if (ghostExists == null) {
@ -115,11 +132,21 @@ class RestlessGhostListeners : InteractionListener {
val ghost = createRestlessGhostNPC()
//despawn ghost after awhile and shut the coffin
queueScript(player, 200) { _ ->
// TODO: convert to queuescript on Scenery objects when engine is capable to be attached to them.
// Use world pulse in the mean time, in the edge case where a player logs off in middle of the script
/* queueScript(player, 200) { _ ->
ghost.clear()
toggleCoffinSceneryObj(player, node)
return@queueScript stopExecuting(player)
}
} */
submitWorldPulse(object : Pulse(200) {
override fun pulse(): Boolean {
ghost.clear()
toggleCoffinSceneryObj(player, node)
return true
}
})
}
}
@ -166,42 +193,88 @@ class RestlessGhostListeners : InteractionListener {
with as core.game.node.scenery.Scenery
SceneryBuilder.replace(with, with.transform(COMPLETE_COFFIN_OPEN))
}
return@onUseWith true
}
on(Scenery.ALTAR_15050, IntType.SCENERY, "search") { player, node ->
on(ALTAR_WITH_SKULL, IntType.SCENERY, "search") { player, node ->
if (!inInventory(player, Items.GHOSTS_SKULL_553)) {
if (!inInventory(player, Items.GHOSTS_SKULL_553) && !inBank(player, Items.GHOSTS_SKULL_553)) {
if (getQuestStage(player, Quests.THE_RESTLESS_GHOST) !in 30..40) {
sendMessage(player, "You search the altar and find nothing.")
} else {
if (freeSlots(player) >= 1) {
if (addItem(player, Items.GHOSTS_SKULL_553)) {
setQuestStage(player, Quests.THE_RESTLESS_GHOST, 40)
sendMessage(player, "The skeleton in the corner suddenly comes to life!")
//skele comes to live from scenery 15057 with an animation,
//but idk how to select it to at least remove/hide it from the world briefly
//animSkeleAlive(player, node as core.game.node.scenery.Scenery)
//spawn in skeleton
val s = createLevel13SkeletonNPC(player)
//update altar to without the skull, altar is now scenery 15051
setVarbit(player, 2130, 1, true)
//if skeleton scenery is visible such first time coming alive
//so that it can only be killed/spawned to attack once to prevent some sort of griefing exploit
if (getVarbit(player, 2128) == 0) {
sendMessage(player, "The skeleton in the corner suddenly comes to life!")
// despawn after awhile if it never dies
// so there isnt a group of them for next visitor lol
queueScript(player, 200) { _ ->
s.clear()
return@queueScript stopExecuting(player)
animSkeleAlive(player)
//spawn in skeleton
val s = createLevel13SkeletonNPC(player)
// despawn after awhile if it never dies so there isnt a group of them for next visitor lol
// TODO: convert to queuescript on Scenery objects when engine is capable to be attached to them.
// Use world pulse in the mean time, in the edge case where a player logs off in middle of the script
/* queueScript(player, 200) { _ ->
s.clear()
return@queueScript stopExecuting(player)
} */
submitWorldPulse(object : Pulse(200) {
override fun pulse(): Boolean {
s.clear()
return true
}
})
}
}
} else {
sendMessage(player, "You don't have enough inventory space.")
}
}
}
return@on true
}
on(ALTAR_NO_SKULL, IntType.SCENERY, "search") { player, node ->
//Mainly for a weird edge case if some how the varbit wasn't set correctly
if (getQuestStage(player, Quests.THE_RESTLESS_GHOST) !in 30..40) {
sendMessage(player, "You search the altar and find nothing.")
} else {
if (!inInventory(player, Items.GHOSTS_SKULL_553) && !inBank(player, Items.GHOSTS_SKULL_553)) {
//guard clause if for when player does the drop trick, etc
if (!addItem(player, Items.GHOSTS_SKULL_553)) {
sendMessage(player, "You don't have enough inventory space.")
}
} else {
// TODO: Authenticity check needed for exact message
sendMessage(player, "You already have the Ghost's Skull!")
}
}
return@on true
}
on(Items.GHOSTS_SKULL_553, IntType.ITEM, "drop") { player, node ->
DropListener.drop(player, node.asItem())
if (getQuestStage(player, Quests.THE_RESTLESS_GHOST) in 30..40) {
//update altar to one with the skull, altar is now scenery 15060
setVarbit(player, 2130, 0, true)
}
return@on true
}
}
}