diff --git a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWListeners.kt b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWListeners.kt index acc48c6f6..91eb22bb0 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWListeners.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop/EWListeners.kt @@ -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) + } + } + } + } + } } } diff --git a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/EW2Listeners.kt b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/EW2Listeners.kt index ab55a9a33..3a5832ae8 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/EW2Listeners.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/EW2Listeners.kt @@ -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 diff --git a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/EW2Zone.kt b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/EW2Zone.kt index 33097f715..fd4048c45 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/EW2Zone.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/EW2Zone.kt @@ -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 { - override fun newInstance(arg: Any?): EW2Zone { ZoneBuilder.configure(this) return this @@ -32,18 +29,14 @@ class EW2Zone : MapZone("Elemental Workshop II", true), Plugin { // 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 } - - } \ No newline at end of file diff --git a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/ElementalWorkshop2.kt b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/ElementalWorkshop2.kt index ca17f62ab..0fe6b7a67 100644 --- a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/ElementalWorkshop2.kt +++ b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/ElementalWorkshop2.kt @@ -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. } diff --git a/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/JigCartNPC.kt b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/JigCartNPC.kt new file mode 100644 index 000000000..7967c2e65 --- /dev/null +++ b/Server/src/main/content/region/kandarin/seers/quest/elementalworkshop2/JigCartNPC.kt @@ -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()) + } +} \ No newline at end of file diff --git a/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt b/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt index 30e4107c9..0f45f3766 100644 --- a/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt +++ b/Server/src/main/core/game/system/command/sets/TeleportCommandSet.kt @@ -142,8 +142,8 @@ class TeleportCommandSet : CommandSet(Privilege.ADMIN){ /** * Finds a list of objects/sceneries in a region */ - define("findobjs", Privilege.ADMIN, "::findobjs REGION ID SCENERY ID", "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 REGION ID SCENERY ID START SCENERY ID END", "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()