need to finish the water section and quest log

This commit is contained in:
aidan 2026-01-27 07:10:38 -06:00
parent 9db6993beb
commit 8e261c65d2
6 changed files with 358 additions and 188 deletions

View file

@ -257,132 +257,206 @@ class EWListeners : InteractionListener {
}
// Workbenches/Anvil
// Before completing EW1 you can only smith and elemental shield. During EW2 you have the option to make a shield, claw, or helm.
onUseWith(IntType.SCENERY, Items.ELEMENTAL_METAL_2893, Scenery.WORKBENCH_3402) { player, used, workbench ->
// if elemental workshop II is in progress, display a dialogue. otherwise, revert to smithing the elemental shield only.
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) >= 5) {
sendDialogueOptions(player, "What would you like to make...", "An elemental shield.", "An elemental claw.", "An elemental helm.")
addDialogueAction(player) { _, buttonId ->
when (buttonId) {
2 -> { // ele shield
// Warn player their smithing level is too low to make the shield
if (player.skills.getLevel(Skills.SMITHING) < 20) {
sendMessage(player, "You need a smithing level of 20 to create an elemental shield.")
return@addDialogueAction
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.SLASHED_BOOK_9715, Items.BATTERED_BOOK_2886))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@addDialogueAction
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@addDialogueAction
}
// Successfully smith the elemental shield
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, elementalShield)
rewardXP(player, Skills.SMITHING, 20.0)
sendMessage(player, "Following the instructions in the book you make an elemental shield.")
// Before completing EW1 you can only make an elemental shield from an elemental bar.
// Smithing an elemental shield will complete EW1.
// During EW2 you have the option to make an elemental shield, claw, or helm from an elemental bar.
// Smithing an elemental mind helm from an elemental mind bar will complete EW2.
onUseWith(IntType.SCENERY, Items.ELEMENTAL_METAL_2893, Items.ELEMENTAL_MIND_BAR_9728, Scenery.WORKBENCH_3402) { player, used, workbench ->
when(used.id) {
Items.ELEMENTAL_METAL_2893 -> {
// if elemental workshop II is in progress, display a dialogue. otherwise, revert to smithing the elemental shield only.
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) >= 5) {
sendDialogueOptions(player, "What would you like to make...", "An elemental shield.", "An elemental claw.", "An elemental helm.")
addDialogueAction(player) { _, buttonId ->
when (buttonId) {
2 -> { // ele shield
// Warn player their smithing level is too low to make the shield
if (player.skills.getLevel(Skills.SMITHING) < 20) {
sendMessage(player, "You need a smithing level of 20 to create an elemental shield.")
return@addDialogueAction
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.SLASHED_BOOK_9715, Items.BATTERED_BOOK_2886))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@addDialogueAction
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@addDialogueAction
}
// Successfully smith the elemental shield
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, elementalShield)
rewardXP(player, Skills.SMITHING, 20.0)
sendMessage(player, "Following the instructions in the book you make an elemental shield.")
}
}
3 -> { // ele claw
// Warn player their smithing level is too low to make the shield
if (player.skills.getLevel(Skills.SMITHING) < 20) {
sendMessage(player, "You need a smithing level of 20 to create an elemental claw.")
return@addDialogueAction
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.CRANE_SCHEMATIC_9718))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@addDialogueAction
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@addDialogueAction
}
// Successfully smith the elemental shield
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, Item(Items.CRANE_CLAW_9720))
rewardXP(player, Skills.SMITHING, 20.0)
sendMessage(player, "Following the instructions from the schematic you make an elemental claw.")
}
}
4 -> { // ele helm
// Warn player their smithing level is too low to make the helm
if (player.skills.getLevel(Skills.SMITHING) < 30) {
sendMessage(player, "You need a smithing level of 30 to create an elemental helm.")
return@addDialogueAction
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.BEATEN_BOOK_9717))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@addDialogueAction
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@addDialogueAction
}
// Successfully smith the elemental helm
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, Item(Items.ELEMENTAL_HELMET_9729))
rewardXP(player, Skills.SMITHING, 20.0)
sendMessage(player, "Following the instructions in the book you make an elemental helm.")
}
}
}
}
3 -> { // ele claw
// Warn player their smithing level is too low to make the shield
if (player.skills.getLevel(Skills.SMITHING) < 20) {
sendMessage(player, "You need a smithing level of 20 to create an elemental claw.")
return@addDialogueAction
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.CRANE_SCHEMATIC_9718))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@addDialogueAction
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@addDialogueAction
}
// Successfully smith the elemental shield
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, Item(Items.CRANE_CLAW_9720))
rewardXP(player, Skills.SMITHING, 20.0)
sendMessage(player, "Following the instructions from the schematic you make an elemental claw.")
}
// EW1 fallback
} else {
// Warn player their smithing level is too low to make the shield
if (player.skills.getLevel(Skills.SMITHING) < 20) {
sendMessage(player, "You need a smithing level of 20 to create an elemental shield.")
return@onUseWith true
}
4 -> { // ele helm
// Warn player their smithing level is too low to make the helm
if (player.skills.getLevel(Skills.SMITHING) < 30) {
sendMessage(player, "You need a smithing level of 30 to create an elemental helm.")
return@addDialogueAction
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.BEATEN_BOOK_9717))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@addDialogueAction
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@addDialogueAction
}
// Successfully smith the elemental helm
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, Item(Items.ELEMENTAL_HELMET_9729))
rewardXP(player, Skills.SMITHING, 20.0)
sendMessage(player, "Following the instructions in the book you make an elemental helm.")
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.SLASHED_BOOK_9715, Items.BATTERED_BOOK_2886))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@onUseWith true
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@onUseWith true
}
// Sanity error check (Should never get thrown)
if (!player.inventory.containsAll(*elementalShieldReqItems)) {
log(this::class.java, Log.ERR, "${player.username} tried to forge an elemental shield without all the required items.")
return@onUseWith false
}
// Successfully smith the elemental shield
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, elementalShield)
rewardXP(player, Skills.SMITHING, 20.0)
sendMessage(player, "Following the instructions in the book you make an elemental shield.")
}
// Check to see if the quest is completed, if not, complete the quest
if (!player.questRepository.getQuest(Quests.ELEMENTAL_WORKSHOP_I).isCompleted(player)) {
player.questRepository.getQuest(Quests.ELEMENTAL_WORKSHOP_I).finish(player)
}
}
}
Items.ELEMENTAL_MIND_BAR_9728 -> {
sendDialogueOptions(player, "Would you like to make...", "An elemental mine shield.", "An elemental mind helm.")
addDialogueAction(player) { _, buttonId ->
when (buttonId) {
2 -> { // ele mind shield
// Warn player their smithing level is too low to make the shield
if (player.skills.getLevel(Skills.SMITHING) < 30) {
sendMessage(player, "You need a smithing level of 30 to create an elemental shield.")
return@addDialogueAction
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.BEATEN_BOOK_9717))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@addDialogueAction
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@addDialogueAction
}
// Successfully smith the elemental mind shield
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, Item(Items.MIND_SHIELD_9731))
rewardXP(player, Skills.SMITHING, 30.0)
sendMessage(player, "Following the instructions in the book you make an elemental mind shield.")
}
}
3 -> { // ele mind helm
// Warn player their smithing level is too low to make the helm
if (player.skills.getLevel(Skills.SMITHING) < 30) {
sendMessage(player, "You need a smithing level of 30 to create an elemental mind helm.")
return@addDialogueAction
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.BEATEN_BOOK_9717))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@addDialogueAction
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@addDialogueAction
}
// Successfully smith the elemental helm
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, Item(Items.MIND_HELMET_9733))
rewardXP(player, Skills.SMITHING, 30.0)
sendMessage(player, "Following the instructions in the book you make an elemental mind helm.")
// EW1 fallback
} else {
// Warn player their smithing level is too low to make the shield
if (player.skills.getLevel(Skills.SMITHING) < 20) {
sendMessage(player, "You need a smithing level of 20 to create an elemental shield.")
return@onUseWith true
}
// Warn player they don't have the required book in their inventory
if (!player.inventory.containsAtLeastOneItem(intArrayOf(Items.SLASHED_BOOK_9715, Items.BATTERED_BOOK_2886))) {
sendDialogue(player, "This workbench is too complicated. You need instructions to follow.")
return@onUseWith true
}
// Warn player they don't have a hammer in their inventory
if (!inInventory(player, Items.HAMMER_2347)) {
sendDialogue(player, "You don't have a tool available to shape the metal.")
return@onUseWith true
}
// Sanity error check (Should never get thrown)
if (!player.inventory.containsAll(*elementalShieldReqItems)) {
log(this::class.java, Log.ERR, "${player.username} tried to forge an elemental shield without all the required items.")
return@onUseWith false
}
// Successfully smith the elemental shield
lock(player, (animationDuration(smithElementalShield) + 2))
runTask(player) {
face(player, workbench)
animate(player, smithElementalShield)
playAudio(player, smithElementalShieldSFX)
replaceSlot(player, used.asItem().slot, elementalShield)
rewardXP(player, Skills.SMITHING, 20.0)
sendMessage(player, "Following the instructions in the book you make an elemental shield.")
}
// Check to see if the quest is completed, if not, complete the quest
if (!player.questRepository.getQuest(Quests.ELEMENTAL_WORKSHOP_I).isCompleted(player)) {
player.questRepository.getQuest(Quests.ELEMENTAL_WORKSHOP_I).finish(player)
// complete quest if it's not done.
if (!isQuestComplete(player, Quests.ELEMENTAL_WORKSHOP_II)) {
finishQuest(player, Quests.ELEMENTAL_WORKSHOP_II)
}
}
}
}
}
}
}

