these animations are breaking my mind

This commit is contained in:
aidan 2026-07-09 14:14:40 -05:00
parent ce85d62e39
commit e2baea400d
4 changed files with 375 additions and 99 deletions

View file

@ -26,7 +26,6 @@ import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.attrWatered
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.attrWinded
import core.api.*
import core.game.activity.ActivityPlugin
import core.game.interaction.IntType
import core.game.interaction.InteractionListener
import core.game.interaction.QueueStrength
@ -34,14 +33,14 @@ import core.game.node.entity.npc.NPC
import core.game.node.entity.player.Player
import core.game.node.entity.skill.Skills
import core.game.world.map.Location
import core.game.world.update.flag.context.Animation
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
// Sounds I still haven't used but should be part of quest somewhere
// Sounds.EW2_MACHINE_LOOP_3150
// Sounds.EW2_AMBIENT_LOOP_3149
/**
* Quest structure and testing notes:
@ -71,22 +70,46 @@ class EW2Listeners : InteractionListener {
companion object {
// graphics
const val goodHatGfx = Graphics.EXTRACTOR_HAT_CHAIR_807
const val badHatGfx = Graphics.IMPROPERLY_EXTRACTOR_HAT_CHAIR_808
const val EXTRACTOR_GOOD_GFX = Graphics.EXTRACTOR_HAT_CHAIR_807
const val EXTRACTOR_BAD_GFX = Graphics.IMPROPERLY_EXTRACTOR_HAT_CHAIR_808
// animations
const val goodHatAnim = Animations.HUMAN_USE_EXTRACTOR_HAT_CHAIR_4884
const val badHatAnim = Animations.HUMAN_IMPROPERLY_USE_EXTRACTOR_HAT_CHAIR_4885
const val CRANE_LOWER = 4887
const val CRANE_RAISE = 4888
const val CRANE_PIVOT_TO_LAVA = 4889
const val CRANE_PIVOT_TO_CART = 4890
const val DOOR_OPEN = 4871 // 4875 is another open
const val DOOR_CLOSE = 4872 // 4876 is another open
const val DOOR_EXTEND = 4873 // 4877 is another extend
const val DOOR_RETRACT = 4874 // 4878 is another retract
// 4879
// 4880
// 4881
// 4882
// 4883
const val EXTRACTOR_GOOD = Animations.HUMAN_USE_EXTRACTOR_HAT_CHAIR_4884
const val EXTRACTOR_BAD = Animations.HUMAN_IMPROPERLY_USE_EXTRACTOR_HAT_CHAIR_4885
// 4886
const val CRANE_LOWER_CART = 4887
const val CRANE_RAISE_CART = 4888
const val CRANE_LOWER_LAVA = 4889
const val CRANE_RAISE_LAVA = 4890
// 4891 (another pivot anim, unused)
const val CRANE_PIVOT = 4892
// 4893
// 4894
// 4895
const val COG_REV = 4896
// 4897
const val FAN_SPIN = 4898
// 4899
// 4900
// 4901
const val TANK_FILL = 4902
const val TANK_DRAIN = 4903
const val COG_FWD = 4906
/**
* This companion object stores helper functions to save and recall workshop state.
* All the machinery states are stored in varbits and are updated in various listeners,
* then synced in the various sync() functions. The whole workshop is synced using the
* EW2Zone enter trigger, so when the player comes back, the workshop is where they left it.
* EW2Session start trigger, so when the player comes back, the workshop is where they left it.
*/
// various states the crane can be in.
@ -157,31 +180,79 @@ class EW2Listeners : InteractionListener {
// position the crane based on varbit states
fun syncCrane(player: Player) {
val mat = getVarbit(player, EW2CraneStateVarbit)
val pos = getVarbit(player, EW2CranePosVarbit)
val index = (mat * 4) + pos
val newId = craneStates[index]
val pos = getVarbit(player, EW2CranePosVarbit) // 0: South Down, 1: South Up, 2: North Down, 3: North Up
val targetIndex = (mat * 4) + pos
val newId = craneStates[targetIndex]
val craneLoc = toInstance(player, Location.create(1952, 5143, 2))
val currentObject = getScenery(craneLoc) ?: return
if (!craneStates.contains(currentObject.id)) return
if (currentObject.id == newId) return
// get the crane's current position
val currentIndex = craneStates.indexOf(currentObject.id)
val currentPos = if (currentIndex != -1) currentIndex % 4 else pos
// select the anim and sound
var animId = -1
var soundId = -1
if (currentPos != pos) {
when {
// lowering into lava
currentPos == 1 && pos == 0 -> {
animId = CRANE_LOWER_LAVA
soundId = Sounds.EW2_CRANE_LOWER_3169
}
// raising from lava
currentPos == 0 && pos == 1 -> {
animId = CRANE_RAISE_LAVA
soundId = Sounds.EW2_CRANE_LOWER_3169 // I can't find raise sound
}
// lowering to cart
currentPos == 3 && pos == 2 -> {
animId = CRANE_LOWER_CART
soundId = Sounds.EW2_CRANE_LOWER_3169
}
// raising from cart
currentPos == 2 && pos == 3 -> {
animId = CRANE_RAISE_CART
soundId = Sounds.EW2_CRANE_LOWER_3169
}
// pivot to cart
currentPos == 1 && pos == 3 -> {
animId = CRANE_PIVOT
soundId = Sounds.EW2_CRANE_TURN_3170
}
// pivot to lava
currentPos == 3 && pos == 1 -> {
animId = CRANE_PIVOT
soundId = Sounds.EW2_CRANE_TURN_3170
}
}
}
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
when (stage) {
// animate the scenery
0 -> {
animateScenery(player, currentObject, 4890) // replace with confirmed anim ID
return@queueScript delayScript(player, 4) // adjust to match anim duration
if (animId != -1) {
val anim = Animation(animId)
animateScenery(player, currentObject, animId)
playAudio(player, soundId)
return@queueScript delayScript(player, anim.duration)
} else return@queueScript delayScript(player, 1)
}
// update the scenery
1 -> {
replaceScenery(currentObject, newId, -1)
playAudio(player, Sounds.EW2_CRANE_TURN_3170)
syncCart(player)
// advance quest stage
if (newId == Scenery.OLD_CRANE_18634) {
if (!getAttribute(player, attrDipped, false) && getQuestStage(
player,
Quests.ELEMENTAL_WORKSHOP_II
) <= 6
) {
if (!getAttribute(player, attrDipped, false) &&
getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 6) {
setAttribute(player, attrDipped, true)
}
}
@ -191,6 +262,7 @@ class EW2Listeners : InteractionListener {
else -> return@queueScript stopExecuting(player)
}
}
syncCart(player)
}
// update the jig cart based on varbit status
@ -211,7 +283,7 @@ class EW2Listeners : InteractionListener {
}
// 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)
teleport(existingCart, targetLocation)
}
// if cart is inside water tank, clear it
if (tankState == 3 || tankState == 4 || tankState == 6 || tankState == 7) {
@ -237,12 +309,24 @@ 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
/*
// updates the cog states (unused right now, could maybe set the anims here)
// spins the cogs
fun syncCogs(player: Player) {
val lever = getVarbit(player, EW2FanLeverVarbit)
val cogs1 = getScenery(toInstance(player,Location.create(1959, 5157, 2)))
val cogs2 = getScenery(toInstance(player,Location.create(1959, 5156, 2)))
if (cogs1 != null && cogs2 != null) {
if (lever == 1) {
// spin cogs
animateScenery(cogs1, COG_FWD)
animateScenery(cogs2, COG_FWD)
} else {
// stop cogs
animateScenery(cogs1, -1)
animateScenery(cogs2, -1)
}
}
}
*/
// visualizes the steam press. right now all it does is spawn the hammer part.
fun syncSteamPress(player: Player) {
@ -255,31 +339,102 @@ class EW2Listeners : InteractionListener {
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
val tankLoc = toInstance(player, location(1951, 5164, 2))
val currentObject = getScenery(tankLoc)
if(waterIn == 0 && waterOut == 0) { // both valves closed, nothing happens
if (waterIn == 0 && waterOut == 0) {
// both valves closed, nothing happens
return
} else if(waterIn == 0 && waterOut == 1) { // drain is open, remove all added scenery
removeScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18660, toInstance(player, location(1951, 5164, 2)))) // full tank
removeScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18661, toInstance(player, 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
addScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18661, toInstance(player, 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)
} else if (waterIn == 0 && waterOut == 1) {
// drain is open, empty the tank
if (currentObject != null && currentObject.id == Scenery.WATER_TANK_18661) {
// tank is full: play drain anim, then remove
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
animateScenery(player, currentObject, TANK_DRAIN)
playAudio(player, Sounds.EW2_WATER_RACK_3184)
return@queueScript delayScript(player, Animation(TANK_DRAIN).duration)
}
1 -> {
removeScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18661, tankLoc))
return@queueScript stopExecuting(player)
}
else -> return@queueScript stopExecuting(player)
}
}
} else if (currentObject != null && currentObject.id == Scenery.WATER_TANK_18660) {
// tank is damp: just remove the scenery
removeScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18660, tankLoc))
playAudio(player, Sounds.EW2_WATER_RACK_3184)
}
} else if (waterIn == 1 && waterOut == 0) {
// inlet is open, fill tank
if (currentObject?.id == Scenery.WATER_TANK_18661) return // already full
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
// add damp tank so we have something to animate
var animTarget = currentObject
if (animTarget == null || animTarget.id != Scenery.WATER_TANK_18660) {
animTarget = core.game.node.scenery.Scenery(Scenery.WATER_TANK_18660, tankLoc)
addScenery(animTarget)
}
animateScenery(player, animTarget, TANK_FILL)
playAudio(player, Sounds.EW2_WATER_FLOW_3183)
return@queueScript delayScript(player, Animation(TANK_FILL).duration)
}
1 -> {
// swap damp for full tank
val existing = getScenery(tankLoc)
if (existing != null) removeScenery(core.game.node.scenery.Scenery(existing.id, tankLoc))
addScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18661, tankLoc))
// cooling the hot bar
if (cart == 3) {
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@queueScript stopExecuting(player)
}
else -> return@queueScript stopExecuting(player)
}
}
return
} else if(waterIn == 1 && waterOut == 1) { // inlet and drain are open, tank is damp
addScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18660, toInstance(player, location(1951, 5164, 2)))) // damp tank
playAudio(player, Sounds.EW2_WATER_FLOW_3183) // fill?
return
} else if (waterIn == 1 && waterOut == 1) {
// inlet and drain are open, tank is damp
if (currentObject?.id == Scenery.WATER_TANK_18661) {
// tank is full: play drain anim, then swap to damp
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
animateScenery(player, currentObject, TANK_DRAIN)
playAudio(player, Sounds.EW2_WATER_FLOW_3183)
return@queueScript delayScript(player, Animation(TANK_DRAIN).duration)
}
1 -> {
removeScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18661, tankLoc))
addScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18660, tankLoc))
return@queueScript stopExecuting(player)
}
else -> return@queueScript stopExecuting(player)
}
}
} else if (currentObject?.id != Scenery.WATER_TANK_18660) {
// tank is empty: add the damp scenery
addScenery(core.game.node.scenery.Scenery(Scenery.WATER_TANK_18660, tankLoc))
playAudio(player, Sounds.EW2_WATER_FLOW_3183)
}
}
}
@ -287,14 +442,64 @@ class EW2Listeners : InteractionListener {
fun syncTankDoor(player: Player) {
val state = getVarbit(player, EW2TankDoorStateVarbit)
val doorLoc = toInstance(player, Location.create(1953, 5162, 2))
val currentObject = getScenery(doorLoc)
val currentObject = getScenery(doorLoc) ?: return
val targetId = tankDoorStates[state]
// remove old scenery then add the new one
if(currentObject != null && currentObject.id != targetId) {
// I know what you're thinking, replaceScenery doesn't work in this situation. Why? idfk
removeScenery(core.game.node.scenery.Scenery(currentObject.id, doorLoc, 1))
addScenery(core.game.node.scenery.Scenery(targetId, doorLoc, 1))
if (currentObject.id == targetId) return
var animId = -1
var soundId = -1
when {
// door opening/closing
(currentObject.id == Scenery.DOOR_18651 && targetId == Scenery.DOOR_18652) ||
(currentObject.id == Scenery.DOOR_18654 && targetId == Scenery.DOOR_18655) ||
(currentObject.id == Scenery.DOOR_18657 && targetId == Scenery.DOOR_18658) -> {
animId = DOOR_OPEN
soundId = Sounds.EW2_DIAL_SPIN_2326
}
(currentObject.id == Scenery.DOOR_18652 && targetId == Scenery.DOOR_18651) ||
(currentObject.id == Scenery.DOOR_18655 && targetId == Scenery.DOOR_18654) ||
(currentObject.id == Scenery.DOOR_18658 && targetId == Scenery.DOOR_18657) -> {
animId = DOOR_CLOSE
soundId = Sounds.EW2_DIAL_SPIN_2326
}
// rack extending/retracting
(currentObject.id == Scenery.DOOR_18652 && targetId == Scenery.DOOR_18653) ||
(currentObject.id == Scenery.DOOR_18655 && targetId == Scenery.DOOR_18656) ||
(currentObject.id == Scenery.DOOR_18658 && targetId == Scenery.DOOR_18659) -> {
animId = DOOR_EXTEND
soundId = Sounds.EW2_SCREW_TURN_3182
}
(currentObject.id == Scenery.DOOR_18653 && targetId == Scenery.DOOR_18652) ||
(currentObject.id == Scenery.DOOR_18656 && targetId == Scenery.DOOR_18655) ||
(currentObject.id == Scenery.DOOR_18659 && targetId == Scenery.DOOR_18658) -> {
animId = DOOR_RETRACT
soundId = Sounds.EW2_SCREW_TURN_3182
}
}
queueScript(player, 0, QueueStrength.SOFT) { stage: Int ->
when (stage) {
0 -> {
if (animId != -1) {
val anim = Animation(animId)
animateScenery(player, currentObject, animId)
if (soundId != -1) playAudio(player, soundId)
return@queueScript delayScript(player, anim.duration)
}
return@queueScript delayScript(player, 1)
}
1 -> {
// replaceScenery doesn't work. why? idfk
removeScenery(core.game.node.scenery.Scenery(currentObject.id, doorLoc, 1))
addScenery(core.game.node.scenery.Scenery(targetId, doorLoc, 1))
syncCart(player)
return@queueScript stopExecuting(player)
}
else -> return@queueScript stopExecuting(player)
}
}
}
@ -302,21 +507,19 @@ class EW2Listeners : InteractionListener {
fun syncFan(player: Player) {
val fanMachine = getVarbit(player, EW2FanLeverVarbit)
if (fanMachine == 1) {
setVarbit(player, EW2FanStateVarbit, 1)
// spins the fan
setVarbit(player, EW2FanStateVarbit, 1, true)
} else {
setVarbit(player, EW2FanStateVarbit, 0)
setVarbit(player, EW2FanStateVarbit, 0, true)
}
}
// helper to convert static location coordinates to the dynamic instance location coordinates
fun toInstance(player: Player, staticLoc: Location): Location {
val activity = player.getAttribute<ActivityPlugin>("activity")
if (activity == null || activity.base == null) return staticLoc
val session = player.getAttribute<EW2Session?>("ew2-session", null) ?: return staticLoc
val offsetX = staticLoc.x - 1920
val offsetY = staticLoc.y - 5120
return activity.base.transform(offsetX, offsetY, staticLoc.z)
return session.base.transform(offsetX, offsetY, staticLoc.z)
}
}
@ -405,7 +608,12 @@ class EW2Listeners : InteractionListener {
// unlocked center hatch down to EW2
on(Scenery.HATCH_18596, IntType.SCENERY, "climb-down") { player, _ ->
sendMessage(player, "You climb down the stairs.")
teleport(player, location(1955, 5155, 2))
// this is the non-instanced area
//teleport(player, location(1955, 5155, 2))
// start the instanced workshop session
EW2Session(player).start()
if(getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) == 4) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 5)
@ -610,6 +818,13 @@ class EW2Listeners : InteractionListener {
playAudio(player, Sounds.EW2_PLACE_BAR_3177)
syncCart(player)
removeItem(player, used)
// advance quest stage
if (getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 5) {
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 6)
setVarbit(player, EW2StageVarbit, 6, true)
}
if(!getAttribute(player, attrJigged, false) && getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 6) {
setAttribute(player, attrJigged, true)
}
@ -661,14 +876,12 @@ class EW2Listeners : InteractionListener {
if (currentPos == 3 && nextPos == 2) {
if (craneMat == 1 && (cartState == 1 || cartState == 2) && cartPos == 0) {
// pick up
setVarbit(player, EW2CraneStateVarbit, cartState + 1)
setVarbit(player, EW2JigCartVarbit, 0)
syncCart(player)
setVarbit(player, EW2CraneStateVarbit, cartState + 1, true)
setVarbit(player, EW2JigCartVarbit, 0, true)
} else if ((craneMat == 2 || craneMat == 3) && cartState == 0 && cartPos == 0) {
// drop off
setVarbit(player, EW2JigCartVarbit, craneMat - 1)
setVarbit(player, EW2CraneStateVarbit, 1)
syncCart(player)
setVarbit(player, EW2JigCartVarbit, craneMat - 1, true)
setVarbit(player, EW2CraneStateVarbit, 1, true)
}
}
@ -676,13 +889,14 @@ class EW2Listeners : InteractionListener {
if (currentPos == 1 && nextPos == 0) {
if (craneMat == 2) {
// if holding elemental bar, transform into hot bar
setVarbit(player, EW2CraneStateVarbit, 3)
setVarbit(player, EW2CraneStateVarbit, 3, true)
playAudio(player, Sounds.EW2_CRANE_LOWER_3169)
}
}
setVarbit(player, EW2CranePosVarbit, nextPos, true)
lockInteractions(player, 5)
animate(player, Animations.HUMAN_PULL_LEVER_4909)
syncCrane(player)
syncCrane(player) // also syncs the cart inside the crane function
return@on true
}
@ -699,6 +913,7 @@ class EW2Listeners : InteractionListener {
val nextPos = currentPos xor 2
setVarbit(player, EW2CranePosVarbit, nextPos, true)
lockInteractions(player, 5)
animate(player, Animations.HUMAN_PULL_LEVER_4909)
syncCrane(player)
return@on true
@ -739,7 +954,7 @@ class EW2Listeners : InteractionListener {
animate(player, Animations.HUMAN_PULL_LEVER_4909)
}
2 -> { // hot ele bar. changes state to hot smashed bar.
setVarbit(player, EW2JigCartVarbit, 3)
setVarbit(player, EW2JigCartVarbit, 3, true)
// "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)
@ -834,7 +1049,7 @@ class EW2Listeners : InteractionListener {
else -> tankState
}
setVarbit(player, EW2TankDoorStateVarbit, nextTankState)
setVarbit(player, EW2TankDoorStateVarbit, nextTankState, true)
syncTankDoor(player)
return@on true
}
@ -865,35 +1080,34 @@ class EW2Listeners : InteractionListener {
runTask(player, 1) {
when (tankState) {
1 -> { // 1 door opened, grabber inside
setVarbit(player, EW2TankDoorStateVarbit, 2) // 2 door opened, grabber out
setVarbit(player, EW2TankDoorStateVarbit, 2, true) // 2 door opened, grabber out
// no cart update
}
2 -> { // 2 door opened, grabber out
// only grab the hot bar. otherwise, put the grabber back in
if(cartState == 3) {
setVarbit(player, EW2TankDoorStateVarbit, 4) // 4 door opened, hot bar inside
setVarbit(player, EW2TankDoorStateVarbit, 4, true) // 4 door opened, hot bar inside
// remove hot bar cart
} else {
setVarbit(player, EW2TankDoorStateVarbit, 1) // 1 door opened, grabber inside
setVarbit(player, EW2TankDoorStateVarbit, 1, true) // 1 door opened, grabber inside
}
}
4 -> { // 4 door opened, hot bar inside
setVarbit(player, EW2TankDoorStateVarbit, 5) // 5 door opened, hot bar out
setVarbit(player, EW2TankDoorStateVarbit, 5, true) // 5 door opened, hot bar out
}
5 -> { // 5 door opened, hot bar out
setVarbit(player, EW2TankDoorStateVarbit, 1) // 1 door opened, grabber inside
setVarbit(player, EW2TankDoorStateVarbit, 1, true) // 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
setVarbit(player, EW2TankDoorStateVarbit, 8, true) // 8 door opened, cooled bar out
}
8 -> { // 8 door opened, cooled bar out
setVarbit(player, EW2TankDoorStateVarbit, 1) // 1 door opened, grabber inside
setVarbit(player, EW2TankDoorStateVarbit, 1, true) // 1 door opened, grabber inside
// add cool bar cart
}
}
syncTankDoor(player)
syncCart(player)
syncTankDoor(player) // also syncs the cart inside there
}
return@on true
}
@ -914,24 +1128,26 @@ class EW2Listeners : InteractionListener {
return@on true
}
player.locks.lockInteractions(4)
lockInteractions(player, 4)
animate(player, 4861)
// if closed, open the valve
if(valveState == 0){
setVarbit(player, EW2ValveWestVarbit, 1, true)
runTask(player, 3) {
queueScript(player, 3, QueueStrength.SOFT) {
syncTank(player)
sendDialogue(player, "You open the valve.")
playAudio(player, Sounds.EW2_WATER_VALVE_3185)
return@queueScript true
}
// if open, close the valve
} else {
setVarbit(player, EW2ValveWestVarbit, 0, true)
runTask(player, 3) {
queueScript(player, 3, QueueStrength.SOFT) {
syncTank(player)
sendDialogue(player, "You close the valve.")
playAudio(player, Sounds.EW2_WATER_VALVE_3185)
return@queueScript true
}
}
return@on true
@ -1038,6 +1254,7 @@ class EW2Listeners : InteractionListener {
}
addItemOrDrop(player, cogToGive)
syncCogs(player)
animate(player, 537)
sendMessage(player, "You remove the cog from the shaft.")
}
@ -1070,6 +1287,7 @@ class EW2Listeners : InteractionListener {
removeItem(player, item)
}
}
syncCogs(player)
return@onUseWith true
}
@ -1096,6 +1314,7 @@ class EW2Listeners : InteractionListener {
removeItem(player, item)
}
}
syncCogs(player)
return@onUseWith true
}
@ -1122,6 +1341,7 @@ class EW2Listeners : InteractionListener {
removeItem(player, item)
}
}
syncCogs(player)
return@onUseWith true
}
@ -1146,6 +1366,7 @@ class EW2Listeners : InteractionListener {
playAudio(player, Sounds.EW2_FANBLADE_3174)
setVarbit(player, EW2FanLeverVarbit, 1, true)
syncFan(player)
syncCogs(player)
// check cart and cool if necessary. otherwise nothing should happen.
if (cartpos == 3 && cartstate == 4) {
setVarbit(player, EW2JigCartVarbit, 5, true)
@ -1158,6 +1379,7 @@ class EW2Listeners : InteractionListener {
sendDialogue(player, "The machine grinds to a standstill.")
setVarbit(player, EW2FanLeverVarbit, 0, true)
syncFan(player)
syncCogs(player)
}
} else { // allCogs != 57, cogs are not correct
sendDialogue(player, "The machine starts up, but the fan does not blow.")
@ -1218,7 +1440,7 @@ class EW2Listeners : InteractionListener {
0,
0
)
visualize(player, goodHatAnim, goodHatGfx)
visualize(player, EXTRACTOR_GOOD, EXTRACTOR_GOOD_GFX)
playAudio(player, Sounds.EW2_EXTRACTOR_OPERATION_3166)
sendGraphics(809, Location.create(1962, 5148, 0))
setVarbit(player, EW2ExtractorGun, 2, true)
@ -1246,7 +1468,7 @@ class EW2Listeners : InteractionListener {
0,
0
)
visualize(player, badHatAnim, badHatGfx)
visualize(player, EXTRACTOR_BAD, EXTRACTOR_BAD_GFX)
playAudio(player, Sounds.EW2_EXTRACTOR_ZAP_3173)
impact(player, 4)
sendMessage(player, "The extractor hat shocks you!.")

View file

@ -1,6 +1,7 @@
package content.region.kandarin.seers.quest.elementalworkshop2
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.syncCart
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.syncCogs
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.syncSteamPress
@ -53,6 +54,7 @@ class EW2Session(val player: Player? = null) : MapArea {
syncTank(p)
syncTankDoor(p)
syncFan(p)
syncCogs(p)
}
// clean up the instanced area

View file

@ -92,10 +92,10 @@ class JunctionBoxInterface : InterfaceListener {
setComponentVisibility(player, junctionBox, pipes[s3 - 1], false); placedCount++
}
setVarbit(player, pipesLeftVarbit, 3 - placedCount)
setVarbit(player, pipesLeftVarbit, 3 - placedCount, true)
// reset any selected
setVarbit(player, pipeSelectVarbit, 0)
setVarbit(player, pipeSelectVarbit, 0, true)
return@onOpen true
}
@ -136,14 +136,14 @@ class JunctionBoxInterface : InterfaceListener {
b4 -> 4; b5 -> 5; b6 -> 6
else -> 0
}
setVarbit(player, pipeSelectVarbit, selection)
setVarbit(player, pipeSelectVarbit, selection, true)
} else {
val pipeIndex = getPipeIndex(currentSelection, buttonID, b1, b2, b3, b4, b5, b6)
if (pipeIndex != -1) {
// check if this specific pipe is already placed
if (isPipeAlreadyPlaced(player, pipeIndex + 1)) {
setVarbit(player, pipeSelectVarbit, 0)
setVarbit(player, pipeSelectVarbit, 0, true)
return@on true
}
@ -155,15 +155,15 @@ class JunctionBoxInterface : InterfaceListener {
// pipe status is saved in these varbits and recalled on open. they are linked to main quest progression status
val saved = when {
getVarbit(player, firstSelect) == 0 -> {
setVarbit(player, firstSelect, pipeIndex + 1); true
setVarbit(player, firstSelect, pipeIndex + 1, true); true
}
getVarbit(player, secondSelect) == 0 -> {
setVarbit(player, secondSelect, pipeIndex + 1); true
setVarbit(player, secondSelect, pipeIndex + 1, true); true
}
getVarbit(player, thirdSelect) == 0 -> {
setVarbit(player, thirdSelect, pipeIndex + 1); true
setVarbit(player, thirdSelect, pipeIndex + 1, true); true
}
else -> false
@ -171,10 +171,10 @@ class JunctionBoxInterface : InterfaceListener {
if (saved) {
val left = getVarbit(player, pipesLeftVarbit)
setVarbit(player, pipesLeftVarbit, left - 1)
setVarbit(player, pipesLeftVarbit, left - 1, true)
}
}
setVarbit(player, pipeSelectVarbit, 0)
setVarbit(player, pipeSelectVarbit, 0, true)
}
// if there are no pipes left, we have placed them all. hammer time!
@ -215,10 +215,10 @@ class JunctionBoxInterface : InterfaceListener {
// Hide the pipe on interface
setComponentVisibility(player, junctionBox, pipes[pipeIndex], true)
// Reset the varbit
setVarbit(player, v, 0)
setVarbit(player, v, 0, true)
// Increment pipes left
val left = getVarbit(player, pipesLeftVarbit)
setVarbit(player, pipesLeftVarbit, left + 1)
setVarbit(player, pipesLeftVarbit, left + 1, true)
playAudio(player, Sounds.EW2_REMOVE_PIPE_3181)
return true
}

View file

@ -1,8 +1,14 @@
package core.game.system.command.sets
import core.api.addScenery
import core.api.animateScenery
import core.api.delayScript
import core.api.log
import core.api.queueScript
import core.api.sendMessage
import core.api.stopExecuting
import core.cache.Cache
import core.game.interaction.QueueStrength
import core.game.node.scenery.Scenery
import core.game.node.scenery.SceneryBuilder
import core.game.node.entity.npc.NPC
@ -121,6 +127,52 @@ class SpawnCommandSet : CommandSet(Privilege.ADMIN){
log(this::class.java, Log.FINE, "object = $`object`")
}
/**
* Spawn object with given ID at the player's location and animate it
*/
define("objanim", usage = "::objanim [objectId] [animFrom] [(opt)animTo] [(opt)delay]", description = "Spawns an object and animates it with the provided anim ID. If a second ID is provided, it iterates through the anims.") { player, args ->
if (args.size < 3) {
sendMessage(player, "Usage: ::objanim [objectId] [animFrom] [(opt)animTo] [(opt)delay]")
return@define
}
val objectId = args[1].toIntOrNull()
val animFrom = args[2].toIntOrNull()
val animTo = args.getOrNull(3)?.toIntOrNull()
val delay = args.getOrNull(4)?.toIntOrNull() ?: 3
if (objectId == null || animFrom == null) {
sendMessage(player, "Invalid arguments. Please use numbers.")
return@define
}
// spawn the object
val obj = core.game.node.scenery.Scenery(objectId, player.location)
addScenery(obj)
// animate a single anim
if (animTo == null) {
animateScenery(player, obj, animFrom)
sendMessage(player, "Spawned object $objectId and playing animation $animFrom.")
return@define
}
// loop through the anims if it's a range
sendMessage(player, "Spawned object $objectId, playing anims $animFrom to $animTo.")
queueScript(player, 1, QueueStrength.STRONG) { stage: Int ->
val currentAnimId = animFrom + stage
animateScenery(player, obj, currentAnimId)
sendMessage(player, "Playing object animation $currentAnimId")
if (currentAnimId >= animTo) {
return@queueScript stopExecuting(player)
}
return@queueScript delayScript(player, delay)
}
return@define
}
define("objectgrid", usage = "::objectgrid <lt>start-id<gt> <lt>end-id<gt> <lt>type<gt> <lt>rotation<gt>", description = "Spawns a 10-wide grid cycling through the given object id range.") { player, args ->
if(args!!.size != 5) {
reject(player, "Usage: objectgrid beginId endId type rotation")