diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/BatteredBookHandler.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/BatteredBookHandler.kt index b25b5d20e..e64501678 100644 --- a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/BatteredBookHandler.kt +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/BatteredBookHandler.kt @@ -8,6 +8,11 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.Items +/** + * Battered book handler for the Elemental Workshop I quest + * + * @author Woah, with love + */ @Initializable class BatteredBookHandler : Book { @@ -20,8 +25,7 @@ class BatteredBookHandler : Book { } override fun finish() { - val stage = player.questRepository.getStage("Elemental Workshop I") - if (stage == 0) { + if (EWUtils.currentStage(player) == 0) { setQuestStage(player, "Elemental Workshop I", 1) } } diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/EWListeners.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/EWListeners.kt index 5c74bd760..4230afd48 100644 --- a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/EWListeners.kt +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/EWListeners.kt @@ -19,6 +19,11 @@ import rs09.game.content.quest.members.elementalworkshop.EWUtils.currentStage import rs09.game.interaction.InteractionListener import rs09.game.system.SystemLogger +/** + * Listeners for the Elemental Workshop I quest + * + * @author Woah, with love + */ class EWListeners : InteractionListener { /* Items */ @@ -58,6 +63,7 @@ class EWListeners : InteractionListener { private val fillStoneBowlAnimation = Animation(Animations.HUMAN_FILL_STONE_BOWL_4862) private val fixBellowsAnimation = Animation(Animations.HUMAN_SEW_LARGE_SCENERY_4862) private val smeltElementalBar = Animation(Animations.HUMAN_FURNACE_SMELTING_3243) + private val smithElementalShield = Animation(Animations.HUMAN_COOKING_RANGE_896) /* Sound effects */ private val fillStoneBowlSFX = Audio(Sounds.FILL_STONE_BOWL_1537, 1) @@ -67,11 +73,15 @@ class EWListeners : InteractionListener { private val pullLeverEnabledSFX = Audio(Sounds.PULL_LEVER_ENABLED_1547) private val pullLeverDisabledSFX = Audio(Sounds.PULL_LEVER_DISABLED_1548) private val bellowLeverSFX = Audio(Sounds.PULL_LEVER_GENERAL_2400) + private val smithElementalShieldSFX = Audio(2721) /* In-game locations */ private val leftWaterControlsLocation = Location.create(2713, 9907, 0) private val rightWaterControlsLocation = Location.create(2726, 9907, 0) + /* Special interactions */ + private val furnaceIDS = intArrayOf(4304, 6189, 11010, 11666, 12100, 12809, 14921, 18497, 26814, 30021, 30510, 36956, 37651) + private val DISABLED = 0 private val ENABLED = 1 @@ -81,7 +91,7 @@ class EWListeners : InteractionListener { * * * * * * * * * * * * * * * * * */ // Bookcase (quest start) on(Scenery.BOOKCASE_26113, SCENERY, "search") { player, _ -> - val stage = player.questRepository.getStage("Elemental Workshop I") + val stage = currentStage(player) if (stage < 3) { // Player already has battered book in inventory @@ -104,13 +114,17 @@ class EWListeners : InteractionListener { "There is a book here titled 'The Elemental Shield'. " + "It can stay here, as you have a copy in your backpack." ) - player.inventory.addIfDoesntHave(batteredKey) + if (player.inventory.addIfDoesntHave(batteredKey)) { + sendItemDialogue(player, Item(Items.BATTERED_KEY_2887),"You also find a key.") + } return@on true } sendItemDialogue(player, Item(Items.SLASHED_BOOK_9715), "You find a book titled 'The Elemental Shield'.") addItem(player, slashedBook.id) - player.inventory.addIfDoesntHave(batteredKey) + if (player.inventory.addIfDoesntHave(batteredKey)) { + sendItemDialogue(player, Item(Items.BATTERED_KEY_2887),"You also find a key.") + } return@on true } @@ -149,6 +163,11 @@ class EWListeners : InteractionListener { * * * * * * * * * * * * * * * * * */ // Odd looking wall handler on(intArrayOf(Scenery.ODD_LOOKING_WALL_26114, Scenery.ODD_LOOKING_WALL_26115), SCENERY, "open") { player, wall -> + // Nothing interesting happens if quest wasn't started. + if (currentStage(player) < 1) { + sendMessage(player, "Nothing interesting happens.") + return@on true + } // Player is allowed to exit without key if (player.location == Location.create(2710, 3496, 0) || player.location == Location.create(2709, 3496, 0)) { DoorActionHandler.handleAutowalkDoor(player, wall.asScenery()) @@ -170,12 +189,19 @@ class EWListeners : InteractionListener { } on(Scenery.STAIRCASE_3415, SCENERY, "climb-down") { player, _ -> + val stage = currentStage(player) + // Prevent player from somehow skipping beginning quest stages + if (stage < 1) { + sendMessage(player, "Nothing interesting happens.") + return@on true + } + // Move player to downstairs location teleport(player, Location.create(2716, 9888, 0)) // If it is the players first time in the workshop - if (currentStage(player) < 6) { + if (stage < 6) { sendPlayerDialogue(player, "Now to explore this area thoroughly, to find what " + - "forgotten secrets it contains.", FacialExpression.NEUTRAL) + "forgotten secrets it contains.", FacialExpression.NEUTRAL) setQuestStage(player, "Elemental Workshop I", 7) } return@on true @@ -233,7 +259,7 @@ class EWListeners : InteractionListener { } // Workbenches/Anvil - onUseWith(SCENERY, Items.ELEMENTAL_METAL_2893, Scenery.WORKBENCH_3402) { player, used, _ -> + onUseWith(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.") @@ -241,12 +267,12 @@ class EWListeners : InteractionListener { } // 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))) { - sendMessage(player, "You are unsure what to do with the bar. Perhaps there is a book to help guide you.") + 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)) { - sendMessage(player, "You don't have a tool available to shape the metal.") + sendDialogue(player, "You don't have a tool available to shape the metal.") return@onUseWith true } // Sanity error check (Should never get thrown) @@ -255,9 +281,19 @@ class EWListeners : InteractionListener { return@onUseWith false } // Successfully smith the elemental shield - replaceSlot(player, used.asItem().slot, elementalShield) - sendMessage(player, "Following the instructions in the book you make an elemental shield.") - player.questRepository.getQuest("Elemental Workshop I").finish(player) + 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("Elemental Workshop I").isCompleted(player)) { + player.questRepository.getQuest("Elemental Workshop I").finish(player) + } return@onUseWith true } @@ -340,8 +376,8 @@ class EWListeners : InteractionListener { return@onUseWith true } - val duration = animationDuration(smeltElementalBar) - lock(player, (duration + 1)) + val barSmeltingDuration = animationDuration(smeltElementalBar) + lock(player, barSmeltingDuration + 2) // Run the "smelting" pulse submitIndividualPulse(player, object : Pulse() { var count = 0 @@ -353,7 +389,7 @@ class EWListeners : InteractionListener { animate(player, Animations.HUMAN_FURNACE_SMELTING_3243) sendMessage(player, "You place the elemental ore and four heaps of coal into the furnace.") } - duration -> { + barSmeltingDuration -> { addItem(player, Items.ELEMENTAL_METAL_2893) sendMessage(player, "You retrieve a bar of elemental metal.") rewardXP(player, Skills.SMITHING, 7.0) @@ -367,6 +403,20 @@ class EWListeners : InteractionListener { return@onUseWith true } + /* Special Interactions: + * onUseWith FURNACE scenery (this handler) + * onUseWith BLAST FURNACE BELT (this handler) + * onCast SUPERHEAT spell (ModernListeners.kt) + * SKIPPED DUE TO SPAGHETTI: on BLAST FURNACE BELT "put-ore-on" (BlastfurnaceListeners.kt) + */ + onUseWith(SCENERY, Items.ELEMENTAL_ORE_2892, *furnaceIDS) { player, _, _ -> + sendMessage(player, "This furnace is not hot enough to smelt elemental ore.") + return@onUseWith true + } + onUseWith(SCENERY, Items.ELEMENTAL_ORE_2892, Scenery.CONVEYOR_BELT_9100) { player, _, _ -> + sendMessage(player, "There would be no point in smelting that.") + return@onUseWith true + } /* * * * * * * * * * * * * * * Water room listeners * @@ -479,9 +529,17 @@ class EWListeners : InteractionListener { return@on true } // Warn player they don't have the required items - if (!player.inventory.containsAll(*bellowFixReqItems)) { - sendMessage(player, "You don't have the required item(s) to fix the bellows.") - return@on true + bellowFixReqItems.forEach { reqItem -> + if (!player.inventory.contains(reqItem, 1)) { + val missingItemMsg = when (reqItem) { + Items.NEEDLE_1733 -> "a needle" + Items.THREAD_1734 -> "some thread" + Items.LEATHER_1741 -> "a piece of leather" + else -> "NULL" // Should never be called; no sense in making an enum + } + sendMessage(player, "You need $missingItemMsg to fix the bellows.") + return@on true + } } // If the player has all the requirements to fix the bellows lock(player, (animationDuration(fixBellowsAnimation) + 1)) @@ -529,8 +587,22 @@ class EWListeners : InteractionListener { setDest(SCENERY, intArrayOf(Scenery.FURNACE_18525, Scenery.FURNACE_18526), "use") { _, _ -> return@setDest Location.create(2724,9875) } - setDest(SCENERY, intArrayOf( Scenery.BELLOWS_18516), "fix") { _, _ -> + setDest(SCENERY, intArrayOf(Scenery.BELLOWS_18516), "fix") { _, _ -> return@setDest Location.create(2733, 9884, 0) } + setDest(SCENERY, intArrayOf(Scenery.ODD_LOOKING_WALL_26115), "open") { player, _ -> + if (inBorders(player, 2709, 3496, 2711, 3498)) { + return@setDest Location.create(2709, 3496, 0) + } else { + return@setDest Location.create(2709, 3495, 0) + } + } + setDest(SCENERY, intArrayOf(Scenery.ODD_LOOKING_WALL_26114), "open") { player, _ -> + if (inBorders(player, 2709, 3496, 2711, 3498)) { + return@setDest Location.create(2710, 3496, 0) + } else { + return@setDest Location.create(2710, 3495, 0) + } + } } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/EWUtils.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/EWUtils.kt index 6799d74a1..c0e39e95f 100644 --- a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/EWUtils.kt +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/EWUtils.kt @@ -7,6 +7,12 @@ import core.game.content.dialogue.book.PageSet import core.game.node.entity.player.Player import org.rs09.consts.Vars +/** + * Utils for the Elemental Workshop I quest + * Book/Varp/Method Utils + * + * @author Woah, with love + */ object EWUtils { // Helpers for the battered/slashed book diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/ElementalRockNPC.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/ElementalRockNPC.kt index a98fa10c1..02873b677 100644 --- a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/ElementalRockNPC.kt +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/ElementalRockNPC.kt @@ -29,6 +29,8 @@ class ElementalRockNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id // Sanity transform back to elemental rock override fun init() { + isWalks = false + isNeverWalks = true transform(NPCs.ELEMENTAL_ROCK_4911) super.init() } @@ -41,19 +43,21 @@ class ElementalRockNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id return intArrayOf(NPCs.EARTH_ELEMENTAL_4910, NPCs.ELEMENTAL_ROCK_4911) } + // The NPC stays in their upright form when the player + // stops attacking and can walk around override fun defineListeners() { on(ids, NPC, "Mine") { player, node -> val tool: SkillingTool? = getTool(player, true) - // Warn player they don't have a high enough mining level - if (player.skills.getStaticLevel(Skills.MINING) < 20) { - sendDialogue(player, "You need a mining level of at least 20 to mine elemental ore.") - return@on true - } // Check to see if the player can proc the NPC if (tool == null) { sendDialogue(player, "You do not have a pickaxe which you have the Mining level to use.") return@on true } + // Warn player they don't have a high enough mining level + if (player.skills.getStaticLevel(Skills.MINING) < 20) { + sendDialogue(player, "You need a mining level of at least 20 to mine elemental ore.") + return@on true + } // Transform the current NPC to 4910 (monster form) pulseManager.run(object : Pulse() { var count = 0 @@ -69,6 +73,8 @@ class ElementalRockNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id // Start attacking the player 3 -> { node.asNpc().attack(player) + node.asNpc().isNeverWalks = false + node.asNpc().isWalks = true return true } } @@ -82,6 +88,8 @@ class ElementalRockNPC(id: Int = 0, location: Location? = null) : AbstractNPC(id // Reset back to rock NPC override fun finalizeDeath(killer: Entity?) { + isWalks = false + isNeverWalks = true transform(NPCs.ELEMENTAL_ROCK_4911) super.finalizeDeath(killer) } diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/ElementalWorkshopQuest.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/ElementalWorkshopQuest.kt index 5b602d360..df64d3239 100644 --- a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/ElementalWorkshopQuest.kt +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/ElementalWorkshopQuest.kt @@ -3,6 +3,7 @@ package rs09.game.content.quest.members.elementalworkshop import api.Commands import api.addItem import api.setAttribute +import api.setVarbit import core.game.node.entity.player.Player import core.game.node.entity.player.link.quest.Quest import core.game.node.entity.skill.Skills @@ -131,5 +132,17 @@ class ElementalWorkshopQuest : Quest("Elemental Workshop I", 52, 51, 1), Command addItem(player, Items.HAMMER_2347) addItem(player, Items.COAL_453, 4) } + define("readyew", Privilege.ADMIN) { player, _ -> + val enabled = 1 + setAttribute(player, "/save:ew1:got_needle", true) + setAttribute(player, "/save:ew1:got_leather", true) + setAttribute(player, "/save:ew1:bellows_fixed", true) + player.questRepository.setStageNonmonotonic(player.questRepository.forIndex(52), 95) + setVarbit(player, Vars.VARP_QUEST_ELEMENTAL_WORKSHOP, EWUtils.BELLOWS_STATE, enabled, true) + setVarbit(player, Vars.VARP_QUEST_ELEMENTAL_WORKSHOP, EWUtils.FURNACE_STATE, enabled, true) + setVarbit(player, Vars.VARP_QUEST_ELEMENTAL_WORKSHOP, EWUtils.WATER_WHEEL_STATE, enabled, true) + setVarbit(player, Vars.VARP_QUEST_ELEMENTAL_WORKSHOP, EWUtils.RIGHT_WATER_CONTROL_STATE, enabled, true) + setVarbit(player, Vars.VARP_QUEST_ELEMENTAL_WORKSHOP, EWUtils.LEFT_WATER_CONTROL_STATE, enabled, true) + } } } \ No newline at end of file diff --git a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/SlashedBookHandler.kt b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/SlashedBookHandler.kt index b0fa09bc9..b3a6940d5 100644 --- a/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/SlashedBookHandler.kt +++ b/Server/src/main/kotlin/rs09/game/content/quest/members/elementalworkshop/SlashedBookHandler.kt @@ -7,6 +7,11 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.Items +/** + * Slashed book handler for the Elemental Workshop I quest + * + * @author Woah, with love + */ @Initializable class SlashedBookHandler : Book { constructor(player: Player?) : super(player, "Book of the elemental shield", Items.SLASHED_BOOK_9715, *EWUtils.PAGES) {} diff --git a/Server/src/main/kotlin/rs09/game/node/entity/skill/magic/ModernListeners.kt b/Server/src/main/kotlin/rs09/game/node/entity/skill/magic/ModernListeners.kt index bc9c48877..c76f784a1 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/skill/magic/ModernListeners.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/skill/magic/ModernListeners.kt @@ -3,6 +3,7 @@ package rs09.game.node.entity.skill.magic import api.events.ItemAlchemizationEvent import api.events.TeleportEvent import api.getAttribute +import api.sendMessage import core.game.content.activity.mta.impl.GraveyardZone import core.game.content.global.Bones import core.game.interaction.MovementPulse @@ -10,8 +11,8 @@ import core.game.node.entity.Entity import core.game.node.entity.impl.Animator.Priority import core.game.node.entity.impl.Projectile import core.game.node.entity.player.Player -import core.game.node.entity.player.link.audio.Audio import core.game.node.entity.player.link.TeleportManager +import core.game.node.entity.player.link.audio.Audio import core.game.node.entity.player.link.diary.DiaryType import core.game.node.entity.skill.Skills import core.game.node.entity.skill.smithing.smelting.Bar @@ -188,6 +189,12 @@ class ModernListeners : SpellListener("modern"){ return } + // Elemental Workshop I special interaction + if(item.id == Items.ELEMENTAL_ORE_2892) { + sendMessage(player, "Even this spell is not hot enough to heat this item.") + return + } + var bar = Bar.forOre(item.id) ?: return if(bar == Bar.IRON && player.inventory.getAmount(Items.COAL_453) >= 2 && player.skills.getLevel(Skills.SMITHING) >= Bar.STEEL.level && player.inventory.contains(Items.IRON_ORE_441,1)) bar = Bar.STEEL