some cart logic

This commit is contained in:
aidan 2026-01-21 19:35:30 -06:00
parent 118f995bef
commit aeb673cc92
2 changed files with 251 additions and 91 deletions

View file

@ -1,14 +1,18 @@
package content.region.kandarin.seers.quest.elementalworkshop2
import content.data.Quests
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2CartLever
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2CranePos
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2CraneState
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2HatchVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2JigCart
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2MachineryVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2PipeVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2Varbit
import core.api.*
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.node.entity.skill.Skills
import core.game.node.scenery.SceneryBuilder
@ -19,6 +23,115 @@ import org.rs09.consts.*
class EW2Listeners : InteractionListener {
companion object {
// various states the crane can be in. they are a pattern, so the logic to flip and lower can be generalized.
val craneStates = intArrayOf(
// Varbit 2644 = 0: Broken
Scenery.OLD_CRANE_18638, // broken crane facing south, claw down
Scenery.OLD_CRANE_18637, // broken crane facing south, claw up
Scenery.OLD_CRANE_18636, // broken crane facing north, claw down
Scenery.OLD_CRANE_18635, // broken crane facing north, claw up
// Varbit 2644 = 1: Fixed/Empty (18623=N-Up, 18624=N-Down, 18625=S-Up, 18626=S-Down)
Scenery.OLD_CRANE_18626, // fixed crane facing south, claw down
Scenery.OLD_CRANE_18625, // fixed crane facing south, claw up
Scenery.OLD_CRANE_18624, // fixed crane facing north, claw down
Scenery.OLD_CRANE_18623, // fixed crane facing north, claw up
// Varbit 2644 = 2: Elemental Bar
Scenery.OLD_CRANE_18630, // fixed crane with ele bar facing south, claw down
Scenery.OLD_CRANE_18629, // fixed crane with ele bar facing south, claw up
Scenery.OLD_CRANE_18628, // fixed crane with ele bar facing north, claw down
Scenery.OLD_CRANE_18627, // fixed crane with ele bar facing north, claw up
// Varbit 2644 = 3: Mind Bar
Scenery.OLD_CRANE_18634, // fixed crane with mind bar facing south, claw down
Scenery.OLD_CRANE_18633, // fixed crane with mind bar facing south, claw up
Scenery.OLD_CRANE_18632, // fixed crane with mind bar facing north, claw down
Scenery.OLD_CRANE_18631 // fixed crane with mind bar facing north, claw up
)
// cart state is stored in varbit 2643
val jigCartStates = intArrayOf(
NPCs.JIG_CART_4913, // empty
NPCs.JIG_CART_4914, // ele bar
NPCs.JIG_CART_4915, // mind bar
NPCs.JIG_CART_4916, // smashed mind bar
NPCs.JIG_CART_4917, // smashed ele bar
NPCs.JIG_CART_4918, // smashed white bar
)
val jigCartLocations = arrayOf(
Location.create(1954, 5147, 2), // south (start)
Location.create(1946, 5155, 2), // west (hammer)
Location.create(1953, 5162, 2), // north (water)
Location.create(1961, 5155, 2) // east (fans)
)
// function to find my crane because it exists at some corner instead of the center.
fun findCraneInArea(center: Location): core.game.node.scenery.Scenery? {
// Search an area around the center
for (x in -2..2) {
for (y in -2..2) {
val checkLoc = center.transform(x, y, 0)
for (id in craneStates) {
val found = RegionManager.getObject(checkLoc.z, checkLoc.x, checkLoc.y, id)
if (found != null) return found
}
}
}
return null
}
// position the crane based on varbit states
fun syncCrane(player: Player) {
val mat = getVarbit(player, EW2CraneState)
val pos = getVarbit(player, EW2CranePos)
val index = (mat * 4) + pos
val newId = craneStates[index]
val craneLoc = Location.create(1954, 5145, 2)
val currentCrane = findCraneInArea(craneLoc)
if (currentCrane != null) {
// todo it would be nice to animate this crane
replaceScenery(currentCrane, newId, -1)
}
}
// update the jig cart based on varbit status
fun syncCart(player: Player) {
val cartState = getVarbit(player, EW2JigCart)
val cartPosIndex = getVarbit(player, EW2CartLever)
val targetId = jigCartStates[cartState]
val targetLocation = jigCartLocations[cartPosIndex]
// find existing cart
val trackCenter = Location.create(1953, 5155, 2)
val existingCart = RegionManager.getLocalNpcs(trackCenter, 15).find {
it.id in jigCartStates
}
if (existingCart != null) {
// update appearance
if (existingCart.id != targetId) {
existingCart.transform(targetId)
}
// update location
if (existingCart.location != targetLocation) {
existingCart.teleport(targetLocation)
}
} else {
// Spawn if missing
val newCart = NPC(targetId, targetLocation)
newCart.init()
}
}
}
override fun defineListeners() {
// Bookcase at digsite where you start quest.
@ -85,6 +198,23 @@ class EW2Listeners : InteractionListener {
return@onUseWith true
}
// unlocked center hatch down to EW2
on(Scenery.HATCH_18596, IntType.SCENERY, "climb-down") { player, _ ->
sendMessage(player, "You climb down the stairs.")
teleport(player, location(1955, 5155, 2))
// set the crane state and cart state when you go down based on the varbits
// if you log in and out during a server restart it'll reset the crane, but just reenter the workshop to fix it.
syncCrane(player)
syncCart(player)
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) == 4) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 5)
setVarbit(player, EW2Varbit, 5)
}
return@on true
}
// stairs back up to EW1
on(Scenery.STAIRS_18598, IntType.SCENERY, "climb-up") { player, _ ->
teleport(player, location(2720, 9892, 0))
@ -106,6 +236,10 @@ class EW2Listeners : InteractionListener {
return@on true
}
// todo small cog crate
// todo medium cog crate
// large cog crate
on(Scenery.CRATE_18616, IntType.SCENERY, "search") { player, _ ->
if (!inInventory(player, Items.LARGE_COG_9724)) {
@ -164,87 +298,40 @@ class EW2Listeners : InteractionListener {
return@on true
}
// various states the crane can be in. they are a pattern, so the logic to flip and lower can be generalized.
val craneStates = intArrayOf(
Scenery.OLD_CRANE_18623, // fixed crane facing north, claw up
Scenery.OLD_CRANE_18624, // fixed crane facing north, claw down
Scenery.OLD_CRANE_18625, // fixed crane facing south, claw up
Scenery.OLD_CRANE_18626, // fixed crane facing south, claw down
Scenery.OLD_CRANE_18627, // fixed crane with ele bar facing north, claw up
Scenery.OLD_CRANE_18628, // fixed crane with ele bar facing north, claw down
Scenery.OLD_CRANE_18629, // fixed crane with ele bar facing south, claw up
Scenery.OLD_CRANE_18630, // fixed crane with ele bar facing south, claw down
Scenery.OLD_CRANE_18631, // fixed crane with mind bar facing north, claw up
Scenery.OLD_CRANE_18632, // fixed crane with mind bar facing north, claw down
Scenery.OLD_CRANE_18633, // fixed crane with mind bar facing south, claw up
Scenery.OLD_CRANE_18634, // fixed crane with mind bar facing south, claw down
Scenery.OLD_CRANE_18635, // broken crane facing north, claw up
Scenery.OLD_CRANE_18636, // broken crane facing north, claw down
Scenery.OLD_CRANE_18637, // broken crane facing south, claw up
Scenery.OLD_CRANE_18638, // broken crane facing south, claw down
)
val CraneStates = intArrayOf(
// Varbit 2644 = 0: Broken
Scenery.OLD_CRANE_18638, // broken crane facing south, claw down
Scenery.OLD_CRANE_18637, // broken crane facing south, claw up
Scenery.OLD_CRANE_18636, // broken crane facing north, claw down
Scenery.OLD_CRANE_18635, // broken crane facing north, claw up
// Varbit 2644 = 1: Fixed/Empty (18623=N-Up, 18624=N-Down, 18625=S-Up, 18626=S-Down)
Scenery.OLD_CRANE_18626, // fixed crane facing south, claw down
Scenery.OLD_CRANE_18625, // fixed crane facing south, claw up
Scenery.OLD_CRANE_18624, // fixed crane facing north, claw down
Scenery.OLD_CRANE_18623, // fixed crane facing north, claw up
// Varbit 2644 = 2: Elemental Bar
Scenery.OLD_CRANE_18630, // fixed crane with ele bar facing south, claw down
Scenery.OLD_CRANE_18629, // fixed crane with ele bar facing south, claw up
Scenery.OLD_CRANE_18628, // fixed crane with ele bar facing north, claw down
Scenery.OLD_CRANE_18627, // fixed crane with ele bar facing north, claw up
// Varbit 2644 = 3: Mind Bar
Scenery.OLD_CRANE_18634, // fixed crane with mind bar facing south, claw down
Scenery.OLD_CRANE_18633, // fixed crane with mind bar facing south, claw up
Scenery.OLD_CRANE_18632, // fixed crane with mind bar facing north, claw down
Scenery.OLD_CRANE_18631 // fixed crane with mind bar facing north, claw up
)
// function to find my crane because it exists at some corner instead of the center.
fun findCraneInArea(center: Location): core.game.node.scenery.Scenery? {
// Search an area around the center
for (x in -2..2) {
for (y in -2..2) {
val checkLoc = center.transform(x, y, 0)
for (id in craneStates) {
val found = RegionManager.getObject(checkLoc.z, checkLoc.x, checkLoc.y, id)
if (found != null) return found
}
}
}
return null
}
// position the crane based on varbit states
fun syncCrane(player: Player) {
val mat = getVarbit(player, EW2CraneState)
val pos = getVarbit(player, EW2CranePos)
val index = (mat * 4) + pos
val newId = CraneStates[index]
val craneLoc = Location.create(1954, 5145, 2)
val currentCrane = findCraneInArea(craneLoc)
if (currentCrane != null) {
replaceScenery(currentCrane, newId, -1)
}
}
// west lever by crane. moves crane up and down.
on(Scenery.AN_OLD_LEVER_18622, IntType.SCENERY, "pull") { player, _ ->
val currentPos = getVarbit(player, EW2CranePos)
val nextPos = currentPos xor 1
val craneMat = getVarbit(player, EW2CraneState)
val cartState = getVarbit(player, EW2JigCart)
// facing north: pick up and drop off bar
if (currentPos == 3 && nextPos == 2) { // Moving from North-Up to North-Down
if (craneMat == 1 && (cartState == 1 || cartState == 2)) {
// pick up
setVarbit(player, EW2CraneState, cartState + 1)
setVarbit(player, EW2JigCart, 0)
sendMessage(player, "The crane claw picks up the bar from the cart.")
syncCart(player)
} else if ((craneMat == 2 || craneMat == 3) && cartState == 0) {
// drop off
setVarbit(player, EW2JigCart, craneMat - 1)
setVarbit(player, EW2CraneState, 1)
sendMessage(player, "You lower the bar onto the jig cart.")
syncCart(player)
}
}
// facing south: process bar
if (currentPos == 1 && nextPos == 0) {
if (craneMat == 2) {
// if holding elemental bar, transform into mind bar
setVarbit(player, EW2CraneState, 3)
sendMessage(player, "As you lower the bar into the machinery, it glows with a strange mind-energy.")
playAudio(player, Sounds.EW2_CRANE_LOWER_3169)
}
}
setVarbit(player, EW2CranePos, nextPos, true)
animate(player, Animations.HUMAN_PULL_LEVER_4909)
syncCrane(player)
@ -257,7 +344,7 @@ class EW2Listeners : InteractionListener {
// crane must be up to rotate
if (currentPos == 0 || currentPos == 2) {
sendMessage(player, "The crane is too low to rotate.")
sendMessage(player, "The arm cannot be rotated while the claw is down.")
return@on true
}
@ -284,19 +371,79 @@ class EW2Listeners : InteractionListener {
return@onUseWith true
}
// unlocked center hatch down to EW2
on(Scenery.HATCH_18596, IntType.SCENERY, "climb-down") { player, _ ->
sendMessage(player, "You climb down the stairs.")
teleport(player, location(1955, 5155, 2))
// opens the junction box
on(Scenery.JUNCTION_BOX_18641, IntType.SCENERY, "open") { player, _ ->
openInterface(player, Components.JUNCTION_BOX_262)
return@on true
}
// set the crane state when you go down based on the varbits
// if you log in and out during a server restart it'll reset the crane, but just reenter the workshop to fix it.
syncCrane(player)
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) == 4) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 5)
setVarbit(player, EW2Varbit, 5)
// take item from the jig cart
on(jigCartStates, IntType.NPC, "take-from") { player, node ->
when(node.id) {
4914 -> {
addItemOrDrop(player, Items.ELEMENTAL_METAL_2893)
sendItemDialogue(player, Items.ELEMENTAL_METAL_2893, "You take the elemental metal.")
}
4915 -> {
//addItemOrDrop(player, Items.ELEMENTAL_MIND_BAR_9728)
//sendItemDialogue(player, Items.ELEMENTAL_MIND_BAR_9728, "You take the elemental mind bar.")
sendMessage(player, "The bar is too hot to touch.")
}
4918 -> {
addItemOrDrop(player, Items.PRIMED_BAR_9727)
sendItemDialogue(player, Items.PRIMED_BAR_9727, "You take the primed bar.")
}
}
animate(player, 537)
setVarbit(player, EW2JigCart, 0, true)
syncCart(player)
return@on true
}
// fix the pipe
onUseWith(IntType.SCENERY, Items.PIPE_9723, Scenery.PIPING_18650) { player, item, _ ->
animate(player, 537)
sendItemDialogue(player, item, "You replace the section of broken pipe.")
playAudio(player, Sounds.EW2_PLACE_PIPE_3179)
setVarbit(player, EW2PipeVarbit, 1, true)
removeItem(player, item)
return@onUseWith true
}
// put regular bar on the jig cart
onUseWith(IntType.NPC, intArrayOf(Items.ELEMENTAL_METAL_2893), NPCs.JIG_CART_4913) { player, used, _ ->
val cranePos = getVarbit(player, EW2CranePos)
// if crane is south down, it's blocking the cart.
if (cranePos == 2) {
sendMessage(player, "You cannot place that while the claw is down.")
return@onUseWith true
}
setVarbit(player, EW2JigCart, 1, true)
animate(player, 537)
syncCart(player)
removeItem(player, used)
return@onUseWith true
}
on(Scenery.LEVER_18620, IntType.SCENERY, "pull") { player, _ ->
val currentPos = getVarbit(player, EW2CartLever)
val cranePos = getVarbit(player, EW2CranePos)
// crane must be up
if (currentPos == 0 && cranePos == 2) {
sendMessage(player, "You cannot do that while the claw is down.")
return@on true
}
// positions cycles 0 -> 1 -> 2 -> 3 -> 0 etc.
val nextPos = (currentPos + 1) % 4
animate(player, Animations.HUMAN_PULL_LEVER_4909)
setVarbit(player, EW2CartLever, nextPos, true)
syncCart(player)
return@on true
}
}
@ -307,6 +454,14 @@ class EW2Listeners : InteractionListener {
return@setDest Location.create(1954, 5148, 2)
}
setDest(IntType.NPC, intArrayOf(NPCs.JIG_CART_4913), "use") { _, _ ->
return@setDest Location.create(1954, 5148, 2)
}
setDest(IntType.NPC, intArrayOf(NPCs.JIG_CART_4914, NPCs.JIG_CART_4915), "take-from") { _, _ ->
return@setDest Location.create(1954, 5148, 2)
}
setDest(IntType.SCENERY, intArrayOf(Scenery.PIPING_18650), "use") { _, _ ->
return@setDest Location.create(1953, 5167, 3)
}

View file

@ -1,12 +1,17 @@
package content.region.kandarin.seers.quest.elementalworkshop2
import content.data.Quests
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.syncCart
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.syncCrane
import core.api.*
import core.game.node.entity.npc.NPC
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.game.world.map.Location
import core.plugin.Initializable
import org.rs09.consts.Items
import org.rs09.consts.NPCs
/**
* ELEMENTAL WORKSHOP II QUEST
@ -23,8 +28,8 @@ class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2Var
const val EW2Varbit = 2639 // Main quest progress. Incremented with quest stages.
const val EW2MachineryVarbit = 2640 // The machinery you have to search for the key. Set to 1 after you read the scroll.
const val EW2HatchVarbit = 2641 // The hatch down to EW2. Set to 1 after you unlock it with the key.
//const val EW2 = 2642 // north lever
const val EW2JigCart = 2643
const val EW2CartLever = 2642 // cart moving lever. 0 = start (south), 1 = west, 2 = north, 3 = east
const val EW2JigCart = 2643 // Jig Cart state. 0 = Empty, 1 = ele bar, 2 = mind bar, 3 = smashed mind, 4 = smashed ele, 5 = primed
const val EW2CraneState = 2644 // Crane State. 0 = Broken, 1 = Fixed/Empty, 2 = Elemental Bar, 3 = Mind Bar.
const val EW2CranePos = 2645 // Crane Position. 0 = South Down, 1 = South Up, 2 = North Down, 3 = North Up.
//const val EW2 = 2646 // junction box