View file

@ -8,6 +8,7 @@ import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2CranePosVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2CraneStateVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2DoorLeverVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2ExtractorGun
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2FanLeverVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2HatchVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2JigCartVarbit
@ -18,11 +19,14 @@ import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2
import core.api.*
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.node.entity.impl.WalkingQueue
import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.system.task.Pulse
import core.game.world.map.Location
import core.game.world.map.RegionManager
import core.game.world.map.path.Pathfinder
import org.rs09.consts.*
class EW2Listeners : InteractionListener {
@ -98,6 +102,7 @@ class EW2Listeners : InteractionListener {
NPCs.JIG_CART_4918, // smashed white bar
)
// locations the jig cart can be at
val jigCartLocations = arrayOf(
Location.create(1954, 5147, 2), // south (start)
Location.create(1946, 5155, 2), // west (hammer)
@ -105,6 +110,7 @@ class EW2Listeners : InteractionListener {
Location.create(1961, 5155, 2) // east (fans)
)
// tank door states are currently not updated due to Arios.
val tankDoorStates = intArrayOf(
Scenery.DOOR_18651, // door closed
Scenery.DOOR_18652,
@ -145,67 +151,52 @@ class EW2Listeners : InteractionListener {
// update the jig cart based on varbit status
fun syncCart(player: Player) {
val cartState = getVarbit(player, EW2JigCartVarbit)
val cartPosIndex = getVarbit(player, EW2CartLeverVarbit)
val cartPosIndex = getVarbit(player, EW2CartLeverVarbit) // cart moving lever. 0 = start (south), 1 = west, 2 = north, 3 = east
val targetId = jigCartStates[cartState]
val targetLocation = jigCartLocations[cartPosIndex]
// find existing cart
// find cart
val trackCenter = Location.create(1953, 5155, 2)
val existingCart = RegionManager.getLocalNpcs(trackCenter, 15).find {
it.id in jigCartStates
}
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) {
// todo it would be nice if the cart moved instead of teleporting. try and make the tracks walkable?
// failsafe to reset the cart where it's supposed to be
if (!existingCart.walkingQueue.isMoving && existingCart.location != targetLocation) {
existingCart.teleport(targetLocation)
}
// if there is no cart, spawn a new one (like if this is the quest start)
} else {
// Spawn if missing (like if this is the quest start)
val newCart = NPC(targetId, targetLocation)
newCart.init()
}
}
// values for the cogs
val cogRange = (Scenery.COG_18667..Scenery.COG_18684).toList().toIntArray() // 18 different cogs. That is enough to give each cog a static/fwd spin/rev spin animation.
val cogRange = (Scenery.COG_18667..Scenery.COG_18684).toList().toIntArray() // 18 different cogs. I'm guessing that is enough to give each cog a static/fwd/rev state (probably).
val smallCogs = intArrayOf(Scenery.COG_18673, Scenery.COG_18667, Scenery.COG_18670) // pin 1, pin 2, pin 3
val medCogs = intArrayOf(Scenery.COG_18674, Scenery.COG_18668, Scenery.COG_18671) // pin 1, pin 2, pin 3
val largeCogs = intArrayOf(Scenery.COG_18675, Scenery.COG_18669, Scenery.COG_18672) // pin 1, pin 2, pin 3
// syncs the tank door based on state of varbit 2653
fun syncTankDoor(player: Player) {
val doorState = getVarbit(player, EW2TankDoorVarbit)
// visualizes the steam press smasher
// todo it doesn't work right now
fun steamPress() {
val pressId = Scenery.STEAM_PRESS_18643
val currentObject = getScenery(Location.create(1945, 5154, 3))
val targetId = tankDoorStates[doorState]
val center = Location.create(1953, 5164, 2)
// check an object actually exists here
if (currentObject != null) {
//println(currentObject.type)
// Scan the 5x5 area around the tank door location
for (x in -2..2) {
for (y in -2..2) {
val checkLoc = center.transform(x, y, 0)
val currentObject = RegionManager.getObject(checkLoc.z, checkLoc.x, checkLoc.y) ?: continue
sendMessage(player, "$currentObject")
sendMessage(player,"$doorState")
// Check if the object is any of the possible door states
if (tankDoorStates.contains(currentObject.id)) {
if (currentObject.id != targetId) {
replaceScenery(currentObject, targetId, -1)
}
return
}
// check that the object is the press
if (pressId == currentObject.id) {
replaceScenery(currentObject, Scenery.STEAM_PRESS_18645, 5) // either this or Scenery.STEAM_PRESS_18644
}
}
}
}
override fun defineListeners() {
@ -312,6 +303,12 @@ class EW2Listeners : InteractionListener {
return@on true
}
// body doors (locked)
on(intArrayOf(Scenery.DOOR_18702, Scenery.DOOR_18703), IntType.SCENERY, "open") { player, _ ->
sendMessage(player, "The door is locked.")
return@on true
}
// schematic crate
on(Scenery.SCHEMATIC_CRATE_18711, IntType.SCENERY, "take-from") { player, _ ->
sendDialogueOptions(player, "There are two schematics here...", "Crane schematic", "Lever schematic")
@ -343,6 +340,14 @@ class EW2Listeners : InteractionListener {
val doorPos = getVarbit(player, EW2DoorLeverVarbit) // 1 if door is open
val fanPos = getVarbit(player, EW2FanLeverVarbit) // 1 if the fan is on
// find the cart
val trackCenter = Location.create(1953, 5155, 2)
val existingCart = RegionManager.getLocalNpcs(trackCenter, 15).find { it.id in jigCartStates }
if (existingCart == null) {
sendMessage(player, "CART MISSING. LOG IN AND OUT TO RESET IT.")
return@on true
}
// crane must be up
if (currentPos == 0 && cranePos == 2) {
sendMessage(player, "You cannot do that while the claw is down.")
@ -359,13 +364,44 @@ class EW2Listeners : InteractionListener {
sendMessage(player, "You cannot do that while the fan is on.")
return@on true
}
// cart must be currently stopped
if (existingCart.walkingQueue.isMoving) {
return@on true
}
// positions cycles 0 -> 1 -> 2 -> 3 -> 0 etc.
val nextPos = (currentPos + 1) % 4
// set path
val path = when (currentPos) {
// south: south (crane) to west (hammer)
0 -> arrayOf(Location.create(1954, 5147, 2), Location.create(1946, 5147, 2), Location.create(1946, 5155, 2))
animate(player, Animations.HUMAN_PULL_LEVER_4909)
setVarbit(player, EW2CartLeverVarbit, nextPos, true)
syncCart(player)
// west: west (hammer) to north (water)
1 -> arrayOf(Location.create(1946, 5155, 2), Location.create(1946, 5162, 2), Location.create(1953, 5162, 2))
// north: north (water) to east (fan)
2 -> arrayOf(Location.create(1953, 5162, 2), Location.create(1961, 5162, 2), Location.create(1961, 5155, 2))
// east: east (fan) to south (crane)
3 -> arrayOf(Location.create(1961, 5155, 2), Location.create(1961, 5147, 2), Location.create(1954, 5147, 2))
// else nothing
else -> arrayOf()
}
if (path.isNotEmpty()) {
animate(player, Animations.HUMAN_PULL_LEVER_4909)
// set the next varbit state
val nextPos = (currentPos + 1) % 4
setVarbit(player, EW2CartLeverVarbit, nextPos, true)
// todo there are weird bugs with walkingQueue. cart sometimes veers off randomly to one of the other destinations. just teleporting for now.
// move
//existingCart.walkingQueue.reset()
//for (step in path) {
// existingCart.walkingQueue.addPath(step.x, step.y)
//}
teleport(existingCart, path[2])
}
return@on true
}
@ -522,28 +558,31 @@ class EW2Listeners : InteractionListener {
if (cartPos == 1) {
when (cartState) {
0 -> { // empty
steamPress()
sendDialogue(player, "You pull the lever and the press operates, but there is nothing on the cart to flatten.")
}
// todo animate the hammer smash
1 -> { // ele bar
setVarbit(player, EW2JigCartVarbit, 4)
//replaceScenery(getScenery(1945, 5154, 3), 18644, 3)
steamPress()
// "hardy" is the real word used. I thought it was a typo for 'hammer' but it's not. https://en.wikipedia.org/wiki/Hardy_tool
sendDialogue(player, "You pull the lever and the press responds. The hardy comes down, hitting the elemental bar. The bar is not hot enough to flatten.")
syncCart(player)
}
2 -> { // hot ele bar
setVarbit(player, EW2JigCartVarbit, 3)
steamPress()
// "hardy" is correct. see above.
sendDialogue(player, "You pull the lever and the press responds. The hardy comes down, hitting the elemental bar. The bar has been flattened.")
syncCart(player)
}
else -> { // smashed hot, smashed cooled, or primed
steamPress()
sendDialogue(player, "You pull the lever and the press responds. The hardy comes down, hitting the elemental bar. The bar is already flattened.")
}
}
} else {
// cart in wrong position
steamPress()
sendDialogue(player, "You pull the lever and the press operates, but the jig cart is not underneath it.")
}
} else {
@ -582,20 +621,12 @@ class EW2Listeners : InteractionListener {
}
// todo north lever
// todo see below, note that the door cannot have its scenery updated because it overlaps with the track and our limited engine can't find it.
// north lever that opens and closes the door
on(Scenery.AN_OLD_LEVER_18648, IntType.SCENERY, "pull") { player, _ ->
val currentState = getVarbit(player, EW2TankDoorVarbit)
// Increment from 0-7, or reset to 0 if at 8
val nextState = if (currentState < 8) currentState + 1 else 0
val trackscen = getScenery(1953, 5162, 2)!!
addScenery(18751, Location.create(1951, 5159, 2))
removeScenery(trackscen)
setVarbit(player, EW2TankDoorVarbit, nextState, true)
syncTankDoor(player)
return@on true
}
@ -666,6 +697,7 @@ class EW2Listeners : InteractionListener {
return@on true
}
// todo see below, note that the pin 2 cannot be taken from because it overlaps with pin 1 and our limited engine can't find it.
// taking the cogs from the pins
on(cogRange, IntType.SCENERY, "take") { player, node ->
// determine what to take
@ -790,6 +822,7 @@ class EW2Listeners : InteractionListener {
return@onUseWith true
}
// todo see above, note that the fan scenery cannot be animated :( because it must overlap with some other object and our limited engine can't find it.
// fan lever. Authentically this check should allow the machine to start and the fan to either not start, start backwards, or start correctly, but I'm simplifying it for my sanity.
on(Scenery.AN_OLD_LEVER_18663, IntType.SCENERY, "pull") { player, _ ->
animate(player, Animations.HUMAN_PULL_LEVER_4909)
@ -812,10 +845,6 @@ class EW2Listeners : InteractionListener {
setVarbit(player, EW2JigCartVarbit, 5, true)
syncCart(player)
}
//todo animate the fan somehow
// find scenery ID {FANSTOPPED} or {FANSTARTED} near tile Location.create(1961, 5154, 2).
// swap for scenery {FANSTOPPED} if EW2FanStateVarbit is 0 or {FANSTARTED} if EW2FanStateVarbit is 1
} else {
// turn off
sendDialogue(player, "The machine grinds to a standstill.")
@ -833,6 +862,37 @@ class EW2Listeners : InteractionListener {
** ------------------------
*/
// todo add graphics to this section
// use bar with extractor gun
onUseWith(IntType.SCENERY, intArrayOf(Items.PRIMED_BAR_9727), Scenery.EXTRACTOR_GUN_18693) { player, item, _ ->
setVarbit(player, EW2ExtractorGun, 1, true)
return@onUseWith true
}
// take primed bar
on(intArrayOf(Scenery.EXTRACTOR_GUN_18694), IntType.SCENERY, "take-from") { player, _ ->
addItemOrDrop(player, Items.PRIMED_BAR_9727)
setVarbit(player, EW2ExtractorGun, 0, true)
return@on true
}
// take mind bar
on(intArrayOf(Scenery.EXTRACTOR_GUN_18695), IntType.SCENERY, "take-from") { player, _ ->
addItemOrDrop(player, Items.ELEMENTAL_MIND_BAR_9728)
setVarbit(player, EW2ExtractorGun, 0, true)
return@on true
}
// sit in chair
on(intArrayOf(Scenery.EXTRACTOR_HAT_18690), IntType.SCENERY, "operate") { player, _ ->
// if bar is in place
if(getVarbit(player, EW2ExtractorGun) == 1) {
setVarbit(player, EW2ExtractorGun, 2, true)
}
return@on true
}
/**
* EXTRACTOR_GUN_18693
* EXTRACTOR_GUN_18694

View file

@ -4,23 +4,20 @@ import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Compa
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.syncCrane
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.game.world.map.RegionManager
import core.plugin.Initializable
import core.game.world.map.zone.MapZone
import core.game.world.map.zone.ZoneBorders
import core.game.world.map.zone.ZoneBuilder
import core.plugin.Plugin
import org.rs09.consts.Scenery
/**
* This updates the Elemental Workshop II state whenever the player enters
* Controls things like crane state and jig cart state.
* This updates the Elemental Workshop II state whenever the player enters,
* keeping the equipment state synced to the saved varbits.
*/
@Initializable
class EW2Zone : MapZone("Elemental Workshop II", true), Plugin<Any?> {
override fun newInstance(arg: Any?): EW2Zone {
ZoneBuilder.configure(this)
return this
@ -32,18 +29,14 @@ class EW2Zone : MapZone("Elemental Workshop II", true), Plugin<Any?> {
// updates the workshop state based on the varbits for Elemental Workshop II
override fun enter(e: Entity?): Boolean {
if(e is Player) {
syncCrane(e)
syncCart(e)
}
return super.enter(e)
}
override fun fireEvent(identifier: String?, vararg args: Any?): Any {
return Unit
}
}

View file

@ -18,7 +18,7 @@ import org.rs09.consts.Items
@Initializable
class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2StageVarbit, 0, 1, 11) {
// a truckload of varbits
// a truckload of varbits - https://chisel.weirdgloop.org/varbs/display?varplayer=896
companion object {
const val EW2Varp1 = 896 // first EW2 varp that packages varbits 2639-2652
const val EW2StageVarbit = 2639 // Main quest progress. Incremented with quest stages.
@ -37,8 +37,8 @@ class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2Sta
const val EW2ValveEastVarbit = 2652 // water valve east. 0 = closed, 1 = open
const val EW2Varp2 = 897 // second EW2 varp that packages varbits 2653-2664
const val EW2TankDoorVarbit = 2653 // tank door, controlled by corkscrew lever. 0 = , 1 = , 2 = , 3 = , 4 = , 5 = , 6 = , 7 = , 8 =
const val EW2DoorLeverVarbit = 2654 // door lever. 0 = closed, 1 = open
const val EW2TankDoorVarbit = 2653 // tank door holding state, controlled by corkscrew lever. 0 = closed, 1 = , 2 = , 3 = , 4 = , 5 = , 6 = , 7 = , 8 = // nine values. jig cart has six
const val EW2DoorLeverVarbit = 2654 // door lever for tank. 0 = closed, 1 = open
const val EW2CogVarbit1 = 2655 // cog pin. 0 = no cog, 1 = small, 2 = med, 3 = large
const val EW2CogVarbit2 = 2656 // cog pin. 0 = no cog, 1 = small, 2 = med, 3 = large
const val EW2CogVarbit3 = 2657 // cog pin. 0 = no cog, 1 = small, 2 = med, 3 = large
@ -46,7 +46,7 @@ class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2Sta
const val EW2FanLeverVarbit = 2659 // fan switch. 0 = fan off, 1 = fan on
//const val EW2FanStateVarbit = 2660 // fan blades. 0 = off, 1 = forward, 2 = reverse
//const val EW2FanStationVarbit = 2661 // overlaps cogs, fan switch, and fan blades varbits
//const val EW2 = 2662 // extractor gun. 0 = empty, 1 = primed bar, 2 = mind bar
const val EW2ExtractorGun = 2662 // extractor gun. 0 = empty, 1 = primed bar, 2 = mind bar
//const val EW2 = 2663 //
//const val EW2 = 2664 // values from 1 to 7 back at the dig site library where you find the book.
}

View file

@ -0,0 +1,43 @@
package content.region.kandarin.seers.quest.elementalworkshop2
import core.game.node.entity.npc.AbstractNPC
import core.game.node.entity.npc.NPC
import core.game.node.entity.npc.NPCBehavior
import core.game.world.map.Location
import core.game.world.map.RegionManager
import core.game.world.map.build.RegionFlags
import core.game.world.map.path.ClipMaskSupplier
import org.rs09.consts.NPCs
/**
* Jig cart in Elemental Workshop II
* The only reason I have this here is to set a custom clipping mask to allow the cart to walk over the track scenery.
* Right now the walking part is broken, so the cart just teleports.
*/
class JigCartNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id, location) {
override fun construct(id: Int, location: Location, vararg objects: Any): AbstractNPC {
return JigCartNPC(id, location)
}
override fun getIds(): IntArray {
return intArrayOf(NPCs.JIG_CART_4913, NPCs.JIG_CART_4914, NPCs.JIG_CART_4915, NPCs.JIG_CART_4916, NPCs.JIG_CART_4917, NPCs.JIG_CART_4918,)
}
}
class JigCartNPCBehavior : NPCBehavior(NPCs.JIG_CART_4913, NPCs.JIG_CART_4914, NPCs.JIG_CART_4915, NPCs.JIG_CART_4916, NPCs.JIG_CART_4917, NPCs.JIG_CART_4918,) {
override fun getClippingSupplier (self: NPC) : ClipMaskSupplier {
return CartClipper
}
}
// this clip mask lets the jig cart walk through scenery
object CartClipper : ClipMaskSupplier {
override fun getClippingFlag (z: Int, x: Int, y: Int) : Int {
val flag = RegionManager.getClippingFlag(z, x, y)
return flag and (RegionFlags.SOLID_TILE.inv()) and (RegionFlags.TILE_OBJECT.inv()) and (RegionFlags.OBJ_10.inv())
}
}

View file

@ -142,8 +142,8 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){
/**
* Finds a list of objects/sceneries in a region
*/
define("findobjs", Privilege.ADMIN, "::findobjs <lt>REGION ID<gt> <lt>SCENERY ID<gt>", "Finds all locations of scenery objects of id."){player, args ->
if(args.size < 4) reject(player, "Usage: region_id scenery_id")
define("findobjs", Privilege.ADMIN, "::findobjs <lt>REGION ID<gt> <lt>SCENERY ID START<gt> <lt>SCENERY ID END<gt>", "Finds all locations of scenery objects of id."){player, args ->
if(args.size < 4) reject(player, "Usage: region_id scenery_id_start scenery_id_end")
val regionId = args[1].toInt()
val sceneryId = args[2].toInt()
val sceneryIdEnd = args[3].toInt()