Made random event teleports more robust, fixing edge cases

This commit is contained in:
Player Name 2025-02-16 07:00:13 +00:00 committed by Ryan
parent be47c1d5c9
commit f1131b7d00
18 changed files with 109 additions and 114 deletions

View file

@ -0,0 +1,23 @@
package content.global.ame
import core.ServerConstants
import core.api.*
import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager.TeleportType
import core.game.world.map.Location
fun kidnapPlayer(player: Player, loc: Location, type: TeleportType) {
setAttribute(player, "kidnapped-by-random", true)
if (getAttribute(player, "/save:original-loc", null) == null) {
setAttribute(player, "/save:original-loc", player.location)
}
teleport(player, loc, type)
}
fun returnPlayer(player: Player) {
player.locks.unlockTeleport()
val destination = getAttribute(player, "/save:original-loc", ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0))
teleport(player, destination)
unlock(player)
removeAttributes(player, "/save:original-loc", "kidnapped-by-random")
}

View file

@ -3,7 +3,7 @@ package content.global.ame
import org.rs09.consts.Items import org.rs09.consts.Items
import content.global.ame.events.MysteriousOldManNPC import content.global.ame.events.MysteriousOldManNPC
import content.global.ame.events.certer.CerterNPC import content.global.ame.events.certer.CerterNPC
import content.global.ame.events.drilldemon.SeargentDamienNPC import content.global.ame.events.drilldemon.SergeantDamienNPC
import content.global.ame.events.drunkendwarf.DrunkenDwarfNPC import content.global.ame.events.drunkendwarf.DrunkenDwarfNPC
import content.global.ame.events.evilbob.EvilBobNPC import content.global.ame.events.evilbob.EvilBobNPC
import content.global.ame.events.evilchicken.EvilChickenNPC import content.global.ame.events.evilchicken.EvilChickenNPC
@ -47,7 +47,7 @@ enum class RandomEvents(val npc: RandomEventNPC, val loot: WeightBasedTable? = n
WeightedItem(Items.LOOP_HALF_OF_A_KEY_987,1,1,0.1) WeightedItem(Items.LOOP_HALF_OF_A_KEY_987,1,1,0.1)
)), )),
MAZE(npc = MazeNPC()), MAZE(npc = MazeNPC()),
DRILL_DEMON(npc = SeargentDamienNPC()), DRILL_DEMON(npc = SergeantDamienNPC()),
EVIL_CHICKEN(npc = EvilChickenNPC()), EVIL_CHICKEN(npc = EvilChickenNPC()),
STRANGE_PLANT(npc = StrangePlantNPC()), STRANGE_PLANT(npc = StrangePlantNPC()),
SWARM(npc = SwarmNPC()), SWARM(npc = SwarmNPC()),

View file

@ -1,9 +1,11 @@
package content.global.ame.events.drilldemon package content.global.ame.events.drilldemon
import core.ServerConstants import content.global.ame.kidnapPlayer
import content.global.ame.returnPlayer
import core.api.* import core.api.*
import core.game.interaction.QueueStrength import core.game.interaction.QueueStrength
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneBorders
import core.game.world.update.flag.context.Animation import core.game.world.update.flag.context.Animation
@ -12,7 +14,6 @@ import org.rs09.consts.NPCs
object DrillDemonUtils { object DrillDemonUtils {
val DD_KEY_TASK = "/save:drilldemon:task" val DD_KEY_TASK = "/save:drilldemon:task"
val DD_KEY_RETURN_LOC = "/save:original-loc"
val DD_SIGN_VARP = 531 val DD_SIGN_VARP = 531
val DD_SIGN_JOG = 0 val DD_SIGN_JOG = 0
val DD_SIGN_SITUP = 1 val DD_SIGN_SITUP = 1
@ -24,10 +25,7 @@ object DrillDemonUtils {
val DD_NPC = NPCs.SERGEANT_DAMIEN_2790 val DD_NPC = NPCs.SERGEANT_DAMIEN_2790
fun teleport(player: Player) { fun teleport(player: Player) {
if (getAttribute(player, DD_KEY_RETURN_LOC, null) == null) { kidnapPlayer(player, Location.create(3163, 4819, 0), TeleportManager.TeleportType.INSTANT)
setAttribute(player, DD_KEY_RETURN_LOC, player.location)
}
teleport(player, Location.create(3163, 4819, 0))
player.interfaceManager.closeDefaultTabs() player.interfaceManager.closeDefaultTabs()
setComponentVisibility(player, 548, 69, true) setComponentVisibility(player, 548, 69, true)
setComponentVisibility(player, 746, 12, true) setComponentVisibility(player, 746, 12, true)
@ -66,14 +64,8 @@ object DrillDemonUtils {
} }
fun cleanup(player: Player) { fun cleanup(player: Player) {
player.locks.unlockTeleport() returnPlayer(player)
unlock(player) removeAttributes(player, DD_KEY_TASK, DD_CORRECT_OFFSET, DD_CORRECT_COUNTER)
val destination = getAttribute(player, DD_KEY_RETURN_LOC, ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0))
teleport(player, destination)
removeAttribute(player, DD_KEY_RETURN_LOC)
removeAttribute(player, DD_KEY_TASK)
removeAttribute(player, DD_CORRECT_OFFSET)
removeAttribute(player, DD_CORRECT_COUNTER)
player.interfaceManager.openDefaultTabs() player.interfaceManager.openDefaultTabs()
setComponentVisibility(player, 548, 69, false) setComponentVisibility(player, 548, 69, false)
setComponentVisibility(player, 746, 12, false) setComponentVisibility(player, 746, 12, false)

View file

@ -10,11 +10,11 @@ import core.game.interaction.QueueStrength
import core.game.system.timer.impl.AntiMacro import core.game.system.timer.impl.AntiMacro
import core.tools.secondsToTicks import core.tools.secondsToTicks
class SeargentDamienNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SERGEANT_DAMIEN_2790) { class SergeantDamienNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(NPCs.SERGEANT_DAMIEN_2790) {
override fun init() { override fun init() {
super.init() super.init()
sendChat(player.username.capitalize() + "! Drop and give me 20!") sendChat(player.username+ "! Drop and give me 20!")
queueScript(player, 4, QueueStrength.SOFT) { stage: Int -> queueScript(player, 4, QueueStrength.SOFT) { stage: Int ->
when (stage) { when (stage) {
0 -> { 0 -> {

View file

@ -1,5 +1,6 @@
package content.global.ame.events.evilbob package content.global.ame.events.evilbob
import content.global.ame.returnPlayer
import core.ServerConstants import core.ServerConstants
import core.api.* import core.api.*
import core.game.dialogue.FacialExpression import core.game.dialogue.FacialExpression
@ -8,8 +9,6 @@ import core.game.interaction.InteractionListener
import core.game.interaction.QueueStrength import core.game.interaction.QueueStrength
import core.game.node.entity.Entity import core.game.node.entity.Entity
import core.game.node.entity.player.link.emote.Emotes import core.game.node.entity.player.link.emote.Emotes
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneBorders
import core.game.world.map.zone.ZoneRestriction import core.game.world.map.zone.ZoneRestriction
@ -121,8 +120,7 @@ class EvilBobListeners : InteractionListener, MapArea {
} }
3 -> { 3 -> {
sendMessage(player, "Welcome back to ${ServerConstants.SERVER_NAME}.") sendMessage(player, "Welcome back to ${ServerConstants.SERVER_NAME}.")
val destination = getAttribute(player, EvilBobUtils.prevLocation, ServerConstants.HOME_LOCATION ?: Location.create(3222, 3218, 0)) returnPlayer(player)
teleport(player, destination)
EvilBobUtils.reward(player) EvilBobUtils.reward(player)
EvilBobUtils.cleanup(player) EvilBobUtils.cleanup(player)
resetAnimator(player) resetAnimator(player)

View file

@ -1,8 +1,10 @@
package content.global.ame.events.evilbob package content.global.ame.events.evilbob
import core.ServerConstants import content.global.ame.kidnapPlayer
import content.global.ame.returnPlayer
import core.api.* import core.api.*
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager
import core.game.node.entity.skill.Skills import core.game.node.entity.skill.Skills
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneBorders
@ -14,7 +16,6 @@ import org.rs09.consts.NPCs
import org.rs09.consts.Scenery import org.rs09.consts.Scenery
object EvilBobUtils { object EvilBobUtils {
const val prevLocation = "/save:original-loc"
const val eventComplete = "/save:evilbob:eventcomplete" const val eventComplete = "/save:evilbob:eventcomplete"
const val assignedFishingZone = "/save:evilbob:fishingzone" const val assignedFishingZone = "/save:evilbob:fishingzone"
const val attentive = "/save:evilbob:attentive" const val attentive = "/save:evilbob:attentive"
@ -53,16 +54,11 @@ object EvilBobUtils {
} }
fun teleport(player: Player) { fun teleport(player: Player) {
if (getAttribute(player, prevLocation, null) == null) { kidnapPlayer(player, Location.create(3419, 4776, 0), TeleportManager.TeleportType.INSTANT)
setAttribute(player, prevLocation, player.location)
}
player.properties.teleportLocation = Location.create(3419, 4776, 0)
} }
fun cleanup(player: Player) { fun cleanup(player: Player) {
player.locks.unlockTeleport() removeAttributes(player, assignedFishingZone, eventComplete, attentive, servantHelpDialogueSeen, attentiveNewSpot, startingDialogueSeen)
player.properties.teleportLocation = getAttribute(player, prevLocation, ServerConstants.HOME_LOCATION)
removeAttributes(player, assignedFishingZone, eventComplete, prevLocation, attentive, servantHelpDialogueSeen, attentiveNewSpot, startingDialogueSeen)
removeAll(player, Items.FISHLIKE_THING_6202) removeAll(player, Items.FISHLIKE_THING_6202)
removeAll(player, Items.FISHLIKE_THING_6202, Container.BANK) removeAll(player, Items.FISHLIKE_THING_6202, Container.BANK)
removeAll(player, Items.FISHLIKE_THING_6206) removeAll(player, Items.FISHLIKE_THING_6206)

View file

@ -1,17 +1,18 @@
package content.global.ame.events.freakyforester package content.global.ame.events.freakyforester
import core.ServerConstants import content.global.ame.kidnapPlayer
import content.global.ame.returnPlayer
import core.api.* import core.api.*
import org.rs09.consts.Items import org.rs09.consts.Items
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneBorders
import core.tools.RandomFunction import core.tools.RandomFunction
object FreakUtils{ object FreakUtils{
const val freakNpc = NPCs.FREAKY_FORESTER_2458 const val freakNpc = NPCs.FREAKY_FORESTER_2458
const val freakPreviousLoc = "/save:original-loc"
const val freakTask = "/save:freakyf:task" const val freakTask = "/save:freakyf:task"
const val freakComplete = "/save:freakyf:complete" const val freakComplete = "/save:freakyf:complete"
const val pheasantKilled = "freakyf:killed" const val pheasantKilled = "freakyf:killed"
@ -28,16 +29,12 @@ object FreakUtils{
} }
fun teleport(player: Player) { fun teleport(player: Player) {
if (getAttribute(player, freakPreviousLoc,null) == null) { kidnapPlayer(player, Location.create(2599, 4777 ,0), TeleportManager.TeleportType.INSTANT)
setAttribute(player, freakPreviousLoc, player.location)
}
teleport(player, Location.create(2599, 4777 ,0))
} }
fun cleanup(player: Player) { fun cleanup(player: Player) {
player.locks.unlockTeleport() returnPlayer(player)
player.properties.teleportLocation = getAttribute(player,freakPreviousLoc, ServerConstants.HOME_LOCATION) removeAttributes(player, freakTask, freakComplete, pheasantKilled)
removeAttributes(player, freakPreviousLoc, freakTask, freakComplete, pheasantKilled)
removeAll(player, Items.RAW_PHEASANT_6178) removeAll(player, Items.RAW_PHEASANT_6178)
removeAll(player, Items.RAW_PHEASANT_6178, Container.BANK) removeAll(player, Items.RAW_PHEASANT_6178, Container.BANK)
removeAll(player, Items.RAW_PHEASANT_6179) removeAll(player, Items.RAW_PHEASANT_6179)

View file

@ -1,5 +1,6 @@
package content.global.ame.events.maze package content.global.ame.events.maze
import content.global.ame.returnPlayer
import core.api.* import core.api.*
import core.api.utils.WeightBasedTable import core.api.utils.WeightBasedTable
import core.api.utils.WeightedItem import core.api.utils.WeightedItem
@ -11,7 +12,6 @@ import core.game.interaction.InteractionListener
import core.game.interaction.QueueStrength import core.game.interaction.QueueStrength
import core.game.node.entity.Entity import core.game.node.entity.Entity
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.scenery.SceneryBuilder
import core.game.system.task.Pulse import core.game.system.task.Pulse
import core.game.world.GameWorld.Pulser import core.game.world.GameWorld.Pulser
import core.game.world.map.Location import core.game.world.map.Location
@ -24,7 +24,6 @@ class MazeInterface : InteractionListener, EventHook<TickEvent>, MapArea {
companion object { companion object {
const val MAZE_TIMER_INTERFACE = Components.MAZETIMER_209 const val MAZE_TIMER_INTERFACE = Components.MAZETIMER_209
const val MAZE_TIMER_VARP = 531 // Interface 209 child 2 config: [531, 0] const val MAZE_TIMER_VARP = 531 // Interface 209 child 2 config: [531, 0]
const val MAZE_ATTRIBUTE_RETURN_LOC = "/save:original-loc"
const val MAZE_ATTRIBUTE_TICKS_LEFT = "maze:percent-ticks-left" const val MAZE_ATTRIBUTE_TICKS_LEFT = "maze:percent-ticks-left"
const val MAZE_ATTRIBUTE_CHESTS_OPEN = "/save:maze:chests-opened" const val MAZE_ATTRIBUTE_CHESTS_OPEN = "/save:maze:chests-opened"
@ -217,9 +216,8 @@ class MazeInterface : InteractionListener, EventHook<TickEvent>, MapArea {
return@queueScript delayScript(player, 3) return@queueScript delayScript(player, 3)
} }
2 -> { 2 -> {
teleport(player, getAttribute(player, MAZE_ATTRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0))) returnPlayer(player)
sendGraphics(Graphics(1577, 0, 0), player.location) sendGraphics(Graphics(1577, 0, 0), player.location)
removeAttribute(player, MAZE_ATTRIBUTE_RETURN_LOC)
animate(player,8941) animate(player,8941)
closeOverlay(player) closeOverlay(player)
return@queueScript delayScript(player, 1) return@queueScript delayScript(player, 1)

View file

@ -1,10 +1,12 @@
package content.global.ame.events.maze package content.global.ame.events.maze
import content.global.ame.RandomEventNPC import content.global.ame.RandomEventNPC
import content.global.ame.kidnapPlayer
import core.api.* import core.api.*
import core.api.utils.WeightBasedTable import core.api.utils.WeightBasedTable
import core.game.interaction.QueueStrength import core.game.interaction.QueueStrength
import core.game.node.entity.npc.NPC 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.system.timer.impl.AntiMacro
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.map.build.DynamicRegion import core.game.world.map.build.DynamicRegion
@ -28,9 +30,6 @@ class MazeNPC(var type: String = "", override var loot: WeightBasedTable? = null
return@queueScript delayScript(player, 3) return@queueScript delayScript(player, 3)
} }
1 -> { 1 -> {
if (getAttribute<Location?>(player, MazeInterface.MAZE_ATTRIBUTE_RETURN_LOC, null) == null) {
setAttribute(player, MazeInterface.MAZE_ATTRIBUTE_RETURN_LOC, player.location)
}
MazeInterface.initMaze(player) MazeInterface.initMaze(player)
// Note: This event is NOT instanced: // Note: This event is NOT instanced:
// Sources: // Sources:
@ -40,7 +39,7 @@ class MazeNPC(var type: String = "", override var loot: WeightBasedTable? = null
// https://youtu.be/0oBCkLArUmc (2011 - even with personal Mysterious Old Man) - "Sorry, this is not the old man you are looking for." // https://youtu.be/0oBCkLArUmc (2011 - even with personal Mysterious Old Man) - "Sorry, this is not the old man you are looking for."
// https://youtu.be/FMuKZm-Ikgs (2011) // https://youtu.be/FMuKZm-Ikgs (2011)
// val region = DynamicRegion.create(11591) // val region = DynamicRegion.create(11591)
teleport(player, MazeInterface.STARTING_POINTS.random()) // 10 random spots kidnapPlayer(player, MazeInterface.STARTING_POINTS.random(), TeleportManager.TeleportType.INSTANT) // 10 random spots
AntiMacro.terminateEventNpc(player) AntiMacro.terminateEventNpc(player)
sendGraphics(Graphics(1577, 0, 0), player.location) sendGraphics(Graphics(1577, 0, 0), player.location)
animate(player,8941) animate(player,8941)

View file

@ -1,6 +1,7 @@
package content.global.ame.events.pillory package content.global.ame.events.pillory
import content.global.ame.RandomEvents import content.global.ame.RandomEvents
import content.global.ame.returnPlayer
import core.api.* import core.api.*
import core.game.dialogue.FacialExpression import core.game.dialogue.FacialExpression
import core.game.interaction.IntType import core.game.interaction.IntType
@ -42,11 +43,10 @@ import org.rs09.consts.Sounds
class PilloryInterface : InterfaceListener, InteractionListener, MapArea { class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
companion object { companion object {
const val PILLORY_LOCK_INTERFACE = 189 const val PILLORY_LOCK_INTERFACE = 189
const val PILLORY_ATRRIBUTE_RETURN_LOC = "/save:original-loc"
const val PILLORY_ATTRIBUTE_EVENT_KEYS = "pillory:event-keys" const val PILLORY_ATTRIBUTE_EVENT_KEYS = "pillory:event-keys"
const val PILLORY_ATTRIBUTE_EVENT_LOCK = "pillory:event-lock" const val PILLORY_ATTRIBUTE_EVENT_LOCK = "pillory:event-lock"
const val PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT = "/save:pillory:target-correct" const val PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT = "/save:pillory:target-correct"
const val PILLORY_ATRRIBUTE_CORRECT_COUNTER = "/save:pillory:num-correct" const val PILLORY_ATTRIBUTE_CORRECT_COUNTER = "/save:pillory:num-correct"
val LOCATIONS = arrayOf( val LOCATIONS = arrayOf(
// Varrock Cages // Varrock Cages
@ -64,8 +64,8 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
) )
fun initPillory(player: Player) { fun initPillory(player: Player) {
setAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) setAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3)
setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)
player.dialogueInterpreter.sendPlainMessage(true, "", "Solve the pillory puzzle to be returned to where you came from.") player.dialogueInterpreter.sendPlainMessage(true, "", "Solve the pillory puzzle to be returned to where you came from.")
} }
@ -82,8 +82,8 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
player.packetDispatch.sendModelOnInterface(9749 + keys[2], PILLORY_LOCK_INTERFACE, 6, 0) player.packetDispatch.sendModelOnInterface(9749 + keys[2], PILLORY_LOCK_INTERFACE, 6, 0)
player.packetDispatch.sendModelOnInterface(9749 + keys[3], PILLORY_LOCK_INTERFACE, 7, 0) player.packetDispatch.sendModelOnInterface(9749 + keys[3], PILLORY_LOCK_INTERFACE, 7, 0)
val numberToGetCorrect = getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) val numberToGetCorrect = getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3)
val correctCount = getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) val correctCount = getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)
for (i in 1.. 6) { for (i in 1.. 6) {
// Set if lock is red or green. // Set if lock is red or green.
if (i <= correctCount) { if (i <= correctCount) {
@ -101,12 +101,12 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
val lock = getAttribute(player, PILLORY_ATTRIBUTE_EVENT_LOCK, -1) val lock = getAttribute(player, PILLORY_ATTRIBUTE_EVENT_LOCK, -1)
if (keys[buttonID] == lock) { if (keys[buttonID] == lock) {
// CORRECT ANSWER // CORRECT ANSWER
setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + 1) setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) + 1)
if (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) <= getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, -1)) { if (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) <= getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, -1)) {
player.dialogueInterpreter.sendPlainMessage(true, "", "You've escaped!") player.dialogueInterpreter.sendPlainMessage(true, "", "You've escaped!")
sendMessage(player, "You've escaped!") sendMessage(player, "You've escaped!")
removeAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT) removeAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT)
removeAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER) removeAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER)
closeInterface(player) closeInterface(player)
queueScript(player, 0, QueueStrength.SOFT) { stage: Int -> queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
when (stage) { when (stage) {
@ -120,10 +120,9 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
1 -> { 1 -> {
val loot = RandomEvents.CERTER.loot!!.roll(player)[0] val loot = RandomEvents.CERTER.loot!!.roll(player)[0]
addItemOrDrop(player, loot.id, loot.amount) addItemOrDrop(player, loot.id, loot.amount)
teleport(player, getAttribute(player, PILLORY_ATRRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0))) returnPlayer(player)
sendGraphics(Graphics(1577, 0, 0), player.location) sendGraphics(Graphics(1577, 0, 0), player.location)
animate(player,8941) animate(player,8941)
removeAttribute(player, PILLORY_ATRRIBUTE_RETURN_LOC)
closeInterface(player) closeInterface(player)
return@queueScript stopExecuting(player) return@queueScript stopExecuting(player)
} }
@ -137,19 +136,19 @@ class PilloryInterface : InterfaceListener, InteractionListener, MapArea {
true, true,
"", "",
"Correct!", "Correct!",
"" + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) + " down, " + "" + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0) + " down, " +
(getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 3) - getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0)) + " to go!") (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 3) - getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)) + " to go!")
// Animation for the star, but it doesn't work. // Animation for the star, but it doesn't work.
player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 1), false) player.packetDispatch.sendInterfaceConfig(PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 1), false)
sendAnimationOnInterface(player, 4135, PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 1)) sendAnimationOnInterface(player, 4135, PILLORY_LOCK_INTERFACE, 16 + getAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 1))
} else { } else {
// WRONG ANSWER // WRONG ANSWER
player.dialogueInterpreter.close() player.dialogueInterpreter.close()
player.dialogueInterpreter.sendDialogues(NPCs.TRAMP_2794 , FacialExpression.OLD_ANGRY1, "Bah, that's not right.","Use the key that matches the hole", "in the spinning lock.") player.dialogueInterpreter.sendDialogues(NPCs.TRAMP_2794 , FacialExpression.OLD_ANGRY1, "Bah, that's not right.","Use the key that matches the hole", "in the spinning lock.")
if (getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 0) < 6) { if (getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 0) < 6) {
setAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, getAttribute(player, PILLORY_ATRRIBUTE_NEEDED_TO_GET_CORRECT, 0) + 1) setAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, getAttribute(player, PILLORY_ATTRIBUTE_NEEDED_TO_GET_CORRECT, 0) + 1)
} }
setAttribute(player, PILLORY_ATRRIBUTE_CORRECT_COUNTER, 0) setAttribute(player, PILLORY_ATTRIBUTE_CORRECT_COUNTER, 0)
closeInterface(player) closeInterface(player)
} }
} }

View file

@ -1,10 +1,12 @@
package content.global.ame.events.pillory package content.global.ame.events.pillory
import content.global.ame.RandomEventNPC import content.global.ame.RandomEventNPC
import content.global.ame.kidnapPlayer
import core.api.* import core.api.*
import core.api.utils.WeightBasedTable import core.api.utils.WeightBasedTable
import core.game.interaction.QueueStrength import core.game.interaction.QueueStrength
import core.game.node.entity.npc.NPC 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.system.timer.impl.AntiMacro
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.update.flag.context.Graphics import core.game.world.update.flag.context.Graphics
@ -29,11 +31,9 @@ class PilloryNPC(override var loot: WeightBasedTable? = null) : RandomEventNPC(N
return@queueScript delayScript(player, 3) return@queueScript delayScript(player, 3)
} }
1 -> { 1 -> {
if (getAttribute<Location?>(player, PilloryInterface.PILLORY_ATRRIBUTE_RETURN_LOC, null) == null) {
setAttribute(player, PilloryInterface.PILLORY_ATRRIBUTE_RETURN_LOC, player.location)
}
PilloryInterface.initPillory(player) PilloryInterface.initPillory(player)
teleport(player, PilloryInterface.LOCATIONS.random()) // 9 random spots! val dest = PilloryInterface.LOCATIONS.random() //9 random spots!
kidnapPlayer(player, dest, TeleportManager.TeleportType.INSTANT)
AntiMacro.terminateEventNpc(player) AntiMacro.terminateEventNpc(player)
sendGraphics(Graphics(1577, 0, 0), player.location) sendGraphics(Graphics(1577, 0, 0), player.location)
animate(player,8941) animate(player,8941)

View file

@ -1,5 +1,6 @@
package content.global.ame.events.quizmaster package content.global.ame.events.quizmaster
import content.global.ame.returnPlayer
import core.ServerConstants import core.ServerConstants
import core.api.* import core.api.*
import core.api.utils.WeightBasedTable import core.api.utils.WeightBasedTable
@ -8,7 +9,6 @@ import core.game.dialogue.DialogueFile
import core.game.dialogue.FacialExpression import core.game.dialogue.FacialExpression
import core.game.interaction.QueueStrength import core.game.interaction.QueueStrength
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.world.map.Location
import core.tools.END_DIALOGUE import core.tools.END_DIALOGUE
import org.rs09.consts.Components import org.rs09.consts.Components
import org.rs09.consts.Items import org.rs09.consts.Items
@ -16,7 +16,6 @@ import org.rs09.consts.Items
class QuizMasterDialogueFile : DialogueFile() { class QuizMasterDialogueFile : DialogueFile() {
companion object { companion object {
const val QUIZMASTER_INTERFACE = Components.MACRO_QUIZSHOW_191 const val QUIZMASTER_INTERFACE = Components.MACRO_QUIZSHOW_191
const val QUIZMASTER_ATTRIBUTE_RETURN_LOC = "/save:original-loc"
const val QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT = "/save:quizmaster:questions-correct" const val QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT = "/save:quizmaster:questions-correct"
const val QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER = "quizmaster:random-answer" const val QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER = "quizmaster:random-answer"
@ -106,7 +105,7 @@ class QuizMasterDialogueFile : DialogueFile() {
5 -> options("1000 Coins", "Random Item").also { stage++ } 5 -> options("1000 Coins", "Random Item").also { stage++ }
6 -> { 6 -> {
resetAnimator(player!!) resetAnimator(player!!)
teleport(player!!, getAttribute(player!!, QUIZMASTER_ATTRIBUTE_RETURN_LOC, Location.create(3222, 3218, 0))) returnPlayer(player!!)
when (buttonID) { when (buttonID) {
1 -> { 1 -> {
queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int -> queueScript(player!!, 0, QueueStrength.SOFT) { stage: Int ->
@ -121,9 +120,7 @@ class QuizMasterDialogueFile : DialogueFile() {
} }
} }
} }
removeAttribute(player!!, QUIZMASTER_ATTRIBUTE_RETURN_LOC) removeAttributes(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER)
removeAttribute(player!!, QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT)
removeAttribute(player!!, QUIZMASTER_ATTRIBUTE_RANDOM_ANSWER)
stage = END_DIALOGUE stage = END_DIALOGUE
end() end()
} }

View file

@ -1,10 +1,12 @@
package content.global.ame.events.quizmaster package content.global.ame.events.quizmaster
import content.global.ame.RandomEventNPC import content.global.ame.RandomEventNPC
import content.global.ame.kidnapPlayer
import core.api.* import core.api.*
import core.api.utils.WeightBasedTable import core.api.utils.WeightBasedTable
import core.game.interaction.QueueStrength import core.game.interaction.QueueStrength
import core.game.node.entity.npc.NPC 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.system.timer.impl.AntiMacro
import core.game.world.map.Location import core.game.world.map.Location
import core.game.world.update.flag.context.Graphics import core.game.world.update.flag.context.Graphics
@ -35,12 +37,8 @@ class QuizMasterNPC(var type: String = "", override var loot: WeightBasedTable?
return@queueScript delayScript(player, 3) return@queueScript delayScript(player, 3)
} }
1 -> { 1 -> {
if (getAttribute<Location?>(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_RETURN_LOC, null) == null) { kidnapPlayer(player, Location(1952, 4764, 1), TeleportManager.TeleportType.INSTANT)
setAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_RETURN_LOC, player.location)
}
setAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0) setAttribute(player, QuizMasterDialogueFile.QUIZMASTER_ATTRIBUTE_QUESTIONS_CORRECT, 0)
//MazeInterface.initMaze(player)
teleport(player, Location(1952, 4764, 1))
AntiMacro.terminateEventNpc(player) AntiMacro.terminateEventNpc(player)
sendGraphics(Graphics(1577, 0, 0), player.location) sendGraphics(Graphics(1577, 0, 0), player.location)
animate(player,8941) animate(player,8941)

View file

@ -10,6 +10,7 @@ import core.game.interaction.InteractionListener
import core.game.interaction.IntType import core.game.interaction.IntType
import content.global.handlers.iface.ExperienceInterface import content.global.handlers.iface.ExperienceInterface
import core.api.MapArea import core.api.MapArea
import core.api.removeItem
import core.game.world.map.zone.ZoneBorders import core.game.world.map.zone.ZoneBorders
import core.game.world.map.zone.ZoneRestriction import core.game.world.map.zone.ZoneRestriction
@ -23,7 +24,7 @@ class SupriseExamListeners : InteractionListener, MapArea {
return@on true return@on true
} }
on(SurpriseExamUtils.SE_DOORS, IntType.SCENERY, "open"){ player, node -> on(SurpriseExamUtils.SE_DOORS, IntType.SCENERY, "open") { player, node ->
val correctDoor = player.getAttribute(SurpriseExamUtils.SE_DOOR_KEY,-1) val correctDoor = player.getAttribute(SurpriseExamUtils.SE_DOOR_KEY,-1)
if(correctDoor == -1){ if(correctDoor == -1){
@ -42,7 +43,7 @@ class SupriseExamListeners : InteractionListener, MapArea {
on(Items.BOOK_OF_KNOWLEDGE_11640, IntType.ITEM, "read") { player, _ -> on(Items.BOOK_OF_KNOWLEDGE_11640, IntType.ITEM, "read") { player, _ ->
player.setAttribute("caller") { skill: Int, p: Player -> player.setAttribute("caller") { skill: Int, p: Player ->
if (p.inventory.remove(Item(Items.BOOK_OF_KNOWLEDGE_11640))) { if (removeItem(p, Items.BOOK_OF_KNOWLEDGE_11640)) {
val level = p.skills.getStaticLevel(skill) val level = p.skills.getStaticLevel(skill)
val experience = level * 15.0 val experience = level * 15.0
p.skills.addExperience(skill, experience) p.skills.addExperience(skill, experience)

View file

@ -1,22 +1,18 @@
package content.global.ame.events.surpriseexam package content.global.ame.events.surpriseexam
import core.Server import content.global.ame.kidnapPlayer
import content.global.ame.returnPlayer
import core.api.* import core.api.*
import core.game.node.entity.impl.PulseType import core.game.node.entity.impl.PulseType
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.item.GroundItemManager
import core.game.node.item.Item
import core.game.system.task.Pulse import core.game.system.task.Pulse
import core.game.world.map.Location import core.game.world.map.Location
import org.rs09.consts.Components import org.rs09.consts.Components
import org.rs09.consts.Items import org.rs09.consts.Items
import core.ServerConstants import core.game.node.entity.player.link.TeleportManager
object SurpriseExamUtils { object SurpriseExamUtils {
val SE_KEY_LOC = "/save:original-loc"
val SE_KEY_INDEX = "supexam:index" val SE_KEY_INDEX = "supexam:index"
val SE_LOGOUT_KEY = "suprise_exam"
val SE_DOOR_KEY = "supexam:door" val SE_DOOR_KEY = "supexam:door"
val INTER_PATTERN_CHILDS = intArrayOf(6,7,8) val INTER_PATTERN_CHILDS = intArrayOf(6,7,8)
val INTER_OPTION_CHILDS = intArrayOf(10,11,12,13) val INTER_OPTION_CHILDS = intArrayOf(10,11,12,13)
@ -30,20 +26,13 @@ object SurpriseExamUtils {
intArrayOf(Items.FLY_FISHING_ROD_309,Items.BARBARIAN_ROD_11323,Items.SMALL_FISHING_NET_303,Items.HARPOON_311) intArrayOf(Items.FLY_FISHING_ROD_309,Items.BARBARIAN_ROD_11323,Items.SMALL_FISHING_NET_303,Items.HARPOON_311)
) )
fun teleport(player: Player){ fun teleport(player: Player) {
if (getAttribute(player, SE_KEY_LOC, null) == null) { kidnapPlayer(player, Location.create(1886, 5025, 0), TeleportManager.TeleportType.INSTANT)
player.setAttribute(SE_KEY_LOC, player.location)
}
registerLogoutListener(player, SE_LOGOUT_KEY){p ->
p.location = getAttribute(p, SE_KEY_LOC, ServerConstants.HOME_LOCATION)
}
player.properties.teleportLocation = Location.create(1886, 5025, 0)
} }
fun cleanup(player: Player){ fun cleanup(player: Player){
player.properties.teleportLocation = player.getAttribute(SE_KEY_LOC, ServerConstants.HOME_LOCATION) returnPlayer(player)
clearLogoutListener(player, SE_LOGOUT_KEY) removeAttributes(player, SE_KEY_INDEX, SE_KEY_CORRECT)
removeAttributes(player, SE_KEY_LOC, SE_KEY_INDEX, SE_KEY_CORRECT)
player.pulseManager.run(object : Pulse(2){ player.pulseManager.run(object : Pulse(2){
override fun pulse(): Boolean { override fun pulse(): Boolean {
addItemOrDrop(player, Items.BOOK_OF_KNOWLEDGE_11640) addItemOrDrop(player, Items.BOOK_OF_KNOWLEDGE_11640)

View file

@ -204,7 +204,7 @@ public final class HouseManager {
} }
/** /**
* Leaves this house. * Leaves this house through the portal.
* @param player The player leaving. * @param player The player leaving.
*/ */
public static void leave(Player player) { public static void leave(Player player) {
@ -215,7 +215,6 @@ public final class HouseManager {
if (house.isInHouse(player)) { if (house.isInHouse(player)) {
player.animate(Animation.RESET); player.animate(Animation.RESET);
player.getProperties().setTeleportLocation(house.location.getExitLocation()); player.getProperties().setTeleportLocation(house.location.getExitLocation());
removeAttribute(player, "original-loc");
} }
} }

View file

@ -3,11 +3,12 @@ package content.global.skill.construction;
import core.game.node.entity.Entity; import core.game.node.entity.Entity;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.world.map.build.DynamicRegion;
import core.game.world.map.zone.MapZone; import core.game.world.map.zone.MapZone;
import core.game.world.map.zone.ZoneRestriction;
import core.game.world.map.RegionManager; import core.game.world.map.RegionManager;
import core.game.world.map.Region; import core.game.world.map.Region;
import core.game.system.task.Pulse; import core.game.system.task.Pulse;
import core.game.world.map.zone.ZoneRestriction;
import static core.api.ContentAPIKt.*; import static core.api.ContentAPIKt.*;
@ -90,6 +91,7 @@ public final class HouseZone extends MapZone {
public boolean leave(Entity e, boolean logout) { public boolean leave(Entity e, boolean logout) {
if (e instanceof Player) { if (e instanceof Player) {
Player p = (Player) e; Player p = (Player) e;
// The below tears down the house if the owner was the one who left
if (house == p.getHouseManager()) { if (house == p.getHouseManager()) {
house.expelGuests(p); house.expelGuests(p);
int toRemove = previousRegion; int toRemove = previousRegion;
@ -110,7 +112,11 @@ public final class HouseZone extends MapZone {
} }
}); });
} }
// Clear logout listener and original-loc (if appropriate)
clearLogoutListener(p, "houselogout"); clearLogoutListener(p, "houselogout");
if (!getAttribute(p, "kidnapped-by-random", false)) {
removeAttribute(p, "/save:original-loc");
}
return true; return true;
} }
return true; return true;

View file

@ -465,14 +465,17 @@ public class Player extends Entity {
// Update wealth tracking // Update wealth tracking
checkForWealthUpdate(false); checkForWealthUpdate(false);
// Check if the player is on the map // Check if the player is on the map, runs only every 6 seconds for performance reasons.
// This is only a sanity check to detect improper usage of the 'original-loc' attribute, hence only do this work if the attribute is set // This is only a sanity check to detect improper usage of the 'original-loc' attribute, hence only do this work if the attribute is set.
if (ContentAPIKt.getAttribute(this, "/save:original-loc", null) != null) { // Only runs when the player is not movement/interaction-locked, so that original-loc does not get wiped e.g. in the middle of the player teleporting to their POH.
int rid = location.getRegionId(); if (GameWorld.getTicks() % 10 == 0 && !getLocks().isMovementLocked() && !getLocks().isInteractionLocked()) {
Region r = RegionManager.forId(rid); if (ContentAPIKt.getAttribute(this, "/save:original-loc", null) != null) {
if (!(r instanceof DynamicRegion) && !getZoneMonitor().isRestricted(ZoneRestriction.OFF_MAP)) { int rid = location.getRegionId();
log(this.getClass(), Log.ERR, "Player " + getUsername() + " has the original-loc attribute set but isn't actually off-map! This indicates a bug in the code that set that attribute. The original-loc is: " + getAttribute("/save:original-loc") + ", good luck debugging!"); Region r = RegionManager.forId(rid);
ContentAPIKt.removeAttribute(this, "original-loc"); if (!(r instanceof DynamicRegion) && !getZoneMonitor().isRestricted(ZoneRestriction.OFF_MAP)) {
log(this.getClass(), Log.ERR, "Player " + getUsername() + " has the original-loc attribute set but isn't actually off-map! This indicates a bug in the code that set that attribute. The original-loc is " + getAttribute("/save:original-loc") + ", the current region is " + rid + ". Good luck debugging!");
ContentAPIKt.removeAttribute(this, "original-loc");
}
} }
} }
} }