mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2026-08-21 10:25:13 -06:00
Merge branch 'ew2' into 'master'
Added Elemental Workshop II Quest Closes #1189 See merge request 2009scape/2009scape!2253
This commit is contained in:
commit
336d38a628
14 changed files with 2993 additions and 58 deletions
|
|
@ -27086,7 +27086,7 @@
|
|||
{
|
||||
"id": "2888",
|
||||
"name": "A stone bowl",
|
||||
"examine": "This is an empty stone bowl. / This is a stone bowl full of lava.",
|
||||
"examine": "This is an empty stone bowl.",
|
||||
"archery_ticket_price": "0",
|
||||
"durability": null,
|
||||
"equipment_slot": "3"
|
||||
|
|
@ -27094,7 +27094,7 @@
|
|||
{
|
||||
"id": "2889",
|
||||
"name": "A stone bowl",
|
||||
"examine": "This is an empty stone bowl. / This is a stone bowl full of lava.",
|
||||
"examine": "This is a stone bowl full of lava.",
|
||||
"archery_ticket_price": "0",
|
||||
"durability": null,
|
||||
"equipment_slot": "3"
|
||||
|
|
@ -77832,7 +77832,7 @@
|
|||
{
|
||||
"id": "9723",
|
||||
"name": "Pipe",
|
||||
"examine": "A pipe that belongs in a cannon stand.",
|
||||
"examine": "A spare section of pipe.",
|
||||
"archery_ticket_price": "0",
|
||||
"destroy": "true",
|
||||
"durability": null,
|
||||
|
|
|
|||
|
|
@ -7343,14 +7343,50 @@
|
|||
"examine": "This lets in more light.",
|
||||
"ids": "1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863"
|
||||
},
|
||||
{
|
||||
"examine": "An empty claw.",
|
||||
"ids": "18623,18624,18625,18626"
|
||||
},
|
||||
{
|
||||
"examine": "A heavy claw.",
|
||||
"ids": "18627,18628,18629,18630,18631,18632,18633,18634"
|
||||
},
|
||||
{
|
||||
"examine": "A broken claw.",
|
||||
"ids": "18635,18636,18637,18638"
|
||||
},
|
||||
{
|
||||
"examine": "These obviously mean keep out!",
|
||||
"ids": "1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875"
|
||||
},
|
||||
{
|
||||
"examine": "The inner workings for the press are in here.",
|
||||
"ids": "18641"
|
||||
},
|
||||
{
|
||||
"examine": "A valve to start and stop the flow of water.",
|
||||
"ids": "18646,18647"
|
||||
},
|
||||
{
|
||||
"examine": "I wonder what it does.",
|
||||
"ids": "18663"
|
||||
},
|
||||
{
|
||||
"examine": "Fly Gnome Air.",
|
||||
"ids": "187"
|
||||
},
|
||||
{
|
||||
"examine": "Seems to connect this level to the one above!",
|
||||
"ids": "18705,18598"
|
||||
},
|
||||
{
|
||||
"examine": "Is that a shopping trolley?",
|
||||
"ids": "18746"
|
||||
},
|
||||
{
|
||||
"examine": "A magical wind tunnel.",
|
||||
"ids": "18758,18759"
|
||||
},
|
||||
{
|
||||
"examine": "I shudder to think what has taken place here.",
|
||||
"ids": "1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,32289"
|
||||
|
|
@ -10645,7 +10681,7 @@
|
|||
},
|
||||
{
|
||||
"examine": "This lever can be operated.",
|
||||
"ids": "3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428"
|
||||
"ids": "3417,3418,3419,3420,3421,3423,3424,3425,3426,3427,3428"
|
||||
},
|
||||
{
|
||||
"examine": "Water powered machinery.",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
package content.global.handlers.item.equipment
|
||||
|
||||
import content.data.Quests
|
||||
import core.api.*
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.update.flag.context.Graphics
|
||||
import org.rs09.consts.Items
|
||||
|
||||
/**
|
||||
* The graphics that run when you equip elemental equipment.
|
||||
*/
|
||||
|
||||
class ElementalEquipmentGraphics : InteractionListener {
|
||||
|
||||
// the graphics that run on equip
|
||||
private val mShieldEquip = 809
|
||||
private val mHelmEquip = 810
|
||||
private val eShieldEquip = 244
|
||||
private val eHelmEquip = 811
|
||||
|
||||
override fun defineListeners() {
|
||||
|
||||
onEquip(Items.ELEMENTAL_SHIELD_2890) { player, _ ->
|
||||
equipShield(player, Quests.ELEMENTAL_WORKSHOP_I, eShieldEquip)
|
||||
}
|
||||
|
||||
onEquip(Items.MIND_SHIELD_9731) { player, _ ->
|
||||
equipShield(player, Quests.ELEMENTAL_WORKSHOP_II, mShieldEquip)
|
||||
}
|
||||
|
||||
onEquip(Items.ELEMENTAL_HELMET_9729) { player, _ ->
|
||||
equipHelm(player, Quests.ELEMENTAL_WORKSHOP_II, eHelmEquip)
|
||||
}
|
||||
|
||||
onEquip(Items.MIND_HELMET_9733) { player, _ ->
|
||||
equipHelm(player, Quests.ELEMENTAL_WORKSHOP_II, mHelmEquip)
|
||||
}
|
||||
}
|
||||
|
||||
private fun equipShield(player: Player, quest: Quests, gfxId: Int): Boolean {
|
||||
if (!isQuestComplete(player, quest)) {
|
||||
sendMessage(player, "You need to have completed ${quest.questName} to equip this.")
|
||||
return false
|
||||
}
|
||||
|
||||
// hide the shield while the gfx plays
|
||||
player.appearance.isHideShield = true
|
||||
player.updateAppearance()
|
||||
visualize(player, -1, Graphics(gfxId, 95))
|
||||
|
||||
// unhide the shield
|
||||
queueScript(player, 2, QueueStrength.SOFT) {
|
||||
player.appearance.isHideShield = false
|
||||
player.updateAppearance()
|
||||
stopExecuting(player)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun equipHelm(player: Player, quest: Quests, gfxId: Int): Boolean {
|
||||
if (!isQuestComplete(player, quest)) {
|
||||
sendMessage(player, "You need to have completed ${quest.questName} to equip this.")
|
||||
return false
|
||||
}
|
||||
|
||||
// play the graphics
|
||||
visualize(player, -1, gfxId)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,10 @@ import core.game.interaction.InteractionListener
|
|||
import core.game.interaction.IntType
|
||||
import core.tools.Log
|
||||
import content.data.Quests
|
||||
import content.global.handlers.iface.BookInterface
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2StageVarbit
|
||||
import core.game.dialogue.DialogueLabeller
|
||||
import core.game.interaction.QueueStrength
|
||||
|
||||
/**
|
||||
* Listeners for the Elemental Workshop I quest
|
||||
|
|
@ -108,22 +112,45 @@ class EWListeners : InteractionListener {
|
|||
}
|
||||
|
||||
// --- AFTER QUEST START ---
|
||||
if (player.inventory.containsItem(slashedBook)) {
|
||||
sendItemDialogue(player, Item(Items.SLASHED_BOOK_9715),
|
||||
"There is a book here titled 'The Elemental Shield'. " +
|
||||
"It can stay here, as you have a copy in your backpack."
|
||||
)
|
||||
if (player.inventory.addIfDoesntHave(batteredKey)) {
|
||||
sendItemDialogue(player, Item(Items.BATTERED_KEY_2887),"You also find a key.")
|
||||
}
|
||||
|
||||
// if player doesn't have book and doesn't have key
|
||||
if (!inInventory(player, slashedBook.id) && !inInventory(player, batteredKey.id)) {
|
||||
addItemOrDrop(player, batteredKey.id)
|
||||
addItemOrDrop(player, slashedBook.id)
|
||||
openDialogue(player, object : DialogueLabeller() {
|
||||
override fun addConversation() {
|
||||
item(slashedBook, "You find a book titled 'The Elemental Shield'.")
|
||||
item(batteredKey,"You also find a key.")
|
||||
}
|
||||
})
|
||||
return@on true
|
||||
}
|
||||
|
||||
sendItemDialogue(player, Item(Items.SLASHED_BOOK_9715), "You find a book titled 'The Elemental Shield'.")
|
||||
addItemOrDrop(player, slashedBook.id)
|
||||
if (player.inventory.addIfDoesntHave(batteredKey)) {
|
||||
sendItemDialogue(player, Item(Items.BATTERED_KEY_2887),"You also find a key.")
|
||||
// if player doesn't have book and does have key
|
||||
if (!inInventory(player, slashedBook.id) && inInventory(player, batteredKey.id)) {
|
||||
addItemOrDrop(player, slashedBook.id)
|
||||
sendItemDialogue(player, slashedBook, "You find a book titled 'The Elemental Shield'.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
// if player does have book but doesn't have key
|
||||
if (inInventory(player, slashedBook.id) && !inInventory(player, batteredKey.id)) {
|
||||
addItemOrDrop(player, batteredKey.id)
|
||||
openDialogue(player, object : DialogueLabeller() {
|
||||
override fun addConversation() {
|
||||
item(slashedBook, "There is a book here titled 'The Elemental Shield'. " + "It can stay here, as you have a copy in your backpack.")
|
||||
item(batteredKey,"You also find a key.")
|
||||
}
|
||||
})
|
||||
return@on true
|
||||
}
|
||||
|
||||
// if player does have book and does have key
|
||||
if (inInventory(player, slashedBook.id) && inInventory(player, batteredKey.id)) {
|
||||
sendItemDialogue(player, slashedBook, "There is a book here titled 'The Elemental Shield'. " + "It can stay here, as you have a copy in your backpack.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
return@on true
|
||||
}
|
||||
|
||||
|
|
@ -215,13 +242,6 @@ class EWListeners : InteractionListener {
|
|||
/* * * * * * * * * * * * * * * *
|
||||
* Workshop Area listeners *
|
||||
* * * * * * * * * * * * * * */
|
||||
// Center hatch, inaccessible
|
||||
// NOTE: REMOVE ME/ADD CORRECT CHECKS FOR ELEMENTAL WORKSHOP II
|
||||
on(Scenery.HATCH_18595, IntType.SCENERY, "open") { player, _ ->
|
||||
sendDialogue(player, "You're unable to open the locked hatch.")
|
||||
return@on true
|
||||
}
|
||||
|
||||
// Stone bowl box, player can get more at any time
|
||||
on(Scenery.BOXES_3397, IntType.SCENERY, "search") { player, _ ->
|
||||
// If the player doesn't have a stone bowl in their inventory
|
||||
|
|
@ -258,40 +278,260 @@ class EWListeners : InteractionListener {
|
|||
}
|
||||
|
||||
// Workbenches/Anvil
|
||||
onUseWith(IntType.SCENERY, Items.ELEMENTAL_METAL_2893, Scenery.WORKBENCH_3402) { player, used, workbench ->
|
||||
// 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)
|
||||
// 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, intArrayOf(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))
|
||||
queueScript(player, 0, QueueStrength.SOFT) { _ ->
|
||||
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.")
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
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))
|
||||
queueScript(player, 0, QueueStrength.SOFT) { _ ->
|
||||
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.")
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
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))
|
||||
queueScript(player, 0, QueueStrength.SOFT) { _ ->
|
||||
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.")
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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))
|
||||
queueScript(player, 0, QueueStrength.SOFT) { _ ->
|
||||
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.")
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
// 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 -> {
|
||||
// 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))
|
||||
queueScript(player, 0, QueueStrength.SOFT) { count ->
|
||||
when(count) {
|
||||
// make the helm
|
||||
0 -> {
|
||||
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.")
|
||||
return@queueScript delayScript(player, smithElementalShield.duration)
|
||||
}
|
||||
|
||||
// complete quest
|
||||
1 -> {
|
||||
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)
|
||||
}
|
||||
return@queueScript delayScript(player, 1)
|
||||
}
|
||||
}
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
|
||||
// after quest, 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.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 mind shield
|
||||
lock(player, (animationDuration(smithElementalShield) + 2))
|
||||
queueScript(player, 0, QueueStrength.SOFT) { _ ->
|
||||
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.")
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
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))
|
||||
queueScript(player, 0, QueueStrength.SOFT) { _ ->
|
||||
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.")
|
||||
return@queueScript stopExecuting(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return@onUseWith true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package content.region.kandarin.seers.quest.elementalworkshop
|
||||
|
||||
import content.global.handlers.iface.BookInterface
|
||||
import core.api.storeBookInHouse
|
||||
import core.game.interaction.IntType
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.game.node.entity.player.Player
|
||||
|
|
@ -25,6 +26,7 @@ class SlashedBookHandler : InteractionListener {
|
|||
override fun defineListeners() {
|
||||
on(Items.SLASHED_BOOK_9715, IntType.ITEM, "read") { player, _ ->
|
||||
BookInterface.openBook(player, BookInterface.FANCY_BOOK_3_49, ::display)
|
||||
storeBookInHouse(player, Items.BATTERED_BOOK_2886)
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,243 @@
|
|||
package content.region.kandarin.seers.quest.elementalworkshop2
|
||||
|
||||
import content.data.Quests
|
||||
import content.global.handlers.iface.*
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2StageVarbit
|
||||
import core.game.interaction.InteractionListener
|
||||
import core.api.*
|
||||
import core.game.dialogue.DialogueLabeller
|
||||
import core.game.interaction.IntType
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.item.Item
|
||||
import org.rs09.consts.Items
|
||||
|
||||
/**
|
||||
* Starts the Elemental Workshop II Quest
|
||||
* Found at Dig Site Library
|
||||
*/
|
||||
|
||||
class BeatenBook : InteractionListener {
|
||||
companion object {
|
||||
private const val TITLE = "Book of the Elemental Helm"
|
||||
private val CONTENTS = arrayOf(
|
||||
// pages 1-2
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("This is the second book in", 55),
|
||||
BookLine("a series which aims to", 56),
|
||||
BookLine("preserve the knowledge", 57),
|
||||
BookLine("gained by artisans of the", 58),
|
||||
BookLine("early Fifth Age. A", 59),
|
||||
BookLine("thorough grasp of the", 60),
|
||||
BookLine("processes and techniques", 61),
|
||||
BookLine("described in my earlier", 62),
|
||||
BookLine("work, 'Book of the", 63),
|
||||
BookLine("Elemental Shield', is", 64),
|
||||
BookLine("necessary to comprehend", 65),
|
||||
),
|
||||
Page(
|
||||
BookLine("the concepts involved in", 66),
|
||||
BookLine("the more technical", 67),
|
||||
BookLine("chapters of this book.", 68),
|
||||
BookLine("", 69),
|
||||
BookLine("", 70),
|
||||
BookLine("", 71),
|
||||
BookLine("", 72),
|
||||
BookLine("", 73),
|
||||
BookLine("", 74),
|
||||
BookLine("", 75),
|
||||
BookLine("", 76),
|
||||
)
|
||||
),
|
||||
// pages 3-4
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Some years following the", 55),
|
||||
BookLine("original discovery of the", 56),
|
||||
BookLine("elemental ore, further", 57),
|
||||
BookLine("investigation was", 58),
|
||||
BookLine("performed by a", 59),
|
||||
BookLine("metallurgist called", 60),
|
||||
BookLine("Vitruvius in collaboration", 61),
|
||||
BookLine("with a freelance mage.", 62),
|
||||
BookLine("Over the course of two", 63),
|
||||
BookLine("years they did many", 64),
|
||||
BookLine("tests on the ore and", 65),
|
||||
),
|
||||
Page(
|
||||
BookLine("refined metal, aiming to", 66),
|
||||
BookLine("optimise the process by", 67),
|
||||
BookLine("which the metal was", 68),
|
||||
BookLine("extracted from its impure", 69),
|
||||
BookLine("ore. From the data they", 70),
|
||||
BookLine("gathered, they discovered", 71),
|
||||
BookLine("the optimum temperature", 72),
|
||||
BookLine("and carbon/ore ratio for", 73),
|
||||
BookLine("the production of", 74),
|
||||
BookLine("elemental metal of the", 75),
|
||||
BookLine("highest quality. The", 76),
|
||||
)
|
||||
),
|
||||
// pages 5-6
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("quality of the resulting", 55),
|
||||
BookLine("metal was assessed on the", 56),
|
||||
BookLine("basis of its ultimate tensile", 57),
|
||||
BookLine("strength, hardness (as", 58),
|
||||
BookLine("compared to a standard", 59),
|
||||
BookLine("diamond-tipped probe),", 60),
|
||||
BookLine("magical absorption", 61),
|
||||
BookLine("capacity per unit mass,", 62),
|
||||
BookLine("grain size and elastic", 63),
|
||||
BookLine("deformation modulus.", 64),
|
||||
BookLine("Their most significant", 65),
|
||||
),
|
||||
Page(
|
||||
BookLine("discovery in this period,", 66),
|
||||
BookLine("however, was the novel", 67),
|
||||
BookLine("technique of 'priming' the", 68),
|
||||
BookLine("ore.", 69),
|
||||
BookLine("", 70),
|
||||
BookLine("", 71),
|
||||
BookLine("", 72),
|
||||
BookLine("", 73),
|
||||
BookLine("", 74),
|
||||
BookLine("", 75),
|
||||
BookLine("", 76),
|
||||
)
|
||||
),
|
||||
// pages 7-8
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("At the time, the", 55),
|
||||
BookLine("significance of priming", 56),
|
||||
BookLine("was not fully appreciated.", 57),
|
||||
BookLine("However, the records kept", 58),
|
||||
BookLine("by Vitruvius state that his", 59),
|
||||
BookLine("apprentice, in an", 60),
|
||||
BookLine("unsuccessful attempt to", 61),
|
||||
BookLine("animate a small ingot of", 62),
|
||||
BookLine("elemental metal as part of", 63),
|
||||
BookLine("a student prank,", 64),
|
||||
BookLine("accidentally instilled his", 65),
|
||||
),
|
||||
Page(
|
||||
BookLine("entire consciousness into", 66),
|
||||
BookLine("the primed ingot. An", 67),
|
||||
BookLine("unfortunate side-effect of", 68),
|
||||
BookLine("this process was to", 69),
|
||||
BookLine("reduce the apprentice's", 70),
|
||||
BookLine("body to a dead shell.", 71),
|
||||
BookLine("Attempts to return his", 72),
|
||||
BookLine("consciousness to his body", 73),
|
||||
BookLine("were regrettably", 74),
|
||||
BookLine("unsuccessful.", 75),
|
||||
BookLine("", 76),
|
||||
)
|
||||
),
|
||||
// pages 9-10
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Vitruvius discovered that", 55),
|
||||
BookLine("the mental energy was so", 56),
|
||||
BookLine("firmly bound to the", 57),
|
||||
BookLine("elemental metal that no", 58),
|
||||
BookLine("dissipation was detectable.", 59),
|
||||
BookLine("Similar experiments with", 60),
|
||||
BookLine("unprimed bars initially", 61),
|
||||
BookLine("yielded comparable", 62),
|
||||
BookLine("results, but the mental", 63),
|
||||
BookLine("energy quickly left the", 64),
|
||||
BookLine("bars and dissipated within", 65),
|
||||
),
|
||||
Page(
|
||||
BookLine("such a short period that", 66),
|
||||
BookLine("no practical applications", 67),
|
||||
BookLine("seemed feasible. However", 68),
|
||||
BookLine("the primed elemental", 69),
|
||||
BookLine("metal showed considerably", 70),
|
||||
BookLine("more promise.", 71),
|
||||
BookLine("", 72),
|
||||
BookLine("", 73),
|
||||
BookLine("", 74),
|
||||
BookLine("", 75),
|
||||
BookLine("", 76),
|
||||
)
|
||||
),
|
||||
// pages 11-12
|
||||
PageSet(
|
||||
Page(
|
||||
BookLine("Researchers have", 55),
|
||||
BookLine("continued to use the", 56),
|
||||
BookLine("terminology defined by", 57),
|
||||
BookLine("Vitruvius for this field of", 58),
|
||||
BookLine("study. In his own", 59),
|
||||
BookLine("notebooks, Vitruvius", 60),
|
||||
BookLine("referred to his", 61),
|
||||
BookLine("preparation technique as", 62),
|
||||
BookLine("'priming', and he referred", 63),
|
||||
BookLine("to his apprentice as 'Idiot'.", 64),
|
||||
BookLine("", 65),
|
||||
),
|
||||
Page(
|
||||
BookLine("", 66),
|
||||
BookLine("", 67),
|
||||
BookLine("", 68),
|
||||
BookLine("", 69),
|
||||
BookLine("", 70),
|
||||
BookLine("", 71),
|
||||
BookLine("", 72),
|
||||
BookLine("", 73),
|
||||
BookLine("", 74),
|
||||
BookLine("", 75),
|
||||
BookLine("", 76),
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun display(player: Player, pageNum: Int, buttonID: Int): Boolean {
|
||||
BookInterface.pageSetup(player, BookInterface.FANCY_BOOK_3_49, TITLE, CONTENTS)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun defineListeners() {
|
||||
on(Items.BEATEN_BOOK_9717, IntType.ITEM, "read") { player, node ->
|
||||
|
||||
// check the player is not already reading the book
|
||||
if (!player.interfaceManager.isOpened) {
|
||||
// increment quest stage if needed
|
||||
if (getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) == 1) {
|
||||
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 2)
|
||||
setVarbit(player, EW2StageVarbit, 2, true)
|
||||
}
|
||||
|
||||
storeBookInHouse(player, node)
|
||||
|
||||
// if the player doesn't have the scroll, drop it
|
||||
if (hasAnItem(player, Items.SCROLL_9721).container == null) {
|
||||
sendMessage(player, "The book has two parts; an introduction and an instruction section.")
|
||||
sendMessage(player, "You flip the book open to the introduction and start reading.")
|
||||
addItemOrDrop(player, Items.SCROLL_9721) // scroll needs to be added here because otherwise in the afterClose block it'll give you 3 lmao
|
||||
openDialogue(player, object : DialogueLabeller() {
|
||||
override fun addConversation() {
|
||||
item(Item(Items.SCROLL_9721), "You find a slip of paper that has been used", "for a bookmark. You put it in your pack to", "study later.")
|
||||
afterClose { player ->
|
||||
BookInterface.openBook(player, BookInterface.FANCY_BOOK_3_49, ::display)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// if player has scroll, open book
|
||||
} else {
|
||||
sendMessage(player, "The book has two parts; an introduction and an instruction section.")
|
||||
sendMessage(player, "You flip the book open to the introduction and start reading.")
|
||||
BookInterface.openBook(player, BookInterface.FANCY_BOOK_3_49, ::display)
|
||||
}
|
||||
} else sendMessage(player, "Please finish what you're doing first.") // this is the same message/logic used for clue scrolls
|
||||
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
package content.region.kandarin.seers.quest.elementalworkshop2
|
||||
|
||||
import content.data.Quests
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.EXTRACTOR_BAD
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.EXTRACTOR_BAD_GFX
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.EXTRACTOR_GOOD
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.EXTRACTOR_GOOD_GFX
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.EXTR_GUN
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.toInstance
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Session.Companion.EW2_REGION
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2ExtractorGun
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2StageVarbit
|
||||
import core.api.*
|
||||
import core.game.activity.Cutscene
|
||||
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.Sounds
|
||||
|
||||
/**
|
||||
* The extractor hat cutscene in EW2
|
||||
*/
|
||||
|
||||
class EW2Cutscene(player: Player, good: Boolean) : Cutscene(player) {
|
||||
override fun setup() {
|
||||
setExit(toInstance(player, Location.create(1961, 5150, 0)))
|
||||
loadRegion(EW2_REGION)
|
||||
}
|
||||
|
||||
val successfulExtract = good
|
||||
|
||||
override fun runStage(stage: Int) {
|
||||
when(stage) {
|
||||
0 -> {
|
||||
teleport(player, 41, 30)
|
||||
moveCamera(37, 25, 350)
|
||||
rotateCamera(42, 29)
|
||||
timedUpdate(0)
|
||||
}
|
||||
|
||||
1 -> {
|
||||
face(player, player.location.transform(1, 0, 0))
|
||||
timedUpdate(0)
|
||||
}
|
||||
|
||||
2 -> {
|
||||
teleport(player, 42, 30)
|
||||
if (successfulExtract) {
|
||||
visualize(player, EXTRACTOR_GOOD, EXTRACTOR_GOOD_GFX)
|
||||
playAudio(player, Sounds.EW2_EXTRACTOR_OPERATION_3166)
|
||||
val gun = getScenery(base.transform(42, 28, 0))
|
||||
if (gun != null) animateScenery(gun, EXTR_GUN)
|
||||
timedUpdate(Animation(EXTRACTOR_GOOD).duration)
|
||||
} else {
|
||||
visualize(player, EXTRACTOR_BAD, EXTRACTOR_BAD_GFX)
|
||||
playAudio(player, Sounds.EW2_EXTRACTOR_ZAP_3173)
|
||||
timedUpdate(Animation(EXTRACTOR_BAD).duration)
|
||||
}
|
||||
}
|
||||
|
||||
3 -> {
|
||||
teleport(player, 41, 30)
|
||||
if (successfulExtract) {
|
||||
// make a mind bar
|
||||
setVarbit(player, EW2ExtractorGun, 2, true)
|
||||
|
||||
// drain magic
|
||||
adjustLevel(player, Skills.MAGIC, -20)
|
||||
sendMessage(player, "You feel magically weakened.")
|
||||
|
||||
// advance quest
|
||||
if (getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) <= 9) {
|
||||
setQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II, 10)
|
||||
setVarbit(player, EW2StageVarbit, 10, true)
|
||||
}
|
||||
} else {
|
||||
impact(player, 4)
|
||||
sendMessage(player, "The extractor hat shocks you!")
|
||||
}
|
||||
timedUpdate(1)
|
||||
}
|
||||
|
||||
4 -> {
|
||||
endWithoutFade {
|
||||
EW2Session(player).start(Location.create(1961, 5150, 0))
|
||||
setExit(toInstance(player, Location.create(1961, 5150, 0)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,85 @@
|
|||
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
|
||||
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.EW2Listeners.Companion.toInstance
|
||||
import core.api.*
|
||||
import core.game.interaction.QueueStrength
|
||||
import core.game.node.entity.Entity
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.world.map.Location
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
import core.game.world.map.zone.ZoneBorders
|
||||
|
||||
/**
|
||||
* Handles an instanced Elemental Workshop II session.
|
||||
*/
|
||||
|
||||
class EW2Session(val player: Player? = null) : MapArea {
|
||||
|
||||
companion object {
|
||||
const val EW2_REGION = 7760
|
||||
}
|
||||
|
||||
lateinit var region: DynamicRegion
|
||||
lateinit var base: Location
|
||||
|
||||
// borders will be registered dynamically in start()
|
||||
override fun defineAreaBorders(): Array<ZoneBorders> {
|
||||
return emptyArray()
|
||||
}
|
||||
|
||||
// start() is triggered by the listener for Scenery.HATCH_18596 and Scenery.STAIRS_18599
|
||||
fun start(loc: Location) {
|
||||
val p = player ?: return
|
||||
|
||||
region = DynamicRegion.create(EW2_REGION)
|
||||
base = region.baseLocation
|
||||
|
||||
zone.register(getRegionBorders(region.id))
|
||||
setAttribute(p, "ew2-session", this)
|
||||
|
||||
// logout listener returns player to the EW1 workshop
|
||||
registerLogoutListener(p, "ew2-logout") {
|
||||
val session = getAttribute<EW2Session?>(p, "ew2-session", null) ?: return@registerLogoutListener
|
||||
p.location = Location.create(2719, 9892, 0)
|
||||
p.locks.unlockTeleport()
|
||||
session.cleanup(p)
|
||||
}
|
||||
|
||||
// sync the workshop state
|
||||
syncCrane(p)
|
||||
syncCart(p)
|
||||
syncSteamPress(p)
|
||||
syncTank(p)
|
||||
syncTankDoor(p)
|
||||
syncFan(p)
|
||||
syncCogs(p)
|
||||
|
||||
val startLoc = toInstance(player, loc)
|
||||
|
||||
// teleport in after the workshop is ready
|
||||
queueScript(player, 1, QueueStrength.SOFT) {
|
||||
teleport(p, startLoc)
|
||||
return@queueScript true
|
||||
}
|
||||
}
|
||||
|
||||
// clean up the instanced area
|
||||
override fun areaLeave(entity: Entity, logout: Boolean) {
|
||||
if (entity is Player && entity == player && !logout) {
|
||||
cleanup(entity)
|
||||
}
|
||||
}
|
||||
|
||||
fun cleanup(p: Player) {
|
||||
zone.unregister(getRegionBorders(region.id))
|
||||
clearLogoutListener(p, "ew2-logout")
|
||||
removeAttribute(p, "ew2-session")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
package content.region.kandarin.seers.quest.elementalworkshop2
|
||||
|
||||
import content.data.Quests
|
||||
import core.api.*
|
||||
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.Items
|
||||
|
||||
/**
|
||||
* ELEMENTAL WORKSHOP II QUEST
|
||||
*
|
||||
* Requirements: 20 Magic, 30 Smithing, completion of Elemental Workshop I
|
||||
* 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
|
||||
class ElementalWorkshop2 : Quest(Quests.ELEMENTAL_WORKSHOP_II, 53, 52, 1, EW2StageVarbit, 0, 1, 11) {
|
||||
|
||||
// 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.
|
||||
const val EW2MachineryVarbit = 2640 // The machinery you have to search for the key. Set to 1 after you read the scroll.
|
||||
const val EW2HatchVarbit = 2641 // The hatch down to EW2. Set to 1 after you unlock it with the key.
|
||||
const val EW2CartLeverVarbit = 2642 // cart moving lever. 0 = start (south), 1 = west, 2 = north, 3 = east
|
||||
const val EW2JigCartVarbit = 2643 // Jig Cart state. 0 = Empty, 1 = ele bar, 2 = hot bar, 3 = smashed hot, 4 = smashed cooled, 5 = primed
|
||||
const val EW2CraneStateVarbit = 2644 // Crane State. 0 = broken, 1 = fixed/empty, 2 = ele bar, 3 = hot bar.
|
||||
const val EW2CranePosVarbit = 2645 // Crane Position. 0 = South Down, 1 = South Up, 2 = North Down, 3 = North Up.
|
||||
const val EW2JctVarbit1 = 2646 // junction box status. see junctionboxinterface for details.
|
||||
const val EW2JctVarbit2 = 2647 // junction box status. see junctionboxinterface for details.
|
||||
const val EW2JctVarbit3 = 2648 // junction box status. see junctionboxinterface for details.
|
||||
//const val EW2JctBoxVarbit = 2649 // junction box - this overlaps 2646, 2647, 2648. could be used to reset whole jct box at once.
|
||||
const val EW2PipeVarbit = 2650 // pipe varbit. 0 = broken, 1 = fixed
|
||||
const val EW2ValveWestVarbit = 2651 // water valve west. 0 = closed, 1 = open
|
||||
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 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.
|
||||
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 EW2ExtractorGun = 2662 // extractor gun. 0 = empty, 1 = primed bar, 2 = mind bar
|
||||
//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
|
||||
}
|
||||
|
||||
/**
|
||||
* Quest Stages and Varbit values:
|
||||
* https://chisel.weirdgloop.org/varbs/display?varbit=2639
|
||||
*
|
||||
* val stage desc.
|
||||
* 0 0 unstarted
|
||||
* 1 1 found the beaten book
|
||||
* 2 2 read the beaten book
|
||||
* 3 3 read the beaten book's scroll
|
||||
* 4 4 found key
|
||||
* 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 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
|
||||
val stage = getStage(player)
|
||||
|
||||
// unstarted
|
||||
if (stage == 0) {
|
||||
line(player, "I can start this quest by reading a", line++)
|
||||
line(player, "!!book?? found at the !!Dig Site??.", line++)
|
||||
line++
|
||||
line(player,"To start this quest I will need:", line++)
|
||||
line(player, "Level 20 Magic", line++, hasLevelStat(player, Skills.MAGIC, 20))
|
||||
line(player, "Level 30 Smithing", line++, hasLevelStat(player, Skills.SMITHING, 30))
|
||||
line(player,"I must have completed the following quests:", line++) // After - I have completed all of the required quests:
|
||||
line(player, "Elemental Workshop I", line++, isQuestComplete(player, Quests.ELEMENTAL_WORKSHOP_I))
|
||||
}
|
||||
|
||||
// stage 1, found the beaten book
|
||||
if (stage >= 1) {
|
||||
line(player, "I have found a book at the Dig Site.", line++, true)
|
||||
// in-progress stage text
|
||||
if(stage == 1) line(player, "I should read the book.", line++)
|
||||
line++
|
||||
}
|
||||
|
||||
// stage 2, read the beaten book
|
||||
if (stage >= 2) {
|
||||
line(player, "The book tells of a way to !!make elemental items??", line++, true)
|
||||
line(player, "even more !!powerful?? than before.", line++, true)
|
||||
// in-progress stage text
|
||||
if(stage == 2) line(player, "I should read the scroll.", line++)
|
||||
line++
|
||||
}
|
||||
|
||||
// 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)
|
||||
// in-progress stage text
|
||||
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 and getting the machines fixed
|
||||
if (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))
|
||||
|
||||
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, 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 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, "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, went through the mind door. I skip using this due to lack of source
|
||||
/*
|
||||
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)
|
||||
}
|
||||
|
||||
// quest complete
|
||||
if (stage >= 100) {
|
||||
line++
|
||||
line(player,"<col=FF0000>QUEST COMPLETE!</col>", line)
|
||||
}
|
||||
}
|
||||
|
||||
// use ::setqueststage 53 0 to reset quest.
|
||||
override fun reset(player: Player) {
|
||||
// these varps wipes all the varbits
|
||||
setVarp(player, EW2Varp1, 0, true)
|
||||
setVarp(player, EW2Varp2, 0, true)
|
||||
|
||||
// remove attributes
|
||||
removeAttribute(player, attrJigged)
|
||||
removeAttribute(player, attrDipped)
|
||||
removeAttribute(player, attrFlattened)
|
||||
removeAttribute(player, attrWatered)
|
||||
removeAttribute(player, attrWinded)
|
||||
|
||||
// sync the quest tab
|
||||
player.getQuestRepository().syncronizeTab(player)
|
||||
super.reset(player)
|
||||
}
|
||||
|
||||
override fun setStage(player: Player, stage: Int) {
|
||||
super.setStage(player, stage)
|
||||
this.updateVarps(player)
|
||||
}
|
||||
|
||||
override fun updateVarps(player: Player) {
|
||||
// The quest stages are perfectly aligned with the varp
|
||||
if (getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II) >= 11) {
|
||||
setVarbit(player, EW2StageVarbit, 11, true) // except for stage 100 which is varp set to 11.
|
||||
} else {
|
||||
setVarbit(player, EW2StageVarbit, getQuestStage(player, Quests.ELEMENTAL_WORKSHOP_II), true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun finish(player: Player) {
|
||||
var ln = 10
|
||||
super.finish(player)
|
||||
player.packetDispatch.sendString("You have completed the Elemental Workshop II Quest!", 277, 4)
|
||||
player.packetDispatch.sendItemZoomOnInterface(Items.MIND_HELMET_9733, 230, 277, 5)
|
||||
|
||||
drawReward(player, "1 Quest Point", ln++)
|
||||
drawReward(player, "7500 Smithing XP,", ln++)
|
||||
drawReward(player, "7500 Crafting XP,", ln++)
|
||||
drawReward(player, "Ability to make and equip", ln++)
|
||||
drawReward(player, "elemental mind equipment", ln)
|
||||
|
||||
setVarbit(player, EW2StageVarbit, 11, true)
|
||||
rewardXP(player, Skills.SMITHING, 7500.0)
|
||||
rewardXP(player, Skills.CRAFTING, 7500.0)
|
||||
|
||||
removeAttribute(player, attrJigged)
|
||||
removeAttribute(player, attrDipped)
|
||||
removeAttribute(player, attrFlattened)
|
||||
removeAttribute(player, attrWatered)
|
||||
removeAttribute(player, attrWinded)
|
||||
}
|
||||
|
||||
override fun newInstance(`object`: Any?): Quest {
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package content.region.kandarin.seers.quest.elementalworkshop2
|
||||
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.EW2Listeners.Companion.jigCartStates
|
||||
import core.game.node.entity.npc.NPC
|
||||
import core.game.node.entity.npc.NPCBehavior
|
||||
import core.game.world.map.path.ClipMaskSupplier
|
||||
|
||||
/**
|
||||
* 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 JigCartNPCBehavior : NPCBehavior(*jigCartStates) {
|
||||
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 {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
package content.region.kandarin.seers.quest.elementalworkshop2
|
||||
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2JctVarbit1
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2JctVarbit2
|
||||
import content.region.kandarin.seers.quest.elementalworkshop2.ElementalWorkshop2.Companion.EW2JctVarbit3
|
||||
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
|
||||
*/
|
||||
|
||||
class JunctionBoxInterface : InterfaceListener {
|
||||
|
||||
private val junctionBox = Components.JUNCTION_BOX_262
|
||||
|
||||
// 1317.cs2 controls the visibility of the pipes based on varbit 4835
|
||||
private val pipesLeftVarbit = 4835 // 0 = no pipes, 1 = one pipe, 2 = two pipes, 3 = three pipes
|
||||
|
||||
// 1319.cs2 controls the highlighting of the pipe based on varbit 4834
|
||||
private val pipeSelectVarbit =
|
||||
4834 // 0 = no select, 1 = top left, 2 = top middle, 3 = top right, 4 = bottom left, 5 = bottom middle, 6 = bottom right
|
||||
|
||||
private val firstSelect = EW2JctVarbit1 // this is the main quest varbit used to save and recall pipe selection. values 0-15
|
||||
private val secondSelect = EW2JctVarbit2 // this is the main quest varbit used to save and recall pipe selection. values 0-15
|
||||
private val thirdSelect = EW2JctVarbit3 // this is the main quest varbit used to save and recall pipe selection. values 0-15
|
||||
|
||||
// the interface children for displaying each placed pipe
|
||||
private val pipes = intArrayOf(
|
||||
5, // from button1 to button4
|
||||
6, // from button2 to button5
|
||||
7, // from button3 to button6
|
||||
|
||||
8, // from button4 to button5 NEEDED TO SOLVE
|
||||
9, // from button4 to button6
|
||||
10,// from button5 to button6
|
||||
11,// from button1 to button5
|
||||
12,// from button1 to button6 NEEDED TO SOLVE
|
||||
|
||||
13,// from button1 to button2
|
||||
14,// from button1 to button3
|
||||
|
||||
15,// from button2 to button4
|
||||
16,// from button2 to button6
|
||||
|
||||
17,// from button2 to button3 NEEDED TO SOLVE
|
||||
18,// from button3 to button4
|
||||
|
||||
19,// from button3 to button5
|
||||
)
|
||||
|
||||
// this solution checker is called in the lever listeners
|
||||
companion object {
|
||||
/**
|
||||
* Checks if the three specific pipes required for the puzzle solution are placed.
|
||||
*/
|
||||
fun isSolutionCorrect(player: Player): Boolean {
|
||||
val s1 = getVarbit(player, EW2JctVarbit1)
|
||||
val s2 = getVarbit(player, EW2JctVarbit2)
|
||||
val s3 = getVarbit(player, EW2JctVarbit3)
|
||||
|
||||
val requiredIndices = intArrayOf(3, 7, 12)
|
||||
val currentValues = intArrayOf(s1, s2, s3)
|
||||
|
||||
return requiredIndices.all { required ->
|
||||
currentValues.contains(required + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun defineInterfaceListeners() {
|
||||
onOpen(junctionBox) { player, _ ->
|
||||
val s1 = getVarbit(player, firstSelect)
|
||||
val s2 = getVarbit(player, secondSelect)
|
||||
val s3 = getVarbit(player, thirdSelect)
|
||||
|
||||
// Hide all pipes initially
|
||||
pipes.forEach { setComponentVisibility(player, junctionBox, it, true) }
|
||||
|
||||
// Count how many pipes are already placed to set pipesLeftVarbit
|
||||
var placedCount = 0
|
||||
if (s1 > 0) {
|
||||
setComponentVisibility(player, junctionBox, pipes[s1 - 1], false); placedCount++
|
||||
}
|
||||
if (s2 > 0) {
|
||||
setComponentVisibility(player, junctionBox, pipes[s2 - 1], false); placedCount++
|
||||
}
|
||||
if (s3 > 0) {
|
||||
setComponentVisibility(player, junctionBox, pipes[s3 - 1], false); placedCount++
|
||||
}
|
||||
|
||||
setVarbit(player, pipesLeftVarbit, 3 - placedCount, true)
|
||||
|
||||
// reset any selected
|
||||
setVarbit(player, pipeSelectVarbit, 0, true)
|
||||
|
||||
return@onOpen true
|
||||
}
|
||||
|
||||
/**
|
||||
* When a button is pressed, we first check to see if the pipeSelect varbit has been set.
|
||||
* If it's zero, this is our first selection. Record it.
|
||||
* If it has a value, select the child to display based on the pipeSelect varbit and current button selection.
|
||||
* After displaying a child, clear pipeSelect and decrement the pipesLeft varbit.
|
||||
* If this is the first selection, record the child in the firstSelect varbit.
|
||||
* If this is the second selection, record the child in the secondSelect varbit.
|
||||
* If this is the third selection, record the child in the thirdSelect varbit.
|
||||
*/
|
||||
on(junctionBox) { player, _, _, buttonID, _, _ ->
|
||||
|
||||
// interface buttons
|
||||
// i think some of this is also controlled by 1318.cs2 fwiw
|
||||
val b1 = 24;
|
||||
val b2 = 25;
|
||||
val b3 = 20
|
||||
val b4 = 21;
|
||||
val b5 = 22;
|
||||
val b6 = 23
|
||||
|
||||
// check if the player is clicking a button that already has a pipe attached. if yes, remove the pipe.
|
||||
if (getVarbit(player, pipeSelectVarbit) == 0) {
|
||||
if (tryDetachPipe(player, buttonID, b1, b2, b3, b4, b5, b6)) {
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
val currentSelection = getVarbit(player, pipeSelectVarbit)
|
||||
|
||||
// connecting a new pipe
|
||||
if (currentSelection == 0) {
|
||||
val selection = when (buttonID) {
|
||||
b1 -> 1; b2 -> 2; b3 -> 3
|
||||
b4 -> 4; b5 -> 5; b6 -> 6
|
||||
else -> 0
|
||||
}
|
||||
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, true)
|
||||
return@on true
|
||||
}
|
||||
|
||||
// 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 {
|
||||
getVarbit(player, firstSelect) == 0 -> {
|
||||
setVarbit(player, firstSelect, pipeIndex + 1, true); true
|
||||
}
|
||||
|
||||
getVarbit(player, secondSelect) == 0 -> {
|
||||
setVarbit(player, secondSelect, pipeIndex + 1, true); true
|
||||
}
|
||||
|
||||
getVarbit(player, thirdSelect) == 0 -> {
|
||||
setVarbit(player, thirdSelect, pipeIndex + 1, true); true
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
|
||||
if (saved) {
|
||||
val left = getVarbit(player, pipesLeftVarbit)
|
||||
setVarbit(player, pipesLeftVarbit, left - 1, true)
|
||||
}
|
||||
}
|
||||
setVarbit(player, pipeSelectVarbit, 0, true)
|
||||
}
|
||||
|
||||
// if there are no pipes left, we have placed them all. hammer time!
|
||||
if (getVarbit(player, pipesLeftVarbit) == 0) {
|
||||
lock(player, 3)
|
||||
runTask(player, 2) {
|
||||
closeInterface(player)
|
||||
sendPlayerDialogue(player, "I hope I got that right.")
|
||||
}
|
||||
}
|
||||
return@on true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any active pipe uses the clicked button as an endpoint.
|
||||
* If so, it removes that pipe and increments the pipesLeftVarbit.
|
||||
*/
|
||||
private fun tryDetachPipe(
|
||||
player: Player,
|
||||
buttonID: Int,
|
||||
b1: Int,
|
||||
b2: Int,
|
||||
b3: Int,
|
||||
b4: Int,
|
||||
b5: Int,
|
||||
b6: Int
|
||||
): Boolean {
|
||||
val saveVarbits = intArrayOf(firstSelect, secondSelect, thirdSelect)
|
||||
|
||||
for (v in saveVarbits) {
|
||||
val pipeIndexPlusOne = getVarbit(player, v)
|
||||
if (pipeIndexPlusOne == 0) continue
|
||||
|
||||
val pipeIndex = pipeIndexPlusOne - 1
|
||||
// Check if the clicked button is one of the two ends for this pipe index
|
||||
if (isButtonPartOfPipe(pipeIndex, buttonID, b1, b2, b3, b4, b5, b6)) {
|
||||
// Hide the pipe on interface
|
||||
setComponentVisibility(player, junctionBox, pipes[pipeIndex], true)
|
||||
// Reset the varbit
|
||||
setVarbit(player, v, 0, true)
|
||||
// Increment pipes left
|
||||
val left = getVarbit(player, pipesLeftVarbit)
|
||||
setVarbit(player, pipesLeftVarbit, left + 1, true)
|
||||
playAudio(player, Sounds.EW2_REMOVE_PIPE_3181)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// just read the function title
|
||||
private fun isPipeAlreadyPlaced(player: Player, pipeID: Int): Boolean {
|
||||
return getVarbit(player, firstSelect) == pipeID ||
|
||||
getVarbit(player, secondSelect) == pipeID ||
|
||||
getVarbit(player, thirdSelect) == pipeID
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the start selection (1-6) and the end button ID to the index in the 'pipes' array.
|
||||
*/
|
||||
private fun getPipeIndex(start: Int, endBtn: Int, b1: Int, b2: Int, b3: Int, b4: Int, b5: Int, b6: Int): Int {
|
||||
return when (start) {
|
||||
1 -> when (endBtn) { // Top Left
|
||||
b4 -> 0; b5 -> 6; b6 -> 7; b2 -> 8; b3 -> 9; else -> -1
|
||||
}
|
||||
|
||||
2 -> when (endBtn) { // Top Mid
|
||||
b5 -> 1; b4 -> 10; b6 -> 11; b1 -> 8; b3 -> 12; else -> -1
|
||||
}
|
||||
|
||||
3 -> when (endBtn) { // Top Right
|
||||
b6 -> 2; b4 -> 13; b5 -> 14; b1 -> 9; b2 -> 12; else -> -1
|
||||
}
|
||||
|
||||
4 -> when (endBtn) { // Bottom Left
|
||||
b1 -> 0; b5 -> 3; b6 -> 4; b2 -> 10; b3 -> 13; else -> -1
|
||||
}
|
||||
|
||||
5 -> when (endBtn) { // Bottom Mid
|
||||
b2 -> 1; b4 -> 3; b6 -> 5; b1 -> 6; b3 -> 14; else -> -1
|
||||
}
|
||||
|
||||
6 -> when (endBtn) { // Bottom Right
|
||||
b3 -> 2; b4 -> 4; b5 -> 5; b1 -> 7; b2 -> 11; else -> -1
|
||||
}
|
||||
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
private fun isButtonPartOfPipe(
|
||||
pipeIndex: Int,
|
||||
buttonID: Int,
|
||||
b1: Int,
|
||||
b2: Int,
|
||||
b3: Int,
|
||||
b4: Int,
|
||||
b5: Int,
|
||||
b6: Int
|
||||
): Boolean {
|
||||
return when (pipeIndex) {
|
||||
0 -> buttonID == b1 || buttonID == b4
|
||||
1 -> buttonID == b2 || buttonID == b5
|
||||
2 -> buttonID == b3 || buttonID == b6
|
||||
3 -> buttonID == b4 || buttonID == b5
|
||||
4 -> buttonID == b4 || buttonID == b6
|
||||
5 -> buttonID == b5 || buttonID == b6
|
||||
6 -> buttonID == b1 || buttonID == b5
|
||||
7 -> buttonID == b1 || buttonID == b6
|
||||
8 -> buttonID == b1 || buttonID == b2
|
||||
9 -> buttonID == b1 || buttonID == b3
|
||||
10 -> buttonID == b2 || buttonID == b4
|
||||
11 -> buttonID == b2 || buttonID == b6
|
||||
12 -> buttonID == b2 || buttonID == b3
|
||||
13 -> buttonID == b3 || buttonID == b4
|
||||
14 -> buttonID == b3 || buttonID == b5
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +64,11 @@ public final class Appearance {
|
|||
*/
|
||||
private boolean ridingMinecart;
|
||||
|
||||
/**
|
||||
* If the player's shield should be hidden (like when equipping elemental shields).
|
||||
*/
|
||||
private boolean hideShield;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code Appearance} {@code Object}.
|
||||
* @param player the player of this appearance.
|
||||
|
|
@ -279,7 +284,7 @@ public final class Appearance {
|
|||
} else {
|
||||
clearBodyPart(3);
|
||||
}
|
||||
if (shield != null) {
|
||||
if (shield != null && !hideShield) {
|
||||
drawItem(5, shield);
|
||||
} else {
|
||||
clearBodyPart(5);
|
||||
|
|
@ -682,6 +687,22 @@ public final class Appearance {
|
|||
this.ridingMinecart = ridingMinecart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hideShield
|
||||
* @return the hideShield
|
||||
*/
|
||||
public boolean isHideShield() {
|
||||
return hideShield;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the hideShield
|
||||
* @param hideShield the hideShield to set.
|
||||
*/
|
||||
public void setHideShield(boolean hideShield) {
|
||||
this.hideShield = hideShield;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a class of cached appearance related information.
|
||||
* @author 'Vexia
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue