This commit is contained in:
aidan 2026-01-30 12:28:39 -06:00
parent 8e261c65d2
commit 60ce5a2390
6 changed files with 746 additions and 196 deletions

View file

@ -17,6 +17,7 @@ import core.game.interaction.InteractionListener
import core.game.interaction.IntType
import core.tools.Log
import content.data.Quests
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2StageVarbit
/**
* Listeners for the Elemental Workshop I quest
@ -261,7 +262,7 @@ class EWListeners : InteractionListener {
// 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 ->
onUseWith(IntType.SCENERY, intArrayOf(Items.ELEMENTAL_METAL_2893, Items.ELEMENTAL_MIND_BAR_9728), Scenery.WORKBENCH_3402) { player, used, workbench ->
when(used.id) {
Items.ELEMENTAL_METAL_2893 -> {
@ -354,7 +355,7 @@ class EWListeners : InteractionListener {
}
}
// EW1 fallback
// EW1 fallback
} else {
// Warn player their smithing level is too low to make the shield
if (player.skills.getLevel(Skills.SMITHING) < 20) {
@ -392,66 +393,101 @@ class EWListeners : InteractionListener {
}
}
}
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.")
// complete quest if it's not done.
if (!isQuestComplete(player, Quests.ELEMENTAL_WORKSHOP_II)) {
finishQuest(player, Quests.ELEMENTAL_WORKSHOP_II)
Items.ELEMENTAL_MIND_BAR_9728 -> {
// if EW2 is not complete, the player makes a mind helmet. after the quest, you have a choice.
if(!isQuestComplete(player, Quests.ELEMENTAL_WORKSHOP_II)) {
// 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@onUseWith true
}
// 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@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
}
// Successfully smith the elemental helm and complete quest
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.")
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 10) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 11)
setVarbit(player, EW2StageVarbit, 11, true)
}
// complete quest if it's not done.
if (!isQuestComplete(player, Quests.ELEMENTAL_WORKSHOP_II)) {
finishQuest(player, Quests.ELEMENTAL_WORKSHOP_II)
}
}
// choice to make helmet or shield
} else {
sendDialogueOptions(player, "Would you like to make...", "An elemental mind 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 mind 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.")
}
}
}
@ -459,7 +495,6 @@ class EWListeners : InteractionListener {
}
}
}
return@onUseWith true
}

View file

@ -0,0 +1,52 @@
package content.region.kandarin.seers.quest.elementalworkshop
import content.data.Quests
import content.region.kandarin.seers.quest.elementalworkshop.EWUtils.BELLOWS_STATE
import content.region.kandarin.seers.quest.elementalworkshop.EWUtils.FURNACE_STATE
import content.region.kandarin.seers.quest.elementalworkshop.EWUtils.LEFT_WATER_CONTROL_STATE
import content.region.kandarin.seers.quest.elementalworkshop.EWUtils.RIGHT_WATER_CONTROL_STATE
import content.region.kandarin.seers.quest.elementalworkshop.EWUtils.WATER_WHEEL_STATE
import core.api.*
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
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
/**
* This updates the Elemental Workshop I state whenever the player enters, if the quest is complete.
* Workshop should maintain state per this video: https://www.youtube.com/watch?v=YKSWisRgGZk
*/
@Initializable
class EWZone : MapZone("Elemental Workshop I", true), Plugin<Any?> {
override fun newInstance(arg: Any?): EWZone {
ZoneBuilder.configure(this)
return this
}
override fun configure() {
super.register(ZoneBorders(2688,9862,2744,9920))
}
// updates the workshop state based on the varbits for Elemental Workshop II
override fun enter(e: Entity?): Boolean {
if(e is Player) {
if(isQuestComplete(e, Quests.ELEMENTAL_WORKSHOP_I)) {
setVarbit(e, LEFT_WATER_CONTROL_STATE, 1)
setVarbit(e, RIGHT_WATER_CONTROL_STATE, 1)
setVarbit(e, WATER_WHEEL_STATE, 1)
setVarbit(e, FURNACE_STATE, 1)
setVarbit(e, BELLOWS_STATE, 1)
}
}
return super.enter(e)
}
override fun fireEvent(identifier: String?, vararg args: Any?): Any {
return Unit
}
}

View file

@ -1,36 +1,57 @@
package content.region.kandarin.seers.quest.elementalworkshop2
import content.data.Quests
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2AllCogsVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2CartLeverVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2CogVarbit1
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2CogVarbit2
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2CogVarbit3
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.EW2TankDoorStatusVarbit
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.EW2FanStateVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2HatchVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2JigCartVarbit
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.EW2StageVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2TankDoorVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2TankDoorStateVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2ValveEastVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2ValveWestVarbit
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.attrDipped
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.attrFlattened
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.attrJigged
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.attrWatered
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.attrWinded
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.badHat
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.eHelmEquip
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.eShieldEquip
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.goodHat
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.mHelmEquip
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.mShieldEquip
import core.game.world.update.flag.context.Graphics
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.node.scenery.SceneryBuilder
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 {
// values from 530_synth_debug_names.txt that are still unused
//val ew2_dial_spin = 2326
//val ew2_ambient_loop = 3149
//val ew2_machine_loop = 3150
// gfx 809 mind shield equip, 810 mind helmet equip
/**
* Quest structure and testing notes:
*
@ -73,7 +94,7 @@ class EW2Listeners : InteractionListener {
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)
// Varbit 2644 = 1: Fixed/Empty
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
@ -85,21 +106,21 @@ class EW2Listeners : InteractionListener {
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
// Varbit 2644 = 3: Hot Bar
Scenery.OLD_CRANE_18634, // fixed crane with hot bar facing south, claw down
Scenery.OLD_CRANE_18633, // fixed crane with hot bar facing south, claw up
Scenery.OLD_CRANE_18632, // fixed crane with hot bar facing north, claw down
Scenery.OLD_CRANE_18631 // fixed crane with hot 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, // hot ele bar
NPCs.JIG_CART_4916, // smashed hot bar
NPCs.JIG_CART_4917, // smashed ele bar
NPCs.JIG_CART_4918, // smashed white bar
NPCs.JIG_CART_4913, // 0 empty
NPCs.JIG_CART_4914, // 1 ele bar
NPCs.JIG_CART_4915, // 2 hot ele bar
NPCs.JIG_CART_4916, // 3 smashed hot bar
NPCs.JIG_CART_4917, // 4 smashed cooled bar
NPCs.JIG_CART_4918, // 5 primed bar
)
// locations the jig cart can be at
@ -110,21 +131,27 @@ class EW2Listeners : InteractionListener {
Location.create(1961, 5155, 2) // east (fans)
)
// tank door states are currently not updated due to Arios.
// tank door states stored in varbit 2653
val tankDoorStates = intArrayOf(
Scenery.DOOR_18651, // door closed
Scenery.DOOR_18652,
Scenery.DOOR_18653,
Scenery.DOOR_18654,
Scenery.DOOR_18655,
Scenery.DOOR_18656,
Scenery.DOOR_18657,
Scenery.DOOR_18658,
Scenery.DOOR_18659
Scenery.DOOR_18651, // 0 door closed
Scenery.DOOR_18652, // 1 door opened, grabber inside
Scenery.DOOR_18653, // 2 door opened, grabber out
Scenery.DOOR_18654, // 3 door closed, hot bar inside
Scenery.DOOR_18655, // 4 door opened, hot bar inside
Scenery.DOOR_18656, // 5 door opened, hot bar out
Scenery.DOOR_18657, // 6 door closed, cooled bar inside
Scenery.DOOR_18658, // 7 door opened, cooled bar inside
Scenery.DOOR_18659 // 8 door opened, cooled bar out
)
// steam press scenery. right now I just use the third one to make the hammer appear
val steamPressStates = intArrayOf(
Scenery.STEAM_PRESS_18643, // top of the steam press
Scenery.STEAM_PRESS_18644, // press with ele bar cart
Scenery.STEAM_PRESS_18645 // press with nothing under it
)
// position the crane based on varbit states
// todo it would be nice to animate this crane
fun syncCrane(player: Player) {
val mat = getVarbit(player, EW2CraneStateVarbit)
val pos = getVarbit(player, EW2CranePosVarbit)
@ -141,8 +168,18 @@ class EW2Listeners : InteractionListener {
if (craneStates.contains(currentObject.id)) {
// replace crane if current state doesn't match what is called for
// todo it would be nice to animate this crane
if (currentObject.id != newId) {
replaceScenery(currentObject, newId, -1)
playAudio(player, Sounds.EW2_CRANE_TURN_3170)
//playAudio(player, Sounds.EW2_CRANE_LOWER_3169)
// if bar is hot set attr for quest log
if(newId == 18634) {
if(!getAttribute(player, attrDipped, false) && getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 6) {
setAttribute(player, attrDipped, true)
}
}
}
}
}
@ -154,6 +191,7 @@ class EW2Listeners : InteractionListener {
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]
val tankState = getVarbit(player, EW2TankDoorStateVarbit) // if tank state is 3, 4, 6, 7 the cart is inside the tank and should be removed.
// find cart
val trackCenter = Location.create(1953, 5155, 2)
@ -163,15 +201,23 @@ class EW2Listeners : InteractionListener {
if (existingCart.id != targetId) {
existingCart.transform(targetId)
}
// failsafe to reset the cart where it's supposed to be
// failsafe to reset the cart where it's supposed to be. right now cart just teleports so this shouldn't trigger
if (!existingCart.walkingQueue.isMoving && existingCart.location != targetLocation) {
existingCart.teleport(targetLocation)
}
// if cart is inside water tank, clear it
if (tankState == 3 || tankState == 4 || tankState == 6 || tankState == 7) {
existingCart.clear()
}
// if there is no cart, spawn a new one (like if this is the quest start)
// if there is no cart, spawn a new one (like if player is just logging in)
} else {
val newCart = NPC(targetId, targetLocation)
newCart.init()
// if cart is inside water tank, clear it
if (tankState == 3 || tankState == 4 || tankState == 6 || tankState == 7) {
newCart.clear()
}
}
}
@ -181,20 +227,76 @@ class EW2Listeners : InteractionListener {
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
// 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))
/*
// updates the cog states (unused right now)
fun syncCogs(player: Player) {
// check an object actually exists here
if (currentObject != null) {
//println(currentObject.type)
}
*/
// 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
/*
// visualizes the steam press. right now all it does is spawn the hammer part. no anims or fancy stuff.
// if you just do a simple scenerybuilder.add it'll overwrite the track, so i've disabled it for now.
fun syncSteamPress(player: Player) {
SceneryBuilder.add(core.game.node.scenery.Scenery(steamPressStates[2], Location.create(1946, 5155, 2), 0))
}
*/
// syncs the water tank state. this is dependent on the valve states and the door state. also changes cart state (cooling bar)
fun syncTank(player: Player) {
val waterIn = getVarbit(player, EW2ValveWestVarbit) // 0 if valve closed, 1 if open
val waterOut = getVarbit(player, EW2ValveEastVarbit) // 0 if valve closed, 1 if open
val cart = getVarbit(player, EW2TankDoorStateVarbit) // whether the cart is in the tank or not
if(waterIn == 0 && waterOut == 0) { // both valves closed, nothing happens
return
} else if(waterIn == 0 && waterOut == 1) { // drain is open, remove all added scenery
SceneryBuilder.remove(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18660, location(1951, 5164, 2))) // full tank
SceneryBuilder.remove(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18661, location(1951, 5164, 2))) // full tank
playAudio(player, Sounds.EW2_WATER_RACK_3184) // drain?
return
} else if(waterIn == 1 && waterOut == 0) { // inlet is open, fill tank
SceneryBuilder.add(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18661, location(1951, 5164, 2))) // full tank
playAudio(player, Sounds.EW2_WATER_FLOW_3183) // fill?
if(cart == 3) { // if cart state is hot bar, transform to cool bar.
setVarbit(player, EW2TankDoorStateVarbit, 6, true)
setVarbit(player, EW2JigCartVarbit, 4, true)
syncTankDoor(player)
playAudio(player, Sounds.EW2_COOL_BAR_3168)
if(!getAttribute(player, attrWatered, false) && getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 6) {
setAttribute(player, attrWatered, true)
}
}
return
} else if(waterIn == 1 && waterOut == 1) { // inlet and drain are open, tank is damp
SceneryBuilder.add(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18660, location(1951, 5164, 2))) // damp tank
playAudio(player, Sounds.EW2_WATER_FLOW_3183) // fill?
return
}
}
// syncs the tank door state. this is dependent on the corkscrew lever and cart state
fun syncTankDoor(player: Player) {
val state = getVarbit(player, EW2TankDoorStateVarbit)
val doorLoc = Location.create(1953, 5162, 2)
val currentObject = getScenery(doorLoc)
val targetId = tankDoorStates[state]
// remove old scenery then add the new one
// todo right now this also deletes a piece of track that shares a tile with the door, but I don't really care.
if(currentObject != null && currentObject.id != targetId) {
SceneryBuilder.remove(core.game.node.scenery.Scenery(currentObject.id, doorLoc, 1))
SceneryBuilder.add(core.game.node.scenery.Scenery(targetId, doorLoc, 1))
}
}
// updates fan state. fun fact, the fan state varbit isn't saved even if you say to save it. gotta make sure it's set on login.
fun syncFan(player: Player) {
val fanMachine = getVarbit(player, EW2FanLeverVarbit)
if (fanMachine == 1) {
setVarbit(player, EW2FanStateVarbit, 1)
} else {
setVarbit(player, EW2FanStateVarbit, 0)
}
}
}
@ -247,6 +349,7 @@ class EW2Listeners : InteractionListener {
}
if(getVarbit(player, EW2MachineryVarbit) == 0)
setVarbit(player, EW2MachineryVarbit, 1, true)
// todo the wiki notes that you must actually walk the path for the varbit to flip. Here i just flip it as soon as you read the scroll.
return@on true
}
@ -255,10 +358,12 @@ class EW2Listeners : InteractionListener {
if(!inInventory(player, Items.KEY_9722)) {
sendItemDialogue(player, Items.KEY_9722, "You find a key hidden in the third pipe.")
addItemOrDrop(player, Items.KEY_9722)
} else {
sendDialogue(player, "You search the machinery but find nothing.")
}
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) == 3) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 4)
setVarbit(player, EW2StageVarbit, 4)
setVarbit(player, EW2StageVarbit, 4, true)
}
return@on true
}
@ -277,7 +382,7 @@ class EW2Listeners : InteractionListener {
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) == 4) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 5)
setVarbit(player, EW2StageVarbit, 5)
setVarbit(player, EW2StageVarbit, 5, true)
}
return@on true
}
@ -337,8 +442,10 @@ class EW2Listeners : InteractionListener {
on(Scenery.LEVER_18620, IntType.SCENERY, "pull") { player, _ ->
val currentPos = getVarbit(player, EW2CartLeverVarbit) // cart moving lever. 0 = start (south), 1 = west, 2 = north, 3 = east
val cranePos = getVarbit(player, EW2CranePosVarbit) // 2 if crane is down on north side
val doorPos = getVarbit(player, EW2DoorLeverVarbit) // 1 if door is open
val fanPos = getVarbit(player, EW2FanLeverVarbit) // 1 if the fan is on
val doorPos = getVarbit(player, EW2TankDoorStatusVarbit) // 1 if door is open
val tankState = getVarbit(player, EW2TankDoorStateVarbit)
val fanState = getVarbit(player, EW2FanLeverVarbit) // 1 if the fan is on
// find the cart
val trackCenter = Location.create(1953, 5155, 2)
@ -358,9 +465,8 @@ class EW2Listeners : InteractionListener {
sendMessage(player, "You cannot do that while the door is open.")
return@on true
}
// todo check the corkscrew because i think that'll shift the cart off the track
// door must be closed
if (currentPos == 3 && fanPos == 1) {
// fan must be off
if (currentPos == 3 && fanState == 1) {
sendMessage(player, "You cannot do that while the fan is on.")
return@on true
}
@ -368,6 +474,11 @@ class EW2Listeners : InteractionListener {
if (existingCart.walkingQueue.isMoving) {
return@on true
}
// cart must not be in the water tank
if (tankState == 3 || tankState == 4 || tankState == 6 || tankState == 7) {
sendMessage(player, "You cannot do that while the cart is inside the tank.")
return@on true
}
// set path
val path = when (currentPos) {
@ -396,11 +507,14 @@ class EW2Listeners : InteractionListener {
// 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)
//}
/*
existingCart.walkingQueue.reset()
for (step in path) {
existingCart.walkingQueue.addPath(step.x, step.y)
}
*/
teleport(existingCart, path[2])
playAudio(player, Sounds.EW2_CART_LOOP_3167)
}
return@on true
@ -418,11 +532,21 @@ class EW2Listeners : InteractionListener {
4915 -> {
sendMessage(player, "The bar is too hot to touch.")
}
4916 -> {
sendMessage(player, "The bar is too hot to touch.")
}
4917 -> {
sendMessage(player, "You should finish the process before taking the bar.")
}
4918 -> {
addItemOrDrop(player, Items.PRIMED_BAR_9727)
sendItemDialogue(player, Items.PRIMED_BAR_9727, "You take the primed bar.")
animate(player, 537)
setVarbit(player, EW2JigCartVarbit, 0, true)
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 6) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 7)
setVarbit(player, EW2StageVarbit, 7, true)
}
}
}
syncCart(player)
@ -441,8 +565,12 @@ class EW2Listeners : InteractionListener {
setVarbit(player, EW2JigCartVarbit, 1, true)
animate(player, 537)
playAudio(player, Sounds.EW2_PLACE_BAR_3177)
syncCart(player)
removeItem(player, used)
if(!getAttribute(player, attrJigged, false) && getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 6) {
setAttribute(player, attrJigged, true)
}
return@onUseWith true
}
@ -465,7 +593,7 @@ class EW2Listeners : InteractionListener {
}
// fix crane
onUseWith(IntType.SCENERY, Items.CRANE_CLAW_9720, Scenery.OLD_CRANE_18636) { player, used, with ->
onUseWith(IntType.SCENERY, Items.CRANE_CLAW_9720, Scenery.OLD_CRANE_18636) { player, used, _ ->
// check if already repaired
if(getVarbit(player, EW2CraneStateVarbit) != 0) {
sendMessage(player, "The crane is already repaired.")
@ -558,36 +686,44 @@ 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.")
playAudio(player, Sounds.EW2_PRESS_BAR_3180)
animate(player, Animations.HUMAN_PULL_LEVER_4909)
}
1 -> { // ele bar
setVarbit(player, EW2JigCartVarbit, 4)
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
// also note during one of the source videos it's authentic that the press state shows a purple ele bar for a moment. weird.
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.")
playAudio(player, Sounds.EW2_PRESS_BAR_3180)
animate(player, Animations.HUMAN_PULL_LEVER_4909)
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.")
playAudio(player, Sounds.EW2_PRESS_BAR_3180)
animate(player, Animations.HUMAN_PULL_LEVER_4909)
syncCart(player)
if(!getAttribute(player, attrFlattened, false) && getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 6) {
setAttribute(player, attrFlattened, true)
}
}
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.")
playAudio(player, Sounds.EW2_PRESS_BAR_3180)
animate(player, Animations.HUMAN_PULL_LEVER_4909)
}
}
} 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 {
// The junction box is not configured correctly
sendDialogue(player, "You pull the lever but nothing happens.")
animate(player, Animations.HUMAN_PULL_LEVER_4909)
}
return@on true
@ -614,50 +750,179 @@ class EW2Listeners : InteractionListener {
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)
playAudio(player, Sounds.EW2_PLACE_PIPE_3433)
setVarbit(player, EW2PipeVarbit, 1, true)
removeItem(player, item)
return@onUseWith true
}
// 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 doorOpen = getVarbit(player, EW2TankDoorStatusVarbit)
val tankState = getVarbit(player, EW2TankDoorStateVarbit)
val tankScen = getScenery(location(1951, 5164, 2))
val currentState = getVarbit(player, EW2TankDoorVarbit)
animate(player, Animations.HUMAN_PULL_LEVER_4909)
// if tank has water, don't open.
if(tankScen != null) {
sendDialogue(player, "You pull the lever but nothing happens. Maybe the tank needs to be empty first.")
return@on true
}
// check the rack is not out
if(tankState == 2 || tankState == 5 || tankState == 8) {
sendDialogue(player, "You pull the lever but nothing happens. Maybe the rack needs retracting first.")
return@on true
}
// update door status open/close
if(doorOpen == 0) {
setVarbit(player, EW2TankDoorStatusVarbit, 1, true)
} else {
setVarbit(player, EW2TankDoorStatusVarbit, 0, true)
}
// update door state
val nextTankState = when (tankState) {
1 -> 0 // Opened -> Closed
0 -> 1 // Closed -> Opened
4 -> 3 // Opened/Hot -> Closed/Hot
3 -> 4 // Closed/Hot -> Opened/Hot
7 -> 6 // Opened/Cooled -> Closed/Cooled
6 -> 7 // Closed/Cooled -> Opened/Cooled
// six seeeven hehehehe
else -> tankState
}
setVarbit(player, EW2TankDoorStateVarbit, nextTankState)
syncTankDoor(player)
return@on true
}
// todo corkscrew lever
// corkscrew lever that grabs and ungrabs the cart as long as the door is open
on(Scenery.CORKSCREW_LEVER_18649, IntType.SCENERY, "turn") { player, _ ->
val cartPos = getVarbit(player, EW2CartLeverVarbit)
val doorStatus = getVarbit(player, EW2TankDoorStatusVarbit) // 0 = closed, 1 = open
val cartState = getVarbit(player, EW2JigCartVarbit)
val tankState = getVarbit(player, EW2TankDoorStateVarbit)
// cart must be at north station
if (cartPos != 2) {
sendMessage(player, "The jig cart is not in position to be grabbed.")
return@on true
}
// door must be open (this also requires tank to be empty)
if (doorStatus == 0) {
sendMessage(player, "The tank door must be open to use the corkscrew.")
return@on true
}
playAudio(player, Sounds.EW2_SCREW_TURN_3182)
animate(player, Animations.HUMAN_TURN_CORKSCREW_LEVER_4905)
// either pull cart in or push it out. transfer between all the door open states
runTask(player, 1) {
when (tankState) {
1 -> { // 1 door opened, grabber inside
setVarbit(player, EW2TankDoorStateVarbit, 2) // 2 door opened, grabber out
// no cart update
}
2 -> { // 2 door opened, grabber out
// only grab the hot bar
if(cartState == 3) setVarbit(player, EW2TankDoorStateVarbit, 4) // 4 door opened, hot bar inside
// remove hot bar cart
}
4 -> { // 4 door opened, hot bar inside
setVarbit(player, EW2TankDoorStateVarbit, 5) // 5 door opened, hot bar out
}
5 -> { // 5 door opened, hot bar out
setVarbit(player, EW2TankDoorStateVarbit, 1) // 1 door opened, grabber inside
// add hot bar cart
}
7 -> { // 7 door opened, cooled bar inside
setVarbit(player, EW2TankDoorStateVarbit, 8) // 8 door opened, cooled bar out
}
8 -> { // 8 door opened, cooled bar out
setVarbit(player, EW2TankDoorStateVarbit, 1) // 1 door opened, grabber inside
// add cool bar cart
}
}
syncTankDoor(player)
syncCart(player)
}
return@on true
}
// todo west water valve
// west water valve fills the chamber if the door is closed "you open the valve" "you close the valve" make sure it's closed or the chamber will fill up again
// changes cart state into flattened mind bar
// west water valve operates the water inflow
on(Scenery.WATER_VALVE_18646, IntType.SCENERY, "turn") { player, _ ->
val valveState = getVarbit(player, EW2ValveWestVarbit) // water valve west. 0 = closed, 1 = open
val door = getVarbit(player, EW2TankDoorStatusVarbit) // 0 if door closed, 1 if open
if(door == 1) {
sendMessage(player, "The valve won't turn, maybe the door needs to be closed first.")
return@on true
}
player.locks.lockInteractions(4)
animate(player, 4861)
// if closed, open the valve
if(valveState == 0){
setVarbit(player, EW2ValveWestVarbit, 1, true)
runTask(player, 3) {
syncTank(player)
sendDialogue(player, "you open the valve")
playAudio(player, Sounds.EW2_WATER_VALVE_3185)
}
// if open, close the valve
} else {
setVarbit(player, EW2ValveWestVarbit, 0, true)
runTask(player, 3) {
syncTank(player)
sendDialogue(player, "you close the valve")
playAudio(player, Sounds.EW2_WATER_VALVE_3185)
}
}
return@on true
}
// todo east water valve
// east water valve drains the tank if it is full "you open the valve"
// east water valve operates the drain
on(Scenery.WATER_VALVE_18647, IntType.SCENERY, "turn") { player, _ ->
val valveState = getVarbit(player, EW2ValveEastVarbit) // water valve west. 0 = closed, 1 = open
val door = getVarbit(player, EW2TankDoorStatusVarbit) // 0 if door closed, 1 if open
if(door == 1) {
sendMessage(player, "The valve won't turn, maybe the door needs to be closed first.")
return@on true
}
player.locks.lockInteractions(4)
animate(player, 4861)
// if closed, open the valve
if(valveState == 0){
setVarbit(player, EW2ValveEastVarbit, 1, true)
runTask(player, 3) {
syncTank(player)
sendDialogue(player, "you open the valve")
playAudio(player, Sounds.EW2_WATER_VALVE_3185)
}
// if open, close the valve
} else {
setVarbit(player, EW2ValveEastVarbit, 0, true)
runTask(player, 3) {
syncTank(player)
sendDialogue(player, "you close the valve")
playAudio(player, Sounds.EW2_WATER_VALVE_3185)
}
}
return@on true
}
/**
* Scenery.WATER_TANK_18660
* Scenery.WATER_TANK_18661
*/
/**------------------------
* SECTION 4 - FAN
** ------------------------
@ -734,18 +999,21 @@ class EW2Listeners : InteractionListener {
setVarbit(player, EW2CogVarbit1, 1, true)
sendItemDialogue(player, item, "You put the small cog onto the shaft.")
animate(player, 537)
playAudio(player, Sounds.EW2_PLACE_COG_3178)
removeItem(player, item)
}
Items.MEDIUM_COG_9725 -> {
setVarbit(player, EW2CogVarbit1, 2, true)
sendItemDialogue(player, item, "You put the medium cog onto the shaft.")
animate(player, 537)
playAudio(player, Sounds.EW2_PLACE_COG_3178)
removeItem(player, item)
}
Items.LARGE_COG_9724 -> {
setVarbit(player, EW2CogVarbit1, 3, true)
sendItemDialogue(player, item, "You put the large cog onto the shaft.")
animate(player, 537)
playAudio(player, Sounds.EW2_PLACE_COG_3178)
removeItem(player, item)
}
}
@ -822,37 +1090,42 @@ 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)
val p1 = getVarbit(player, EW2CogVarbit1)
val p2 = getVarbit(player, EW2CogVarbit2)
val p3 = getVarbit(player, EW2CogVarbit3)
val allCogs = getVarbit(player, EW2AllCogsVarbit)
val lever = getVarbit(player, EW2FanLeverVarbit)
val cartpos = getVarbit(player, EW2CartLeverVarbit) // needs to be 3 to be at this station
val cartstate = getVarbit(player, EW2JigCartVarbit) // needs to be state 4: smashed cooled
// check if the cogs are right. pin 1 (2655) should have the small cog. pin 2 (2656) should have the med cog. pin 3 (2656) should have the large cog.
if (p1 == 1 && p2 == 2 && p3 == 3) {
if (allCogs == 57) {
if(lever == 0) {
// turn on
sendDialogue(player, "The machine rumbles and the fan starts to blow.") // Is authentically two messages of "The machine starts rumbling." and "The fan starts to blow.", but I am simplifying this check.
playAudio(player, Sounds.EW2_MACHINE_RUMBLE_3175)
playAudio(player, Sounds.EW2_FANBLADE_3174)
setVarbit(player, EW2FanLeverVarbit, 1, true)
syncFan(player)
// check cart and cool if necessary. otherwise nothing should happen.
if (cartpos == 3 && cartstate == 4) {
setVarbit(player, EW2JigCartVarbit, 5, true)
syncCart(player)
if(!getAttribute(player, attrWinded, false) && getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 6) {
setAttribute(player, attrWinded, true)
}
}
} else {
// turn off
sendDialogue(player, "The machine grinds to a standstill.")
setVarbit(player, EW2FanLeverVarbit, 0, true)
setVarbit(player, EW2FanStateVarbit, 0, true)
syncFan(player)
}
// cogs are not correct
} else {
sendDialogue(player, "The machine starts up, but the fan does not blow.")
playAudio(player, Sounds.EW2_MACHINE_RUMBLE_3175)
}
return@on true
}
@ -862,47 +1135,127 @@ 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)
if(removeItem(player, item)) {
setVarbit(player, EW2ExtractorGun, 1, true)
animate(player, 537)
sendDialogue(player, "You place the primed bar under the device.")
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 8) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 9)
setVarbit(player, EW2StageVarbit, 9, true)
}
}
return@onUseWith true
}
// take primed bar
on(intArrayOf(Scenery.EXTRACTOR_GUN_18694), IntType.SCENERY, "take-from") { player, _ ->
addItemOrDrop(player, Items.PRIMED_BAR_9727)
animate(player, 537)
setVarbit(player, EW2ExtractorGun, 0, true)
sendDialogue(player, "You take the primed bar.")
return@on true
}
// take mind bar
on(intArrayOf(Scenery.EXTRACTOR_GUN_18695), IntType.SCENERY, "take-from") { player, _ ->
addItemOrDrop(player, Items.ELEMENTAL_MIND_BAR_9728)
animate(player, 537)
setVarbit(player, EW2ExtractorGun, 0, true)
sendDialogue(player, "You take the elemental mind bar.")
return@on true
}
// sit in chair
// todo the extractor gun needs a graphic
// todo per one of the sources the camera angle changes for this.
on(intArrayOf(Scenery.EXTRACTOR_HAT_18690), IntType.SCENERY, "operate") { player, _ ->
// if bar is in place
// check magic level
if(getDynLevel(player, Skills.MAGIC) < 20) {
sendMessage(player, "You must have a Magic level of 20 and above to use the device.")
return@on true
}
// if bar is in place, charge it and drain magic
if(getVarbit(player, EW2ExtractorGun) == 1) {
setVarbit(player, EW2ExtractorGun, 2, true)
runTask(player) {
forceMove(
player,
Location.create(1961, 5150, 0),
Location.create(1962, 5150, 0),
0,
0
)
visualize(player, Animations.HUMAN_USE_EXTRACTOR_HAT_CHAIR_4884, goodHat)
playAudio(player, Sounds.EW2_EXTRACTOR_OPERATION_3166)
sendGraphics(809, Location.create(1962, 5148, 0))
setVarbit(player, EW2ExtractorGun, 2, true)
adjustLevel(player, Skills.MAGIC, -20)
sendMessage(player, "You feel magically weakened.")
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 9) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 10)
setVarbit(player, EW2StageVarbit, 10, true)
}
}
forceMove(
player,
Location.create(1962, 5150, 0),
Location.create(1961, 5150, 0),
200,
2
)
// if bar is not in place (or if it's already a primed bar), hit player
} else {
runTask(player) { // 50 client cycles = 1 second
forceMove(
player,
Location.create(1961, 5150, 0),
Location.create(1962, 5150, 0),
0,
0
)
visualize(player, Animations.HUMAN_IMPROPERLY_USE_EXTRACTOR_HAT_CHAIR_4885, badHat)
playAudio(player, Sounds.EW2_EXTRACTOR_ZAP_3173)
impact(player, 4)
sendMessage(player, "The extractor hat shocks you!.")
}
forceMove(
player,
Location.create(1962, 5150, 0),
Location.create(1961, 5150, 0),
350,
2
)
}
return@on true
}
/**
* EXTRACTOR_GUN_18693
* EXTRACTOR_GUN_18694
* EXTRACTOR_GUN_18695
* EXTRACTOR_GUN_18696
* EXTRACTOR_HAT_18690
* EXTRACTOR_HAT_18691
* EXTRACTOR_HAT_TOP_18692
/**------------------------
* EXTRA
** ------------------------
*/
// equip graphics for helmets and shields. the shields should not technically show until the graphic finishes, but I can't find an easy way to do that.
onEquip(Items.MIND_HELMET_9733) { player, _ ->
sendGraphics(mHelmEquip, player.location)
return@onEquip true
}
onEquip(Items.MIND_SHIELD_9731) { player, _ ->
sendGraphics(Graphics(mShieldEquip,95), player.location)
return@onEquip true
}
onEquip(Items.ELEMENTAL_HELMET_9729) { player, _ ->
sendGraphics(eHelmEquip, player.location)
return@onEquip true
}
onEquip(Items.ELEMENTAL_SHIELD_2890) { player, _ ->
sendGraphics(Graphics(eShieldEquip,95), player.location)
return@onEquip true
}
}
// fixes to get right interact locations
@ -915,7 +1268,7 @@ class EW2Listeners : InteractionListener {
return@setDest Location.create(1954, 5148, 2)
}
setDest(IntType.NPC, intArrayOf(NPCs.JIG_CART_4914, NPCs.JIG_CART_4915), "take-from") { _, _ ->
setDest(IntType.NPC, intArrayOf(NPCs.JIG_CART_4914, NPCs.JIG_CART_4915, NPCs.JIG_CART_4916, NPCs.JIG_CART_4917, NPCs.JIG_CART_4918), "take-from") { _, _ ->
return@setDest Location.create(1954, 5148, 2)
}

View file

@ -1,14 +1,23 @@
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 content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.syncFan
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.syncTank
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.syncTankDoor
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2StageVarbit
import core.api.*
import core.game.node.entity.Entity
import core.game.node.entity.player.Player
import core.game.node.scenery.SceneryBuilder
import core.game.world.map.Location
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,
@ -30,8 +39,19 @@ 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) {
if(getQuestStage(e, Quests.ELEMENTAL_WORKSHOP_II) <= 5) {
setQuestStage(e, Quests.ELEMENTAL_WORKSHOP_II, 6)
setVarbit(e, EW2StageVarbit, 6, true)
}
SceneryBuilder.add(core.game.node.scenery.Scenery(Scenery.DOOR_18651, Location.create(1953, 5162, 2), 1))
syncCrane(e)
syncCart(e)
//syncSteamPress(e)
syncTank(e)
syncTankDoor(e)
syncFan(e)
}
return super.enter(e)
}

View file

@ -6,13 +6,15 @@ 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.plugin.Initializable
import org.rs09.consts.Graphics
import org.rs09.consts.Items
/**
* ELEMENTAL WORKSHOP II QUEST
*
* Requirements: 20 Magic, 30 Smithing, completion of Elemental Workshop I
* Primary Source: https://www.youtube.com/watch?v=YKSWisRgGZk
* Primary Sources: https://www.youtube.com/watch?v=YKSWisRgGZk, https://www.youtube.com/watch?v=hv2rCofydXo
* Wiki: https://runescape.wiki/w/Elemental_Workshop_II?oldid=849620
*/
@Initializable
@ -37,18 +39,32 @@ 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 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 EW2TankDoorStateVarbit = 2653 // tank door holding state, controlled by corkscrew lever. 0 = closed, 1 = door opened grabber inside, 2 = door opened grabber out, 3 = door closed hot bar inside, 4 = door opened hot bar inside, 5 = door opened hot bar out, 6 = door closed cooled bar inside, 7 = door opened cooled bar inside, 8 = door closed cooled bar out
const val EW2TankDoorStatusVarbit = 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
//const val EW2AllCogsVarbit = 2658 // overlaps the cog varbits. could be used to reset all cogs at once.
const val EW2AllCogsVarbit = 2658 // overlaps the cog varbits.
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 EW2FanStateVarbit = 2660 // fan blades. 0 = off, 1 = forward, 2 = reverse
//const val EW2FanStationVarbit = 2661 // overlaps cogs, fan switch, and fan blades varbits
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.
//const val EW2mystery1 = 2663 // no idea what this one does. it's in the place of the hammer lever?
//const val EW2mystery2 = 2664 // no idea what this one does. values from 1 to 7 back at the dig site library where you find the book.
const val attrJigged = "/save:quest:ew2-jigged" //true after you put a bar on the jig cart
const val attrDipped = "/save:quest:ew2-dipped" //true after dip the bar in the lava
const val attrFlattened = "/save:quest:ew2-flattened" //true after you flatten the hot bar
const val attrWatered = "/save:quest:ew2-watered" //true after you cool the bar in the tank
const val attrWinded = "/save:quest:ew2-winded" //true after you cool the bar in the wind tunnel
// defining these graphics here because the graphics consts conflicts with the graphics object in the listeners
const val goodHat = Graphics.EXTRACTOR_HAT_CHAIR_807
const val badHat = Graphics.IMPROPERLY_EXTRACTOR_HAT_CHAIR_808
const val mShieldEquip = 809
const val mHelmEquip = 810
const val eShieldEquip = 244
const val eHelmEquip = 811
}
/**
@ -61,18 +77,21 @@ class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2Sta
* 2 2 read the beaten book
* 3 3 read the beaten book's scroll
* 4 4 found key
* 5 5 went down center hatch
* 6 6 read the crane schematic
* 7 7 read the lever schematic?
* 5 5 went down center hatch. need to fix equipment
* 6 6 inside the workshop. processing bar
* 7 7 take primed bar
* 8 8 went through the mind door
* 9 9 primed a mind bar
* 10 10 primed a mind bar?
* 9 9 placed a primed bar
* 10 10 sat in the extractor
* 11 100 smithed a mind helmet, quest complete
*/
override fun drawJournal(player: Player, stage: Int) {
// Quest journal source: https://www.youtube.com/watch?v=hv2rCofydXo
super.drawJournal(player, stage)
var line = 12
var stage = getStage(player)
val stage = getStage(player)
// unstarted
if (stage == 0) {
@ -105,57 +124,116 @@ class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2Sta
// stage 3, read the scroll from the beaten book
if (stage >= 3) {
line(player, "The note found with the book has a strange code written on it.", line++, stage > 3)
line(player, "The note found with the book has a !!strange code?? written on it.", line++, stage > 3)
// in-progress stage text
//if(stage == 3) line(player, "", line++)
if(stage == 3) line(player, "I wonder what it means.", line++)
line++
}
// stage 4, finding the key
if (stage >= 4) {
line(player, "By following the code on the !!note?? I was able to !!find a key??.", line++, stage > 4)
// in-progress stage text
if(stage == 4) line(player, "Now I just have to find what it opens.", line++)
line++
}
// stage 5, going down the center hatch
// stage 5, going down the center hatch and getting the machines fixed
if (stage >= 5) {
line(player, "The !!key?? I've found opens the !!large hatch?? in the !!workshop??; there are !!4 machines?? on this level to fix:", line++, stage > 5)
line(player, "The crane - now the claw has been replaced the crane looks like it's in good working order.", line++, stage > 5)
line(player, "The pipes - the pipes have now been fitted and it should work as long as it's powered.", line++, stage > 5)
line(player, "The tank - this should work fine now I have replaced the pipe.", line++, stage > 5)
line(player, "A wind tunnel - I have fitted all the cogs on to the pins. The win tunnel should now work as long as it's powered.", line++, stage > 5)
line(player, "A wind tunnel - I have fitted all the cogs on to the pins. The win tunnel should now work as long as it's powered.", line++, stage > 5)
line(player, "Climbing down through the hatch I found a new area in the", line++, (getVarbit(player, EW2CraneStateVarbit) != 0 && JunctionBoxInterface.isSolutionCorrect(player) && getVarbit(player, EW2PipeVarbit) != 0 && getVarbit(player, EW2AllCogsVarbit) == 57))
line(player, "workshop; there are 4 machines on this level to !!fix??:", line++, (getVarbit(player, EW2CraneStateVarbit) != 0 && JunctionBoxInterface.isSolutionCorrect(player) && getVarbit(player, EW2PipeVarbit) != 0 && getVarbit(player, EW2AllCogsVarbit) == 57))
line(player, "I have found a track-mounted jig on which I was able to clamp an elemental bar.", line++, stage > 5)
line(player, "I used the press to flatten the hot elemental bar.", line++, stage > 5)
line(player, "The water tank was used to cool the elemental bar down.", line++, stage > 5)
line(player, "The wind tunnel proved a great way to dry off the wet bar.", line++, stage > 5)
line(player, "I have primed a bar of elemental ore.", line++, stage > 5)
line(player, "I placed the primed bar on the device found in the room with the mind symbols on the door.", line++, stage > 5)
line(player, "Operating the device charged the primed bar with some of my own mind power.", line++, stage > 5)
line(player, "I have made an elemental mind bar, now I just have to make one of the helms from it.", line++, stage > 5)
line(player, "Creating the elemental mind helm was easy with the book for instruction.", line++, stage > 5)
line(player, "", line++, stage > 5)
if(getVarbit(player, EW2CraneStateVarbit) == 0)line(player, "The crane - this looks in a state of disrepair.", line++)
// "The crane - this looks in a state of disrepair, but I have \n created a replacement claw for it."
if(getVarbit(player, EW2CraneStateVarbit) != 0)line(player, "The crane - now the claw has been replaced the crane", line++, true)
if(getVarbit(player, EW2CraneStateVarbit) != 0)line(player, "looks like it's in good working order.", line++, true)
line++
if(!JunctionBoxInterface.isSolutionCorrect(player))line(player, "The press - I should see if this needs fixing.", line++)
// "The press - I should try to fit all the pipes in the right order."
if(JunctionBoxInterface.isSolutionCorrect(player))line(player, "The press - the pipes have now been fitted and ", line++, true)
if(JunctionBoxInterface.isSolutionCorrect(player))line(player, "it should work as long as it's powered.", line++, true)
line++
if(getVarbit(player, EW2PipeVarbit) == 0)line(player, "The tank - I'll need to fix this before I can use it.", line++)
if(getVarbit(player, EW2PipeVarbit) != 0)line(player, "The tank - this should work fine now I have replaced the pipe.", line++, true)
line++
if(getVarbit(player, EW2AllCogsVarbit) != 57)line(player, "A wind tunnel - it looks like a few bits are missing from it.", line++)
if(getVarbit(player, EW2AllCogsVarbit) == 57)line(player, "A wind tunnel - I have fitted all the cogs on to the pins.", line++, true)
if(getVarbit(player, EW2AllCogsVarbit) == 57)line(player, "The wind tunnel should now work as long as it's powered.", line++, true)
line++
}
// stage 6
if (stage >= 6) {
line(player, "", line++, stage > 6)
// stage 6, inside the workshop. put bar on cart
if (stage >= 6 && getAttribute(player, attrJigged, false)) {
line(player, "I have found a track-mounted jig", line++, stage > 6)
line(player, "on which I was able to clamp an elemental bar.", line++, stage > 6)
line++
}
// stage 7
// stage 6, inside the workshop. dipped
if (stage >= 6 && getAttribute(player, attrDipped, false)) {
line(player, "I was able to operate the crane and dip the elemental bar", line++, stage > 6)
line(player, "into the lava. The bar is now very hot.", line++, stage > 6)
line++
}
// stage 6, inside the workshop. flattened bar
if (stage >= 6 && getAttribute(player, attrFlattened, false)) {
line(player, "I used the press to flatten the hot elemental bar.", line++, stage > 6)
line++
}
// stage 6, inside the workshop. water tanked bar
if (stage >= 6 && getAttribute(player, attrWatered, false)) {
line(player, "The water tank was used to cool the elemental bar down.", line++, stage > 6)
line++
}
// stage 6, inside the workshop. wind tunneled bar
if (stage >= 6 && getAttribute(player, attrWinded, false)) {
line(player, "The wind tunnel proved a great way to dry off the wet bar.", line++, stage > 6)
line++
}
// stage 7, retrieve primed bar
if (stage >= 7) {
line(player, "", line++, stage > 7)
line(player, "I have primed a bar of elemental ore, I wonder what to do", line++, stage > 7)
line(player, "with it.", line++, stage > 7)
line++
}
// stage 8
// stage 8, went through the mind door
/*
if (stage >= 8) {
line(player, "", line++, stage > 8)
line++
}
*/
// stage 9, placed a primed bar
if (stage >= 9) {
line(player, "I placed the primed bar on the device", line++, stage > 9)
line(player, "found in the room with the mind symbols on the door.", line++, stage > 9)
line++
}
// stage 10, sat in the extractor
if (stage >= 10) {
line(player, "Operating the device charged the", line++, stage > 10)
line(player, "primed bar with some of my own mind power.", line++, stage > 10)
line++
line(player, "I have made an elemental mind bar,", line++, stage > 10)
line(player, "now I just have to make one of the helms from it.", line++, stage > 10)
line++
}
// stage 11, smithed a mind helmet, quest complete
if (stage >= 11) {
line(player, "Creating the elemental mind helm", line++, stage > 11)
line(player, "was easy with the book for instruction.", line++, stage > 11)
}
}
// use ::setqueststage 53 0 to reset quest.
@ -163,6 +241,11 @@ class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2Sta
// these varps wipes all the varbits
setVarp(player, EW2Varp1, 0, true)
setVarp(player, EW2Varp2, 0, true)
removeAttribute(player, attrJigged)
removeAttribute(player, attrDipped)
removeAttribute(player, attrFlattened)
removeAttribute(player, attrWatered)
removeAttribute(player, attrWinded)
player.getQuestRepository().syncronizeTab(player)
super.reset(player)
}
@ -171,7 +254,7 @@ class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2Sta
var ln = 10
super.finish(player)
player.packetDispatch.sendString("You have completed the Elemental Workshop II quest!", 277, 4)
player.packetDispatch.sendItemZoomOnInterface(Items.ELEMENTAL_HELMET_9729, 230, 277, 5)
player.packetDispatch.sendItemZoomOnInterface(Items.MIND_HELMET_9733, 230, 277, 5)
drawReward(player, "1 Quest Point", ln++)
drawReward(player, "7,500 Smithing XP,", ln++)
@ -183,7 +266,11 @@ class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2Sta
rewardXP(player, Skills.SMITHING, 7500.0)
rewardXP(player, Skills.CRAFTING, 7500.0)
// remove attributes
removeAttribute(player, attrJigged)
removeAttribute(player, attrDipped)
removeAttribute(player, attrFlattened)
removeAttribute(player, attrWatered)
removeAttribute(player, attrWinded)
}
override fun newInstance(`object`: Any?): Quest {

View file

@ -7,6 +7,7 @@ import core.api.*
import core.game.interaction.InterfaceListener
import core.game.node.entity.player.Player
import org.rs09.consts.Components
import org.rs09.consts.Sounds
/**
* Junction box in Elemental Workshop II
@ -149,6 +150,7 @@ class JunctionBoxInterface : InterfaceListener {
// place the pipe
val pipeChild = pipes[pipeIndex]
setComponentVisibility(player, junctionBox, pipeChild, false)
playAudio(player, Sounds.EW2_PLACE_PIPE_3179)
// pipe status is saved in these varbits and recalled on open. they are linked to main quest progression status
val saved = when {
@ -217,6 +219,7 @@ class JunctionBoxInterface : InterfaceListener {
// Increment pipes left
val left = getVarbit(player, pipesLeftVarbit)
setVarbit(player, pipesLeftVarbit, left + 1)
playAudio(player, Sounds.EW2_REMOVE_PIPE_3181)
return true
}
}