diff --git a/Server/data/ObjectParser.xml b/Server/data/ObjectParser.xml
index b10a0d445..e8670de77 100644
--- a/Server/data/ObjectParser.xml
+++ b/Server/data/ObjectParser.xml
@@ -4,6 +4,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Server/data/configs/item_configs.json b/Server/data/configs/item_configs.json
index bf79f32e1..848f90580 100644
--- a/Server/data/configs/item_configs.json
+++ b/Server/data/configs/item_configs.json
@@ -63812,6 +63812,15 @@
"archery_ticket_price": "0",
"id": "6965"
},
+ {
+ "examine": "A key to the prison.",
+ "grand_exchange_price": "0",
+ "durability": null,
+ "name": "Prison key",
+ "tradeable": "false",
+ "archery_ticket_price": "0",
+ "id": "6966"
+ },
{
"lendable": "true",
"examine": "Makes the wearer pretty intimidating.",
diff --git a/Server/data/configs/npc_configs.json b/Server/data/configs/npc_configs.json
index d4efc299f..1005baafc 100644
--- a/Server/data/configs/npc_configs.json
+++ b/Server/data/configs/npc_configs.json
@@ -30123,7 +30123,55 @@
"attack_level": "1"
},
{
- "examine": "Looks after farming tools.",
+ "examine": "He wants to escape!",
+ "melee_animation": "0",
+ "range_animation": "0",
+ "defence_animation": "0",
+ "magic_animation": "0",
+ "death_animation": "0",
+ "name": "Prison Pete",
+ "defence_level": "1",
+ "safespot": null,
+ "lifepoints": "10",
+ "strength_level": "1",
+ "id": "3118",
+ "range_level": "1",
+ "attack_level": "1"
+ },
+ {
+ "examine": "It looks like an animal.",
+ "melee_animation": "0",
+ "range_animation": "0",
+ "defence_animation": "0",
+ "magic_animation": "0",
+ "death_animation": "0",
+ "name": "Balloon Animal",
+ "defence_level": "1",
+ "safespot": null,
+ "lifepoints": "10",
+ "strength_level": "1",
+ "id": "3119",
+ "range_level": "1",
+ "attack_level": "1"
+ },
+ {
+ "examine": "It looks like an animal.",
+ "melee_animation": "0",
+ "range_animation": "0",
+ "defence_animation": "0",
+ "magic_animation": "0",
+ "death_animation": "0",
+ "name": "Balloon Animal",
+ "defence_level": "1",
+ "safespot": null,
+ "lifepoints": "10",
+ "strength_level": "1",
+ "id": "3120",
+ "range_level": "1",
+ "attack_level": "1"
+ },
+ {
+ "examine": "It looks like an animal.",
"melee_animation": "0",
"range_animation": "0",
"defence_animation": "0",
@@ -30139,7 +30187,7 @@
"attack_level": "1"
},
{
- "examine": "I saw the witchdoctor",
+ "examine": "It looks like an animal.",
"melee_animation": "0",
"range_animation": "0",
"defence_animation": "0",
diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json
index 46a5a18e7..77921191d 100644
--- a/Server/data/configs/npc_spawns.json
+++ b/Server/data/configs/npc_spawns.json
@@ -6675,6 +6675,26 @@
"npc_id": "3115",
"loc_data": "{2439,4444,0,1,3}-"
},
+ {
+ "npc_id": "3118",
+ "loc_data": "{2084,4460,0,0,1}-"
+ },
+ {
+ "npc_id": "3119",
+ "loc_data": "{2078,4462,0,1,0}-{2082,4466,0,1,0}-{2087,4470,0,1,0}-{2090,4464,0,1,0}-{2091,4461,0,1,0}-"
+ },
+ {
+ "npc_id": "3120",
+ "loc_data": "{2080,4464,0,1,0}-{2082,4472,0,1,0}-{2083,4462,0,1,0}-{2083,4463,0,1,0}-{2084,4468,0,1,0}-{2088,4464,0,1,0}-"
+ },
+ {
+ "npc_id": "3121",
+ "loc_data": "{2078,4466,0,1,0}-{2080,4470,0,1,0}-{2085,4463,0,1,0}-{2086,4467,0,1,0}-{2091,4470,0,1,0}-"
+ },
+ {
+ "npc_id": "3122",
+ "loc_data": "{2080,4467,0,1,0}-{2084,4465,0,1,0}-{2084,4470,0,1,0}-{2087,4462,0,1,0}-{2089,4466,0,1,0}-"
+ },
{
"npc_id": "3123",
"loc_data": "{3344,2827,0,1,5}-"
diff --git a/Server/data/configs/xteas.json b/Server/data/configs/xteas.json
index 5b8de21a7..41fdf2610 100644
--- a/Server/data/configs/xteas.json
+++ b/Server/data/configs/xteas.json
@@ -348,10 +348,6 @@
"regionId": "8260",
"keys": "-357122149,-546918388,1659548066,2023267334"
},
- {
- "regionId": "8261",
- "keys": "14881828,-6662814,58238456,146761213"
- },
{
"regionId": "8262",
"keys": "937196178,1968517712,1697292009,-2036678778"
diff --git a/Server/src/main/content/global/ame/RandomEvents.kt b/Server/src/main/content/global/ame/RandomEvents.kt
index db5ad9b2e..2c82d6be8 100644
--- a/Server/src/main/content/global/ame/RandomEvents.kt
+++ b/Server/src/main/content/global/ame/RandomEvents.kt
@@ -12,6 +12,7 @@ import content.global.ame.events.maze.MazeNPC
import content.global.ame.events.genie.GenieNPC
import content.global.ame.events.candlelight.PiousPeteNPC
import content.global.ame.events.pillory.PilloryNPC
+import content.global.ame.events.prisonpete.PrisonPeteNPC
import content.global.ame.events.rickturpentine.RickTurpentineNPC
import content.global.ame.events.rivertroll.RiverTrollRENPC
import content.global.ame.events.rockgolem.RockGolemRENPC
@@ -55,6 +56,7 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n
STRANGE_PLANT(npc = StrangePlantNPC()),
SWARM(npc = SwarmNPC()),
EVIL_BOB(npc = EvilBobNPC(), skillIds = intArrayOf(Skills.FISHING, Skills.MAGIC)),
+ PRISON_PETE(npc= PrisonPeteNPC()),
DRUNKEN_DWARF(npc = DrunkenDwarfNPC()),
RICK_TURPENTINE(npc = RickTurpentineNPC(), loot = CERTER.loot),
SURPRISE_EXAM(npc = MysteriousOldManNPC(), type = "sexam"),
diff --git a/Server/src/main/content/global/ame/events/prisonpete/PrisonPeteDialogue.kt b/Server/src/main/content/global/ame/events/prisonpete/PrisonPeteDialogue.kt
new file mode 100644
index 000000000..eb9ecf3b4
--- /dev/null
+++ b/Server/src/main/content/global/ame/events/prisonpete/PrisonPeteDialogue.kt
@@ -0,0 +1,130 @@
+package content.global.ame.events.prisonpete
+
+import core.ServerConstants
+import core.api.*
+import core.game.dialogue.DialogueBuilder
+import core.game.dialogue.DialogueBuilderFile
+import core.game.dialogue.DialoguePlugin
+import core.game.dialogue.FacialExpression
+import core.game.node.entity.player.Player
+import core.plugin.Initializable
+import org.rs09.consts.Items
+import org.rs09.consts.NPCs
+
+@Initializable
+class PrisonPeteDialogue (player: Player? = null) : DialoguePlugin(player) {
+ override fun handle(interfaceId: Int, buttonId: Int): Boolean {
+ openDialogue(player, PrisonPeteDialogueFile(), npc)
+ return true
+ }
+ override fun newInstance(player: Player): DialoguePlugin {
+ return PrisonPeteDialogue(player)
+ }
+ override fun getIds(): IntArray {
+ return intArrayOf(NPCs.PRISON_PETE_3118)
+ }
+}
+
+class PrisonPeteDialogueFile : DialogueBuilderFile() {
+
+ override fun create(b: DialogueBuilder) {
+ b.onPredicate { _ -> true }
+ .branch {
+ player -> if (removeItem(player, Items.PRISON_KEY_6966)) { 1 } else { 0 } }
+ .let{ branch ->
+
+ branch.onValue(1)
+ .branch { player ->
+ if (getAttribute(player, PrisonPeteListeners.attributeTimesUnlocked, 0) >= 3) {
+ return@branch 1
+ }
+ return@branch 0
+ }
+ .let { branch2 ->
+ branch.onValue(1)
+
+
+ return@let branch2.onValue(0)
+ }
+ .npc(FacialExpression.FRIENDLY, "Ooh, thanks! I'll see if it's the right one...")
+ .branch { player ->
+ val poppedBalloon = getAttribute(player, PrisonPeteListeners.attributePoppedBalloonIndex, 0)
+ val correctBalloon = getAttribute(player, PrisonPeteListeners.attributeCurrentBalloonIndex, 0)
+ if (poppedBalloon != 0 && poppedBalloon == correctBalloon) {
+ setAttribute(player, PrisonPeteListeners.attributeTimesUnlocked, getAttribute(player, PrisonPeteListeners.attributeTimesUnlocked, 0) + 1)
+ if (getAttribute(player, PrisonPeteListeners.attributeTimesUnlocked, 0) >= 3) {
+ return@branch 2
+ }
+ setAttribute(player, PrisonPeteListeners.attributeCurrentBalloonIndex, 0)
+ return@branch 1
+ } else {
+ return@branch 0
+ }
+ }
+ .let { branch2 ->
+ branch2.onValue(2)
+ .npc(FacialExpression.FRIENDLY, "You did it, you got all the keys right!", "Thank you! You're my friend FOREVER!")
+ .playerl(FacialExpression.FRIENDLY, "Let's get out of here before the cat notices.")
+ .end()
+
+ branch2.onValue(1)
+ .npc(FacialExpression.FRIENDLY, "Hooray, you got the right one! Now pull the lever again", "and let's get the next lock unlocked.")
+ .end()
+
+ branch2.onValue(0)
+ .npc(FacialExpression.SAD, "Aww, that was the wrong key! You must have popped", "the wrong sort of animal. Try the big lever again; it'll", "tell you which animal to pop.")
+ .end()
+
+ }
+
+ branch.onValue(0)
+ .options("What would you like to say?").let { optionBuilder ->
+
+ optionBuilder.option("What is this place?")
+ .playerl(FacialExpression.THINKING,"What is this place?")
+ .npc(FacialExpression.SAD, "Don't you remember? This is ScapeRune's prison.", "Evil Bob caught you and brought you here.")
+ .player(FacialExpression.ANGRY, "What gives him the right to lock me up?", "I demand to see a lawyer! I know my rights!")
+ .npc(FacialExpression.SAD, "Evil Bob doesn't care about people's rights.", "He's cruel and utterly merciless. He's a cat.")
+ .player(FacialExpression.ANGRY, "How do I get out of here?", "I can't be held captive by a cat!")
+ .npc(FacialExpression.SAD, "Some of these balloon animals have keys in them, and if", "you pull the big lever it tells you which shape animal", "contains the correct key, but I can never find it.")
+ .npc(FacialExpression.SAD, "You need to pull the lever to find out which shape", "animal contains the key, then pop that sort of animal to", "get the key.")
+ .npc(FacialExpression.SAD, "Bring me any keys you get and", "I'll try them on the doors.")
+ // This is a future thing. Since this random event is in transition, I would follow other random events of this era and not have the 15 min countdown.
+// .playerl(FacialExpression.THINKING,"What happens if I get it wrong?")
+// .npc(FacialExpression.SAD, "You haven't get a life sentence, so they'll let you out in", "[15] minutes, but you should be able to escape much", "faster if you go pull that lever and pop the right balloon", "animals.")
+ // Note the [15] minutes part counts down, Prison pete would say "you have 9 minutes left" and yada
+ .end()
+
+ optionBuilder.option("How do I get out of here?")
+ .player(FacialExpression.ANGRY, "How do I get out of here?", "I can't be held captive by a cat!")
+ .npc(FacialExpression.SAD, "Some of these balloon animals have keys in them, and if", "you pull the big lever it tells you which shape animal", "contains the correct key, but I can never find it.")
+ .npc(FacialExpression.SAD, "You need to pull the lever to find out which shape", "animal contains the key, then pop that sort of animal to", "get the key.")
+ .npc(FacialExpression.SAD, "Bring me any keys you get and", "I'll try them on the doors.")
+ // This is a future thing. Since this random event is in transition, I would follow other random events of this era and not have the 15 min countdown.
+// .playerl(FacialExpression.THINKING,"What happens if I get it wrong?")
+// .npc(FacialExpression.SAD, "You haven't get a life sentence, so they'll let you out in", "[15] minutes, but you should be able to escape much", "faster if you go pull that lever and pop the right balloon", "animals.")
+ // Note the [15] minutes part counts down, Prison pete would say "you have 9 minutes left" and yada
+ .end()
+ }
+ }
+
+ }
+}
+
+class PrisonPeteIntroDialogueFile : DialogueBuilderFile() {
+
+ override fun create(b: DialogueBuilder) {
+ b.onPredicate { _ -> true }
+ .playerl(FacialExpression.AMAZED, "What on ${ServerConstants.SERVER_NAME} just happened?")
+ .npc(FacialExpression.SAD, "This isn't ${ServerConstants.SERVER_NAME} anymore, this is Scape2009.", "So you've been captured, too?")
+ .playerl(FacialExpression.THINKING, "Captured?")
+ .npcl(FacialExpression.SAD, "Yes, Evil Bob captured me and stuck me in this prison.")
+ .player(FacialExpression.ANGRY, "How do I get out of here?", "I can't be held captive by a cat!")
+ .npcl(FacialExpression.SAD, "Some of these balloon animals have keys in them, and if you pull the big lever it tells you which shape animal contains the correct key, but I can never find it.")
+ .npcl(FacialExpression.SAD, "You need to pull the lever to find out which shape animal contains the key, then pop that sort of animal to get the key.")
+ .npc(FacialExpression.SAD, "Bring me any keys you get and", "I'll try them on the doors.")
+ .playerl(FacialExpression.THINKING,"What happens if I get it wrong?")
+ .npc(FacialExpression.SAD, "You haven't get a life sentence, so they'll let you out in", "[15] minutes, but you should be able to escape much", "faster if you go pull that lever and pop the right balloon", "animals.")
+ .end()
+ }
+}
\ No newline at end of file
diff --git a/Server/src/main/content/global/ame/events/prisonpete/PrisonPeteListeners.kt b/Server/src/main/content/global/ame/events/prisonpete/PrisonPeteListeners.kt
new file mode 100644
index 000000000..fcd36b0f9
--- /dev/null
+++ b/Server/src/main/content/global/ame/events/prisonpete/PrisonPeteListeners.kt
@@ -0,0 +1,206 @@
+package content.global.ame.events.prisonpete
+
+import content.global.ame.RandomEvents
+import content.global.ame.returnPlayer
+import core.api.*
+import core.game.dialogue.FacialExpression
+import core.game.interaction.InteractionListener
+import core.game.interaction.InterfaceListener
+import core.game.interaction.QueueStrength
+import core.game.node.entity.Entity
+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.zone.ZoneBorders
+import core.game.world.map.zone.ZoneRestriction
+import core.game.world.update.flag.context.Graphics
+import org.rs09.consts.*
+
+// Model 6474 is interesting
+// http://youtu.be/a1R5vdqiBCQ
+// http://youtu.be/6PKLqIjoR4c
+// http://youtu.be/7eHhptb80WU
+// http://youtu.be/28Ah8i6PUK0
+/**
+ * Prison Pete Random / Evil Bob 2
+ * Do note that this is the most patchwork random ever, due to the map being in transition to a newer one.
+ * The old one (seen in osrs too) has a corridor on the east with 3 barriers.
+ * The new one (seen in rs3) came in around Jan 2009 and includes a locked door to the south.
+ * Due to the shit map and half fucked version of objects, we are following the locked door variation.
+ * Note that there are a lot of moving parts due to Jigglyflex trying stupid shit.
+ * There used to be a 15 mins timer, but I think it's later, so I'm here to make you suffer this random event.
+ *
+ * Note: On server load, some sceneries are patched into Prison Pete in ObjectParser.xml file.
+ */
+class PrisonPeteListeners : InteractionListener, InterfaceListener, MapArea {
+
+ companion object {
+ val balloons = intArrayOf(0, NPCs.BALLOON_ANIMAL_3119,NPCs.BALLOON_ANIMAL_3120,NPCs.BALLOON_ANIMAL_3121,NPCs.BALLOON_ANIMAL_3122)
+ val models = intArrayOf(0, 10734, 10735, 10736, 10737)
+ const val attributeReturnLoc = "/save:original-loc"
+ const val attributeTimesUnlocked = "/save:prisonpete:timesUnlocked"
+ const val attributeCurrentBalloonIndex = "prisonpete:currentballoon"
+ const val attributePoppedBalloonIndex = "prisonpete:poppedballoon"
+
+ fun randomizeBalloon(player: Player) {
+ setAttribute(player, attributeCurrentBalloonIndex, (1..4).random())
+ }
+ }
+
+ var count = 1
+ override fun defineListeners() {
+
+ /**
+ * Alright, this is the most infuriating component.
+ * I cannot for the life of me get this goddamn thing to animate.
+ * So here's some details
+ *
+ * Clicking on the lever should open Components.PRISONPETE_273
+ * child 1 is the text below
+ * child 2 is the button overlaying the balloon
+ * child 3 is the balloon image
+ * child 4-6 is unknown
+ *
+ * There are 2 sets of balloon animal MODELS.
+ * 10734, 10735, 10736, 10737 - Models used for NPCs 3119, 3120, 3121, 3122
+ * 10749, 10750, 10751, 10752 - Models used for the component(PRISONPETE_273) because 10753 is the grill for it.
+ *
+ * Animation 3047 is the "old" rotating animation, ([3048, 3049, 3050, 3052] are walking animations for balloons)
+ * but the first set animates it waaay too tiny,
+ * and the second set doesn't animate at all.
+ *
+ * I've tried a lot of animations, but I can't find it, so the replacment here is to use:
+ * the first set, with animation 7163 as a workaround
+ *
+ * Update: I've determined from a1R5vdqiBCQ that this is a challenging one.
+ * You can click on the interface, which changes the way the thing spins.
+ * I'm assuming one of the other childs (4,5,6) are axis controls, that I don't know how to control.
+ * maybe all that 562_interface_configs.txt and stuff
+ * player.packetDispatch.sendIfaceSettings(281, 5, Components.PRISONPETE_273, 23, 23)
+ *
+ */
+ on(Scenery.LEVER_26191, SCENERY, "pull") { player, node ->
+ openInterface(player, Components.PRISONPETE_273)
+ randomizeBalloon(player)
+ player.packetDispatch.sendModelOnInterface(models[getAttribute(player, attributeCurrentBalloonIndex, 0)], Components.PRISONPETE_273, 3, 0)
+ sendAnimationOnInterface(player,7163, Components.PRISONPETE_273, 3)
+ return@on true
+ }
+
+ // Burst a balloon.
+ on(intArrayOf(NPCs.BALLOON_ANIMAL_3119,NPCs.BALLOON_ANIMAL_3120,NPCs.BALLOON_ANIMAL_3121,NPCs.BALLOON_ANIMAL_3122), NPC, "pop") { player, node ->
+ if (inInventory(player, Items.PRISON_KEY_6966)){
+ sendNPCDialogueLines(player, NPCs.PRISON_PETE_3118, FacialExpression.ANGRY, false,"Hey, bring me that key you've got!", "I wanna get out of here!") // B6FwlfnRtAo
+ } else if (getAttribute(player, attributeCurrentBalloonIndex, 0) == 0) {
+ sendNPCDialogueLines(player, NPCs.PRISON_PETE_3118, FacialExpression.ANGRY, false,"You're meant to pull the lever to find out", "which sort of animal to pop!") // a1R5vdqiBCQ
+ } else {
+ animate(player, 10017)
+ sendGraphics(524, node.location)
+ (node as NPC).finalizeDeath(player)
+ queueScript(player, 1, QueueStrength.SOFT) {
+ animate(player, 7270)
+ if(player.inventory.isFull) {
+ sendDialogue(player, "You don't have room to pick up any keys.") // qqncnqOc_MA
+ addItemOrDrop(player, Items.PRISON_KEY_6966)
+ return@queueScript stopExecuting(player)
+ }
+ addItemOrDrop(player, Items.PRISON_KEY_6966)
+ sendNPCDialogueLines(player, NPCs.PRISON_PETE_3118, FacialExpression.FRIENDLY, false,"Great, now you've got a key!", "Bring it to me so I can try it on the door")
+ setAttribute(player, attributePoppedBalloonIndex, balloons.indexOf(node.id))
+ // Technically, the person autowalks to prison pete, but screw that lmao.
+ return@queueScript stopExecuting(player)
+ }
+ }
+ return@on true
+ }
+
+
+ on(Items.PRISON_KEY_6966, ITEM, "drop") { player, node ->
+ // http://youtu.be/c3DJGIVG3MM
+ sendMessage(player,"The key disappears as it hits the ground.")
+ return@on true
+ }
+
+ on(Scenery.LOCKED_DOOR_26188, SCENERY, "open") { player, node ->
+ if (getAttribute(player, attributeTimesUnlocked, 0) >= 3) {
+ sendMessage(player, "You quickly escape the prison with Pete.")
+ removeAttribute(player, attributeTimesUnlocked)
+ closeInterface(player)
+ queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
+ when (stage) {
+ 0 -> {
+ lock(player, 6)
+ sendGraphics(Graphics(1576, 0, 0), player.location)
+ animate(player,8939)
+ playAudio(player, Sounds.TELEPORT_ALL_200)
+ return@queueScript delayScript(player, 3)
+ }
+ 1 -> {
+ val loot = RandomEvents.CERTER.loot!!.roll(player)[0]
+ addItemOrDrop(player, loot.id, loot.amount)
+ returnPlayer(player)
+ sendGraphics(Graphics(1577, 0, 0), player.location)
+ animate(player,8941)
+ closeInterface(player)
+ return@queueScript stopExecuting(player)
+ }
+ else -> return@queueScript stopExecuting(player)
+ }
+ }
+
+ } else {
+ sendMessage(player, "You need 3 more keys to unlock this gate.") // Inauthentic
+ if (inInventory(player, Items.PRISON_KEY_6966)){
+ sendNPCDialogueLines(player, NPCs.PRISON_PETE_3118, FacialExpression.ANGRY, false,"Hey, bring me that key you've got!", "I wanna get out of here!") // B6FwlfnRtAo
+ } else if (getAttribute(player, attributeCurrentBalloonIndex, 0) == 0) {
+ sendNPCDialogueLines(player, NPCs.PRISON_PETE_3118, FacialExpression.ANGRY, false,"You're meant to pull the lever to find out", "which sort of animal to pop!") // a1R5vdqiBCQ
+ }
+ }
+ return@on true
+ }
+
+ // End of 15 mins:
+ // SFiAALVHrR8
+ // npc(FacialExpression.SAD, "You've served your sentence, so you can walk out now.", "Lucky you!")
+ // player(FacialExpression.THINKING, "Aren't you coming?")
+ // npc(FacialExpression.SAD, "No, I've got a life sentence. Maybe if you'd been able", "to get the door open for yourself I could have escaped", "with you.")
+ // player(FacialExpression.SAD, "I'm sorry.")
+ // npc(FacialExpression.SAD, "Oh, don't worry. Someone always rescues me", "eventually. Then Evil Bob drags me back again. It's", "been going on for ages. Now, you'd better get out", "before you're arrested for loitering.")
+ // You can now at any point, click the gate and walk out as per normal.
+ }
+
+ override fun defineInterfaceListeners() {
+ on(Components.PRISONPETE_273) { player, _, _, buttonID, _, _ ->
+ if (buttonID == 2) {
+ // So this is the new thing that happens.
+ // On click, this will cause the object to spin in a different direction.
+ // Unfortunately I don't know how to do this.
+ }
+ return@on true
+ }
+ }
+ override fun defineAreaBorders(): Array {
+ return arrayOf(getRegionBorders(8261))
+ }
+
+ override fun getRestrictions(): Array {
+ return arrayOf(ZoneRestriction.RANDOM_EVENTS, ZoneRestriction.CANNON, ZoneRestriction.FOLLOWERS, ZoneRestriction.TELEPORT, ZoneRestriction.OFF_MAP)
+ }
+
+ override fun areaEnter(entity: Entity) {
+ if (entity is Player) {
+ // sendMessage(entity, "Head for the center of the maze.")
+ }
+ }
+
+ override fun areaLeave(entity: Entity, logout: Boolean) {
+ if (entity is Player) {
+ //entity.unhook(this)
+ }
+ }
+ override fun entityStep(entity: Entity, location: Location, lastLocation: Location) {
+ if (entity is Player) {
+ //entity.hook(Event.Tick, this)
+ }
+ }
+}
diff --git a/Server/src/main/content/global/ame/events/prisonpete/PrisonPeteNPC.kt b/Server/src/main/content/global/ame/events/prisonpete/PrisonPeteNPC.kt
new file mode 100644
index 000000000..58e3fd252
--- /dev/null
+++ b/Server/src/main/content/global/ame/events/prisonpete/PrisonPeteNPC.kt
@@ -0,0 +1,46 @@
+package content.global.ame.events.prisonpete
+
+import content.global.ame.RandomEventNPC
+import content.global.ame.kidnapPlayer
+import core.api.*
+import core.api.utils.WeightBasedTable
+import core.game.interaction.QueueStrength
+import core.game.node.entity.npc.NPC
+import core.game.node.entity.player.link.TeleportManager
+import core.game.system.timer.impl.AntiMacro
+import core.game.world.map.Location
+import core.game.world.update.flag.context.Graphics
+import org.rs09.consts.NPCs
+import org.rs09.consts.Sounds
+
+/** Technically its EvilBobNpc, but there's already another random with him. */
+class PrisonPeteNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.EVIL_BOB_2478) {
+
+ override fun init() {
+ super.init()
+ sendChat("meow")
+ queueScript(player, 4, QueueStrength.SOFT) { stage: Int ->
+ when (stage) {
+ 0 -> {
+ lock(player, 6)
+ sendChat(player, "No... what? Nooooooooooooo!")
+ visualize(player, 714, Graphics(308, 100, 50))
+ playAudio(player, Sounds.TELEPORT_ALL_200)
+ return@queueScript delayScript(player, 3)
+ }
+ 1 -> {
+ kidnapPlayer(player, Location(2083, 4461 ,0), TeleportManager.TeleportType.INSTANT)
+ sendMessage(player, "Welcome to Scape2009.")
+ openDialogue(player, PrisonPeteDialogue(), NPCs.PRISON_PETE_3118)
+ AntiMacro.terminateEventNpc(player)
+ return@queueScript stopExecuting(player)
+ }
+ else -> return@queueScript stopExecuting(player)
+ }
+ }
+ }
+
+ override fun talkTo(npc: NPC) {
+ // The cat doesn't talk.
+ }
+}
\ No newline at end of file