From bf8b0b61521b18fef53f543221e496790eab764e Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 9 Nov 2024 15:34:53 +0100 Subject: [PATCH 01/60] progress --- .../quests/thecurseofarrav/RubbleMiner.java | 194 +++++++ .../thecurseofarrav/TheCurseOfArrav.java | 548 ++++++++++++++++++ .../thecurseofarrav/TilePuzzleSolver.java | 396 +++++++++++++ .../questinfo/QuestHelperQuest.java | 2 + .../questhelper/questinfo/QuestVarbits.java | 1 + .../conditional/ConditionForStep.java | 5 +- .../conditional/ObjectCondition.java | 29 +- 7 files changed, 1169 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/RubbleMiner.java create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/RubbleMiner.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/RubbleMiner.java new file mode 100644 index 0000000000..339f0b8518 --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/RubbleMiner.java @@ -0,0 +1,194 @@ +package com.questhelper.helpers.quests.thecurseofarrav; + +import com.questhelper.helpers.quests.thepathofglouphrie.DiscInsertionStep; +import com.questhelper.requirements.Requirement; +import com.questhelper.requirements.conditional.Conditions; +import com.questhelper.requirements.conditional.ObjectCondition; +import com.questhelper.requirements.item.ItemRequirement; +import com.questhelper.requirements.util.LogicType; +import com.questhelper.requirements.widget.WidgetPresenceRequirement; +import com.questhelper.steps.*; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.annotation.Nullable; +import javax.inject.Inject; + +import com.questhelper.steps.tools.QuestPerspective; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.*; +import net.runelite.api.coords.Direction; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.GameTick; +import net.runelite.client.eventbus.Subscribe; +import org.apache.commons.lang3.tuple.Pair; + +import static com.questhelper.requirements.util.LogicHelper.and; +import static com.questhelper.requirements.util.LogicHelper.nor; + +@Slf4j +public class RubbleMiner extends DetailedOwnerStep { + @Inject + Client client; + + private List mineSteps; + private List conditions; + private ConditionalStep conditionalStep; + + private int operation; + + public RubbleMiner(TheCurseOfArrav theCurseOfArrav) { + super(theCurseOfArrav, "Make your way through the Trollweiss cave, mining rubble with your pickaxe."); + } + + + private void addMineRubbleStep(int x, int y, RubbleLevel rubbleLevel, Direction direction) { + var validObjectIDs = rubbleLevel.getObjectIDs(); + assert !validObjectIDs.isEmpty(); + + var validIDSet = new HashSet<>(validObjectIDs); + + var wp = new WorldPoint(x, y, 0); + var operation = this.operation++; + var text = String.format("[%d] Mine the rubble from the %s side", operation, direction.toString().toLowerCase()); + log.info("setting up mine rubble step: {}: {}", operation, text); + var mainObjectID = validObjectIDs.get(0); + var step = new ObjectStep(getQuestHelper(), mainObjectID, wp, text); + var offsetX = x; + var offsetY = y; + switch (direction) { + case NORTH: + offsetY += 1; + break; + case SOUTH: + offsetY -= 1; + break; + case WEST: + offsetX -= 1; + break; + case EAST: + offsetX += 1; + break; + } + var posWp = new WorldPoint(offsetX, offsetY, 0); + step.addTileMarker(posWp, SpriteID.SKILL_MINING); + for (var alternateIDs : validObjectIDs) { + // todo this adds the first object again xd + step.addAlternateObjects(alternateIDs); + } + + var conditionText = String.format("[%d] Rubble mined from the %s side", operation, direction.toString().toLowerCase()); + var conditionThatThisStepHasBeenDone = new ObjectCondition(validIDSet, wp); + conditionThatThisStepHasBeenDone.setText(text); + + this.mineSteps.add(step); + this.conditions.add(conditionThatThisStepHasBeenDone); + } + + @Subscribe + public void onGameTick(GameTick event) { + updateSteps(); + } + + @Override + public void startUp() { + updateSteps(); + } + + @Override + protected void setupSteps() { + this.operation = 1; + this.mineSteps = new ArrayList<>(); + this.conditions = new ArrayList<>(); + + var todo = new DetailedQuestStep(getQuestHelper(), "todo"); + + this.addMineRubbleStep(2764, 10266, RubbleLevel.Two, Direction.SOUTH); + this.addMineRubbleStep(2775, 10258, RubbleLevel.One, Direction.SOUTH); + this.addMineRubbleStep(2764, 10266, RubbleLevel.One, Direction.EAST); + this.addMineRubbleStep(2764, 10267, RubbleLevel.One, Direction.SOUTH); + + // after reversing + // mineStep 0: mine C + // mineStep 1: mine B + // mineStep 2: mine A + + // condition 0: A is not at the given state + // condition 1: B is not at the given state + // condition 2: C is not at the given state + + // i = 0: Mine C, if B and A are mined + // i = 1: Mine B, if A is mined + // i = 2: Mine A, with no condition + + conditionalStep = new ConditionalStep(getQuestHelper(), todo); + Collections.reverse(mineSteps); + + assert this.mineSteps.size() == this.conditions.size(); + + { + var allDone = new DetailedQuestStep(getQuestHelper(), "you are all done lol"); + var conditionList = new ArrayList(); + for (var condition : this.conditions) { + var xd2 = new Conditions(LogicType.NAND, condition); + xd2.setText(condition.getDisplayText()); + allDone.addRequirement(xd2); + } + var xd = new Conditions(LogicType.NAND, conditionList); + conditionalStep.addStep(xd, allDone); + } + for (var i = 0; i < mineSteps.size(); i++) { + var mineStep = mineSteps.get(i); + var conditionList = new ArrayList(); + StringBuilder text = new StringBuilder(); + for (var j = 0; j < this.conditions.size() - i - 1; j++) { + conditionList.add(this.conditions.get(j)); + text.append(this.conditions.get(j).getDisplayText()); + var xd2 = new Conditions(LogicType.NAND, this.conditions.get(j)); + xd2.setText(this.conditions.get(j).getDisplayText()); + mineStep.addRequirement(xd2); + } + + var xd = new Conditions(LogicType.NOR, conditionList); + xd.setText(text.toString()); + + conditionalStep.addStep(xd, mineStep); + } + } + + protected void updateSteps() { + startUpStep(this.conditionalStep); + } + + @Override + public List getSteps() { + var steps = new ArrayList(); + + steps.add(this.conditionalStep); + for (var step : this.mineSteps) { + steps.add(step); + } + + return steps; + } + + @Getter + enum RubbleLevel { + Three(123), + Two(ObjectID.RUBBLE_50598), + One(ObjectID.RUBBLE_50587, ObjectID.RUBBLE_50589); + + private final List objectIDs; + + RubbleLevel(Integer... possibleObjectIDs) { + this.objectIDs = new ArrayList(); + for (var xd : possibleObjectIDs) { + this.objectIDs.add(xd); + } + // Collections.addAll(this.objectIDs, possibleObjectIDs); + } + } +} diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java new file mode 100644 index 0000000000..468bf6f3ed --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -0,0 +1,548 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.questhelper.helpers.quests.thecurseofarrav; + +import com.questhelper.bank.banktab.BankSlotIcons; +import com.questhelper.collections.ItemCollections; +import com.questhelper.panel.PanelDetails; +import com.questhelper.questhelpers.BasicQuestHelper; +import com.questhelper.questinfo.QuestHelperQuest; +import com.questhelper.requirements.Requirement; +import com.questhelper.requirements.conditional.ObjectCondition; +import com.questhelper.requirements.item.ItemRequirement; +import com.questhelper.requirements.item.TeleportItemRequirement; +import com.questhelper.requirements.player.CombatLevelRequirement; +import com.questhelper.requirements.player.FreeInventorySlotRequirement; +import com.questhelper.requirements.player.SkillRequirement; +import com.questhelper.requirements.quest.QuestRequirement; +import static com.questhelper.requirements.util.LogicHelper.and; +import static com.questhelper.requirements.util.LogicHelper.not; +import com.questhelper.requirements.var.VarbitRequirement; +import com.questhelper.requirements.zone.Zone; +import com.questhelper.requirements.zone.ZoneRequirement; +import com.questhelper.rewards.ExperienceReward; +import com.questhelper.rewards.QuestPointReward; +import com.questhelper.rewards.UnlockReward; +import com.questhelper.steps.ConditionalStep; +import com.questhelper.steps.ItemStep; +import com.questhelper.steps.NpcStep; +import com.questhelper.steps.ObjectStep; +import com.questhelper.steps.PuzzleWrapperStep; +import com.questhelper.steps.QuestStep; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import net.runelite.api.ItemID; +import net.runelite.api.NpcID; +import net.runelite.api.ObjectID; +import net.runelite.api.QuestState; +import net.runelite.api.Skill; +import net.runelite.api.SpriteID; +import net.runelite.api.coords.WorldPoint; + +/** + * The quest guide for the "The Curse of Arrav" OSRS quest + *

+ * The OSRS wiki guide and Slayermusiq1's Quest Guide was referenced for this guide + */ +public class TheCurseOfArrav extends BasicQuestHelper +{ + /// Required items + private ItemRequirement dwellberries3; + private ItemRequirement ringOfLife; + private ItemRequirement anyPickaxe; + private ItemRequirement anyGrappleableCrossbow; + private ItemRequirement mithrilGrapple; + private ItemRequirement insulatedBoots; + + /// Recommended items + // teleport to fairy ring + // fairy ring staff + // trollheim teleport / ghommal's hilt + // antivenom + // lumberyard teleport + // melee (crush) combat gear for golem + // ranged combat gear for arrav + private ItemRequirement crushCombatGear; + private ItemRequirement rangedCombatGear; + private ItemRequirement food; + private ItemRequirement staminaPotion; + private ItemRequirement prayerPotion; + // 2 inv slots + + /// Mid-quest item requirements + private ItemRequirement experimentalKebab; + private ItemRequirement goodTestKebab; + private ItemRequirement goodTestKebabs; + + /// Zones & their requirements + private Zone wolfDen; + private ZoneRequirement inWolfDen; + private Zone fortisColosseum; + private ZoneRequirement inFortisColosseum; + + /// Steps + private QuestStep startQuest; + private QuestStep enterTomb; + private ObjectStep getFirstKey; + private ObjectStep getSecondKey; + private ObjectStep pullSouthLever; + private ObjectStep pullNorthLever; + private ObjectStep enterGolemArena; + private NpcStep fightGolemGuard; + private ObjectStep enterTombBasement; + private QuestStep unsortedStep6; + private ConditionalStep unsortedStep10; + private PuzzleWrapperStep solveTilePuzzle; + private QuestStep unsortedStep12; + private QuestStep unsortedStep14; + private QuestStep unsortedStep16; + private QuestStep unsortedStep18; + private QuestStep unsortedStep20; + private QuestStep unsortedStep22; + private QuestStep unsortedStep24; + private QuestStep unsortedStep26; + private QuestStep unsortedStep28; + private QuestStep unsortedStep30; + private QuestStep unsortedStep32; + private QuestStep unsortedStep34; + private QuestStep unsortedStep36; + private QuestStep unsortedStep38; + private QuestStep unsortedStep40; + private QuestStep unsortedStep42; + private QuestStep unsortedStep44; + private QuestStep unsortedStep46; + private QuestStep unsortedStep48; + private QuestStep unsortedStep50; + private QuestStep unsortedStep52; + private QuestStep unsortedStep54; + private QuestStep unsortedStep56; + private QuestStep unsortedStep58; + private PuzzleWrapperStep rubbleMiner; + + + @Override + public Map loadSteps() + { + initializeRequirements(); + setupSteps(); + + var steps = new HashMap(); + + steps.put(0, startQuest); + steps.put(2, startQuest); + steps.put(4, enterTomb); + steps.put(6, unsortedStep6); + steps.put(8, unsortedStep6); + steps.put(10, unsortedStep10); + steps.put(12, unsortedStep12); + steps.put(14, unsortedStep12); + steps.put(16, unsortedStep16); + steps.put(18, unsortedStep18); + steps.put(20, unsortedStep20); + steps.put(22, unsortedStep20); + steps.put(24, unsortedStep24); + steps.put(26, unsortedStep26); + steps.put(28, unsortedStep28); + steps.put(30, unsortedStep30); + steps.put(32, unsortedStep32); + steps.put(34, unsortedStep34); + steps.put(36, unsortedStep36); + steps.put(38, unsortedStep38); + steps.put(40, unsortedStep40); + steps.put(42, unsortedStep42); + steps.put(44, unsortedStep44); + steps.put(46, unsortedStep46); + steps.put(48, unsortedStep48); + steps.put(50, unsortedStep50); + steps.put(52, unsortedStep52); + steps.put(54, unsortedStep54); + steps.put(56, unsortedStep56); + steps.put(58, unsortedStep58); + + return steps; + } + + @Override + protected void setupZones() + { + } + + @Override + protected void setupRequirements() + { + dwellberries3 = new ItemRequirement("Dwellberries", ItemID.DWELLBERRIES, 3); + ringOfLife = new ItemRequirement("Ring of life", ItemID.RING_OF_LIFE); + anyPickaxe = new ItemRequirement("Any pickaxe", ItemCollections.PICKAXES).isNotConsumed(); + anyGrappleableCrossbow = new ItemRequirement("Any crossbow", ItemCollections.CROSSBOWS).isNotConsumed(); + mithrilGrapple = new ItemRequirement("Mith grapple", ItemID.MITH_GRAPPLE_9419).isNotConsumed(); + // TODO: Check if the other insulated boots can be used + insulatedBoots = new ItemRequirement("Insulated boots", ItemID.INSULATED_BOOTS).isNotConsumed(); + + staminaPotion = new ItemRequirement("Stamina potion", ItemCollections.STAMINA_POTIONS, 1); + prayerPotion = new ItemRequirement("Prayer potion", ItemCollections.PRAYER_POTIONS, 1); + crushCombatGear = new ItemRequirement("Melee combat gear (crush preferred)", -1, -1); + crushCombatGear.setDisplayItemId(BankSlotIcons.getCombatGear()); + food = new ItemRequirement("Food", ItemCollections.GOOD_EATING_FOOD, -1); + } + + public void setupSteps() + { + var todo = new NpcStep(this, 5, "TODO XD"); + + startQuest = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Talk to Elias south of Ruins of Uzer (DLQ FAIRY RING)."); + startQuest.addDialogStep("Yes."); + + enterTomb = new ObjectStep(this, ObjectID.ENTRY_50201, new WorldPoint(3486, 3023, 0), "Enter the tomb south-west of Elias."); + // TODO: Ensure player can get hint to return + + var insideTomb = new Zone(new WorldPoint(3842, 4603, 0), new WorldPoint(3900, 4547, 0)); + var insideTombReq = new ZoneRequirement(insideTomb); + var hasFirstKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY); + getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton to the south of the entrance."); + var hasSecondKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY_30309); + getSecondKey = new ObjectStep(this, ObjectID.SKELETON_50353, new WorldPoint(3880, 4585, 0), "Get the second Mastaba key from the skeleton east of the entrance."); + var bySouthLever = new Zone(new WorldPoint(3893, 4554, 0), new WorldPoint(3894, 4552, 0)); + var bySouthLeverReq = new ZoneRequirement(bySouthLever); + pullSouthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4553, 0), "Pull the lever to the south-east.", hasSecondKey); + pullSouthLever.addDialogStep("Yes."); + var getToSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3891, 4554, 0), "Search the Odd markings to the south to get to the south lever. Search the markings again if you fail."); + var needToInsertKeyInSouthLever = new VarbitRequirement(11482, 0); + var needToFlipSouthLever = new VarbitRequirement(11482, 1); + var haveFlippedSouthLever = new VarbitRequirement(11482, 2); + var leaveSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3892, 4554, 0), "Search the Odd markings next to you to get out."); + pullSouthLever.addSubSteps(getToSouthLever, leaveSouthLever); + + var byNorthLever = new Zone(new WorldPoint(3894, 4597, 0), new WorldPoint(3893, 4599, 0)); + var byNorthLeverReq = new ZoneRequirement(byNorthLever); + var getToNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3891, 4597, 0), "Search the Odd markings to the north to get to the north lever. Search the markings again if you fail."); + pullNorthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4598, 0), "Pull the lever to the north-east.", hasFirstKey); + pullNorthLever.addDialogStep("Yes."); + var needToInsertKeyInNorthLever = new VarbitRequirement(11481, 0); + var needToFlipNorthLever = new VarbitRequirement(11481, 1); + var haveFlippedNorthLever = new VarbitRequirement(11481, 2); + var leaveNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3892, 4597, 0), "Search the Odd markings next to you to get out."); + pullNorthLever.addSubSteps(getToNorthLever, leaveNorthLever); + + unsortedStep6 = new ConditionalStep(this, enterTomb); + + // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? + ((ConditionalStep) unsortedStep6).addStep(not(insideTombReq), enterTomb); + + // If the user has flipped the south lever & needs to get out of the little room + ((ConditionalStep) unsortedStep6).addStep(and(haveFlippedSouthLever, bySouthLeverReq), leaveSouthLever); + // If the user has flipped the north lever & needs to get out of the little room + ((ConditionalStep) unsortedStep6).addStep(and(haveFlippedNorthLever, byNorthLeverReq), leaveNorthLever); + + // If the user has not already put the key in the south lever, and does not have the key + ((ConditionalStep) unsortedStep6).addStep(and(needToInsertKeyInSouthLever, not(hasSecondKey)), getSecondKey); + // If the user has not already put the key in the north lever, and does not have the key + ((ConditionalStep) unsortedStep6).addStep(and(needToInsertKeyInNorthLever, not(hasFirstKey)), getFirstKey); + + // If the user has the key & stands by the south lever + ((ConditionalStep) unsortedStep6).addStep(and(needToFlipSouthLever, bySouthLeverReq), pullSouthLever); + // If the user needs to flip the south lever, but is not inside the little room, get to the little room + ((ConditionalStep) unsortedStep6).addStep(not(haveFlippedSouthLever), getToSouthLever); + + // If the user has the key & stands by the north lever + ((ConditionalStep) unsortedStep6).addStep(and(needToFlipNorthLever, byNorthLeverReq), pullNorthLever); + // If the user needs to flip the north lever, but is not inside the little room, get to the little room + ((ConditionalStep) unsortedStep6).addStep(needToFlipNorthLever, getToNorthLever); + + // Once last lever was pulled, quest varbit changed from 6 to 8, then 8 to 10 at the same tick + // This might have to do with which order you pulled the levers in + + var golemArenaZone = new Zone(new WorldPoint(3856, 4592, 0), new WorldPoint(3884, 4599, 0)); + var insideGolenArena = new ZoneRequirement(golemArenaZone); + enterGolemArena = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Open the imposing doors, ready to fight the Golem guard."); + fightGolemGuard = new NpcStep(this, NpcID.GOLEM_GUARD, new WorldPoint(3860, 4595, 0), "Fight the Golem guard. He is weak to crush style weapons. Use Protect from Melee to avoid damage from his attacks. When the screen shakes, step away from him to avoid taking damage."); + unsortedStep10 = new ConditionalStep(this, enterGolemArena); + // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? + unsortedStep10.addStep(not(insideTombReq), enterTomb); + unsortedStep10.addStep(byNorthLeverReq, leaveNorthLever); + unsortedStep10.addStep(bySouthLeverReq, leaveSouthLever); + unsortedStep10.addStep(insideGolenArena, fightGolemGuard); + + var enterGolemArenaWithoutFight = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Open the imposing doors to the north-east of the tomb."); + enterTombBasement = new ObjectStep(this, ObjectID.STAIRS_55785, new WorldPoint(3860, 4596, 0), "Climb the stairs down the tomb basement."); + enterTombBasement.addSubSteps(enterGolemArenaWithoutFight); + + solveTilePuzzle = new TilePuzzleSolver(this).puzzleWrapStep("Move across the floor tile puzzle."); + + var insideTombSecondFloor = new Zone(new WorldPoint(3719, 4674, 0), new WorldPoint(3770, 4732, 0)); + var insideTombSecondFloorAfterFinishingPuzzle = new Zone(new WorldPoint(3845, 4674, 0), new WorldPoint(3900, 4732, 0)); + var insideTombSecondFloorReq = new ZoneRequirement(insideTombSecondFloor, insideTombSecondFloorAfterFinishingPuzzle); + + var searchShelvesForUrn = new ObjectStep(this, ObjectID.SHELVES_55796, new WorldPoint(3854, 4722, 0), "Search the shelves to the west for an oil-filled canopic jar."); + var oilFilledCanopicJar = new ItemRequirement("Oil-filled canopic jar", ItemID.CANOPIC_JAR_OIL); + + var inspectMurals = new ObjectStep(this, ObjectID.MURAL_55790, new WorldPoint(3852, 4687, 0), "Inspect the murals in the room to the south.", oilFilledCanopicJar); + + var finishedTilePuzzle = new VarbitRequirement(11483, 1); + unsortedStep12 = new ConditionalStep(this, todo); + ((ConditionalStep) unsortedStep12).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); + ((ConditionalStep) unsortedStep12).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle, oilFilledCanopicJar), todo); + ((ConditionalStep) unsortedStep12).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); + ((ConditionalStep) unsortedStep12).addStep(insideTombSecondFloorReq, solveTilePuzzle); + ((ConditionalStep) unsortedStep12).addStep(not(insideTombReq), enterTomb); + ((ConditionalStep) unsortedStep12).addStep(and(insideTombReq, insideGolenArena), enterTombBasement); + ((ConditionalStep) unsortedStep12).addStep(and(insideTombReq), enterGolemArenaWithoutFight); + + var oilAndBerryFilledCanopicJar = new ItemRequirement("Canopic jar (oil and berries)", ItemID.CANOPIC_JAR_OIL_AND_BERRIES); + + var combineJarWithDwellberries = new ItemStep(this, "Combine the Dwellberries with the Canopic jar.", oilFilledCanopicJar.highlighted(), dwellberries3.highlighted(), ringOfLife); + var combineJarWithRingOfLife = new ItemStep(this, "Combine the Dwellberries with the Ring of life.", oilAndBerryFilledCanopicJar.highlighted(), ringOfLife.highlighted()); + + unsortedStep16 = new ConditionalStep(this, todo); + ((ConditionalStep) unsortedStep16).addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); + ((ConditionalStep) unsortedStep16).addStep(oilFilledCanopicJar, combineJarWithDwellberries); + ((ConditionalStep) unsortedStep16).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); + ((ConditionalStep) unsortedStep16).addStep(not(insideTombReq), enterTomb); + ((ConditionalStep) unsortedStep16).addStep(and(insideTombReq, insideGolenArena), enterTombBasement); + ((ConditionalStep) unsortedStep16).addStep(and(insideTombReq), enterGolemArenaWithoutFight); + + var fairyRingDLQ = new TeleportItemRequirement("Fairy Ring [DLQ]", ItemCollections.FAIRY_STAFF); + + var returnToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); + returnToElias.addTeleport(fairyRingDLQ); + var returnToEliasByWalking = new ObjectStep(this, ObjectID.STAIRS_55786, new WorldPoint(3894, 4714, 0), "Return to to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); + returnToEliasByWalking.addTeleport(fairyRingDLQ); + var returnToEliasByWalkingMidway = new ObjectStep(this, ObjectID.STAIRS_50202, new WorldPoint(3848, 4577, 0), "Return to to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); + returnToEliasByWalkingMidway.addTeleport(fairyRingDLQ); + var returnToEliasByWalkingMidwayGolem = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Return to to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); + returnToEliasByWalkingMidwayGolem.addTeleport(fairyRingDLQ); + + returnToElias.addSubSteps(returnToEliasByWalking, returnToEliasByWalkingMidway, returnToEliasByWalkingMidwayGolem); + + unsortedStep18 = new ConditionalStep(this, returnToElias); + ((ConditionalStep)unsortedStep18).addStep(insideTombSecondFloorReq, returnToEliasByWalking); + ((ConditionalStep)unsortedStep18).addStep(insideGolenArena, returnToEliasByWalkingMidwayGolem); + ((ConditionalStep)unsortedStep18).addStep(insideTombReq, returnToEliasByWalkingMidway); + // ardy cloak + fairy ring takes 50s, walking takes 1m12s + + var trollheimTeleport = new TeleportItemRequirement("Trollheim Teleport", ItemID.TROLLHEIM_TELEPORT); + trollheimTeleport.addAlternates(ItemCollections.GHOMMALS_HILT); + var headToTrollheim = new ObjectStep(this, ObjectID.CAVE_ENTRANCE_5007, new WorldPoint(2821, 3744, 0), "Enter the cave next to Trollheim. You can use a Trollheim teleport tablet or the GWD Ghommal's Hilt teleport to get close."); + headToTrollheim.addTeleport(trollheimTeleport); + + var trollheimCave = new Zone(11167); + var inTrollheimCave = new ZoneRequirement(trollheimCave); + var continueThroughTrollheimCave = new ObjectStep(this, ObjectID.CREVASSE, new WorldPoint(2772, 10233, 0), "Continue through the Trollheim cave, exiting at the Crevasse to the north-west. Use Protect from Melee to avoid taking damage from the Ice Trolls."); + + var trollweissMountain = new Zone(11068); + var onTrollweissMountain = new ZoneRequirement(trollweissMountain); + var enterTrollweissCave = new ObjectStep(this, ObjectID.CAVE_55779, new WorldPoint(2809, 3861, 0), "Enter the Trollweiss cave to the east."); + + var trollweissCave1 = new Zone(11168); + var inTrollweissCave = new ZoneRequirement(trollweissCave1); + + var whereToStandSprite = SpriteID.COMBAT_STYLE_PICKAXE_SMASH; + + // Rubble 50598 = 2 hits + // Rubble 50587/50589 = 1 hit + + // var mineRubble1FromSouth = new ObjectStep(this, ObjectID.RUBBLE_50598, new WorldPoint(2764, 10266, 0), "Mine the rubble from the south."); + // mineRubble1FromSouth.addTileMarker(new WorldPoint(2764, 10265, 0), whereToStandSprite); + + // var rubble1MinedOnce = new ObjectCondition(ObjectID.RUBBLE_50589, new WorldPoint(2764, 10266, 0)); + // var rubble2Mined = not(new ObjectCondition(ObjectID.RUBBLE_50589, new WorldPoint(2775, 10258, 0))); + + // var mineRubble2FromSouth = new ObjectStep(this, ObjectID.RUBBLE_50587, new WorldPoint(2775, 10258, 0), "Mine the rubble from the south."); + // mineRubble2FromSouth.addTileMarker(new WorldPoint(2775, 10257, 0), whereToStandSprite); + // mineRubble2FromSouth.setLinePoints(List.of(new WorldPoint(2763, 10264, 0), new WorldPoint(2769, 10254, 0), new WorldPoint(2775, 10255, 0))); + + rubbleMiner = new RubbleMiner(this).puzzleWrapStep("make your way through the mine"); + + unsortedStep20 = new ConditionalStep(this, headToTrollheim); + ((ConditionalStep) unsortedStep20).addStep(inTrollweissCave, rubbleMiner); + ((ConditionalStep) unsortedStep20).addStep(onTrollweissMountain, enterTrollweissCave); + ((ConditionalStep) unsortedStep20).addStep(inTrollheimCave, continueThroughTrollheimCave); + + unsortedStep22 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 22"); + unsortedStep24 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 24"); + unsortedStep26 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 26"); + unsortedStep28 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 28"); + unsortedStep30 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 30"); + unsortedStep32 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 32"); + unsortedStep34 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 34"); + unsortedStep36 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 36"); + unsortedStep38 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 38"); + unsortedStep40 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 40"); + unsortedStep42 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 42"); + unsortedStep44 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 44"); + unsortedStep46 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 46"); + unsortedStep48 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 48"); + unsortedStep50 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 50"); + unsortedStep52 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 52"); + unsortedStep54 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 54"); + unsortedStep56 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 56"); + unsortedStep58 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 58"); + + } + + @Override + public List getItemRequirements() + { + return List.of( + dwellberries3, + ringOfLife, + anyPickaxe, + anyGrappleableCrossbow, + mithrilGrapple, + insulatedBoots + ); + } + + @Override + public List getItemRecommended() + { + return List.of( + staminaPotion, + prayerPotion, + crushCombatGear, + food + ); + } + + @Override + public List getGeneralRecommended() + { + return List.of( + new CombatLevelRequirement(85), + new SkillRequirement(Skill.PRAYER, 43, false, "43+ Prayer to use protection prayers") + ); + } + + @Override + public List getGeneralRequirements() + { + return List.of( + new QuestRequirement(QuestHelperQuest.DEFENDER_OF_VARROCK, QuestState.FINISHED), + new QuestRequirement(QuestHelperQuest.TROLL_ROMANCE, QuestState.FINISHED), + new SkillRequirement(Skill.MINING, 64), + new SkillRequirement(Skill.RANGED, 62), + new SkillRequirement(Skill.THIEVING, 62), + new SkillRequirement(Skill.AGILITY, 61), + new SkillRequirement(Skill.STRENGTH, 58), + new SkillRequirement(Skill.SLAYER, 37) + ); + } + + @Override + public List getCombatRequirements() + { + return List.of( + "Golem guard (lvl 141)", + "Arrav (lvl 339)" + ); + } + + @Override + public QuestPointReward getQuestPointReward() + { + return new QuestPointReward(2); + } + + @Override + public List getExperienceRewards() + { + return List.of( + new ExperienceReward(Skill.MINING, 40_000), + new ExperienceReward(Skill.THIEVING, 40_000), + new ExperienceReward(Skill.AGILITY, 40_000) + ); + } + + @Override + public List getUnlockRewards() + { + return List.of( + new UnlockReward("Access to Zemouregal's Fort") + ); + } + + @Override + public List getPanels() + { + var panels = new ArrayList(); + + panels.add(new PanelDetails("Tomb Raiding", List.of( + startQuest, + enterTomb, + getFirstKey, + getSecondKey, + pullSouthLever, + pullNorthLever, + enterGolemArena, + fightGolemGuard, + enterTombBasement, + solveTilePuzzle, + unsortedStep16, + unsortedStep18 + ), List.of( + new FreeInventorySlotRequirement(2) + // TODO + ))); + panels.add(new PanelDetails("Fort Invasion", List.of( + unsortedStep20, + rubbleMiner, + unsortedStep22, + unsortedStep24, + unsortedStep26, + unsortedStep28, + unsortedStep30, + unsortedStep32, + unsortedStep34, + unsortedStep36, + unsortedStep38, + unsortedStep40, + unsortedStep42, + unsortedStep44, + unsortedStep46, + unsortedStep48, + unsortedStep50, + unsortedStep52, + unsortedStep54, + unsortedStep56, + unsortedStep58 + // TODO + ), List.of(staminaPotion, prayerPotion, crushCombatGear, food))); + panels.add(new PanelDetails("Hearty Heist", List.of( + // TODO + ), List.of( + // TODO + ))); + + panels.add(new PanelDetails("The Hero of Avarrocka", List.of( + // TODO + ), List.of( + // TODO + ))); + + return panels; + } + +} diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java new file mode 100644 index 0000000000..07c0a56328 --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java @@ -0,0 +1,396 @@ +package com.questhelper.helpers.quests.thecurseofarrav; + +import com.questhelper.steps.DetailedOwnerStep; +import com.questhelper.steps.DetailedQuestStep; +import com.questhelper.steps.ObjectStep; +import com.questhelper.steps.QuestStep; +import com.questhelper.steps.tools.QuestPerspective; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import javax.annotation.Nullable; +import javax.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.NullObjectID; +import net.runelite.api.ObjectID; +import net.runelite.api.Tile; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.GameTick; +import net.runelite.client.eventbus.Subscribe; +import org.apache.commons.lang3.tuple.Pair; + +@Slf4j +public class TilePuzzleSolver extends DetailedOwnerStep +{ + /** + * Width & height of the tile puzzle + */ + private static final int SIZE = 12; + private static final int GREEN_TILE = NullObjectID.NULL_50296; + private static final int BLUE_TILE = NullObjectID.NULL_50294; + private static final int RED_TILE = NullObjectID.NULL_50295; + private static final int YELLOW_TILE = NullObjectID.NULL_50297; + private static final Set VALID_TILES = Set.of(GREEN_TILE, BLUE_TILE, RED_TILE, YELLOW_TILE); + + /** + * a 2-dimensional array of the tiles. [x][y] + * The value is the object ID (i.e. the color of the tile) + */ + private final int[][] tiles = new int[SIZE][SIZE]; + + @Inject + Client client; + + /** + * State of the tiles array. + * False if tiles have not had their object IDs filled in. + * True if they have had their object IDs filled in. + */ + private boolean tilesConfigured = false; + private ObjectStep firstObjectStepXD; + private ObjectStep[][] objectSteps; + + List shortestPath = null; + private DetailedQuestStep fallbackStep; + private QuestStep finishPuzzleStep; + private ObjectStep mostRecentStep = null; + + public TilePuzzleSolver(TheCurseOfArrav theCurseOfArrav) + { + super(theCurseOfArrav, "Solve the floor tile puzzle. Follow the instructions in the overlay."); + } + + /** + * @param startX local X coordinate of the tiles array for where to start searching + * @param startY local Y coordinate of the tiles array for where to start searching + * @return A list of local X/Y coordinates if a path to the end was found + */ + private @Nullable List findPath(int startX, int startY) + { + assert (startX >= 0 && startX < SIZE); + assert (startY >= 0 && startY < SIZE); + assert (this.tilesConfigured); + + int startObjectId = this.tiles[startX][startY]; + var visited = new boolean[SIZE][SIZE]; + var queue = new LinkedList(); + queue.add(new int[]{startX, startY}); + visited[startX][startY] = true; + + var parent = new int[SIZE][SIZE][2]; + parent[startX][startY] = new int[]{-1, -1}; + + int[][] directions = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; + + while (!queue.isEmpty()) + { + var current = queue.poll(); + var x = current[0]; + var y = current[1]; + + if (x == 0) + { + var path = new ArrayList(); + var retracedStep = new int[]{x, y}; + while (retracedStep[0] != -1 && retracedStep[1] != -1) + { + path.add(0, retracedStep); + retracedStep = parent[retracedStep[0]][retracedStep[1]]; + } + return path; + } + + for (var direction : directions) + { + int newX = x + direction[0]; + int newY = y + direction[1]; + + if (newX >= 0 && newX < SIZE && newY >= 0 && newY < SIZE && !visited[newX][newY] && areObjectIdsCompatible(this.tiles[newX][newY], startObjectId)) + { + queue.add(new int[]{newX, newY}); + visited[newX][newY] = true; + parent[newX][newY] = new int[]{x, y}; + } + } + } + + return null; + } + + private boolean areObjectIdsCompatible(int a, int b) + { + assert (VALID_TILES.contains(a)); + assert (VALID_TILES.contains(b)); + + if (a == GREEN_TILE || a == BLUE_TILE) + { + return b == GREEN_TILE || b == BLUE_TILE; + } + + if (a == RED_TILE || a == YELLOW_TILE) + { + return b == RED_TILE || b == YELLOW_TILE; + } + + return false; + } + + private Pair findPuzzleStart(Tile[][] wvTiles) + { + // stupidly search for first tile with a green, red, blue, or yellow tile + for (int x = 0; x < wvTiles.length; x++) + { + for (int y = 0; y < wvTiles[x].length; y++) + { + var tile = wvTiles[x][y]; + var groundObject = tile.getGroundObject(); + if (groundObject != null) + { + if (VALID_TILES.contains(groundObject.getId())) + { + return Pair.of(x, y); + } + } + } + } + + return null; + } + + /** + * Look through the world view and attempt to fill up the tiles array + */ + private void tryFillTiles() + { + var localPlayer = client.getLocalPlayer(); + if (localPlayer == null) + { + return; + } + + var worldView = localPlayer.getWorldView(); + var squareOfTiles = worldView.getScene().getTiles()[worldView.getPlane()]; + + var puzzleStart = this.findPuzzleStart(squareOfTiles); + if (puzzleStart == null) + { + return; + } + + var firstPuzzleX = puzzleStart.getLeft(); + var firstPuzzleY = puzzleStart.getRight(); + + assert (firstPuzzleX != null); + assert (firstPuzzleY != null); + + log.debug("Found first puzzle tile at {}/{}", firstPuzzleX, firstPuzzleY); + + for (int x = 0; x < 12; x++) + { + var offsetX = x + firstPuzzleX; + if (offsetX >= squareOfTiles.length) + { + log.debug("X({} + {}) out of bounds when mapping puzzle tiles", x, firstPuzzleX); + return; + } + + for (int y = 0; y < 12; y++) + { + var offsetY = y + firstPuzzleY; + if (offsetY >= squareOfTiles[offsetX].length) + { + log.debug("Y({} + {}) out of bounds when mapping puzzle tiles", y, firstPuzzleY); + return; + } + + var tile = squareOfTiles[offsetX][offsetY]; + var groundObject = tile.getGroundObject(); + if (groundObject == null) + { + log.debug("X({} + {}) Y({} + {}) had no ground object", x, firstPuzzleX, y, firstPuzzleY); + return; + } + + if (!VALID_TILES.contains(groundObject.getId())) + { + log.debug("X({} + {}) Y({} + {}) had an invalid ground object ({})", x, firstPuzzleX, y, firstPuzzleY, groundObject.getId()); + return; + } + + this.tiles[x][y] = groundObject.getId(); + } + } + + this.tilesConfigured = true; + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (!this.tilesConfigured) + { + this.tryFillTiles(); + } + + if (this.tilesConfigured && this.shortestPath == null) + { + // Figure out the shortest path + var possiblePaths = new ArrayList>(); + for (int y = 0; y < 12; y++) + { + var path = this.findPath(11, y); + if (path != null) + { + log.debug("Found possible path starting at {}/{}. Length {}", 11, y, path.size()); + possiblePaths.add(path); + } + } + + for (var possiblePath : possiblePaths) + { + if (this.shortestPath == null || possiblePath.size() < this.shortestPath.size()) + { + this.shortestPath = possiblePath; + } + } + + if (this.shortestPath == null) + { + // TODO: tell user to just find a way to solve it lol + } + else + { + // TODO: figure out how to highlight this? make object steps? + // How do I get the correct world points? maybe check objectstep to see if we offset it somewhere with instance points or something + } + } + + updateSteps(); + } + + @Override + public void startUp() + { + updateSteps(); + } + + @Override + protected void setupSteps() + { + objectSteps = new ObjectStep[SIZE][SIZE]; + var baseX = 3737; + var baseY = 4709; + var plane = 0; + for (int x = 0; x < SIZE; ++x) + { + var objectText = "Click the tile to pass through the puzzle."; + if (x == 11) { + objectText = "Click the tile to start the puzzle."; + } + for (int y = 0; y < SIZE; ++y) + { + var wp = new WorldPoint(baseX + x, baseY + y, plane); + var objectStep = new ObjectStep(getQuestHelper(), GREEN_TILE, wp, objectText); + objectStep.addAlternateObjects(BLUE_TILE, RED_TILE, YELLOW_TILE); + if (firstObjectStepXD == null) { + firstObjectStepXD = objectStep; + } + objectSteps[x][y] = objectStep; + } + } + + fallbackStep = new DetailedQuestStep(getQuestHelper(), new WorldPoint(3734, 4714, 0), "Unable to figure out a path, click your way across lol"); // TODO + + finishPuzzleStep = new ObjectStep(getQuestHelper(), ObjectID.LEVER_50205, new WorldPoint(3735, 4719, 0), "Finish the puzzle by clicking the lever."); + } + + protected void updateSteps() + { + if (this.shortestPath == null) { + startUpStep(fallbackStep); + return; + } + + var localPlayer = client.getLocalPlayer(); + if (localPlayer == null) { + startUpStep(fallbackStep); + return; + } + + var playerWp = localPlayer.getWorldLocation(); + var localPoint = QuestPerspective.getRealWorldPointFromLocal(client, localPlayer.getWorldLocation()); + if (localPoint == null) { + startUpStep(fallbackStep); + return; + } + + + var baseX = 3737; + var baseY = 4709; + + var xInPuzzle = localPoint.getX() - baseX; + var yInPuzzle = localPoint.getY() - baseY; + + var puzzleStartX = this.shortestPath.get(0)[0]; + var puzzleStartY = this.shortestPath.get(0)[1]; + + if (xInPuzzle >= 0 && xInPuzzle < SIZE && yInPuzzle >= 0 && yInPuzzle < SIZE) { + log.info("Player is in the puzzle, at {}/{}", xInPuzzle, yInPuzzle); + boolean nextIsOurCoolStep = false; + for (var pathPos : this.shortestPath) { + if (nextIsOurCoolStep) { + startUpStep(objectSteps[pathPos[0]][pathPos[1]]); + return; + } + if (pathPos[0] == xInPuzzle && pathPos[1] == yInPuzzle) { + nextIsOurCoolStep = true; + this.mostRecentStep = objectSteps[pathPos[0]][pathPos[1]]; + } + } + if (nextIsOurCoolStep) { + log.info("user is at end"); + startUpStep(finishPuzzleStep); + return; + } + + if (this.mostRecentStep != null) + { + log.debug("user stepped off the path, lead them back"); + startUpStep(this.mostRecentStep); + return; + } + } else { + log.debug("player is outside of puzzle: {} / {} / {}/{}", playerWp, localPoint, xInPuzzle, yInPuzzle); + var userIsPastPuzzle = localPoint.getX() <= baseX; // TODO: If the user walks to the cave to the south, we might tell the user to just click the lever. I need to figure out the correct zone here. polish pass! + if (userIsPastPuzzle) { + // highlight lever + startUpStep(finishPuzzleStep); + } else { + // highlight puzzle start + startUpStep(objectSteps[puzzleStartX][puzzleStartY]); + } + } + } + + @Override + public List getSteps() + { + var steps = new ArrayList(); + steps.add(fallbackStep); + steps.add(firstObjectStepXD); + + for (int x = 0; x < SIZE; ++x) + { + for (int y = 0; y < SIZE; ++y) + { + steps.add(objectSteps[x][y]); + } + } + + steps.add(finishPuzzleStep); + + return steps; + } +} diff --git a/src/main/java/com/questhelper/questinfo/QuestHelperQuest.java b/src/main/java/com/questhelper/questinfo/QuestHelperQuest.java index ac68fba933..6b681feb94 100644 --- a/src/main/java/com/questhelper/questinfo/QuestHelperQuest.java +++ b/src/main/java/com/questhelper/questinfo/QuestHelperQuest.java @@ -234,6 +234,7 @@ import com.questhelper.helpers.quests.templeoftheeye.TempleOfTheEye; import com.questhelper.helpers.quests.theascentofarceuus.TheAscentOfArceuus; import com.questhelper.helpers.quests.thecorsaircurse.TheCorsairCurse; +import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; import com.questhelper.helpers.quests.thedepthsofdespair.TheDepthsOfDespair; import com.questhelper.helpers.quests.thedigsite.TheDigSite; import com.questhelper.helpers.quests.theeyesofglouphrie.TheEyesOfGlouphrie; @@ -485,6 +486,7 @@ public enum QuestHelperQuest DEATH_ON_THE_ISLE(new DeathOnTheIsle(), Quest.DEATH_ON_THE_ISLE, QuestVarbits.QUEST_DEATH_ON_THE_ISLE, QuestDetails.Type.P2P, QuestDetails.Difficulty.INTERMEDIATE), MEAT_AND_GREET(new MeatAndGreet(), Quest.MEAT_AND_GREET, QuestVarbits.QUEST_MEAT_AND_GREET, QuestDetails.Type.P2P, QuestDetails.Difficulty.EXPERIENCED), THE_HEART_OF_DARKNESS(new TheHeartOfDarkness(), Quest.THE_HEART_OF_DARKNESS, QuestVarbits.QUEST_THE_HEART_OF_DARKNESS, QuestDetails.Type.P2P, QuestDetails.Difficulty.EXPERIENCED), + THE_CURSE_OF_ARRAV(new TheCurseOfArrav(), Quest.THE_CURSE_OF_ARRAV, QuestVarbits.QUEST_THE_CURSE_OF_ARRAV, QuestDetails.Type.P2P, QuestDetails.Difficulty.MASTER), //Miniquests ENTER_THE_ABYSS(new EnterTheAbyss(), Quest.ENTER_THE_ABYSS, QuestVarPlayer.QUEST_ENTER_THE_ABYSS, QuestDetails.Type.MINIQUEST, QuestDetails.Difficulty.MINIQUEST), diff --git a/src/main/java/com/questhelper/questinfo/QuestVarbits.java b/src/main/java/com/questhelper/questinfo/QuestVarbits.java index fdd2338259..ec653f8ea8 100644 --- a/src/main/java/com/questhelper/questinfo/QuestVarbits.java +++ b/src/main/java/com/questhelper/questinfo/QuestVarbits.java @@ -119,6 +119,7 @@ public enum QuestVarbits QUEST_DEATH_ON_THE_ISLE(11210), QUEST_MEAT_AND_GREET(11182), QUEST_THE_HEART_OF_DARKNESS(11117), + QUEST_THE_CURSE_OF_ARRAV(11479), /** * mini-quest varbits, these don't hold the completion value. */ diff --git a/src/main/java/com/questhelper/requirements/conditional/ConditionForStep.java b/src/main/java/com/questhelper/requirements/conditional/ConditionForStep.java index dc4d0316dd..3183b16ec0 100644 --- a/src/main/java/com/questhelper/requirements/conditional/ConditionForStep.java +++ b/src/main/java/com/questhelper/requirements/conditional/ConditionForStep.java @@ -63,10 +63,13 @@ public void updateHandler() .forEach(req -> ((InitializableRequirement) req).updateHandler()); } + @Setter + private String text = ""; + @Nonnull @Override public String getDisplayText() // conditions don't need display text (yet?) { - return ""; + return this.text; } } diff --git a/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java b/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java index 072dbdb720..f579d84859 100644 --- a/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java +++ b/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java @@ -32,10 +32,12 @@ import net.runelite.api.Tile; import net.runelite.api.TileObject; import net.runelite.api.coords.WorldPoint; +import java.util.List; +import java.util.Set; public class ObjectCondition extends ConditionForStep { - private final int objectID; + private final Set objectIDs; private final Zone zone; @Setter @@ -46,7 +48,7 @@ public class ObjectCondition extends ConditionForStep public ObjectCondition(int objectID) { - this.objectID = objectID; + this.objectIDs = Set.of(objectID); this.zone = null; } @@ -54,7 +56,7 @@ public ObjectCondition(int objectID, WorldPoint worldPoint) { assert(worldPoint != null); - this.objectID = objectID; + this.objectIDs = Set.of(objectID); this.zone = new Zone(worldPoint); } @@ -62,10 +64,18 @@ public ObjectCondition(int objectID, Zone zone) { assert(zone != null); - this.objectID = objectID; + this.objectIDs = Set.of(objectID); this.zone = zone; } + public ObjectCondition(Set objectIDs, WorldPoint worldPoint) + { + assert(worldPoint != null); + + this.objectIDs = objectIDs; + this.zone = new Zone(worldPoint); + } + public boolean check(Client client) { Tile[][] tiles; @@ -118,7 +128,16 @@ private boolean checkTile(Tile tile, Client client) private boolean checkForObjects(TileObject object) { - return object != null && (object.getId() == objectID || objectID == -1); + if (object == null) { + return false; + } + + // SPECIAL CASE FROM BEFORE: do we really need this? + if (this.objectIDs.contains(-1)) { + return true; + } + + return this.objectIDs.contains(object.getId()); } @Override From 2da24ea656cd919ecfa5205396699442f7a65ed9 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 9 Nov 2024 16:54:58 +0100 Subject: [PATCH 02/60] progress 2 --- .../quests/thecurseofarrav/RubbleMiner.java | 194 --------------- .../thecurseofarrav/TheCurseOfArrav.java | 28 ++- .../rubblesolvers/RubbleSolver.java | 227 ++++++++++++++++++ .../rubblesolvers/RubbleSolverOne.java | 84 +++++++ .../rubblesolvers/RubbleSolverThree.java | 71 ++++++ .../rubblesolvers/RubbleSolverTwo.java | 71 ++++++ .../rubblesolvers/RubbleType.java | 24 ++ 7 files changed, 498 insertions(+), 201 deletions(-) delete mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/RubbleMiner.java create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/RubbleMiner.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/RubbleMiner.java deleted file mode 100644 index 339f0b8518..0000000000 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/RubbleMiner.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.questhelper.helpers.quests.thecurseofarrav; - -import com.questhelper.helpers.quests.thepathofglouphrie.DiscInsertionStep; -import com.questhelper.requirements.Requirement; -import com.questhelper.requirements.conditional.Conditions; -import com.questhelper.requirements.conditional.ObjectCondition; -import com.questhelper.requirements.item.ItemRequirement; -import com.questhelper.requirements.util.LogicType; -import com.questhelper.requirements.widget.WidgetPresenceRequirement; -import com.questhelper.steps.*; - -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import javax.annotation.Nullable; -import javax.inject.Inject; - -import com.questhelper.steps.tools.QuestPerspective; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.*; -import net.runelite.api.coords.Direction; -import net.runelite.api.coords.LocalPoint; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.GameTick; -import net.runelite.client.eventbus.Subscribe; -import org.apache.commons.lang3.tuple.Pair; - -import static com.questhelper.requirements.util.LogicHelper.and; -import static com.questhelper.requirements.util.LogicHelper.nor; - -@Slf4j -public class RubbleMiner extends DetailedOwnerStep { - @Inject - Client client; - - private List mineSteps; - private List conditions; - private ConditionalStep conditionalStep; - - private int operation; - - public RubbleMiner(TheCurseOfArrav theCurseOfArrav) { - super(theCurseOfArrav, "Make your way through the Trollweiss cave, mining rubble with your pickaxe."); - } - - - private void addMineRubbleStep(int x, int y, RubbleLevel rubbleLevel, Direction direction) { - var validObjectIDs = rubbleLevel.getObjectIDs(); - assert !validObjectIDs.isEmpty(); - - var validIDSet = new HashSet<>(validObjectIDs); - - var wp = new WorldPoint(x, y, 0); - var operation = this.operation++; - var text = String.format("[%d] Mine the rubble from the %s side", operation, direction.toString().toLowerCase()); - log.info("setting up mine rubble step: {}: {}", operation, text); - var mainObjectID = validObjectIDs.get(0); - var step = new ObjectStep(getQuestHelper(), mainObjectID, wp, text); - var offsetX = x; - var offsetY = y; - switch (direction) { - case NORTH: - offsetY += 1; - break; - case SOUTH: - offsetY -= 1; - break; - case WEST: - offsetX -= 1; - break; - case EAST: - offsetX += 1; - break; - } - var posWp = new WorldPoint(offsetX, offsetY, 0); - step.addTileMarker(posWp, SpriteID.SKILL_MINING); - for (var alternateIDs : validObjectIDs) { - // todo this adds the first object again xd - step.addAlternateObjects(alternateIDs); - } - - var conditionText = String.format("[%d] Rubble mined from the %s side", operation, direction.toString().toLowerCase()); - var conditionThatThisStepHasBeenDone = new ObjectCondition(validIDSet, wp); - conditionThatThisStepHasBeenDone.setText(text); - - this.mineSteps.add(step); - this.conditions.add(conditionThatThisStepHasBeenDone); - } - - @Subscribe - public void onGameTick(GameTick event) { - updateSteps(); - } - - @Override - public void startUp() { - updateSteps(); - } - - @Override - protected void setupSteps() { - this.operation = 1; - this.mineSteps = new ArrayList<>(); - this.conditions = new ArrayList<>(); - - var todo = new DetailedQuestStep(getQuestHelper(), "todo"); - - this.addMineRubbleStep(2764, 10266, RubbleLevel.Two, Direction.SOUTH); - this.addMineRubbleStep(2775, 10258, RubbleLevel.One, Direction.SOUTH); - this.addMineRubbleStep(2764, 10266, RubbleLevel.One, Direction.EAST); - this.addMineRubbleStep(2764, 10267, RubbleLevel.One, Direction.SOUTH); - - // after reversing - // mineStep 0: mine C - // mineStep 1: mine B - // mineStep 2: mine A - - // condition 0: A is not at the given state - // condition 1: B is not at the given state - // condition 2: C is not at the given state - - // i = 0: Mine C, if B and A are mined - // i = 1: Mine B, if A is mined - // i = 2: Mine A, with no condition - - conditionalStep = new ConditionalStep(getQuestHelper(), todo); - Collections.reverse(mineSteps); - - assert this.mineSteps.size() == this.conditions.size(); - - { - var allDone = new DetailedQuestStep(getQuestHelper(), "you are all done lol"); - var conditionList = new ArrayList(); - for (var condition : this.conditions) { - var xd2 = new Conditions(LogicType.NAND, condition); - xd2.setText(condition.getDisplayText()); - allDone.addRequirement(xd2); - } - var xd = new Conditions(LogicType.NAND, conditionList); - conditionalStep.addStep(xd, allDone); - } - for (var i = 0; i < mineSteps.size(); i++) { - var mineStep = mineSteps.get(i); - var conditionList = new ArrayList(); - StringBuilder text = new StringBuilder(); - for (var j = 0; j < this.conditions.size() - i - 1; j++) { - conditionList.add(this.conditions.get(j)); - text.append(this.conditions.get(j).getDisplayText()); - var xd2 = new Conditions(LogicType.NAND, this.conditions.get(j)); - xd2.setText(this.conditions.get(j).getDisplayText()); - mineStep.addRequirement(xd2); - } - - var xd = new Conditions(LogicType.NOR, conditionList); - xd.setText(text.toString()); - - conditionalStep.addStep(xd, mineStep); - } - } - - protected void updateSteps() { - startUpStep(this.conditionalStep); - } - - @Override - public List getSteps() { - var steps = new ArrayList(); - - steps.add(this.conditionalStep); - for (var step : this.mineSteps) { - steps.add(step); - } - - return steps; - } - - @Getter - enum RubbleLevel { - Three(123), - Two(ObjectID.RUBBLE_50598), - One(ObjectID.RUBBLE_50587, ObjectID.RUBBLE_50589); - - private final List objectIDs; - - RubbleLevel(Integer... possibleObjectIDs) { - this.objectIDs = new ArrayList(); - for (var xd : possibleObjectIDs) { - this.objectIDs.add(xd); - } - // Collections.addAll(this.objectIDs, possibleObjectIDs); - } - } -} diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 468bf6f3ed..09df79ae04 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -26,11 +26,13 @@ import com.questhelper.bank.banktab.BankSlotIcons; import com.questhelper.collections.ItemCollections; +import com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers.RubbleSolverOne; +import com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers.RubbleSolverThree; +import com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers.RubbleSolverTwo; import com.questhelper.panel.PanelDetails; import com.questhelper.questhelpers.BasicQuestHelper; import com.questhelper.questinfo.QuestHelperQuest; import com.questhelper.requirements.Requirement; -import com.questhelper.requirements.conditional.ObjectCondition; import com.questhelper.requirements.item.ItemRequirement; import com.questhelper.requirements.item.TeleportItemRequirement; import com.questhelper.requirements.player.CombatLevelRequirement; @@ -141,7 +143,9 @@ public class TheCurseOfArrav extends BasicQuestHelper private QuestStep unsortedStep54; private QuestStep unsortedStep56; private QuestStep unsortedStep58; - private PuzzleWrapperStep rubbleMiner; + private PuzzleWrapperStep rubbleMiner1; + private PuzzleWrapperStep rubbleMiner2; + private PuzzleWrapperStep rubbleMiner3; @Override @@ -374,15 +378,25 @@ public void setupSteps() // mineRubble2FromSouth.addTileMarker(new WorldPoint(2775, 10257, 0), whereToStandSprite); // mineRubble2FromSouth.setLinePoints(List.of(new WorldPoint(2763, 10264, 0), new WorldPoint(2769, 10254, 0), new WorldPoint(2775, 10255, 0))); - rubbleMiner = new RubbleMiner(this).puzzleWrapStep("make your way through the mine"); + rubbleMiner1 = new RubbleSolverOne(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); + rubbleMiner2 = new RubbleSolverTwo(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); + rubbleMiner3 = new RubbleSolverThree(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); unsortedStep20 = new ConditionalStep(this, headToTrollheim); - ((ConditionalStep) unsortedStep20).addStep(inTrollweissCave, rubbleMiner); + ((ConditionalStep) unsortedStep20).addStep(inTrollweissCave, rubbleMiner1); ((ConditionalStep) unsortedStep20).addStep(onTrollweissMountain, enterTrollweissCave); ((ConditionalStep) unsortedStep20).addStep(inTrollheimCave, continueThroughTrollheimCave); - unsortedStep22 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 22"); - unsortedStep24 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 24"); + unsortedStep24 = new ConditionalStep(this, headToTrollheim); + ((ConditionalStep) unsortedStep24).addStep(inTrollweissCave, rubbleMiner2); + ((ConditionalStep) unsortedStep24).addStep(onTrollweissMountain, enterTrollweissCave); + ((ConditionalStep) unsortedStep24).addStep(inTrollheimCave, continueThroughTrollheimCave); + + unsortedStep26 = new ConditionalStep(this, headToTrollheim); + ((ConditionalStep) unsortedStep26).addStep(inTrollweissCave, rubbleMiner3); + ((ConditionalStep) unsortedStep26).addStep(onTrollweissMountain, enterTrollweissCave); + ((ConditionalStep) unsortedStep26).addStep(inTrollheimCave, continueThroughTrollheimCave); + unsortedStep26 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 26"); unsortedStep28 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 28"); unsortedStep30 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 30"); @@ -508,7 +522,7 @@ public List getPanels() ))); panels.add(new PanelDetails("Fort Invasion", List.of( unsortedStep20, - rubbleMiner, + rubbleMiner1, unsortedStep22, unsortedStep24, unsortedStep26, diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java new file mode 100644 index 0000000000..b19f20da62 --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java @@ -0,0 +1,227 @@ +package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; + +import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; +import com.questhelper.requirements.Requirement; +import com.questhelper.requirements.conditional.Conditions; +import com.questhelper.requirements.conditional.ObjectCondition; +import com.questhelper.requirements.util.LogicType; +import com.questhelper.steps.*; + +import java.util.*; +import javax.inject.Inject; + +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.*; +import net.runelite.api.coords.Direction; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.GameTick; +import net.runelite.client.eventbus.Subscribe; + +@Slf4j +public abstract class RubbleSolver extends DetailedOwnerStep { + @Inject + protected Client client; + + private List mineSteps; + private List conditions; + private List inverseConditions; + private ConditionalStep conditionalStep; + + private int stepCounter; + + public RubbleSolver(TheCurseOfArrav theCurseOfArrav) { + super(theCurseOfArrav, "Make your way through the Trollweiss cave, mining rubble with your pickaxe."); + } + + protected void addMineRubbleStep(int x, int y, RubbleType rubbleType, Direction direction) { + var validObjectIDs = rubbleType.getObjectIDs(); + assert !validObjectIDs.isEmpty(); + + var validIDSet = new HashSet<>(validObjectIDs); + + var wp = new WorldPoint(x, y, 0); + var stepCounter = this.stepCounter++; + var text = String.format("[%d] Mine the rubble from the %s side", stepCounter, direction.toString().toLowerCase()); + log.info("setting up mine rubble step: {}: {}", stepCounter, text); + var mainObjectID = validObjectIDs.get(0); + var step = new ObjectStep(getQuestHelper(), mainObjectID, wp, text); + var offsetX = x; + var offsetY = y; + switch (direction) { + case NORTH: + offsetY += 1; + break; + case SOUTH: + offsetY -= 1; + break; + case WEST: + offsetX -= 1; + break; + case EAST: + offsetX += 1; + break; + } + var posWp = new WorldPoint(offsetX, offsetY, 0); + step.addTileMarker(posWp, SpriteID.SKILL_MINING); + for (var alternateIDs : validObjectIDs) { + // todo this adds the first object again xd + step.addAlternateObjects(alternateIDs); + } + + var conditionText = String.format("[%d] Rubble mined from the %s side", stepCounter, direction.toString().toLowerCase()); + var inverseConditionText = String.format("[%d] Rubble needs to be mined from the %s side", stepCounter, direction.toString().toLowerCase()); + var conditionThatRubbleIsStillThere = new ObjectCondition(validIDSet, wp); + var conditionThatRubbleHasBeenMined = new Conditions(LogicType.NAND, conditionThatRubbleIsStillThere); + conditionThatRubbleIsStillThere.setText(inverseConditionText); + conditionThatRubbleHasBeenMined.setText(conditionText); + + this.mineSteps.add(step); + this.conditions.add(conditionThatRubbleHasBeenMined); + this.inverseConditions.add(conditionThatRubbleIsStillThere); + } + + @Subscribe + public void onGameTick(GameTick event) { + updateSteps(); + } + + @Override + public void startUp() { + updateSteps(); + } + + protected abstract void setupRubbleSteps(); + + @Override + protected void setupSteps() { + this.stepCounter = 1; + this.mineSteps = new ArrayList<>(); + this.conditions = new ArrayList<>(); + this.inverseConditions = new ArrayList<>(); + + var todo = new DetailedQuestStep(getQuestHelper(), "todo"); + + this.setupRubbleSteps(); + + // Roadblock 1 (when quest state varbit is 22) + this.addMineRubbleStep(2764, 10266, RubbleType.Two, Direction.SOUTH); // 1 + this.addMineRubbleStep(2775, 10258, RubbleType.One, Direction.SOUTH); // 2 + this.addMineRubbleStep(2764, 10266, RubbleType.One, Direction.EAST); // 3 + this.addMineRubbleStep(2764, 10267, RubbleType.One, Direction.SOUTH); // 4 + + // Roadblock 2 (when quest state varbit is 24) + this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); // 5 + this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); // 6 + this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); // 7 + this.addMineRubbleStep(2766, 10279, RubbleType.Two, Direction.NORTH); // 8 + this.addMineRubbleStep(2766, 10278, RubbleType.Two, Direction.WEST); // 9 + this.addMineRubbleStep(2766, 10278, RubbleType.One, Direction.SOUTH); // 10 + this.addMineRubbleStep(2766, 10279, RubbleType.One, Direction.SOUTH); // 11 + this.addMineRubbleStep(2767, 10278, RubbleType.One, Direction.WEST); // 12 + this.addMineRubbleStep(2767, 10279, RubbleType.Two, Direction.WEST); // 13 + this.addMineRubbleStep(2768, 10279, RubbleType.One, Direction.WEST); // 14 + this.addMineRubbleStep(2767, 10279, RubbleType.One, Direction.SOUTH); // 15 + this.addMineRubbleStep(2768, 10280, RubbleType.Three, Direction.SOUTH); // 16: THIS TRIGGERS A STONE FALL OR SOMETHING :) + this.addMineRubbleStep(2768, 10281, RubbleType.One, Direction.SOUTH); // 17 + this.addMineRubbleStep(2769, 10281, RubbleType.Two, Direction.WEST); // 18 + this.addMineRubbleStep(2767, 10281, RubbleType.One, Direction.EAST); // 19 + this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); // 20 + this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); // 21 + this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); // 22 + + // Roadblock 3 + this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 23 + this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 24 + this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 25 + + this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.WEST); + + this.addMineRubbleStep(2789, 10283, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2789, 10284, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.SOUTH); + this.addMineRubbleStep(2790, 10285, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2791, 10285, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2789, 10283, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2790, 10283, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2791, 10283, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2790, 10282, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2791, 10282, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2791, 10283, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2791, 10285, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.SOUTH); + this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2793, 10285, RubbleType.Two, Direction.WEST); + + this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 26 (or when??) + + // after reversing + // mineStep 0: mine C + // mineStep 1: mine B + // mineStep 2: mine A + + // condition 0: A is mined + // condition 1: B is mined + // condition 2: C is mined + + // i = 0: Mine C, if B and A are mined, and C is not mined + // i = 1: Mine B, if A is mined + // i = 2: Mine A, with no condition + + conditionalStep = new ConditionalStep(getQuestHelper(), todo); + Collections.reverse(this.mineSteps); + Collections.reverse(this.inverseConditions); + + assert this.mineSteps.size() == this.conditions.size(); + assert this.mineSteps.size() == this.inverseConditions.size(); + + // { + // var allDone = new DetailedQuestStep(getQuestHelper(), "you are all done lol"); + // var conditionList = new ArrayList(); + // for (var condition : this.conditions) { + // allDone.addRequirement(condition); + // } + // var xd = new Conditions(LogicType.AND, conditionList); + // conditionalStep.addStep(xd, allDone); + // } + for (var i = 0; i < mineSteps.size(); i++) { + var mineStep = mineSteps.get(i); + + var conditionList = new ArrayList(); + + mineStep.addRequirement(this.inverseConditions.get(i)); + conditionList.add(this.inverseConditions.get(i)); + + StringBuilder text = new StringBuilder(); + for (var j = 0; j < this.conditions.size() - i - 1; j++) { + var condition = this.conditions.get(j); + conditionList.add(condition); + text.append(this.conditions.get(j).getDisplayText()); + mineStep.addRequirement(condition); + } + + var xd = new Conditions(LogicType.AND, conditionList); + xd.setText(text.toString()); + + conditionalStep.addStep(xd, mineStep); + } + } + + protected void updateSteps() { + startUpStep(this.conditionalStep); + } + + @Override + public List getSteps() { + var steps = new ArrayList(); + + steps.add(this.conditionalStep); + for (var step : this.mineSteps) { + steps.add(step); + } + + return steps; + } + +} diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java new file mode 100644 index 0000000000..7cc50bc87f --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java @@ -0,0 +1,84 @@ +package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; + +import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; +import com.questhelper.requirements.Requirement; +import com.questhelper.requirements.conditional.Conditions; +import com.questhelper.requirements.conditional.ObjectCondition; +import com.questhelper.requirements.util.LogicType; +import com.questhelper.steps.*; + +import java.util.*; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.*; +import net.runelite.api.coords.Direction; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.GameTick; +import net.runelite.client.eventbus.Subscribe; + +/** + * This class describes the rubble mining steps required for Roadblock 1 (when quest state varbit is 22) + */ +@Slf4j +public class RubbleSolverOne extends RubbleSolver +{ + public RubbleSolverOne(TheCurseOfArrav theCurseOfArrav) { + super(theCurseOfArrav); + } + + @Override + protected void setupRubbleSteps() { + this.addMineRubbleStep(2764, 10266, RubbleType.Two, Direction.SOUTH); // 1 + this.addMineRubbleStep(2775, 10258, RubbleType.One, Direction.SOUTH); // 2 + this.addMineRubbleStep(2764, 10266, RubbleType.One, Direction.EAST); // 3 + this.addMineRubbleStep(2764, 10267, RubbleType.One, Direction.SOUTH); // 4 + + // Roadblock 2 (when quest state varbit is 24) + this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); // 5 + this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); // 6 + this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); // 7 + this.addMineRubbleStep(2766, 10279, RubbleType.Two, Direction.NORTH); // 8 + this.addMineRubbleStep(2766, 10278, RubbleType.Two, Direction.WEST); // 9 + this.addMineRubbleStep(2766, 10278, RubbleType.One, Direction.SOUTH); // 10 + this.addMineRubbleStep(2766, 10279, RubbleType.One, Direction.SOUTH); // 11 + this.addMineRubbleStep(2767, 10278, RubbleType.One, Direction.WEST); // 12 + this.addMineRubbleStep(2767, 10279, RubbleType.Two, Direction.WEST); // 13 + this.addMineRubbleStep(2768, 10279, RubbleType.One, Direction.WEST); // 14 + this.addMineRubbleStep(2767, 10279, RubbleType.One, Direction.SOUTH); // 15 + this.addMineRubbleStep(2768, 10280, RubbleType.Three, Direction.SOUTH); // 16: THIS TRIGGERS A STONE FALL OR SOMETHING :) + this.addMineRubbleStep(2768, 10281, RubbleType.One, Direction.SOUTH); // 17 + this.addMineRubbleStep(2769, 10281, RubbleType.Two, Direction.WEST); // 18 + this.addMineRubbleStep(2767, 10281, RubbleType.One, Direction.EAST); // 19 + this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); // 20 + this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); // 21 + this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); // 22 + + // Roadblock 3 + this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 23 + this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 24 + this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 25 + + this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.WEST); + + this.addMineRubbleStep(2789, 10283, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2789, 10284, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.SOUTH); + this.addMineRubbleStep(2790, 10285, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2791, 10285, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2789, 10283, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2790, 10283, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2791, 10283, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2790, 10282, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2791, 10282, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2791, 10283, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2791, 10285, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.SOUTH); + this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2793, 10285, RubbleType.Two, Direction.WEST); + + this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 26 (or when??) + } +} diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java new file mode 100644 index 0000000000..67f16e89e1 --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java @@ -0,0 +1,71 @@ +package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; + +import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.coords.Direction; + +/** + * This class describes the rubble mining steps required for Roadblock 1 (when quest state varbit is 22) + */ +@Slf4j +public class RubbleSolverThree extends RubbleSolver +{ + public RubbleSolverThree(TheCurseOfArrav theCurseOfArrav) { + super(theCurseOfArrav); + } + + @Override + protected void setupRubbleSteps() { + this.addMineRubbleStep(2764, 10266, RubbleType.Two, Direction.SOUTH); // 1 + this.addMineRubbleStep(2775, 10258, RubbleType.One, Direction.SOUTH); // 2 + this.addMineRubbleStep(2764, 10266, RubbleType.One, Direction.EAST); // 3 + this.addMineRubbleStep(2764, 10267, RubbleType.One, Direction.SOUTH); // 4 + + // Roadblock 2 (when quest state varbit is 24) + this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); // 5 + this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); // 6 + this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); // 7 + this.addMineRubbleStep(2766, 10279, RubbleType.Two, Direction.NORTH); // 8 + this.addMineRubbleStep(2766, 10278, RubbleType.Two, Direction.WEST); // 9 + this.addMineRubbleStep(2766, 10278, RubbleType.One, Direction.SOUTH); // 10 + this.addMineRubbleStep(2766, 10279, RubbleType.One, Direction.SOUTH); // 11 + this.addMineRubbleStep(2767, 10278, RubbleType.One, Direction.WEST); // 12 + this.addMineRubbleStep(2767, 10279, RubbleType.Two, Direction.WEST); // 13 + this.addMineRubbleStep(2768, 10279, RubbleType.One, Direction.WEST); // 14 + this.addMineRubbleStep(2767, 10279, RubbleType.One, Direction.SOUTH); // 15 + this.addMineRubbleStep(2768, 10280, RubbleType.Three, Direction.SOUTH); // 16: THIS TRIGGERS A STONE FALL OR SOMETHING :) + this.addMineRubbleStep(2768, 10281, RubbleType.One, Direction.SOUTH); // 17 + this.addMineRubbleStep(2769, 10281, RubbleType.Two, Direction.WEST); // 18 + this.addMineRubbleStep(2767, 10281, RubbleType.One, Direction.EAST); // 19 + this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); // 20 + this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); // 21 + this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); // 22 + + // Roadblock 3 + this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 23 + this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 24 + this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 25 + + this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.WEST); + + this.addMineRubbleStep(2789, 10283, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2789, 10284, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.SOUTH); + this.addMineRubbleStep(2790, 10285, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2791, 10285, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2789, 10283, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2790, 10283, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2791, 10283, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2790, 10282, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2791, 10282, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2791, 10283, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2791, 10285, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.SOUTH); + this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2793, 10285, RubbleType.Two, Direction.WEST); + + this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 26 (or when??) + } +} diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java new file mode 100644 index 0000000000..bd7b4118d6 --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java @@ -0,0 +1,71 @@ +package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; + +import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.coords.Direction; + +/** + * This class describes the rubble mining steps required for Roadblock 1 (when quest state varbit is 22) + */ +@Slf4j +public class RubbleSolverTwo extends RubbleSolver +{ + public RubbleSolverTwo(TheCurseOfArrav theCurseOfArrav) { + super(theCurseOfArrav); + } + + @Override + protected void setupRubbleSteps() { + this.addMineRubbleStep(2764, 10266, RubbleType.Two, Direction.SOUTH); // 1 + this.addMineRubbleStep(2775, 10258, RubbleType.One, Direction.SOUTH); // 2 + this.addMineRubbleStep(2764, 10266, RubbleType.One, Direction.EAST); // 3 + this.addMineRubbleStep(2764, 10267, RubbleType.One, Direction.SOUTH); // 4 + + // Roadblock 2 (when quest state varbit is 24) + this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); // 5 + this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); // 6 + this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); // 7 + this.addMineRubbleStep(2766, 10279, RubbleType.Two, Direction.NORTH); // 8 + this.addMineRubbleStep(2766, 10278, RubbleType.Two, Direction.WEST); // 9 + this.addMineRubbleStep(2766, 10278, RubbleType.One, Direction.SOUTH); // 10 + this.addMineRubbleStep(2766, 10279, RubbleType.One, Direction.SOUTH); // 11 + this.addMineRubbleStep(2767, 10278, RubbleType.One, Direction.WEST); // 12 + this.addMineRubbleStep(2767, 10279, RubbleType.Two, Direction.WEST); // 13 + this.addMineRubbleStep(2768, 10279, RubbleType.One, Direction.WEST); // 14 + this.addMineRubbleStep(2767, 10279, RubbleType.One, Direction.SOUTH); // 15 + this.addMineRubbleStep(2768, 10280, RubbleType.Three, Direction.SOUTH); // 16: THIS TRIGGERS A STONE FALL OR SOMETHING :) + this.addMineRubbleStep(2768, 10281, RubbleType.One, Direction.SOUTH); // 17 + this.addMineRubbleStep(2769, 10281, RubbleType.Two, Direction.WEST); // 18 + this.addMineRubbleStep(2767, 10281, RubbleType.One, Direction.EAST); // 19 + this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); // 20 + this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); // 21 + this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); // 22 + + // Roadblock 3 + this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 23 + this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 24 + this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 25 + + this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.WEST); + + this.addMineRubbleStep(2789, 10283, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2789, 10284, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.SOUTH); + this.addMineRubbleStep(2790, 10285, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2791, 10285, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2789, 10283, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2790, 10283, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2791, 10283, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2790, 10282, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2791, 10282, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2791, 10283, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2791, 10285, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.SOUTH); + this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2793, 10285, RubbleType.Two, Direction.WEST); + + this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 26 (or when??) + } +} diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java new file mode 100644 index 0000000000..0d636f3361 --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java @@ -0,0 +1,24 @@ +package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; + +import lombok.Getter; +import net.runelite.api.ObjectID; +import java.util.ArrayList; +import java.util.List; + +@Getter +public enum RubbleType +{ + Three(ObjectID.RUBBLE_50603, ObjectID.RUBBLE_50604), + Two(ObjectID.RUBBLE_50598, ObjectID.RUBBLE_50602), + One(ObjectID.RUBBLE_50587, ObjectID.RUBBLE_50589, ObjectID.RUBBLE_50590, ObjectID.RUBBLE_50594, ObjectID.RUBBLE_50597); + + private final List objectIDs; + + RubbleType(Integer... possibleObjectIDs) { + this.objectIDs = new ArrayList(); + for (var xd : possibleObjectIDs) { + this.objectIDs.add(xd); + } + // Collections.addAll(this.objectIDs, possibleObjectIDs); + } +} From 19f6d6829eab05a7fc7ca0cd9641af2c70ad6fec Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 9 Nov 2024 17:03:11 +0100 Subject: [PATCH 03/60] why lag --- .../thecurseofarrav/TheCurseOfArrav.java | 6 +-- .../rubblesolvers/RubbleSolverOne.java | 47 ------------------- .../rubblesolvers/RubbleSolverThree.java | 28 +---------- .../rubblesolvers/RubbleSolverTwo.java | 35 +------------- 4 files changed, 4 insertions(+), 112 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 09df79ae04..fc03e50ea1 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -120,11 +120,9 @@ public class TheCurseOfArrav extends BasicQuestHelper private ConditionalStep unsortedStep10; private PuzzleWrapperStep solveTilePuzzle; private QuestStep unsortedStep12; - private QuestStep unsortedStep14; private QuestStep unsortedStep16; private QuestStep unsortedStep18; private QuestStep unsortedStep20; - private QuestStep unsortedStep22; private QuestStep unsortedStep24; private QuestStep unsortedStep26; private QuestStep unsortedStep28; @@ -397,7 +395,6 @@ public void setupSteps() ((ConditionalStep) unsortedStep26).addStep(onTrollweissMountain, enterTrollweissCave); ((ConditionalStep) unsortedStep26).addStep(inTrollheimCave, continueThroughTrollheimCave); - unsortedStep26 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 26"); unsortedStep28 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 28"); unsortedStep30 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 30"); unsortedStep32 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 32"); @@ -523,7 +520,8 @@ public List getPanels() panels.add(new PanelDetails("Fort Invasion", List.of( unsortedStep20, rubbleMiner1, - unsortedStep22, + rubbleMiner2, + rubbleMiner3, unsortedStep24, unsortedStep26, unsortedStep28, diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java index 7cc50bc87f..407fb17d7c 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java @@ -33,52 +33,5 @@ protected void setupRubbleSteps() { this.addMineRubbleStep(2775, 10258, RubbleType.One, Direction.SOUTH); // 2 this.addMineRubbleStep(2764, 10266, RubbleType.One, Direction.EAST); // 3 this.addMineRubbleStep(2764, 10267, RubbleType.One, Direction.SOUTH); // 4 - - // Roadblock 2 (when quest state varbit is 24) - this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); // 5 - this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); // 6 - this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); // 7 - this.addMineRubbleStep(2766, 10279, RubbleType.Two, Direction.NORTH); // 8 - this.addMineRubbleStep(2766, 10278, RubbleType.Two, Direction.WEST); // 9 - this.addMineRubbleStep(2766, 10278, RubbleType.One, Direction.SOUTH); // 10 - this.addMineRubbleStep(2766, 10279, RubbleType.One, Direction.SOUTH); // 11 - this.addMineRubbleStep(2767, 10278, RubbleType.One, Direction.WEST); // 12 - this.addMineRubbleStep(2767, 10279, RubbleType.Two, Direction.WEST); // 13 - this.addMineRubbleStep(2768, 10279, RubbleType.One, Direction.WEST); // 14 - this.addMineRubbleStep(2767, 10279, RubbleType.One, Direction.SOUTH); // 15 - this.addMineRubbleStep(2768, 10280, RubbleType.Three, Direction.SOUTH); // 16: THIS TRIGGERS A STONE FALL OR SOMETHING :) - this.addMineRubbleStep(2768, 10281, RubbleType.One, Direction.SOUTH); // 17 - this.addMineRubbleStep(2769, 10281, RubbleType.Two, Direction.WEST); // 18 - this.addMineRubbleStep(2767, 10281, RubbleType.One, Direction.EAST); // 19 - this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); // 20 - this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); // 21 - this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); // 22 - - // Roadblock 3 - this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 23 - this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 24 - this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 25 - - this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.WEST); - - this.addMineRubbleStep(2789, 10283, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2789, 10284, RubbleType.Three, Direction.WEST); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.SOUTH); - this.addMineRubbleStep(2790, 10285, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2791, 10285, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2789, 10283, RubbleType.One, Direction.NORTH); - this.addMineRubbleStep(2790, 10283, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2791, 10283, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2790, 10282, RubbleType.One, Direction.NORTH); - this.addMineRubbleStep(2791, 10282, RubbleType.Three, Direction.WEST); - this.addMineRubbleStep(2791, 10283, RubbleType.One, Direction.SOUTH); - this.addMineRubbleStep(2791, 10285, RubbleType.One, Direction.SOUTH); - this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.SOUTH); - this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2793, 10285, RubbleType.Two, Direction.WEST); - - this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 26 (or when??) } } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java index 67f16e89e1..1597e62a20 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java @@ -5,7 +5,7 @@ import net.runelite.api.coords.Direction; /** - * This class describes the rubble mining steps required for Roadblock 1 (when quest state varbit is 22) + * This class describes the rubble mining steps required for Roadblock 3 (when quest state varbit is 26) */ @Slf4j public class RubbleSolverThree extends RubbleSolver @@ -16,32 +16,6 @@ public RubbleSolverThree(TheCurseOfArrav theCurseOfArrav) { @Override protected void setupRubbleSteps() { - this.addMineRubbleStep(2764, 10266, RubbleType.Two, Direction.SOUTH); // 1 - this.addMineRubbleStep(2775, 10258, RubbleType.One, Direction.SOUTH); // 2 - this.addMineRubbleStep(2764, 10266, RubbleType.One, Direction.EAST); // 3 - this.addMineRubbleStep(2764, 10267, RubbleType.One, Direction.SOUTH); // 4 - - // Roadblock 2 (when quest state varbit is 24) - this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); // 5 - this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); // 6 - this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); // 7 - this.addMineRubbleStep(2766, 10279, RubbleType.Two, Direction.NORTH); // 8 - this.addMineRubbleStep(2766, 10278, RubbleType.Two, Direction.WEST); // 9 - this.addMineRubbleStep(2766, 10278, RubbleType.One, Direction.SOUTH); // 10 - this.addMineRubbleStep(2766, 10279, RubbleType.One, Direction.SOUTH); // 11 - this.addMineRubbleStep(2767, 10278, RubbleType.One, Direction.WEST); // 12 - this.addMineRubbleStep(2767, 10279, RubbleType.Two, Direction.WEST); // 13 - this.addMineRubbleStep(2768, 10279, RubbleType.One, Direction.WEST); // 14 - this.addMineRubbleStep(2767, 10279, RubbleType.One, Direction.SOUTH); // 15 - this.addMineRubbleStep(2768, 10280, RubbleType.Three, Direction.SOUTH); // 16: THIS TRIGGERS A STONE FALL OR SOMETHING :) - this.addMineRubbleStep(2768, 10281, RubbleType.One, Direction.SOUTH); // 17 - this.addMineRubbleStep(2769, 10281, RubbleType.Two, Direction.WEST); // 18 - this.addMineRubbleStep(2767, 10281, RubbleType.One, Direction.EAST); // 19 - this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); // 20 - this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); // 21 - this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); // 22 - - // Roadblock 3 this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 23 this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 24 this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 25 diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java index bd7b4118d6..f342c595bd 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java @@ -5,7 +5,7 @@ import net.runelite.api.coords.Direction; /** - * This class describes the rubble mining steps required for Roadblock 1 (when quest state varbit is 22) + * This class describes the rubble mining steps required for Roadblock 2 (when quest state varbit is 24) */ @Slf4j public class RubbleSolverTwo extends RubbleSolver @@ -16,12 +16,6 @@ public RubbleSolverTwo(TheCurseOfArrav theCurseOfArrav) { @Override protected void setupRubbleSteps() { - this.addMineRubbleStep(2764, 10266, RubbleType.Two, Direction.SOUTH); // 1 - this.addMineRubbleStep(2775, 10258, RubbleType.One, Direction.SOUTH); // 2 - this.addMineRubbleStep(2764, 10266, RubbleType.One, Direction.EAST); // 3 - this.addMineRubbleStep(2764, 10267, RubbleType.One, Direction.SOUTH); // 4 - - // Roadblock 2 (when quest state varbit is 24) this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); // 5 this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); // 6 this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); // 7 @@ -40,32 +34,5 @@ protected void setupRubbleSteps() { this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); // 20 this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); // 21 this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); // 22 - - // Roadblock 3 - this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 23 - this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 24 - this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 25 - - this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.WEST); - - this.addMineRubbleStep(2789, 10283, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2789, 10284, RubbleType.Three, Direction.WEST); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.SOUTH); - this.addMineRubbleStep(2790, 10285, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2791, 10285, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2789, 10283, RubbleType.One, Direction.NORTH); - this.addMineRubbleStep(2790, 10283, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2791, 10283, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2790, 10282, RubbleType.One, Direction.NORTH); - this.addMineRubbleStep(2791, 10282, RubbleType.Three, Direction.WEST); - this.addMineRubbleStep(2791, 10283, RubbleType.One, Direction.SOUTH); - this.addMineRubbleStep(2791, 10285, RubbleType.One, Direction.SOUTH); - this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.SOUTH); - this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2793, 10285, RubbleType.Two, Direction.WEST); - - this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 26 (or when??) } } From 65e3f382a9b1a5448891178460d6a9f5ca46694c Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 9 Nov 2024 17:12:35 +0100 Subject: [PATCH 04/60] only pass once conditions with list of requirements / logictype --- .../thecurseofarrav/rubblesolvers/RubbleSolver.java | 4 ++-- .../questhelper/requirements/conditional/Conditions.java | 9 +++++++++ .../requirements/conditional/ObjectCondition.java | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java index b19f20da62..e637ac1444 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java @@ -71,7 +71,7 @@ protected void addMineRubbleStep(int x, int y, RubbleType rubbleType, Direction var conditionText = String.format("[%d] Rubble mined from the %s side", stepCounter, direction.toString().toLowerCase()); var inverseConditionText = String.format("[%d] Rubble needs to be mined from the %s side", stepCounter, direction.toString().toLowerCase()); var conditionThatRubbleIsStillThere = new ObjectCondition(validIDSet, wp); - var conditionThatRubbleHasBeenMined = new Conditions(LogicType.NAND, conditionThatRubbleIsStillThere); + var conditionThatRubbleHasBeenMined = new Conditions(true, LogicType.NAND, conditionThatRubbleIsStillThere); conditionThatRubbleIsStillThere.setText(inverseConditionText); conditionThatRubbleHasBeenMined.setText(conditionText); @@ -201,7 +201,7 @@ protected void setupSteps() { mineStep.addRequirement(condition); } - var xd = new Conditions(LogicType.AND, conditionList); + var xd = new Conditions(true, LogicType.AND, conditionList); xd.setText(text.toString()); conditionalStep.addStep(xd, mineStep); diff --git a/src/main/java/com/questhelper/requirements/conditional/Conditions.java b/src/main/java/com/questhelper/requirements/conditional/Conditions.java index 0ef0b1f94e..9bf414947e 100644 --- a/src/main/java/com/questhelper/requirements/conditional/Conditions.java +++ b/src/main/java/com/questhelper/requirements/conditional/Conditions.java @@ -131,6 +131,15 @@ public Conditions(boolean onlyNeedToPassOnce, Requirement... conditions) this.logicType = LogicType.AND; } + public Conditions(boolean onlyNeedToPassOnce, LogicType logicType, ArrayList conditions) + { + assert(conditions.stream().noneMatch(Objects::isNull)); + + this.conditions = new ArrayList<>(conditions); + this.logicType = logicType; + this.onlyNeedToPassOnce = onlyNeedToPassOnce; + } + @Override @Nonnull public String getDisplayText() diff --git a/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java b/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java index f579d84859..0ae8a4d552 100644 --- a/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java +++ b/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java @@ -76,6 +76,7 @@ public ObjectCondition(Set objectIDs, WorldPoint worldPoint) this.zone = new Zone(worldPoint); } + @Override public boolean check(Client client) { Tile[][] tiles; From 59f0ef815bf817a0494b4b6b6a39d0625dc9234b Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 9 Nov 2024 18:05:01 +0100 Subject: [PATCH 05/60] progress --- .../thecurseofarrav/TheCurseOfArrav.java | 47 ++++++++-- .../rubblesolvers/RubbleSolver.java | 86 ++++--------------- .../rubblesolvers/RubbleSolverFour.java | 49 +++++++++++ .../rubblesolvers/RubbleSolverOne.java | 2 +- .../rubblesolvers/RubbleSolverThree.java | 21 ++--- .../rubblesolvers/RubbleSolverTwo.java | 2 +- .../rubblesolvers/RubbleType.java | 4 +- 7 files changed, 121 insertions(+), 90 deletions(-) create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index fc03e50ea1..ae08fd2a04 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -26,6 +26,7 @@ import com.questhelper.bank.banktab.BankSlotIcons; import com.questhelper.collections.ItemCollections; +import com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers.RubbleSolverFour; import com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers.RubbleSolverOne; import com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers.RubbleSolverThree; import com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers.RubbleSolverTwo; @@ -144,6 +145,7 @@ public class TheCurseOfArrav extends BasicQuestHelper private PuzzleWrapperStep rubbleMiner1; private PuzzleWrapperStep rubbleMiner2; private PuzzleWrapperStep rubbleMiner3; + private PuzzleWrapperStep rubbleMiner4; @Override @@ -379,6 +381,9 @@ public void setupSteps() rubbleMiner1 = new RubbleSolverOne(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); rubbleMiner2 = new RubbleSolverTwo(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); rubbleMiner3 = new RubbleSolverThree(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); + rubbleMiner4 = new RubbleSolverFour(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); + + rubbleMiner1.addSubSteps(rubbleMiner2, rubbleMiner3, rubbleMiner4); unsortedStep20 = new ConditionalStep(this, headToTrollheim); ((ConditionalStep) unsortedStep20).addStep(inTrollweissCave, rubbleMiner1); @@ -395,10 +400,40 @@ public void setupSteps() ((ConditionalStep) unsortedStep26).addStep(onTrollweissMountain, enterTrollweissCave); ((ConditionalStep) unsortedStep26).addStep(inTrollheimCave, continueThroughTrollheimCave); - unsortedStep28 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 28"); - unsortedStep30 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 30"); - unsortedStep32 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 32"); - unsortedStep34 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 34"); + unsortedStep28 = new ConditionalStep(this, headToTrollheim); + ((ConditionalStep) unsortedStep28).addStep(inTrollweissCave, rubbleMiner4); + ((ConditionalStep) unsortedStep28).addStep(onTrollweissMountain, enterTrollweissCave); + ((ConditionalStep) unsortedStep28).addStep(inTrollheimCave, continueThroughTrollheimCave); + + + var climbUpstairsAndTalkToArrav = new ObjectStep(this, ObjectID.STAIRS_50508, new WorldPoint(2811, 10267, 0), "Climb up the stairs in the room with the red tile floor and talk to Arrav."); + unsortedStep30 = new ConditionalStep(this, headToTrollheim); + ((ConditionalStep) unsortedStep30).addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); + ((ConditionalStep) unsortedStep30).addStep(onTrollweissMountain, enterTrollweissCave); + ((ConditionalStep) unsortedStep30).addStep(inTrollheimCave, continueThroughTrollheimCave); + + var arravHouseFirstRoom = new Zone(new WorldPoint(2848, 3868, 0), new WorldPoint(2858, 3873, 0)); + var inArravHouseFirstRoom = new ZoneRequirement(arravHouseFirstRoom); + var talkToArrav = new NpcStep(this, NpcID.ARRAV_14129, new WorldPoint(2856, 3871, 0), "Talk to Arrav."); + + unsortedStep32 = new ConditionalStep(this, headToTrollheim); + ((ConditionalStep) unsortedStep32).addStep(inArravHouseFirstRoom, talkToArrav); + ((ConditionalStep) unsortedStep32).addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); + ((ConditionalStep) unsortedStep32).addStep(onTrollweissMountain, enterTrollweissCave); + ((ConditionalStep) unsortedStep32).addStep(inTrollheimCave, continueThroughTrollheimCave); + + var arravHouseSecondRoom = new Zone(new WorldPoint(2859, 2873, 0), new WorldPoint(2863, 3865, 0)); + var inArravHouseSecondRoom = new ZoneRequirement(arravHouseSecondRoom); + + var goToNextRoom = new ObjectStep(this, ObjectID.DOOR_50514, new WorldPoint(2859, 3870, 0), "Enter the room to your east and search the tapestry for ?."); + var searchTapestry = new ObjectStep(this, ObjectID.TAPESTRY_50516, new WorldPoint(2861, 3865, 0), "Search the tapestry in the south of the room."); + unsortedStep34 = new ConditionalStep(this, headToTrollheim); + ((ConditionalStep) unsortedStep34).addStep(inArravHouseSecondRoom, searchTapestry); + ((ConditionalStep) unsortedStep34).addStep(inArravHouseFirstRoom, goToNextRoom); + ((ConditionalStep) unsortedStep34).addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); + ((ConditionalStep) unsortedStep34).addStep(onTrollweissMountain, enterTrollweissCave); + ((ConditionalStep) unsortedStep34).addStep(inTrollheimCave, continueThroughTrollheimCave); + unsortedStep36 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 36"); unsortedStep38 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 38"); unsortedStep40 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 40"); @@ -522,9 +557,7 @@ public List getPanels() rubbleMiner1, rubbleMiner2, rubbleMiner3, - unsortedStep24, - unsortedStep26, - unsortedStep28, + rubbleMiner4, unsortedStep30, unsortedStep32, unsortedStep34, diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java index e637ac1444..822ef88b1c 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java @@ -29,8 +29,8 @@ public abstract class RubbleSolver extends DetailedOwnerStep { private int stepCounter; - public RubbleSolver(TheCurseOfArrav theCurseOfArrav) { - super(theCurseOfArrav, "Make your way through the Trollweiss cave, mining rubble with your pickaxe."); + public RubbleSolver(TheCurseOfArrav theCurseOfArrav, String number) { + super(theCurseOfArrav, "Make your way through the Trollweiss cave, mining rubble with your pickaxe. " + number); } protected void addMineRubbleStep(int x, int y, RubbleType rubbleType, Direction direction) { @@ -103,59 +103,6 @@ protected void setupSteps() { this.setupRubbleSteps(); - // Roadblock 1 (when quest state varbit is 22) - this.addMineRubbleStep(2764, 10266, RubbleType.Two, Direction.SOUTH); // 1 - this.addMineRubbleStep(2775, 10258, RubbleType.One, Direction.SOUTH); // 2 - this.addMineRubbleStep(2764, 10266, RubbleType.One, Direction.EAST); // 3 - this.addMineRubbleStep(2764, 10267, RubbleType.One, Direction.SOUTH); // 4 - - // Roadblock 2 (when quest state varbit is 24) - this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); // 5 - this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); // 6 - this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); // 7 - this.addMineRubbleStep(2766, 10279, RubbleType.Two, Direction.NORTH); // 8 - this.addMineRubbleStep(2766, 10278, RubbleType.Two, Direction.WEST); // 9 - this.addMineRubbleStep(2766, 10278, RubbleType.One, Direction.SOUTH); // 10 - this.addMineRubbleStep(2766, 10279, RubbleType.One, Direction.SOUTH); // 11 - this.addMineRubbleStep(2767, 10278, RubbleType.One, Direction.WEST); // 12 - this.addMineRubbleStep(2767, 10279, RubbleType.Two, Direction.WEST); // 13 - this.addMineRubbleStep(2768, 10279, RubbleType.One, Direction.WEST); // 14 - this.addMineRubbleStep(2767, 10279, RubbleType.One, Direction.SOUTH); // 15 - this.addMineRubbleStep(2768, 10280, RubbleType.Three, Direction.SOUTH); // 16: THIS TRIGGERS A STONE FALL OR SOMETHING :) - this.addMineRubbleStep(2768, 10281, RubbleType.One, Direction.SOUTH); // 17 - this.addMineRubbleStep(2769, 10281, RubbleType.Two, Direction.WEST); // 18 - this.addMineRubbleStep(2767, 10281, RubbleType.One, Direction.EAST); // 19 - this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); // 20 - this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); // 21 - this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); // 22 - - // Roadblock 3 - this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 23 - this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 24 - this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 25 - - this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.WEST); - - this.addMineRubbleStep(2789, 10283, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2789, 10284, RubbleType.Three, Direction.WEST); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.SOUTH); - this.addMineRubbleStep(2790, 10285, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2791, 10285, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2789, 10283, RubbleType.One, Direction.NORTH); - this.addMineRubbleStep(2790, 10283, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2791, 10283, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2790, 10282, RubbleType.One, Direction.NORTH); - this.addMineRubbleStep(2791, 10282, RubbleType.Three, Direction.WEST); - this.addMineRubbleStep(2791, 10283, RubbleType.One, Direction.SOUTH); - this.addMineRubbleStep(2791, 10285, RubbleType.One, Direction.SOUTH); - this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.SOUTH); - this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2793, 10285, RubbleType.Two, Direction.WEST); - - this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 26 (or when??) - // after reversing // mineStep 0: mine C // mineStep 1: mine B @@ -170,8 +117,8 @@ protected void setupSteps() { // i = 2: Mine A, with no condition conditionalStep = new ConditionalStep(getQuestHelper(), todo); - Collections.reverse(this.mineSteps); - Collections.reverse(this.inverseConditions); + // Collections.reverse(this.mineSteps); + // Collections.reverse(this.inverseConditions); assert this.mineSteps.size() == this.conditions.size(); assert this.mineSteps.size() == this.inverseConditions.size(); @@ -187,22 +134,23 @@ protected void setupSteps() { // } for (var i = 0; i < mineSteps.size(); i++) { var mineStep = mineSteps.get(i); + var inverseCondition = this.inverseConditions.get(i); - var conditionList = new ArrayList(); + // var conditionList = new ArrayList(); - mineStep.addRequirement(this.inverseConditions.get(i)); - conditionList.add(this.inverseConditions.get(i)); + mineStep.addRequirement(inverseCondition); + // conditionList.add(this.inverseConditions.get(i)); - StringBuilder text = new StringBuilder(); - for (var j = 0; j < this.conditions.size() - i - 1; j++) { - var condition = this.conditions.get(j); - conditionList.add(condition); - text.append(this.conditions.get(j).getDisplayText()); - mineStep.addRequirement(condition); - } + // StringBuilder text = new StringBuilder(); + // for (var j = 0; j < this.conditions.size() - i - 1; j++) { + // var condition = this.conditions.get(j); + // conditionList.add(condition); + // text.append(this.conditions.get(j).getDisplayText()); + // mineStep.addRequirement(condition); + // } - var xd = new Conditions(true, LogicType.AND, conditionList); - xd.setText(text.toString()); + var xd = new Conditions(LogicType.AND, inverseCondition); + xd.setText(inverseCondition.getDisplayText()); conditionalStep.addStep(xd, mineStep); } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java new file mode 100644 index 0000000000..1f2f21f969 --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java @@ -0,0 +1,49 @@ +package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; + +import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.coords.Direction; + +/** + * This class describes the rubble mining steps required for Roadblock 3 (when quest state varbit is 26) + */ +@Slf4j +public class RubbleSolverFour extends RubbleSolver +{ + public RubbleSolverFour(TheCurseOfArrav theCurseOfArrav) { + super(theCurseOfArrav, "4"); + } + + @Override + protected void setupRubbleSteps() { + this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 1 + this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 2 + this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 3 + this.addMineRubbleStep(2788, 10267, RubbleType.Two, Direction.NORTH); // 4 + this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 5 + this.addMineRubbleStep(2788, 10267, RubbleType.One, Direction.WEST); // 6 + + // Last part from south + this.addMineRubbleStep(2803, 10264, RubbleType.Three, Direction.SOUTH); // 7 + this.addMineRubbleStep(2803, 10265, RubbleType.Two, Direction.SOUTH); // 8 + + // Last part from north + this.addMineRubbleStep(2803, 10267, RubbleType.One, Direction.NORTH); // 9 + this.addMineRubbleStep(2803, 10266, RubbleType.Three, Direction.NORTH); // 10 + this.addMineRubbleStep(2804, 10266, RubbleType.Two, Direction.NORTH); // 11 + + // Last part from west + this.addMineRubbleStep(2802, 10266, RubbleType.Two, Direction.WEST); // 12 + this.addMineRubbleStep(2801, 10265, RubbleType.One, Direction.NORTH); // 13 + this.addMineRubbleStep(2802, 10265, RubbleType.One, Direction.WEST); // 14 + this.addMineRubbleStep(2803, 10265, RubbleType.One, Direction.WEST); // 15 + this.addMineRubbleStep(2802, 10266, RubbleType.One, Direction.SOUTH); // 16 + this.addMineRubbleStep(2803, 10266, RubbleType.Two, Direction.WEST); // 17 + this.addMineRubbleStep(2804, 10265, RubbleType.Two, Direction.WEST); // 18 + this.addMineRubbleStep(2803, 10266, RubbleType.One, Direction.SOUTH); // 19 + this.addMineRubbleStep(2804, 10266, RubbleType.One, Direction.WEST); // 20 + this.addMineRubbleStep(2804, 10265, RubbleType.One, Direction.NORTH); // 21 + this.addMineRubbleStep(2805, 10265, RubbleType.One, Direction.WEST); // 22 + this.addMineRubbleStep(2806, 10265, RubbleType.One, Direction.WEST); // 23 + } +} diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java index 407fb17d7c..5ea75dda5e 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java @@ -24,7 +24,7 @@ public class RubbleSolverOne extends RubbleSolver { public RubbleSolverOne(TheCurseOfArrav theCurseOfArrav) { - super(theCurseOfArrav); + super(theCurseOfArrav, "1"); } @Override diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java index 1597e62a20..43697f6927 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java @@ -11,22 +11,23 @@ public class RubbleSolverThree extends RubbleSolver { public RubbleSolverThree(TheCurseOfArrav theCurseOfArrav) { - super(theCurseOfArrav); + super(theCurseOfArrav, "3"); } @Override protected void setupRubbleSteps() { - this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 23 - this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 24 - this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 25 + // These 3 steps are technically part of the next solver, but it's better to get these done asap + this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 1 + this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 2 + this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 3 - this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); // 4 + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); // 5 + this.addMineRubbleStep(2789, 10285, RubbleType.Two, Direction.WEST); // 6 this.addMineRubbleStep(2789, 10283, RubbleType.Two, Direction.WEST); this.addMineRubbleStep(2789, 10284, RubbleType.Three, Direction.WEST); - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.SOUTH); + this.addMineRubbleStep(2789, 10285, RubbleType.One, Direction.SOUTH); this.addMineRubbleStep(2790, 10285, RubbleType.One, Direction.WEST); this.addMineRubbleStep(2791, 10285, RubbleType.Two, Direction.WEST); this.addMineRubbleStep(2789, 10283, RubbleType.One, Direction.NORTH); @@ -37,8 +38,8 @@ protected void setupRubbleSteps() { this.addMineRubbleStep(2791, 10283, RubbleType.One, Direction.SOUTH); this.addMineRubbleStep(2791, 10285, RubbleType.One, Direction.SOUTH); this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.SOUTH); - this.addMineRubbleStep(2792, 10285, RubbleType.Two, Direction.WEST); - this.addMineRubbleStep(2793, 10285, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2792, 10285, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2793, 10285, RubbleType.One, Direction.WEST); this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 26 (or when??) } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java index f342c595bd..c65e280dde 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java @@ -11,7 +11,7 @@ public class RubbleSolverTwo extends RubbleSolver { public RubbleSolverTwo(TheCurseOfArrav theCurseOfArrav) { - super(theCurseOfArrav); + super(theCurseOfArrav, "2"); } @Override diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java index 0d636f3361..4350f47e76 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java @@ -9,8 +9,8 @@ public enum RubbleType { Three(ObjectID.RUBBLE_50603, ObjectID.RUBBLE_50604), - Two(ObjectID.RUBBLE_50598, ObjectID.RUBBLE_50602), - One(ObjectID.RUBBLE_50587, ObjectID.RUBBLE_50589, ObjectID.RUBBLE_50590, ObjectID.RUBBLE_50594, ObjectID.RUBBLE_50597); + Two(ObjectID.RUBBLE_50598, ObjectID.RUBBLE_50602, ObjectID.RUBBLE_50601, ObjectID.RUBBLE_50599), + One(ObjectID.RUBBLE_50587, ObjectID.RUBBLE_50589, ObjectID.RUBBLE_50590, ObjectID.RUBBLE_50594, ObjectID.RUBBLE_50597, ObjectID.RUBBLE_50588); private final List objectIDs; From 7cb8b34e3c0011ab46528cb29049b59a90896758 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 10 Nov 2024 16:01:26 +0100 Subject: [PATCH 06/60] more progress --- .../thecurseofarrav/MetalDoorSolver.java | 328 ++++++++++++++++++ .../thecurseofarrav/TheCurseOfArrav.java | 311 +++++++++++++---- .../rubblesolvers/RubbleSolver.java | 1 - .../widget/WidgetModelRequirement.java | 4 +- .../widget/WidgetTextRequirement.java | 28 +- .../steps/widget/WidgetDetails.java | 7 + .../thecurseofarrav/MetalDoorSolverTest.java | 67 ++++ 7 files changed, 684 insertions(+), 62 deletions(-) create mode 100644 src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java create mode 100644 src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java new file mode 100644 index 0000000000..782bbfd11b --- /dev/null +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java @@ -0,0 +1,328 @@ +package com.questhelper.helpers.quests.thecurseofarrav; + +import com.questhelper.requirements.item.ItemRequirement; +import com.questhelper.requirements.widget.WidgetModelRequirement; +import com.questhelper.requirements.widget.WidgetPresenceRequirement; +import com.questhelper.requirements.widget.WidgetTextRequirement; +import com.questhelper.steps.ConditionalStep; +import com.questhelper.steps.DetailedOwnerStep; +import com.questhelper.steps.DetailedQuestStep; +import com.questhelper.steps.ItemStep; +import com.questhelper.steps.ObjectStep; +import com.questhelper.steps.QuestStep; +import java.util.List; +import java.util.regex.Pattern; +import javax.inject.Inject; +import com.questhelper.steps.WidgetStep; +import com.questhelper.steps.widget.WidgetDetails; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.ItemID; +import net.runelite.api.ObjectID; +import net.runelite.api.annotations.Interface; +import net.runelite.api.coords.WorldPoint; +import net.runelite.api.events.GameTick; +import net.runelite.client.eventbus.Subscribe; +import static com.questhelper.requirements.util.LogicHelper.and; +import static com.questhelper.requirements.util.LogicHelper.not; + +@Slf4j +public class MetalDoorSolver extends DetailedOwnerStep +{ + private static final int STRIP_1_INDEX = 2; + private static final int STRIP_2_INDEX = 1; + private static final int STRIP_3_INDEX = 3; + private static final int STRIP_4_INDEX = 0; + /** + * Maps the relevant numbers from the Metal door puzzle to their corresponding rows. + * The first column is for strip 4 + * The second column is for strip 2 + * The third column is for strip 1 + * The fourth column is for strip 3 + */ + private static final int[][] CODE_MAPPING = new int[][]{ + { // A + 7, 9, 6, 4, + }, + { // B + 5, 3, 1, 0, + }, + { // C + 2, 8, 6, 3, + }, + { // D + 0, 6, 4, 7, + }, + { // E + 4, 3, 6, 4, + }, + { // F + 2, 2, 1, 9, + }, + { // G + 2, 3, 2, 6, + }, + { // H + 4, 3, 8, 1, + }, + { // I + 9, 3, 0, 9, + }, + }; + + private static final @Interface int PUZZLE_GROUP_ID = 903; + private static final int PUZZLE_BTN_UP_CHILD_ID = 21; + private static final int PUZZLE_BTN_DOWN_CHILD_ID = 22; + + private static final int PUZZLE_NUMBER_0_MODEL_ID = 50567; + private static final int PUZZLE_NUMBER_1_MODEL_ID = 50542; + private static final int PUZZLE_NUMBER_2_MODEL_ID = 50540; + private static final int PUZZLE_NUMBER_3_MODEL_ID = 50557; + private static final int PUZZLE_NUMBER_4_MODEL_ID = 50562; + private static final int PUZZLE_NUMBER_5_MODEL_ID = 50555; + private static final int PUZZLE_NUMBER_6_MODEL_ID = 50568; + private static final int PUZZLE_NUMBER_7_MODEL_ID = 50566; + private static final int PUZZLE_NUMBER_8_MODEL_ID = 50575; + private static final int PUZZLE_NUMBER_9_MODEL_ID = 50553; + private static final int[] PUZZLE_NUMBERS = new int[]{PUZZLE_NUMBER_0_MODEL_ID, PUZZLE_NUMBER_1_MODEL_ID, PUZZLE_NUMBER_2_MODEL_ID, PUZZLE_NUMBER_3_MODEL_ID, PUZZLE_NUMBER_4_MODEL_ID, PUZZLE_NUMBER_5_MODEL_ID, PUZZLE_NUMBER_6_MODEL_ID, PUZZLE_NUMBER_7_MODEL_ID, PUZZLE_NUMBER_8_MODEL_ID, PUZZLE_NUMBER_9_MODEL_ID}; + + private static final int PUZZLE_ENTER_CHILD_ID = 23; + private static final int PUZZLE_BACK_CHILD_ID = 24; + private static final int PUZZLE_PASSWORD_CURRENT_CHILD_ID = 25; + private static final int PUZZLE_PASSWORD_1_CHILD_ID = 26; + private static final int PUZZLE_PASSWORD_2_CHILD_ID = 27; + private static final int PUZZLE_PASSWORD_3_CHILD_ID = 28; + private static final int PUZZLE_PASSWORD_4_CHILD_ID = 29; + + /** + * Group ID of the "MESBOX" widget containing our code + */ + private static final @Interface int MESBOX_GROUP_ID = 229; + + /** + * Child ID of the "MESBOX" widget containing our code + */ + private static final int MESBOX_CHILD_ID = 1; + + private static final Pattern CODE_PATTERN = Pattern.compile("It reads ([A-I]{4})."); + + @Inject + Client client; + + /** + * The code read from the Code key + */ + private String code = null; + + /** + * The final password to the metal door, calculating using the code + */ + private int[] doorPassword = null; + + private ItemStep readCode; + private ObjectStep clickMetalDoors; + private ConditionalStep solvePuzzle; + private QuestStep solvePuzzleFallback; + private WidgetTextRequirement firstNumberCorrect; + private WidgetTextRequirement secondNumberCorrect; + private WidgetTextRequirement thirdNumberCorrect; + private WidgetTextRequirement fourthNumberCorrect; + private WidgetModelRequirement inputFirstCorrect; + private WidgetModelRequirement inputSecondCorrect; + private WidgetModelRequirement inputThirdCorrect; + private WidgetModelRequirement inputFourthCorrect; + + public MetalDoorSolver(TheCurseOfArrav theCurseOfArrav) + { + super(theCurseOfArrav, "Solve the Metal door puzzle by following the instructions in the overlay."); + } + + /** + * The numbers of the metal door puzzle are always the same, and in the same position. + * The decoder strips always keep the hole in the same position. + * Because of this, given a code, we can automatically figure out the final password. + *

+ * STRIP 4 + * | + * | STRIP 2 + * | | + * | | STRIP 1 + * | | | + * | | | STRIP 3 + * | | | | + * V V V V + * A 3 7 2 9 1 6 5 4 3 + * B 6 5 4 3 2 1 9 0 4 + * C 7 2 1 8 7 6 4 3 2 + * D 9 0 7 6 5 4 3 7 1 + * E 9 4 1 3 3 6 2 4 8 + * F 6 2 3 2 4 1 6 9 7 + * G 0 2 1 3 7 2 5 6 3 + * H 9 4 6 3 8 8 0 1 9 + * I 4 9 2 3 1 0 4 9 2 + * + * @param code The code from the "Code key" (e.g. IFCB) + * @return 4 ints corresponding to the final password for the metal door + */ + public static int[] calculate(String code) + { + if (code == null || code.length() != 4) + { + return null; + } + + // In case they throw us lowercase codes in some random patch + code = code.toUpperCase(); + + // The first char of the code (e.g. 'I' in "IFCB") + var pos1 = code.charAt(0); + // The second char of the code (e.g. 'F' in "IFCB") + var pos2 = code.charAt(1); + // The third char of the code (e.g. 'C' in "IFCB") + var pos3 = code.charAt(2); + // The fourth char of the code (e.g. 'B' in "IFCB") + var pos4 = code.charAt(3); + + // Convert those chars to indexes in our `CODE_MAPPING` array + var pos1RowIndex = pos1 - 'A'; + var pos2RowIndex = pos2 - 'A'; + var pos3RowIndex = pos3 - 'A'; + var pos4RowIndex = pos4 - 'A'; + + // Ensure the characters we've received have correctly mapped to indexes we support + if ( + pos1RowIndex < 0 || pos1RowIndex > 8 + || pos2RowIndex < 0 || pos2RowIndex > 8 + || pos3RowIndex < 0 || pos3RowIndex > 8 + || pos4RowIndex < 0 || pos4RowIndex > 8 + ) + { + return null; + } + + var pos1Result = CODE_MAPPING[pos1RowIndex][STRIP_1_INDEX]; + var pos2Result = CODE_MAPPING[pos2RowIndex][STRIP_2_INDEX]; + var pos3Result = CODE_MAPPING[pos3RowIndex][STRIP_3_INDEX]; + var pos4Result = CODE_MAPPING[pos4RowIndex][STRIP_4_INDEX]; + return new int[]{ + pos1Result, + pos2Result, + pos3Result, + pos4Result + }; + } + + @Subscribe + public void onGameTick(GameTick event) + { + if (this.code != null) + { + return; + } + + var textWidget = client.getWidget(MESBOX_GROUP_ID, MESBOX_CHILD_ID); + if (textWidget == null) + { + return; + } + + var matcher = CODE_PATTERN.matcher(textWidget.getText()); + if (matcher.find()) + { + this.code = matcher.group(1); + this.doorPassword = calculate(this.code); + if (this.doorPassword != null) { + firstNumberCorrect.setText(String.valueOf(this.doorPassword[0])); + inputFirstCorrect.setId(PUZZLE_NUMBERS[this.doorPassword[0]]); + secondNumberCorrect.setText(String.valueOf(this.doorPassword[1])); + inputSecondCorrect.setId(PUZZLE_NUMBERS[this.doorPassword[1]]); + thirdNumberCorrect.setText(String.valueOf(this.doorPassword[2])); + inputThirdCorrect.setId(PUZZLE_NUMBERS[this.doorPassword[2]]); + fourthNumberCorrect.setText(String.valueOf(this.doorPassword[3])); + inputFourthCorrect.setId(PUZZLE_NUMBERS[this.doorPassword[3]]); + } + updateSteps(); + } + } + + private void updatePuzzleSteps() + { + } + + @Override + public void startUp() + { + updateSteps(); + } + + @Override + protected void setupSteps() + { + var decoderStrips = new ItemRequirement("Decoder strips", ItemID.DECODER_STRIPS); + var codeKey = new ItemRequirement("Code key", ItemID.CODE_KEY); + readCode = new ItemStep(getQuestHelper(), "Read the Code key in your inventory.", codeKey.highlighted(), decoderStrips); // TODO + + clickMetalDoors = new ObjectStep(getQuestHelper(), ObjectID.METAL_DOORS, new WorldPoint(3612, 4582, 0), "Open the metal doors and solve the puzzle.", codeKey, decoderStrips); + + var puzzleWidgetOpen = new WidgetPresenceRequirement(PUZZLE_GROUP_ID, PUZZLE_BTN_UP_CHILD_ID); + + solvePuzzleFallback = new DetailedQuestStep(getQuestHelper(), "solve the puzzle somehow"); + + var firstNumberEmpty = new WidgetTextRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_1_CHILD_ID, "-"); + var secondNumberEmpty = new WidgetTextRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_2_CHILD_ID, "-"); + var thirdNumberEmpty = new WidgetTextRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_3_CHILD_ID, "-"); + var fourthNumberEmpty = new WidgetTextRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_4_CHILD_ID, "-"); + firstNumberCorrect = new WidgetTextRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_1_CHILD_ID, "X"); + secondNumberCorrect = new WidgetTextRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_2_CHILD_ID, "X"); + thirdNumberCorrect = new WidgetTextRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_3_CHILD_ID, "X"); + fourthNumberCorrect = new WidgetTextRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_4_CHILD_ID, "X"); + + inputFirstCorrect = new WidgetModelRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_CURRENT_CHILD_ID, -1); + inputSecondCorrect = new WidgetModelRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_CURRENT_CHILD_ID, -1); + inputThirdCorrect = new WidgetModelRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_CURRENT_CHILD_ID, -1); + inputFourthCorrect = new WidgetModelRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_CURRENT_CHILD_ID, -1); + + var clickUp = new WidgetStep(getQuestHelper(), "Click the Up button.", new WidgetDetails(PUZZLE_GROUP_ID, PUZZLE_BTN_UP_CHILD_ID)); + var submitNumber = new WidgetStep(getQuestHelper(), "Click the Enter button.", new WidgetDetails(PUZZLE_GROUP_ID, PUZZLE_ENTER_CHILD_ID)); + var pressBack = new WidgetStep(getQuestHelper(), "Click the Back button.", new WidgetDetails(PUZZLE_GROUP_ID, PUZZLE_BACK_CHILD_ID)); + + solvePuzzle = new ConditionalStep(getQuestHelper(), pressBack); + solvePuzzle.addStep(not(puzzleWidgetOpen), clickMetalDoors); + solvePuzzle.addStep(and(fourthNumberCorrect, thirdNumberCorrect, secondNumberCorrect, firstNumberCorrect), submitNumber); + solvePuzzle.addStep(and(fourthNumberEmpty, inputFourthCorrect, firstNumberCorrect, secondNumberCorrect, thirdNumberCorrect), submitNumber); + solvePuzzle.addStep(and(fourthNumberEmpty, firstNumberCorrect, secondNumberCorrect, thirdNumberCorrect), clickUp); + solvePuzzle.addStep(and(thirdNumberEmpty, inputThirdCorrect, firstNumberCorrect, secondNumberCorrect), submitNumber); + solvePuzzle.addStep(and(thirdNumberEmpty, firstNumberCorrect, secondNumberCorrect), clickUp); + solvePuzzle.addStep(and(secondNumberEmpty, inputSecondCorrect, firstNumberCorrect), submitNumber); + solvePuzzle.addStep(and(secondNumberEmpty, firstNumberCorrect), clickUp); + solvePuzzle.addStep(and(firstNumberEmpty, inputFirstCorrect), submitNumber); + solvePuzzle.addStep(firstNumberEmpty, clickUp); + } + + protected void updateSteps() + { + if (this.code == null) + { + startUpStep(readCode); + return; + } + + if (this.doorPassword == null) { + startUpStep(solvePuzzleFallback); + return; + } + + startUpStep(solvePuzzle); + } + + @Override + public List getSteps() + { + return List.of( + this.readCode, + this.clickMetalDoors, + this.solvePuzzleFallback, + this.solvePuzzle + ); + } +} diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index ae08fd2a04..021172e5b1 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -42,6 +42,7 @@ import com.questhelper.requirements.quest.QuestRequirement; import static com.questhelper.requirements.util.LogicHelper.and; import static com.questhelper.requirements.util.LogicHelper.not; +import static com.questhelper.requirements.util.LogicHelper.or; import com.questhelper.requirements.var.VarbitRequirement; import com.questhelper.requirements.zone.Zone; import com.questhelper.requirements.zone.ZoneRequirement; @@ -49,6 +50,7 @@ import com.questhelper.rewards.QuestPointReward; import com.questhelper.rewards.UnlockReward; import com.questhelper.steps.ConditionalStep; +import com.questhelper.steps.DetailedQuestStep; import com.questhelper.steps.ItemStep; import com.questhelper.steps.NpcStep; import com.questhelper.steps.ObjectStep; @@ -60,6 +62,7 @@ import java.util.Map; import net.runelite.api.ItemID; import net.runelite.api.NpcID; +import net.runelite.api.NullObjectID; import net.runelite.api.ObjectID; import net.runelite.api.QuestState; import net.runelite.api.Skill; @@ -97,15 +100,16 @@ public class TheCurseOfArrav extends BasicQuestHelper // 2 inv slots /// Mid-quest item requirements - private ItemRequirement experimentalKebab; - private ItemRequirement goodTestKebab; - private ItemRequirement goodTestKebabs; + private ItemRequirement basePlans; + private ItemRequirement baseKey; /// Zones & their requirements - private Zone wolfDen; - private ZoneRequirement inWolfDen; - private Zone fortisColosseum; - private ZoneRequirement inFortisColosseum; + private ZoneRequirement inZemouregalsBaseSection1; + private ZoneRequirement inZemouregalsBaseSection2; + private ZoneRequirement inZemouregalsBaseSection3; + private ZoneRequirement inZemouregalsBaseSection4; + private ZoneRequirement inZemouregalsBaseKitchen; + private ZoneRequirement inZemouregalsBaseSewer; /// Steps private QuestStep startQuest; @@ -130,14 +134,10 @@ public class TheCurseOfArrav extends BasicQuestHelper private QuestStep unsortedStep30; private QuestStep unsortedStep32; private QuestStep unsortedStep34; - private QuestStep unsortedStep36; - private QuestStep unsortedStep38; - private QuestStep unsortedStep40; private QuestStep unsortedStep42; private QuestStep unsortedStep44; private QuestStep unsortedStep46; private QuestStep unsortedStep48; - private QuestStep unsortedStep50; private QuestStep unsortedStep52; private QuestStep unsortedStep54; private QuestStep unsortedStep56; @@ -146,6 +146,25 @@ public class TheCurseOfArrav extends BasicQuestHelper private PuzzleWrapperStep rubbleMiner2; private PuzzleWrapperStep rubbleMiner3; private PuzzleWrapperStep rubbleMiner4; + private PuzzleWrapperStep metalDoorSolver; + private NpcStep returnToEliasWithBaseItems; + private ItemRequirement canopicJarFull; + private NpcStep headToZemouregalsBaseAndTalkToElias; + private ObjectStep enterZemouregalsBase; + private DetailedQuestStep getToBackOfZemouregalsBase; + private QuestRequirement haveKilledGolem; + private QuestRequirement haveMadeCanopicJar; + private QuestRequirement haveMinedAFullPath; + private QuestRequirement haveUsedPlans; + private QuestRequirement haveUsedKey; + private ObjectStep searchTableForDecoderStrips; + private ObjectStep enterStorageRoom; + private ObjectStep openChestForCodeKey; + private NpcStep interpretPlansWithElias; + private NpcStep fightArrav; + private ObjectStep enterBossRoom; + private ObjectStep grappleAcross; + private ObjectStep openMetalDoors; @Override @@ -174,14 +193,14 @@ public Map loadSteps() steps.put(30, unsortedStep30); steps.put(32, unsortedStep32); steps.put(34, unsortedStep34); - steps.put(36, unsortedStep36); - steps.put(38, unsortedStep38); - steps.put(40, unsortedStep40); + steps.put(36, returnToEliasWithBaseItems); + steps.put(38, interpretPlansWithElias); + steps.put(40, interpretPlansWithElias); steps.put(42, unsortedStep42); steps.put(44, unsortedStep44); steps.put(46, unsortedStep46); steps.put(48, unsortedStep48); - steps.put(50, unsortedStep50); + steps.put(50, unsortedStep48); steps.put(52, unsortedStep52); steps.put(54, unsortedStep54); steps.put(56, unsortedStep56); @@ -193,23 +212,50 @@ public Map loadSteps() @Override protected void setupZones() { + // Right as you head into the base + inZemouregalsBaseSection1 = new ZoneRequirement(new Zone(new WorldPoint(3536, 4577, 0), new WorldPoint(3564, 4547, 0))); + // After you've passed the first door + inZemouregalsBaseSection2 = new ZoneRequirement( + new Zone(new WorldPoint(3535, 4562, 0), new WorldPoint(3523, 4602, 0)), + new Zone(new WorldPoint(3523, 4602, 0), new WorldPoint(3539, 4594, 0)) + ); + // After you've passed the second door + inZemouregalsBaseSection3 = new ZoneRequirement(new Zone(new WorldPoint(3576, 4610, 0), new WorldPoint(3540, 4588, 0))); + // After you've passed the third door (the one requiring the base key) + inZemouregalsBaseSection4 = new ZoneRequirement(new Zone(new WorldPoint(3577, 4615, 0), new WorldPoint(3605, 4592, 0))); + inZemouregalsBaseKitchen = new ZoneRequirement(new Zone(new WorldPoint(3613, 4604, 0), new WorldPoint(3606, 4598, 0))); + inZemouregalsBaseSewer = new ZoneRequirement(new Zone(14919)); } @Override protected void setupRequirements() { + haveKilledGolem = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 12); + haveMadeCanopicJar = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 18); + haveMinedAFullPath = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 30); + haveUsedPlans = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 38); + haveUsedKey = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 46); + var haveMetArrav = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 54); + dwellberries3 = new ItemRequirement("Dwellberries", ItemID.DWELLBERRIES, 3); + dwellberries3.setConditionToHide(haveMadeCanopicJar); ringOfLife = new ItemRequirement("Ring of life", ItemID.RING_OF_LIFE); + ringOfLife.setConditionToHide(haveMadeCanopicJar); anyPickaxe = new ItemRequirement("Any pickaxe", ItemCollections.PICKAXES).isNotConsumed(); + anyPickaxe.setConditionToHide(haveMinedAFullPath); anyGrappleableCrossbow = new ItemRequirement("Any crossbow", ItemCollections.CROSSBOWS).isNotConsumed(); + anyGrappleableCrossbow.setConditionToHide(haveMetArrav); mithrilGrapple = new ItemRequirement("Mith grapple", ItemID.MITH_GRAPPLE_9419).isNotConsumed(); - // TODO: Check if the other insulated boots can be used + mithrilGrapple.setConditionToHide(haveMetArrav); insulatedBoots = new ItemRequirement("Insulated boots", ItemID.INSULATED_BOOTS).isNotConsumed(); staminaPotion = new ItemRequirement("Stamina potion", ItemCollections.STAMINA_POTIONS, 1); prayerPotion = new ItemRequirement("Prayer potion", ItemCollections.PRAYER_POTIONS, 1); crushCombatGear = new ItemRequirement("Melee combat gear (crush preferred)", -1, -1); - crushCombatGear.setDisplayItemId(BankSlotIcons.getCombatGear()); + crushCombatGear.setDisplayItemId(BankSlotIcons.getMeleeCombatGear()); + crushCombatGear.setConditionToHide(haveKilledGolem); + rangedCombatGear = new ItemRequirement("Ranged combat gear for killing Arrav", -1, -1); + rangedCombatGear.setDisplayItemId(BankSlotIcons.getRangedCombatGear()); food = new ItemRequirement("Food", ItemCollections.GOOD_EATING_FOOD, -1); } @@ -330,21 +376,21 @@ public void setupSteps() var fairyRingDLQ = new TeleportItemRequirement("Fairy Ring [DLQ]", ItemCollections.FAIRY_STAFF); - var returnToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); + var returnToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); returnToElias.addTeleport(fairyRingDLQ); - var returnToEliasByWalking = new ObjectStep(this, ObjectID.STAIRS_55786, new WorldPoint(3894, 4714, 0), "Return to to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); + var returnToEliasByWalking = new ObjectStep(this, ObjectID.STAIRS_55786, new WorldPoint(3894, 4714, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); returnToEliasByWalking.addTeleport(fairyRingDLQ); - var returnToEliasByWalkingMidway = new ObjectStep(this, ObjectID.STAIRS_50202, new WorldPoint(3848, 4577, 0), "Return to to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); + var returnToEliasByWalkingMidway = new ObjectStep(this, ObjectID.STAIRS_50202, new WorldPoint(3848, 4577, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); returnToEliasByWalkingMidway.addTeleport(fairyRingDLQ); - var returnToEliasByWalkingMidwayGolem = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Return to to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); + var returnToEliasByWalkingMidwayGolem = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); returnToEliasByWalkingMidwayGolem.addTeleport(fairyRingDLQ); returnToElias.addSubSteps(returnToEliasByWalking, returnToEliasByWalkingMidway, returnToEliasByWalkingMidwayGolem); unsortedStep18 = new ConditionalStep(this, returnToElias); - ((ConditionalStep)unsortedStep18).addStep(insideTombSecondFloorReq, returnToEliasByWalking); - ((ConditionalStep)unsortedStep18).addStep(insideGolenArena, returnToEliasByWalkingMidwayGolem); - ((ConditionalStep)unsortedStep18).addStep(insideTombReq, returnToEliasByWalkingMidway); + ((ConditionalStep) unsortedStep18).addStep(insideTombSecondFloorReq, returnToEliasByWalking); + ((ConditionalStep) unsortedStep18).addStep(insideGolenArena, returnToEliasByWalkingMidwayGolem); + ((ConditionalStep) unsortedStep18).addStep(insideTombReq, returnToEliasByWalkingMidway); // ardy cloak + fairy ring takes 50s, walking takes 1m12s var trollheimTeleport = new TeleportItemRequirement("Trollheim Teleport", ItemID.TROLLHEIM_TELEPORT); @@ -422,7 +468,7 @@ public void setupSteps() ((ConditionalStep) unsortedStep32).addStep(onTrollweissMountain, enterTrollweissCave); ((ConditionalStep) unsortedStep32).addStep(inTrollheimCave, continueThroughTrollheimCave); - var arravHouseSecondRoom = new Zone(new WorldPoint(2859, 2873, 0), new WorldPoint(2863, 3865, 0)); + var arravHouseSecondRoom = new Zone(new WorldPoint(2863, 3865, 0), new WorldPoint(2859, 3873, 0)); var inArravHouseSecondRoom = new ZoneRequirement(arravHouseSecondRoom); var goToNextRoom = new ObjectStep(this, ObjectID.DOOR_50514, new WorldPoint(2859, 3870, 0), "Enter the room to your east and search the tapestry for ?."); @@ -434,19 +480,143 @@ public void setupSteps() ((ConditionalStep) unsortedStep34).addStep(onTrollweissMountain, enterTrollweissCave); ((ConditionalStep) unsortedStep34).addStep(inTrollheimCave, continueThroughTrollheimCave); - unsortedStep36 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 36"); - unsortedStep38 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 38"); - unsortedStep40 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 40"); - unsortedStep42 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 42"); - unsortedStep44 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 44"); - unsortedStep46 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 46"); - unsortedStep48 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 48"); - unsortedStep50 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 50"); - unsortedStep52 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 52"); - unsortedStep54 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 54"); - unsortedStep56 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 56"); - unsortedStep58 = new NpcStep(this, NpcID.YELLOW_FORTUNE_SECRETARY, "Step 58"); + var tapestryFindText = "Can be acquired by heading back to Zemouregal's Fort past the Trollweiss mining dungeon and searching the tapestry."; + basePlans = new ItemRequirement("Base plans", ItemID.BASE_PLANS); + basePlans.setConditionToHide(haveUsedPlans); + basePlans.setTooltip(tapestryFindText); // only needed until varbit 38 + baseKey = new ItemRequirement("Base key", ItemID.BASE_KEY); + baseKey.setConditionToHide(haveUsedKey); + baseKey.setTooltip(tapestryFindText); // no longer needed when varbit hits 46 + + returnToEliasWithBaseItems = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to Elias south of Ruins of Uzer and ask him for help interpreting the plans.", basePlans, baseKey); + returnToEliasWithBaseItems.addTeleport(fairyRingDLQ); + + interpretPlansWithElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to Elias south of Ruins of Uzer and ask him for help interpreting the plans.", baseKey); + interpretPlansWithElias.addTeleport(fairyRingDLQ); + + returnToEliasWithBaseItems.addSubSteps(interpretPlansWithElias); + + // 40 -> 42 + // 9658: 5 -> 6 + + canopicJarFull = new ItemRequirement("Canopic jar (full)", ItemID.CANOPIC_JAR_FULL); + canopicJarFull.setTooltip("You can get a new one from Elias at the entrance of Zemouregal's base if you've lost it."); // this is at least true after the mining part + // need 1 inventory slot free + headToZemouregalsBaseAndTalkToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3341, 3516, 0), "Head to Zemouregal's base east of Varrock's sawmill and talk to Elias.", anyGrappleableCrossbow, mithrilGrapple, rangedCombatGear, insulatedBoots, canopicJarFull, baseKey); // todo add teleport + headToZemouregalsBaseAndTalkToElias.addDialogStep("Ready when you are."); + unsortedStep42 = new ConditionalStep(this, headToZemouregalsBaseAndTalkToElias); + enterZemouregalsBase = new ObjectStep(this, NullObjectID.NULL_50689, new WorldPoint(3343, 3515, 0), "Enter Zemouregal's base east of Varrock's sawmill.", anyGrappleableCrossbow, mithrilGrapple, rangedCombatGear, insulatedBoots, canopicJarFull, baseKey); // todo add teleport + + + getToBackOfZemouregalsBase = new DetailedQuestStep(this, "Make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage."); + var passZemouregalsBaseDoor1 = new ObjectStep(this, ObjectID.GATE_50149, new WorldPoint(3536, 4571, 0), "Open the gate and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFull, insulatedBoots); + var passZemouregalsBaseDoor2 = new ObjectStep(this, ObjectID.GATE_50150, new WorldPoint(3540, 4597, 0), "Open the gate and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFull, insulatedBoots); + var passZemouregalsBaseDoor3 = new ObjectStep(this, ObjectID.DOOR_50152, new WorldPoint(3576, 4604, 0), "Open the door and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFull, insulatedBoots); + var passZemouregalsBaseDoor4 = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3605, 4603, 0), "Open the gate and make your way to the back of Zemouregal's base.", canopicJarFull, insulatedBoots); + + unsortedStep44 = new ConditionalStep(this, enterZemouregalsBase); + ((ConditionalStep) unsortedStep44).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + ((ConditionalStep) unsortedStep44).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + ((ConditionalStep) unsortedStep44).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + + var enterZemouregalsBaseSewer = new ObjectStep(this, ObjectID.PIPE_50523, new WorldPoint(3609, 4598, 0), "Enter the sewers and make your way to the back of Zemouregal's base.", canopicJarFull, insulatedBoots.highlighted().equipped()); + + var exitZemouregalsBaseSewer = new ObjectStep(this, ObjectID.PIPE_50525, new WorldPoint(3741, 4573, 0), "Head south to exit the sewers and make your way to the back of Zemouregal's base.", canopicJarFull, insulatedBoots.highlighted().equipped()); + + getToBackOfZemouregalsBase.addSubSteps(passZemouregalsBaseDoor1, passZemouregalsBaseDoor2, passZemouregalsBaseDoor3, passZemouregalsBaseDoor4, enterZemouregalsBaseSewer, exitZemouregalsBaseSewer); + + // 44 -> 46 when opening door, consuming the base key + + unsortedStep46 = new ConditionalStep(this, enterZemouregalsBase); + ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + + var inSecondPart = new ZoneRequirement(new Zone(new WorldPoint(3590, 4538, 0), new WorldPoint(3622, 4597, 0))); + var inStorageRoom = new ZoneRequirement(new Zone(new WorldPoint(3614, 4571, 0), new WorldPoint(3605, 4563, 0))); + var decoderStrips = new ItemRequirement("Decoder strips", ItemID.DECODER_STRIPS); + searchTableForDecoderStrips = new ObjectStep(this, ObjectID.TABLE_50533, "Search the table for some decoder strips."); + enterStorageRoom = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3609, 4572, 0), "Enter the storage room to the south-east."); + var exitStorageRoom = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3609, 4572, 0), "Exit the storage room."); + var codeKey = new ItemRequirement("Code key", ItemID.CODE_KEY); + + openChestForCodeKey = new ObjectStep(this, ObjectID.CHEST_50530, new WorldPoint(3609, 4565, 0), "Open the chest for the code key."); + + var metalDoorSolverReal = new MetalDoorSolver(this); + metalDoorSolverReal.addSubSteps(exitStorageRoom); + + this.metalDoorSolver = metalDoorSolverReal.puzzleWrapStep(); + + + // also used for 50 + unsortedStep48 = new ConditionalStep(this, enterZemouregalsBase); + // TODO: DECODER STRIPS ARE NOT NECESSARY. REMOVE THEM :) + ((ConditionalStep) unsortedStep48).addStep(and(inSecondPart, not(inStorageRoom), decoderStrips, codeKey), metalDoorSolver); + ((ConditionalStep) unsortedStep48).addStep(and(inStorageRoom, not(decoderStrips)), searchTableForDecoderStrips); + ((ConditionalStep) unsortedStep48).addStep(and(inStorageRoom, not(codeKey)), openChestForCodeKey); + ((ConditionalStep) unsortedStep48).addStep(and(inStorageRoom, decoderStrips), exitStorageRoom); + ((ConditionalStep) unsortedStep48).addStep(and(inSecondPart, not(codeKey)), enterStorageRoom); + ((ConditionalStep) unsortedStep48).addStep(and(inSecondPart, not(decoderStrips)), enterStorageRoom); + ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + + openMetalDoors = new ObjectStep(this, ObjectID.METAL_DOORS, new WorldPoint(3612, 4582, 0), "Step through through the metal doors.", canopicJarFull, anyGrappleableCrossbow, mithrilGrapple); + + var inGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3612, 4587, 0), new WorldPoint(3625, 4579, 0))); + grappleAcross = new ObjectStep(this, ObjectID.PIPE_50542, new WorldPoint(3615, 4582, 0), "Grapple across the pipe", anyGrappleableCrossbow.highlighted().equipped(), mithrilGrapple.highlighted().equipped()); + + var pastGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3621, 4589, 0), new WorldPoint(3645, 4578, 0))); + + enterBossRoom = new ObjectStep(this, ObjectID.PEDESTAL_50539, new WorldPoint(3638, 4582, 0), "Attempt to take Arrav's heart from the pedestal, ready for a fight. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid most of Arravs damage. When Arrav throws an axe towards you, step to the side or behind him.", rangedCombatGear); + + unsortedStep52 = new ConditionalStep(this, enterZemouregalsBase); + ((ConditionalStep) unsortedStep52).addStep(pastGrapplePuzzleRoom, enterBossRoom); + ((ConditionalStep) unsortedStep52).addStep(inGrapplePuzzleRoom, grappleAcross); + ((ConditionalStep) unsortedStep52).addStep(inSecondPart, openMetalDoors); + ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + + // User has engaged Arrav + + fightArrav = new NpcStep(this, NpcID.ARRAV_14132, new WorldPoint(3635, 4582, 0), "fight arrav xd"); + unsortedStep54 = new ConditionalStep(this, enterZemouregalsBase); + ((ConditionalStep) unsortedStep54).addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), fightArrav); + ((ConditionalStep) unsortedStep54).addStep(inSecondPart, openMetalDoors); + ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + + + // 54 -> 56 when beating arrav + + var watchTheDialog = new DetailedQuestStep(this, "Watch the dialog."); + fightArrav.addSubSteps(watchTheDialog); + unsortedStep56 = new ConditionalStep(this, enterZemouregalsBase); + ((ConditionalStep) unsortedStep56).addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), watchTheDialog); + ((ConditionalStep) unsortedStep56).addStep(inSecondPart, openMetalDoors); + ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + + unsortedStep58 = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Talk to Elias to finish the quest."); } @Override @@ -549,8 +719,16 @@ public List getPanels() unsortedStep16, unsortedStep18 ), List.of( - new FreeInventorySlotRequirement(2) - // TODO + dwellberries3, + ringOfLife, + crushCombatGear + // Requirements + ), List.of( + // Recommended + new FreeInventorySlotRequirement(2), + staminaPotion, + prayerPotion, + food ))); panels.add(new PanelDetails("Fort Invasion", List.of( unsortedStep20, @@ -560,31 +738,46 @@ public List getPanels() rubbleMiner4, unsortedStep30, unsortedStep32, - unsortedStep34, - unsortedStep36, - unsortedStep38, - unsortedStep40, - unsortedStep42, - unsortedStep44, - unsortedStep46, - unsortedStep48, - unsortedStep50, - unsortedStep52, - unsortedStep54, - unsortedStep56, - unsortedStep58 - // TODO - ), List.of(staminaPotion, prayerPotion, crushCombatGear, food))); - panels.add(new PanelDetails("Hearty Heist", List.of( + unsortedStep34 // TODO ), List.of( - // TODO + // Requirements + anyPickaxe + ), List.of( + // Recommended + staminaPotion ))); - - panels.add(new PanelDetails("The Hero of Avarrocka", List.of( + panels.add(new PanelDetails("Hearty Heist", List.of( + // Steps + returnToEliasWithBaseItems, + headToZemouregalsBaseAndTalkToElias, + enterZemouregalsBase, + getToBackOfZemouregalsBase, + enterStorageRoom, + searchTableForDecoderStrips, + openChestForCodeKey, + metalDoorSolver, + openMetalDoors, + grappleAcross, + enterBossRoom, + fightArrav, + unsortedStep58 // TODO ), List.of( - // TODO + // Requirements + basePlans, + baseKey, + anyGrappleableCrossbow, + mithrilGrapple, + rangedCombatGear, + insulatedBoots, + canopicJarFull + ), List.of( + // Recommended + new FreeInventorySlotRequirement(1), + staminaPotion, + prayerPotion, + food ))); return panels; diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java index 822ef88b1c..437e1ca4c7 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java @@ -42,7 +42,6 @@ protected void addMineRubbleStep(int x, int y, RubbleType rubbleType, Direction var wp = new WorldPoint(x, y, 0); var stepCounter = this.stepCounter++; var text = String.format("[%d] Mine the rubble from the %s side", stepCounter, direction.toString().toLowerCase()); - log.info("setting up mine rubble step: {}: {}", stepCounter, text); var mainObjectID = validObjectIDs.get(0); var step = new ObjectStep(getQuestHelper(), mainObjectID, wp, text); var offsetX = x; diff --git a/src/main/java/com/questhelper/requirements/widget/WidgetModelRequirement.java b/src/main/java/com/questhelper/requirements/widget/WidgetModelRequirement.java index a7c9fbf77b..ffc8b10981 100644 --- a/src/main/java/com/questhelper/requirements/widget/WidgetModelRequirement.java +++ b/src/main/java/com/questhelper/requirements/widget/WidgetModelRequirement.java @@ -26,12 +26,14 @@ */ package com.questhelper.requirements.widget; +import lombok.Setter; import net.runelite.api.Client; import net.runelite.api.widgets.Widget; public class WidgetModelRequirement extends WidgetPresenceRequirement { - private final int id; + @Setter + private int id; public WidgetModelRequirement(int groupId, int childId, int childChildId, int id) { diff --git a/src/main/java/com/questhelper/requirements/widget/WidgetTextRequirement.java b/src/main/java/com/questhelper/requirements/widget/WidgetTextRequirement.java index 2f1cd9b7c8..677914b4b2 100644 --- a/src/main/java/com/questhelper/requirements/widget/WidgetTextRequirement.java +++ b/src/main/java/com/questhelper/requirements/widget/WidgetTextRequirement.java @@ -47,7 +47,9 @@ public class WidgetTextRequirement extends SimpleRequirement private final int groupId; private final int childId; - private final List text; + + private List text; + private int childChildId = -1; private boolean checkChildren; @@ -58,6 +60,30 @@ public class WidgetTextRequirement extends SimpleRequirement @Setter private String displayText = ""; + /** + * Use this if you need to update a widget requirement dynamically. + *

+ * Updating the text will reset the `hasPassed` variable. + * + * @param text list of valid strings for this widget check + */ + public void setText(@Nonnull List text) { + this.setHasPassed(false); + + this.text = text; + } + + /** + * Use this if you need to update a widget requirement dynamically. + *

+ * Updating the text will reset the `hasPassed` variable. + * + * @param text valid string for this widget check + */ + public void setText(@Nonnull String text) { + this.setText(List.of(text)); + } + public WidgetTextRequirement(@Component int componentId, String... text) { var pair = Utils.unpackWidget(componentId); diff --git a/src/main/java/com/questhelper/steps/widget/WidgetDetails.java b/src/main/java/com/questhelper/steps/widget/WidgetDetails.java index 9070198924..42a4bdfdb4 100644 --- a/src/main/java/com/questhelper/steps/widget/WidgetDetails.java +++ b/src/main/java/com/questhelper/steps/widget/WidgetDetails.java @@ -37,6 +37,13 @@ public class WidgetDetails public int childID; public int childChildID; + public WidgetDetails(int groupID, int childID) + { + this.groupID = groupID; + this.childID = childID; + this.childChildID = -1; + } + public WidgetDetails(@Component int componentId) { var pair = Utils.unpackWidget(componentId); diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java new file mode 100644 index 0000000000..aaaeecd28f --- /dev/null +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java @@ -0,0 +1,67 @@ +package com.questhelper.helpers.quests.thecurseofarrav; + +import net.runelite.api.coords.WorldPoint; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +public class MetalDoorSolverTest +{ + @Test + public void testValidCodes() + { + // from pajdonk + assertArrayEquals(new int[]{0, 2, 3, 5},MetalDoorSolver.calculate("IFCB")); + + // from Gupinic + assertArrayEquals(new int[]{1, 3, 7, 2}, MetalDoorSolver.calculate("FBDG")); + } + + @Test + public void testLowercaseValidCodes() + { + // from pajdonk + assertArrayEquals(new int[]{0, 2, 3, 5},MetalDoorSolver.calculate("ifcb")); + + // from Gupinic + assertArrayEquals(new int[]{1, 3, 7, 2}, MetalDoorSolver.calculate("fbdg")); + } + + @Test + public void testInvalidCodes() + { + // Some character in the code is not valid + assertNull(MetalDoorSolver.calculate("JAAA")); + assertNull(MetalDoorSolver.calculate("AJAA")); + assertNull(MetalDoorSolver.calculate("AAJA")); + assertNull(MetalDoorSolver.calculate("AAAJ")); + } + + @Test + public void testCodeTooLong() + { + assertNull(MetalDoorSolver.calculate("AAAAA")); + assertNull(MetalDoorSolver.calculate("AAAAAAAAA")); + assertNull(MetalDoorSolver.calculate("AAAA ")); + } + + @Test + public void testCodeTooShort() + { + assertNull(MetalDoorSolver.calculate("AAA")); + assertNull(MetalDoorSolver.calculate("AA")); + assertNull(MetalDoorSolver.calculate("A")); + assertNull(MetalDoorSolver.calculate("")); + } + + @Test + public void testCodeIsNull() + { + assertNull(MetalDoorSolver.calculate(null)); + } +} From 6df98b536140fb5d4cc7db9b7fc6d44e8db1d375 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 14:59:20 +0100 Subject: [PATCH 07/60] test: Add puzzle test from Avsynthe --- .../helpers/quests/thecurseofarrav/MetalDoorSolverTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java index aaaeecd28f..5e5fc37ad4 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java @@ -20,6 +20,9 @@ public void testValidCodes() // from Gupinic assertArrayEquals(new int[]{1, 3, 7, 2}, MetalDoorSolver.calculate("FBDG")); + + // from Avsynthe + assertArrayEquals(new int[]{1, 8, 4, 5}, MetalDoorSolver.calculate("FCEB")); } @Test From bd54ee727c2811e72659ad4248c73ed0b0605057 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 14:59:30 +0100 Subject: [PATCH 08/60] test: Add puzzle test from Zoinkwiz --- .../helpers/quests/thecurseofarrav/MetalDoorSolverTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java index 5e5fc37ad4..e3f2cd1b4d 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java @@ -23,6 +23,9 @@ public void testValidCodes() // from Avsynthe assertArrayEquals(new int[]{1, 8, 4, 5}, MetalDoorSolver.calculate("FCEB")); + + // from Zoinkwiz + assertArrayEquals(new int[]{6, 3, 6, 4}, MetalDoorSolver.calculate("AEGH")); } @Test From dfd64d073ba5e202a4442d15ba9f0921c0698576 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 15:44:39 +0100 Subject: [PATCH 09/60] fix: Add teleport requirement to start --- .../quests/thecurseofarrav/TheCurseOfArrav.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 021172e5b1..6500cdda12 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -85,8 +85,7 @@ public class TheCurseOfArrav extends BasicQuestHelper private ItemRequirement insulatedBoots; /// Recommended items - // teleport to fairy ring - // fairy ring staff + private TeleportItemRequirement fairyRingDLQ; // trollheim teleport / ghommal's hilt // antivenom // lumberyard teleport @@ -237,6 +236,7 @@ protected void setupRequirements() haveUsedKey = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 46); var haveMetArrav = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 54); + // Required items dwellberries3 = new ItemRequirement("Dwellberries", ItemID.DWELLBERRIES, 3); dwellberries3.setConditionToHide(haveMadeCanopicJar); ringOfLife = new ItemRequirement("Ring of life", ItemID.RING_OF_LIFE); @@ -249,6 +249,8 @@ protected void setupRequirements() mithrilGrapple.setConditionToHide(haveMetArrav); insulatedBoots = new ItemRequirement("Insulated boots", ItemID.INSULATED_BOOTS).isNotConsumed(); + // Recommended items + fairyRingDLQ = new TeleportItemRequirement("Fairy Ring [DLQ]", ItemCollections.FAIRY_STAFF); staminaPotion = new ItemRequirement("Stamina potion", ItemCollections.STAMINA_POTIONS, 1); prayerPotion = new ItemRequirement("Prayer potion", ItemCollections.PRAYER_POTIONS, 1); crushCombatGear = new ItemRequirement("Melee combat gear (crush preferred)", -1, -1); @@ -263,7 +265,8 @@ public void setupSteps() { var todo = new NpcStep(this, 5, "TODO XD"); - startQuest = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Talk to Elias south of Ruins of Uzer (DLQ FAIRY RING)."); + startQuest = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Talk to Elias south of Ruins of Uzer to start the quest."); + ((NpcStep) startQuest).addTeleport(fairyRingDLQ); startQuest.addDialogStep("Yes."); enterTomb = new ObjectStep(this, ObjectID.ENTRY_50201, new WorldPoint(3486, 3023, 0), "Enter the tomb south-west of Elias."); @@ -374,7 +377,6 @@ public void setupSteps() ((ConditionalStep) unsortedStep16).addStep(and(insideTombReq, insideGolenArena), enterTombBasement); ((ConditionalStep) unsortedStep16).addStep(and(insideTombReq), enterGolemArenaWithoutFight); - var fairyRingDLQ = new TeleportItemRequirement("Fairy Ring [DLQ]", ItemCollections.FAIRY_STAFF); var returnToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); returnToElias.addTeleport(fairyRingDLQ); From 1780ce64517d24758bc7ea910394f749aa15bb4d Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:09:16 +0100 Subject: [PATCH 10/60] random refactor --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 6500cdda12..716c73c4d5 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -156,6 +156,7 @@ public class TheCurseOfArrav extends BasicQuestHelper private QuestRequirement haveMinedAFullPath; private QuestRequirement haveUsedPlans; private QuestRequirement haveUsedKey; + private QuestRequirement haveMetArrav; private ObjectStep searchTableForDecoderStrips; private ObjectStep enterStorageRoom; private ObjectStep openChestForCodeKey; @@ -234,7 +235,7 @@ protected void setupRequirements() haveMinedAFullPath = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 30); haveUsedPlans = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 38); haveUsedKey = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 46); - var haveMetArrav = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 54); + haveMetArrav = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 54); // Required items dwellberries3 = new ItemRequirement("Dwellberries", ItemID.DWELLBERRIES, 3); From 73cff5e5595eb8afc28c261b5709c258ab77e32d Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:36:23 +0100 Subject: [PATCH 11/60] refactor: make free inv requirement a class member --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 716c73c4d5..0a4ed156ed 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -96,6 +96,7 @@ public class TheCurseOfArrav extends BasicQuestHelper private ItemRequirement food; private ItemRequirement staminaPotion; private ItemRequirement prayerPotion; + private FreeInventorySlotRequirement twoFreeInventorySlots; // 2 inv slots /// Mid-quest item requirements @@ -260,6 +261,7 @@ protected void setupRequirements() rangedCombatGear = new ItemRequirement("Ranged combat gear for killing Arrav", -1, -1); rangedCombatGear.setDisplayItemId(BankSlotIcons.getRangedCombatGear()); food = new ItemRequirement("Food", ItemCollections.GOOD_EATING_FOOD, -1); + twoFreeInventorySlots = new FreeInventorySlotRequirement(2); } public void setupSteps() @@ -728,7 +730,7 @@ public List getPanels() // Requirements ), List.of( // Recommended - new FreeInventorySlotRequirement(2), + twoFreeInventorySlots, staminaPotion, prayerPotion, food From 074134e152cd734e809e9934babb42a40f7107da Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:37:48 +0100 Subject: [PATCH 12/60] refactor: don't use triple-slash comments for sections --- .../quests/thecurseofarrav/TheCurseOfArrav.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 0a4ed156ed..02f787f04d 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -76,7 +76,7 @@ */ public class TheCurseOfArrav extends BasicQuestHelper { - /// Required items + // Required items private ItemRequirement dwellberries3; private ItemRequirement ringOfLife; private ItemRequirement anyPickaxe; @@ -84,7 +84,7 @@ public class TheCurseOfArrav extends BasicQuestHelper private ItemRequirement mithrilGrapple; private ItemRequirement insulatedBoots; - /// Recommended items + // Recommended items private TeleportItemRequirement fairyRingDLQ; // trollheim teleport / ghommal's hilt // antivenom @@ -99,11 +99,11 @@ public class TheCurseOfArrav extends BasicQuestHelper private FreeInventorySlotRequirement twoFreeInventorySlots; // 2 inv slots - /// Mid-quest item requirements + // Mid-quest item requirements private ItemRequirement basePlans; private ItemRequirement baseKey; - /// Zones & their requirements + // Zones & their requirements private ZoneRequirement inZemouregalsBaseSection1; private ZoneRequirement inZemouregalsBaseSection2; private ZoneRequirement inZemouregalsBaseSection3; @@ -111,7 +111,7 @@ public class TheCurseOfArrav extends BasicQuestHelper private ZoneRequirement inZemouregalsBaseKitchen; private ZoneRequirement inZemouregalsBaseSewer; - /// Steps + // Steps private QuestStep startQuest; private QuestStep enterTomb; private ObjectStep getFirstKey; From df7763659fb4357abe122b1bae21ee58d9a37c7a Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:38:32 +0100 Subject: [PATCH 13/60] refactor: make `insideTomb` ZoneRequirement a class member --- .../thecurseofarrav/TheCurseOfArrav.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 02f787f04d..48468971ef 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -104,6 +104,8 @@ public class TheCurseOfArrav extends BasicQuestHelper private ItemRequirement baseKey; // Zones & their requirements + /// Top floor of the tomb (Uzer Mastaba) + private ZoneRequirement insideTomb; private ZoneRequirement inZemouregalsBaseSection1; private ZoneRequirement inZemouregalsBaseSection2; private ZoneRequirement inZemouregalsBaseSection3; @@ -213,6 +215,8 @@ public Map loadSteps() @Override protected void setupZones() { + insideTomb = new ZoneRequirement(new Zone(new WorldPoint(3842, 4603, 0), new WorldPoint(3900, 4547, 0))); + // Right as you head into the base inZemouregalsBaseSection1 = new ZoneRequirement(new Zone(new WorldPoint(3536, 4577, 0), new WorldPoint(3564, 4547, 0))); // After you've passed the first door @@ -269,14 +273,12 @@ public void setupSteps() var todo = new NpcStep(this, 5, "TODO XD"); startQuest = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Talk to Elias south of Ruins of Uzer to start the quest."); - ((NpcStep) startQuest).addTeleport(fairyRingDLQ); + startQuest.addTeleport(fairyRingDLQ); startQuest.addDialogStep("Yes."); enterTomb = new ObjectStep(this, ObjectID.ENTRY_50201, new WorldPoint(3486, 3023, 0), "Enter the tomb south-west of Elias."); // TODO: Ensure player can get hint to return - var insideTomb = new Zone(new WorldPoint(3842, 4603, 0), new WorldPoint(3900, 4547, 0)); - var insideTombReq = new ZoneRequirement(insideTomb); var hasFirstKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY); getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton to the south of the entrance."); var hasSecondKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY_30309); @@ -306,7 +308,7 @@ public void setupSteps() unsortedStep6 = new ConditionalStep(this, enterTomb); // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? - ((ConditionalStep) unsortedStep6).addStep(not(insideTombReq), enterTomb); + ((ConditionalStep) unsortedStep6).addStep(not(insideTomb), enterTomb); // If the user has flipped the south lever & needs to get out of the little room ((ConditionalStep) unsortedStep6).addStep(and(haveFlippedSouthLever, bySouthLeverReq), leaveSouthLever); @@ -337,7 +339,7 @@ public void setupSteps() fightGolemGuard = new NpcStep(this, NpcID.GOLEM_GUARD, new WorldPoint(3860, 4595, 0), "Fight the Golem guard. He is weak to crush style weapons. Use Protect from Melee to avoid damage from his attacks. When the screen shakes, step away from him to avoid taking damage."); unsortedStep10 = new ConditionalStep(this, enterGolemArena); // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? - unsortedStep10.addStep(not(insideTombReq), enterTomb); + unsortedStep10.addStep(not(insideTomb), enterTomb); unsortedStep10.addStep(byNorthLeverReq, leaveNorthLever); unsortedStep10.addStep(bySouthLeverReq, leaveSouthLever); unsortedStep10.addStep(insideGolenArena, fightGolemGuard); @@ -363,9 +365,9 @@ public void setupSteps() ((ConditionalStep) unsortedStep12).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle, oilFilledCanopicJar), todo); ((ConditionalStep) unsortedStep12).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); ((ConditionalStep) unsortedStep12).addStep(insideTombSecondFloorReq, solveTilePuzzle); - ((ConditionalStep) unsortedStep12).addStep(not(insideTombReq), enterTomb); - ((ConditionalStep) unsortedStep12).addStep(and(insideTombReq, insideGolenArena), enterTombBasement); - ((ConditionalStep) unsortedStep12).addStep(and(insideTombReq), enterGolemArenaWithoutFight); + ((ConditionalStep) unsortedStep12).addStep(not(insideTomb), enterTomb); + ((ConditionalStep) unsortedStep12).addStep(and(insideTomb, insideGolenArena), enterTombBasement); + ((ConditionalStep) unsortedStep12).addStep(and(insideTomb), enterGolemArenaWithoutFight); var oilAndBerryFilledCanopicJar = new ItemRequirement("Canopic jar (oil and berries)", ItemID.CANOPIC_JAR_OIL_AND_BERRIES); @@ -376,9 +378,9 @@ public void setupSteps() ((ConditionalStep) unsortedStep16).addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); ((ConditionalStep) unsortedStep16).addStep(oilFilledCanopicJar, combineJarWithDwellberries); ((ConditionalStep) unsortedStep16).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); - ((ConditionalStep) unsortedStep16).addStep(not(insideTombReq), enterTomb); - ((ConditionalStep) unsortedStep16).addStep(and(insideTombReq, insideGolenArena), enterTombBasement); - ((ConditionalStep) unsortedStep16).addStep(and(insideTombReq), enterGolemArenaWithoutFight); + ((ConditionalStep) unsortedStep16).addStep(not(insideTomb), enterTomb); + ((ConditionalStep) unsortedStep16).addStep(and(insideTomb, insideGolenArena), enterTombBasement); + ((ConditionalStep) unsortedStep16).addStep(and(insideTomb), enterGolemArenaWithoutFight); var returnToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); @@ -395,7 +397,7 @@ public void setupSteps() unsortedStep18 = new ConditionalStep(this, returnToElias); ((ConditionalStep) unsortedStep18).addStep(insideTombSecondFloorReq, returnToEliasByWalking); ((ConditionalStep) unsortedStep18).addStep(insideGolenArena, returnToEliasByWalkingMidwayGolem); - ((ConditionalStep) unsortedStep18).addStep(insideTombReq, returnToEliasByWalkingMidway); + ((ConditionalStep) unsortedStep18).addStep(insideTomb, returnToEliasByWalkingMidway); // ardy cloak + fairy ring takes 50s, walking takes 1m12s var trollheimTeleport = new TeleportItemRequirement("Trollheim Teleport", ItemID.TROLLHEIM_TELEPORT); From 80e7c3c91498ad42382daa93e2e8666269ce56b6 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:39:30 +0100 Subject: [PATCH 14/60] nit: Supress the `field can be local` lint --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 48468971ef..77c7265ff0 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -74,6 +74,7 @@ *

* The OSRS wiki guide and Slayermusiq1's Quest Guide was referenced for this guide */ +@SuppressWarnings("FieldCanBeLocal") public class TheCurseOfArrav extends BasicQuestHelper { // Required items From bda646c7eaf9ce7d59163772e96ab819152ec838 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:41:46 +0100 Subject: [PATCH 15/60] fix: Quest step types --- .../thecurseofarrav/TheCurseOfArrav.java | 241 +++++++++--------- 1 file changed, 121 insertions(+), 120 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 77c7265ff0..97bdfdbce5 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -115,8 +115,8 @@ public class TheCurseOfArrav extends BasicQuestHelper private ZoneRequirement inZemouregalsBaseSewer; // Steps - private QuestStep startQuest; - private QuestStep enterTomb; + private NpcStep startQuest; + private ObjectStep enterTomb; private ObjectStep getFirstKey; private ObjectStep getSecondKey; private ObjectStep pullSouthLever; @@ -124,27 +124,28 @@ public class TheCurseOfArrav extends BasicQuestHelper private ObjectStep enterGolemArena; private NpcStep fightGolemGuard; private ObjectStep enterTombBasement; - private QuestStep unsortedStep6; + private ConditionalStep unsortedStep6; private ConditionalStep unsortedStep10; private PuzzleWrapperStep solveTilePuzzle; - private QuestStep unsortedStep12; - private QuestStep unsortedStep16; - private QuestStep unsortedStep18; - private QuestStep unsortedStep20; - private QuestStep unsortedStep24; - private QuestStep unsortedStep26; - private QuestStep unsortedStep28; - private QuestStep unsortedStep30; - private QuestStep unsortedStep32; - private QuestStep unsortedStep34; - private QuestStep unsortedStep42; - private QuestStep unsortedStep44; - private QuestStep unsortedStep46; - private QuestStep unsortedStep48; - private QuestStep unsortedStep52; - private QuestStep unsortedStep54; - private QuestStep unsortedStep56; - private QuestStep unsortedStep58; + private ConditionalStep unsortedStep12; + private ConditionalStep unsortedStep16; + private ConditionalStep unsortedStep18; + private ConditionalStep unsortedStep20; + private ConditionalStep unsortedStep24; + private ConditionalStep unsortedStep26; + private ConditionalStep unsortedStep28; + private ConditionalStep unsortedStep30; + private ConditionalStep unsortedStep32; + private ConditionalStep unsortedStep34; + private ConditionalStep unsortedStep42; + private ConditionalStep unsortedStep44; + private ConditionalStep unsortedStep46; + private ConditionalStep unsortedStep48; + private ConditionalStep unsortedStep52; + private ConditionalStep unsortedStep54; + private ConditionalStep unsortedStep56; + private NpcStep finishQuest; + private PuzzleWrapperStep rubbleMiner1; private PuzzleWrapperStep rubbleMiner2; private PuzzleWrapperStep rubbleMiner3; @@ -208,7 +209,7 @@ public Map loadSteps() steps.put(52, unsortedStep52); steps.put(54, unsortedStep54); steps.put(56, unsortedStep56); - steps.put(58, unsortedStep58); + steps.put(58, finishQuest); return steps; } @@ -309,27 +310,27 @@ public void setupSteps() unsortedStep6 = new ConditionalStep(this, enterTomb); // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? - ((ConditionalStep) unsortedStep6).addStep(not(insideTomb), enterTomb); + unsortedStep6.addStep(not(insideTomb), enterTomb); // If the user has flipped the south lever & needs to get out of the little room - ((ConditionalStep) unsortedStep6).addStep(and(haveFlippedSouthLever, bySouthLeverReq), leaveSouthLever); + unsortedStep6.addStep(and(haveFlippedSouthLever, bySouthLeverReq), leaveSouthLever); // If the user has flipped the north lever & needs to get out of the little room - ((ConditionalStep) unsortedStep6).addStep(and(haveFlippedNorthLever, byNorthLeverReq), leaveNorthLever); + unsortedStep6.addStep(and(haveFlippedNorthLever, byNorthLeverReq), leaveNorthLever); // If the user has not already put the key in the south lever, and does not have the key - ((ConditionalStep) unsortedStep6).addStep(and(needToInsertKeyInSouthLever, not(hasSecondKey)), getSecondKey); + unsortedStep6.addStep(and(needToInsertKeyInSouthLever, not(hasSecondKey)), getSecondKey); // If the user has not already put the key in the north lever, and does not have the key - ((ConditionalStep) unsortedStep6).addStep(and(needToInsertKeyInNorthLever, not(hasFirstKey)), getFirstKey); + unsortedStep6.addStep(and(needToInsertKeyInNorthLever, not(hasFirstKey)), getFirstKey); // If the user has the key & stands by the south lever - ((ConditionalStep) unsortedStep6).addStep(and(needToFlipSouthLever, bySouthLeverReq), pullSouthLever); + unsortedStep6.addStep(and(needToFlipSouthLever, bySouthLeverReq), pullSouthLever); // If the user needs to flip the south lever, but is not inside the little room, get to the little room - ((ConditionalStep) unsortedStep6).addStep(not(haveFlippedSouthLever), getToSouthLever); + unsortedStep6.addStep(not(haveFlippedSouthLever), getToSouthLever); // If the user has the key & stands by the north lever - ((ConditionalStep) unsortedStep6).addStep(and(needToFlipNorthLever, byNorthLeverReq), pullNorthLever); + unsortedStep6.addStep(and(needToFlipNorthLever, byNorthLeverReq), pullNorthLever); // If the user needs to flip the north lever, but is not inside the little room, get to the little room - ((ConditionalStep) unsortedStep6).addStep(needToFlipNorthLever, getToNorthLever); + unsortedStep6.addStep(needToFlipNorthLever, getToNorthLever); // Once last lever was pulled, quest varbit changed from 6 to 8, then 8 to 10 at the same tick // This might have to do with which order you pulled the levers in @@ -362,13 +363,13 @@ public void setupSteps() var finishedTilePuzzle = new VarbitRequirement(11483, 1); unsortedStep12 = new ConditionalStep(this, todo); - ((ConditionalStep) unsortedStep12).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); - ((ConditionalStep) unsortedStep12).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle, oilFilledCanopicJar), todo); - ((ConditionalStep) unsortedStep12).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); - ((ConditionalStep) unsortedStep12).addStep(insideTombSecondFloorReq, solveTilePuzzle); - ((ConditionalStep) unsortedStep12).addStep(not(insideTomb), enterTomb); - ((ConditionalStep) unsortedStep12).addStep(and(insideTomb, insideGolenArena), enterTombBasement); - ((ConditionalStep) unsortedStep12).addStep(and(insideTomb), enterGolemArenaWithoutFight); + unsortedStep12.addStep(and(insideTombSecondFloorReq, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); + unsortedStep12.addStep(and(insideTombSecondFloorReq, finishedTilePuzzle, oilFilledCanopicJar), todo); + unsortedStep12.addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); + unsortedStep12.addStep(insideTombSecondFloorReq, solveTilePuzzle); + unsortedStep12.addStep(not(insideTomb), enterTomb); + unsortedStep12.addStep(and(insideTomb, insideGolenArena), enterTombBasement); + unsortedStep12.addStep(and(insideTomb), enterGolemArenaWithoutFight); var oilAndBerryFilledCanopicJar = new ItemRequirement("Canopic jar (oil and berries)", ItemID.CANOPIC_JAR_OIL_AND_BERRIES); @@ -376,12 +377,12 @@ public void setupSteps() var combineJarWithRingOfLife = new ItemStep(this, "Combine the Dwellberries with the Ring of life.", oilAndBerryFilledCanopicJar.highlighted(), ringOfLife.highlighted()); unsortedStep16 = new ConditionalStep(this, todo); - ((ConditionalStep) unsortedStep16).addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); - ((ConditionalStep) unsortedStep16).addStep(oilFilledCanopicJar, combineJarWithDwellberries); - ((ConditionalStep) unsortedStep16).addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); - ((ConditionalStep) unsortedStep16).addStep(not(insideTomb), enterTomb); - ((ConditionalStep) unsortedStep16).addStep(and(insideTomb, insideGolenArena), enterTombBasement); - ((ConditionalStep) unsortedStep16).addStep(and(insideTomb), enterGolemArenaWithoutFight); + unsortedStep16.addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); + unsortedStep16.addStep(oilFilledCanopicJar, combineJarWithDwellberries); + unsortedStep16.addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); + unsortedStep16.addStep(not(insideTomb), enterTomb); + unsortedStep16.addStep(and(insideTomb, insideGolenArena), enterTombBasement); + unsortedStep16.addStep(and(insideTomb), enterGolemArenaWithoutFight); var returnToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); @@ -396,9 +397,9 @@ public void setupSteps() returnToElias.addSubSteps(returnToEliasByWalking, returnToEliasByWalkingMidway, returnToEliasByWalkingMidwayGolem); unsortedStep18 = new ConditionalStep(this, returnToElias); - ((ConditionalStep) unsortedStep18).addStep(insideTombSecondFloorReq, returnToEliasByWalking); - ((ConditionalStep) unsortedStep18).addStep(insideGolenArena, returnToEliasByWalkingMidwayGolem); - ((ConditionalStep) unsortedStep18).addStep(insideTomb, returnToEliasByWalkingMidway); + unsortedStep18.addStep(insideTombSecondFloorReq, returnToEliasByWalking); + unsortedStep18.addStep(insideGolenArena, returnToEliasByWalkingMidwayGolem); + unsortedStep18.addStep(insideTomb, returnToEliasByWalkingMidway); // ardy cloak + fairy ring takes 50s, walking takes 1m12s var trollheimTeleport = new TeleportItemRequirement("Trollheim Teleport", ItemID.TROLLHEIM_TELEPORT); @@ -440,41 +441,41 @@ public void setupSteps() rubbleMiner1.addSubSteps(rubbleMiner2, rubbleMiner3, rubbleMiner4); unsortedStep20 = new ConditionalStep(this, headToTrollheim); - ((ConditionalStep) unsortedStep20).addStep(inTrollweissCave, rubbleMiner1); - ((ConditionalStep) unsortedStep20).addStep(onTrollweissMountain, enterTrollweissCave); - ((ConditionalStep) unsortedStep20).addStep(inTrollheimCave, continueThroughTrollheimCave); + unsortedStep20.addStep(inTrollweissCave, rubbleMiner1); + unsortedStep20.addStep(onTrollweissMountain, enterTrollweissCave); + unsortedStep20.addStep(inTrollheimCave, continueThroughTrollheimCave); unsortedStep24 = new ConditionalStep(this, headToTrollheim); - ((ConditionalStep) unsortedStep24).addStep(inTrollweissCave, rubbleMiner2); - ((ConditionalStep) unsortedStep24).addStep(onTrollweissMountain, enterTrollweissCave); - ((ConditionalStep) unsortedStep24).addStep(inTrollheimCave, continueThroughTrollheimCave); + unsortedStep24.addStep(inTrollweissCave, rubbleMiner2); + unsortedStep24.addStep(onTrollweissMountain, enterTrollweissCave); + unsortedStep24.addStep(inTrollheimCave, continueThroughTrollheimCave); unsortedStep26 = new ConditionalStep(this, headToTrollheim); - ((ConditionalStep) unsortedStep26).addStep(inTrollweissCave, rubbleMiner3); - ((ConditionalStep) unsortedStep26).addStep(onTrollweissMountain, enterTrollweissCave); - ((ConditionalStep) unsortedStep26).addStep(inTrollheimCave, continueThroughTrollheimCave); + unsortedStep26.addStep(inTrollweissCave, rubbleMiner3); + unsortedStep26.addStep(onTrollweissMountain, enterTrollweissCave); + unsortedStep26.addStep(inTrollheimCave, continueThroughTrollheimCave); unsortedStep28 = new ConditionalStep(this, headToTrollheim); - ((ConditionalStep) unsortedStep28).addStep(inTrollweissCave, rubbleMiner4); - ((ConditionalStep) unsortedStep28).addStep(onTrollweissMountain, enterTrollweissCave); - ((ConditionalStep) unsortedStep28).addStep(inTrollheimCave, continueThroughTrollheimCave); + unsortedStep28.addStep(inTrollweissCave, rubbleMiner4); + unsortedStep28.addStep(onTrollweissMountain, enterTrollweissCave); + unsortedStep28.addStep(inTrollheimCave, continueThroughTrollheimCave); var climbUpstairsAndTalkToArrav = new ObjectStep(this, ObjectID.STAIRS_50508, new WorldPoint(2811, 10267, 0), "Climb up the stairs in the room with the red tile floor and talk to Arrav."); unsortedStep30 = new ConditionalStep(this, headToTrollheim); - ((ConditionalStep) unsortedStep30).addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); - ((ConditionalStep) unsortedStep30).addStep(onTrollweissMountain, enterTrollweissCave); - ((ConditionalStep) unsortedStep30).addStep(inTrollheimCave, continueThroughTrollheimCave); + unsortedStep30.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); + unsortedStep30.addStep(onTrollweissMountain, enterTrollweissCave); + unsortedStep30.addStep(inTrollheimCave, continueThroughTrollheimCave); var arravHouseFirstRoom = new Zone(new WorldPoint(2848, 3868, 0), new WorldPoint(2858, 3873, 0)); var inArravHouseFirstRoom = new ZoneRequirement(arravHouseFirstRoom); var talkToArrav = new NpcStep(this, NpcID.ARRAV_14129, new WorldPoint(2856, 3871, 0), "Talk to Arrav."); unsortedStep32 = new ConditionalStep(this, headToTrollheim); - ((ConditionalStep) unsortedStep32).addStep(inArravHouseFirstRoom, talkToArrav); - ((ConditionalStep) unsortedStep32).addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); - ((ConditionalStep) unsortedStep32).addStep(onTrollweissMountain, enterTrollweissCave); - ((ConditionalStep) unsortedStep32).addStep(inTrollheimCave, continueThroughTrollheimCave); + unsortedStep32.addStep(inArravHouseFirstRoom, talkToArrav); + unsortedStep32.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); + unsortedStep32.addStep(onTrollweissMountain, enterTrollweissCave); + unsortedStep32.addStep(inTrollheimCave, continueThroughTrollheimCave); var arravHouseSecondRoom = new Zone(new WorldPoint(2863, 3865, 0), new WorldPoint(2859, 3873, 0)); var inArravHouseSecondRoom = new ZoneRequirement(arravHouseSecondRoom); @@ -482,11 +483,11 @@ public void setupSteps() var goToNextRoom = new ObjectStep(this, ObjectID.DOOR_50514, new WorldPoint(2859, 3870, 0), "Enter the room to your east and search the tapestry for ?."); var searchTapestry = new ObjectStep(this, ObjectID.TAPESTRY_50516, new WorldPoint(2861, 3865, 0), "Search the tapestry in the south of the room."); unsortedStep34 = new ConditionalStep(this, headToTrollheim); - ((ConditionalStep) unsortedStep34).addStep(inArravHouseSecondRoom, searchTapestry); - ((ConditionalStep) unsortedStep34).addStep(inArravHouseFirstRoom, goToNextRoom); - ((ConditionalStep) unsortedStep34).addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); - ((ConditionalStep) unsortedStep34).addStep(onTrollweissMountain, enterTrollweissCave); - ((ConditionalStep) unsortedStep34).addStep(inTrollheimCave, continueThroughTrollheimCave); + unsortedStep34.addStep(inArravHouseSecondRoom, searchTapestry); + unsortedStep34.addStep(inArravHouseFirstRoom, goToNextRoom); + unsortedStep34.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); + unsortedStep34.addStep(onTrollweissMountain, enterTrollweissCave); + unsortedStep34.addStep(inTrollheimCave, continueThroughTrollheimCave); var tapestryFindText = "Can be acquired by heading back to Zemouregal's Fort past the Trollweiss mining dungeon and searching the tapestry."; @@ -524,9 +525,9 @@ public void setupSteps() var passZemouregalsBaseDoor4 = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3605, 4603, 0), "Open the gate and make your way to the back of Zemouregal's base.", canopicJarFull, insulatedBoots); unsortedStep44 = new ConditionalStep(this, enterZemouregalsBase); - ((ConditionalStep) unsortedStep44).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - ((ConditionalStep) unsortedStep44).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - ((ConditionalStep) unsortedStep44).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + unsortedStep44.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + unsortedStep44.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + unsortedStep44.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); var enterZemouregalsBaseSewer = new ObjectStep(this, ObjectID.PIPE_50523, new WorldPoint(3609, 4598, 0), "Enter the sewers and make your way to the back of Zemouregal's base.", canopicJarFull, insulatedBoots.highlighted().equipped()); @@ -537,12 +538,12 @@ public void setupSteps() // 44 -> 46 when opening door, consuming the base key unsortedStep46 = new ConditionalStep(this, enterZemouregalsBase); - ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - ((ConditionalStep) unsortedStep46).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + unsortedStep46.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + unsortedStep46.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + unsortedStep46.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + unsortedStep46.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + unsortedStep46.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + unsortedStep46.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); var inSecondPart = new ZoneRequirement(new Zone(new WorldPoint(3590, 4538, 0), new WorldPoint(3622, 4597, 0))); var inStorageRoom = new ZoneRequirement(new Zone(new WorldPoint(3614, 4571, 0), new WorldPoint(3605, 4563, 0))); @@ -563,18 +564,18 @@ public void setupSteps() // also used for 50 unsortedStep48 = new ConditionalStep(this, enterZemouregalsBase); // TODO: DECODER STRIPS ARE NOT NECESSARY. REMOVE THEM :) - ((ConditionalStep) unsortedStep48).addStep(and(inSecondPart, not(inStorageRoom), decoderStrips, codeKey), metalDoorSolver); - ((ConditionalStep) unsortedStep48).addStep(and(inStorageRoom, not(decoderStrips)), searchTableForDecoderStrips); - ((ConditionalStep) unsortedStep48).addStep(and(inStorageRoom, not(codeKey)), openChestForCodeKey); - ((ConditionalStep) unsortedStep48).addStep(and(inStorageRoom, decoderStrips), exitStorageRoom); - ((ConditionalStep) unsortedStep48).addStep(and(inSecondPart, not(codeKey)), enterStorageRoom); - ((ConditionalStep) unsortedStep48).addStep(and(inSecondPart, not(decoderStrips)), enterStorageRoom); - ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - ((ConditionalStep) unsortedStep48).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + unsortedStep48.addStep(and(inSecondPart, not(inStorageRoom), decoderStrips, codeKey), metalDoorSolver); + unsortedStep48.addStep(and(inStorageRoom, not(decoderStrips)), searchTableForDecoderStrips); + unsortedStep48.addStep(and(inStorageRoom, not(codeKey)), openChestForCodeKey); + unsortedStep48.addStep(and(inStorageRoom, decoderStrips), exitStorageRoom); + unsortedStep48.addStep(and(inSecondPart, not(codeKey)), enterStorageRoom); + unsortedStep48.addStep(and(inSecondPart, not(decoderStrips)), enterStorageRoom); + unsortedStep48.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + unsortedStep48.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + unsortedStep48.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + unsortedStep48.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + unsortedStep48.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + unsortedStep48.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); openMetalDoors = new ObjectStep(this, ObjectID.METAL_DOORS, new WorldPoint(3612, 4582, 0), "Step through through the metal doors.", canopicJarFull, anyGrappleableCrossbow, mithrilGrapple); @@ -586,28 +587,28 @@ public void setupSteps() enterBossRoom = new ObjectStep(this, ObjectID.PEDESTAL_50539, new WorldPoint(3638, 4582, 0), "Attempt to take Arrav's heart from the pedestal, ready for a fight. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid most of Arravs damage. When Arrav throws an axe towards you, step to the side or behind him.", rangedCombatGear); unsortedStep52 = new ConditionalStep(this, enterZemouregalsBase); - ((ConditionalStep) unsortedStep52).addStep(pastGrapplePuzzleRoom, enterBossRoom); - ((ConditionalStep) unsortedStep52).addStep(inGrapplePuzzleRoom, grappleAcross); - ((ConditionalStep) unsortedStep52).addStep(inSecondPart, openMetalDoors); - ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - ((ConditionalStep) unsortedStep52).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + unsortedStep52.addStep(pastGrapplePuzzleRoom, enterBossRoom); + unsortedStep52.addStep(inGrapplePuzzleRoom, grappleAcross); + unsortedStep52.addStep(inSecondPart, openMetalDoors); + unsortedStep52.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + unsortedStep52.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + unsortedStep52.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + unsortedStep52.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + unsortedStep52.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + unsortedStep52.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); // User has engaged Arrav fightArrav = new NpcStep(this, NpcID.ARRAV_14132, new WorldPoint(3635, 4582, 0), "fight arrav xd"); unsortedStep54 = new ConditionalStep(this, enterZemouregalsBase); - ((ConditionalStep) unsortedStep54).addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), fightArrav); - ((ConditionalStep) unsortedStep54).addStep(inSecondPart, openMetalDoors); - ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - ((ConditionalStep) unsortedStep54).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + unsortedStep54.addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), fightArrav); + unsortedStep54.addStep(inSecondPart, openMetalDoors); + unsortedStep54.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + unsortedStep54.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + unsortedStep54.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + unsortedStep54.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + unsortedStep54.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + unsortedStep54.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); // 54 -> 56 when beating arrav @@ -615,16 +616,16 @@ public void setupSteps() var watchTheDialog = new DetailedQuestStep(this, "Watch the dialog."); fightArrav.addSubSteps(watchTheDialog); unsortedStep56 = new ConditionalStep(this, enterZemouregalsBase); - ((ConditionalStep) unsortedStep56).addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), watchTheDialog); - ((ConditionalStep) unsortedStep56).addStep(inSecondPart, openMetalDoors); - ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - ((ConditionalStep) unsortedStep56).addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); - - unsortedStep58 = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Talk to Elias to finish the quest."); + unsortedStep56.addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), watchTheDialog); + unsortedStep56.addStep(inSecondPart, openMetalDoors); + unsortedStep56.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + unsortedStep56.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + unsortedStep56.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + unsortedStep56.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + unsortedStep56.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + unsortedStep56.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + + finishQuest = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Talk to Elias to finish the quest."); } @Override @@ -769,7 +770,7 @@ public List getPanels() grappleAcross, enterBossRoom, fightArrav, - unsortedStep58 + finishQuest // TODO ), List.of( // Requirements From 20ec36243846ef9b5656f5fcb5dde3125204a814 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:43:14 +0100 Subject: [PATCH 16/60] fix: remove unused variables --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 97bdfdbce5..1b6a446358 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -66,7 +66,6 @@ import net.runelite.api.ObjectID; import net.runelite.api.QuestState; import net.runelite.api.Skill; -import net.runelite.api.SpriteID; import net.runelite.api.coords.WorldPoint; /** @@ -418,8 +417,6 @@ public void setupSteps() var trollweissCave1 = new Zone(11168); var inTrollweissCave = new ZoneRequirement(trollweissCave1); - var whereToStandSprite = SpriteID.COMBAT_STYLE_PICKAXE_SMASH; - // Rubble 50598 = 2 hits // Rubble 50587/50589 = 1 hit From 29969be516492dd4469bb221069509e7f5eec413 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:45:11 +0100 Subject: [PATCH 17/60] nit: remove commented out code --- .../quests/thecurseofarrav/TheCurseOfArrav.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 1b6a446358..57753df20e 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -417,19 +417,6 @@ public void setupSteps() var trollweissCave1 = new Zone(11168); var inTrollweissCave = new ZoneRequirement(trollweissCave1); - // Rubble 50598 = 2 hits - // Rubble 50587/50589 = 1 hit - - // var mineRubble1FromSouth = new ObjectStep(this, ObjectID.RUBBLE_50598, new WorldPoint(2764, 10266, 0), "Mine the rubble from the south."); - // mineRubble1FromSouth.addTileMarker(new WorldPoint(2764, 10265, 0), whereToStandSprite); - - // var rubble1MinedOnce = new ObjectCondition(ObjectID.RUBBLE_50589, new WorldPoint(2764, 10266, 0)); - // var rubble2Mined = not(new ObjectCondition(ObjectID.RUBBLE_50589, new WorldPoint(2775, 10258, 0))); - - // var mineRubble2FromSouth = new ObjectStep(this, ObjectID.RUBBLE_50587, new WorldPoint(2775, 10258, 0), "Mine the rubble from the south."); - // mineRubble2FromSouth.addTileMarker(new WorldPoint(2775, 10257, 0), whereToStandSprite); - // mineRubble2FromSouth.setLinePoints(List.of(new WorldPoint(2763, 10264, 0), new WorldPoint(2769, 10254, 0), new WorldPoint(2775, 10255, 0))); - rubbleMiner1 = new RubbleSolverOne(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); rubbleMiner2 = new RubbleSolverTwo(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); rubbleMiner3 = new RubbleSolverThree(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); From 506d0325d18a8a5172bb5530d7358b36dc0a5b7c Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:45:18 +0100 Subject: [PATCH 18/60] Reword the Protect from Melee phrasing from Arrav boss fight --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 57753df20e..7272969dfb 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -568,7 +568,7 @@ public void setupSteps() var pastGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3621, 4589, 0), new WorldPoint(3645, 4578, 0))); - enterBossRoom = new ObjectStep(this, ObjectID.PEDESTAL_50539, new WorldPoint(3638, 4582, 0), "Attempt to take Arrav's heart from the pedestal, ready for a fight. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid most of Arravs damage. When Arrav throws an axe towards you, step to the side or behind him.", rangedCombatGear); + enterBossRoom = new ObjectStep(this, ObjectID.PEDESTAL_50539, new WorldPoint(3638, 4582, 0), "Attempt to take Arrav's heart from the pedestal, ready for a fight. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid some of the incoming damage. When Arrav throws an axe towards you, step to the side or behind him.", rangedCombatGear); unsortedStep52 = new ConditionalStep(this, enterZemouregalsBase); unsortedStep52.addStep(pastGrapplePuzzleRoom, enterBossRoom); From a8484bbffc26f40943fb606b37c5391d3339c590 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:48:52 +0100 Subject: [PATCH 19/60] nit: reword directions in "Tomb Raiding" --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 7272969dfb..9a26db2b77 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -281,7 +281,7 @@ public void setupSteps() // TODO: Ensure player can get hint to return var hasFirstKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY); - getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton to the south of the entrance."); + getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton south of the entrance."); var hasSecondKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY_30309); getSecondKey = new ObjectStep(this, ObjectID.SKELETON_50353, new WorldPoint(3880, 4585, 0), "Get the second Mastaba key from the skeleton east of the entrance."); var bySouthLever = new Zone(new WorldPoint(3893, 4554, 0), new WorldPoint(3894, 4552, 0)); From 25a74302752c7d52590a228b2e1ee46921e67c7f Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:49:05 +0100 Subject: [PATCH 20/60] nit: remove some empty lines --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 9a26db2b77..be0fb7e133 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -775,5 +775,4 @@ public List getPanels() return panels; } - } From 76a6a45d7715211e16bbb6a3a6d259e5d23e2428 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 16:50:33 +0100 Subject: [PATCH 21/60] nit: ungender the golem --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index be0fb7e133..2c91ba5d82 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -337,7 +337,7 @@ public void setupSteps() var golemArenaZone = new Zone(new WorldPoint(3856, 4592, 0), new WorldPoint(3884, 4599, 0)); var insideGolenArena = new ZoneRequirement(golemArenaZone); enterGolemArena = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Open the imposing doors, ready to fight the Golem guard."); - fightGolemGuard = new NpcStep(this, NpcID.GOLEM_GUARD, new WorldPoint(3860, 4595, 0), "Fight the Golem guard. He is weak to crush style weapons. Use Protect from Melee to avoid damage from his attacks. When the screen shakes, step away from him to avoid taking damage."); + fightGolemGuard = new NpcStep(this, NpcID.GOLEM_GUARD, new WorldPoint(3860, 4595, 0), "Fight the Golem guard. It is weak to crush style weapons. Use Protect from Melee to avoid damage from his attacks. When the screen shakes, step away from him to avoid taking damage."); unsortedStep10 = new ConditionalStep(this, enterGolemArena); // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? unsortedStep10.addStep(not(insideTomb), enterTomb); From 99f5fbea56afb30633d9ae5fde4e669cfb0f0958 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 17:05:22 +0100 Subject: [PATCH 22/60] refactor: make insideTombSecondFloorReq a class member --- .../thecurseofarrav/TheCurseOfArrav.java | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 2c91ba5d82..565dc094d1 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -91,8 +91,8 @@ public class TheCurseOfArrav extends BasicQuestHelper // lumberyard teleport // melee (crush) combat gear for golem // ranged combat gear for arrav - private ItemRequirement crushCombatGear; - private ItemRequirement rangedCombatGear; + private ItemRequirement golemCombatGear; + private ItemRequirement arravCombatGear; private ItemRequirement food; private ItemRequirement staminaPotion; private ItemRequirement prayerPotion; @@ -106,6 +106,8 @@ public class TheCurseOfArrav extends BasicQuestHelper // Zones & their requirements /// Top floor of the tomb (Uzer Mastaba) private ZoneRequirement insideTomb; + /// Second floor of the tomb (Uzer Mastaba) + private ZoneRequirement insideTombSecondFloor; private ZoneRequirement inZemouregalsBaseSection1; private ZoneRequirement inZemouregalsBaseSection2; private ZoneRequirement inZemouregalsBaseSection3; @@ -217,6 +219,10 @@ public Map loadSteps() protected void setupZones() { insideTomb = new ZoneRequirement(new Zone(new WorldPoint(3842, 4603, 0), new WorldPoint(3900, 4547, 0))); + insideTombSecondFloor = new ZoneRequirement( + new Zone(new WorldPoint(3719, 4674, 0), new WorldPoint(3770, 4732, 0)), + new Zone(new WorldPoint(3845, 4674, 0), new WorldPoint(3900, 4732, 0)) + ); // Right as you head into the base inZemouregalsBaseSection1 = new ZoneRequirement(new Zone(new WorldPoint(3536, 4577, 0), new WorldPoint(3564, 4547, 0))); @@ -260,11 +266,12 @@ protected void setupRequirements() fairyRingDLQ = new TeleportItemRequirement("Fairy Ring [DLQ]", ItemCollections.FAIRY_STAFF); staminaPotion = new ItemRequirement("Stamina potion", ItemCollections.STAMINA_POTIONS, 1); prayerPotion = new ItemRequirement("Prayer potion", ItemCollections.PRAYER_POTIONS, 1); - crushCombatGear = new ItemRequirement("Melee combat gear (crush preferred)", -1, -1); - crushCombatGear.setDisplayItemId(BankSlotIcons.getMeleeCombatGear()); - crushCombatGear.setConditionToHide(haveKilledGolem); - rangedCombatGear = new ItemRequirement("Ranged combat gear for killing Arrav", -1, -1); - rangedCombatGear.setDisplayItemId(BankSlotIcons.getRangedCombatGear()); + golemCombatGear = new ItemRequirement("Crush or ranged combat gear to fight the Golem guard (lvl 141)", -1, -1); + golemCombatGear.setDisplayItemId(BankSlotIcons.getCombatGear()); + golemCombatGear.setConditionToHide(haveKilledGolem); + arravCombatGear = new ItemRequirement("Ranged or melee combat gear for killing Arrav", -1, -1); + arravCombatGear.setTooltip("If you bring Melee gear, it's advisable to bring some ranged weapon swap for killing the Zombies as they spawn"); + arravCombatGear.setDisplayItemId(BankSlotIcons.getRangedCombatGear()); food = new ItemRequirement("Food", ItemCollections.GOOD_EATING_FOOD, -1); twoFreeInventorySlots = new FreeInventorySlotRequirement(2); } @@ -351,9 +358,6 @@ public void setupSteps() solveTilePuzzle = new TilePuzzleSolver(this).puzzleWrapStep("Move across the floor tile puzzle."); - var insideTombSecondFloor = new Zone(new WorldPoint(3719, 4674, 0), new WorldPoint(3770, 4732, 0)); - var insideTombSecondFloorAfterFinishingPuzzle = new Zone(new WorldPoint(3845, 4674, 0), new WorldPoint(3900, 4732, 0)); - var insideTombSecondFloorReq = new ZoneRequirement(insideTombSecondFloor, insideTombSecondFloorAfterFinishingPuzzle); var searchShelvesForUrn = new ObjectStep(this, ObjectID.SHELVES_55796, new WorldPoint(3854, 4722, 0), "Search the shelves to the west for an oil-filled canopic jar."); var oilFilledCanopicJar = new ItemRequirement("Oil-filled canopic jar", ItemID.CANOPIC_JAR_OIL); @@ -362,10 +366,10 @@ public void setupSteps() var finishedTilePuzzle = new VarbitRequirement(11483, 1); unsortedStep12 = new ConditionalStep(this, todo); - unsortedStep12.addStep(and(insideTombSecondFloorReq, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); - unsortedStep12.addStep(and(insideTombSecondFloorReq, finishedTilePuzzle, oilFilledCanopicJar), todo); - unsortedStep12.addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); - unsortedStep12.addStep(insideTombSecondFloorReq, solveTilePuzzle); + unsortedStep12.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); + unsortedStep12.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), todo); + unsortedStep12.addStep(and(insideTombSecondFloor, finishedTilePuzzle), searchShelvesForUrn); + unsortedStep12.addStep(insideTombSecondFloor, solveTilePuzzle); unsortedStep12.addStep(not(insideTomb), enterTomb); unsortedStep12.addStep(and(insideTomb, insideGolenArena), enterTombBasement); unsortedStep12.addStep(and(insideTomb), enterGolemArenaWithoutFight); @@ -378,7 +382,7 @@ public void setupSteps() unsortedStep16 = new ConditionalStep(this, todo); unsortedStep16.addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); unsortedStep16.addStep(oilFilledCanopicJar, combineJarWithDwellberries); - unsortedStep16.addStep(and(insideTombSecondFloorReq, finishedTilePuzzle), searchShelvesForUrn); + unsortedStep16.addStep(and(insideTombSecondFloor, finishedTilePuzzle), searchShelvesForUrn); unsortedStep16.addStep(not(insideTomb), enterTomb); unsortedStep16.addStep(and(insideTomb, insideGolenArena), enterTombBasement); unsortedStep16.addStep(and(insideTomb), enterGolemArenaWithoutFight); @@ -396,7 +400,7 @@ public void setupSteps() returnToElias.addSubSteps(returnToEliasByWalking, returnToEliasByWalkingMidway, returnToEliasByWalkingMidwayGolem); unsortedStep18 = new ConditionalStep(this, returnToElias); - unsortedStep18.addStep(insideTombSecondFloorReq, returnToEliasByWalking); + unsortedStep18.addStep(insideTombSecondFloor, returnToEliasByWalking); unsortedStep18.addStep(insideGolenArena, returnToEliasByWalkingMidwayGolem); unsortedStep18.addStep(insideTomb, returnToEliasByWalkingMidway); // ardy cloak + fairy ring takes 50s, walking takes 1m12s @@ -496,10 +500,10 @@ public void setupSteps() canopicJarFull = new ItemRequirement("Canopic jar (full)", ItemID.CANOPIC_JAR_FULL); canopicJarFull.setTooltip("You can get a new one from Elias at the entrance of Zemouregal's base if you've lost it."); // this is at least true after the mining part // need 1 inventory slot free - headToZemouregalsBaseAndTalkToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3341, 3516, 0), "Head to Zemouregal's base east of Varrock's sawmill and talk to Elias.", anyGrappleableCrossbow, mithrilGrapple, rangedCombatGear, insulatedBoots, canopicJarFull, baseKey); // todo add teleport + headToZemouregalsBaseAndTalkToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3341, 3516, 0), "Head to Zemouregal's base east of Varrock's sawmill and talk to Elias.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFull, baseKey); // todo add teleport headToZemouregalsBaseAndTalkToElias.addDialogStep("Ready when you are."); unsortedStep42 = new ConditionalStep(this, headToZemouregalsBaseAndTalkToElias); - enterZemouregalsBase = new ObjectStep(this, NullObjectID.NULL_50689, new WorldPoint(3343, 3515, 0), "Enter Zemouregal's base east of Varrock's sawmill.", anyGrappleableCrossbow, mithrilGrapple, rangedCombatGear, insulatedBoots, canopicJarFull, baseKey); // todo add teleport + enterZemouregalsBase = new ObjectStep(this, NullObjectID.NULL_50689, new WorldPoint(3343, 3515, 0), "Enter Zemouregal's base east of Varrock's sawmill.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFull, baseKey); // todo add teleport getToBackOfZemouregalsBase = new DetailedQuestStep(this, "Make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage."); @@ -568,7 +572,7 @@ public void setupSteps() var pastGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3621, 4589, 0), new WorldPoint(3645, 4578, 0))); - enterBossRoom = new ObjectStep(this, ObjectID.PEDESTAL_50539, new WorldPoint(3638, 4582, 0), "Attempt to take Arrav's heart from the pedestal, ready for a fight. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid some of the incoming damage. When Arrav throws an axe towards you, step to the side or behind him.", rangedCombatGear); + enterBossRoom = new ObjectStep(this, ObjectID.PEDESTAL_50539, new WorldPoint(3638, 4582, 0), "Attempt to take Arrav's heart from the pedestal, ready for a fight. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid some of the incoming damage. When Arrav throws an axe towards you, step to the side or behind him.", arravCombatGear); unsortedStep52 = new ConditionalStep(this, enterZemouregalsBase); unsortedStep52.addStep(pastGrapplePuzzleRoom, enterBossRoom); @@ -631,7 +635,8 @@ public List getItemRecommended() return List.of( staminaPotion, prayerPotion, - crushCombatGear, + golemCombatGear, + arravCombatGear, food ); } @@ -640,6 +645,7 @@ public List getItemRecommended() public List getGeneralRecommended() { return List.of( + twoFreeInventorySlots, new CombatLevelRequirement(85), new SkillRequirement(Skill.PRAYER, 43, false, "43+ Prayer to use protection prayers") ); @@ -714,7 +720,7 @@ public List getPanels() ), List.of( dwellberries3, ringOfLife, - crushCombatGear + golemCombatGear // Requirements ), List.of( // Recommended @@ -762,7 +768,7 @@ public List getPanels() baseKey, anyGrappleableCrossbow, mithrilGrapple, - rangedCombatGear, + arravCombatGear, insulatedBoots, canopicJarFull ), List.of( From 56db84c2f98ce62faa3cbbf284df56f3cbc6cd6b Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 17:05:47 +0100 Subject: [PATCH 23/60] nit: Reword combat gear/prayer recommendation texts --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 565dc094d1..25baa4168b 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -266,11 +266,11 @@ protected void setupRequirements() fairyRingDLQ = new TeleportItemRequirement("Fairy Ring [DLQ]", ItemCollections.FAIRY_STAFF); staminaPotion = new ItemRequirement("Stamina potion", ItemCollections.STAMINA_POTIONS, 1); prayerPotion = new ItemRequirement("Prayer potion", ItemCollections.PRAYER_POTIONS, 1); - golemCombatGear = new ItemRequirement("Crush or ranged combat gear to fight the Golem guard (lvl 141)", -1, -1); + golemCombatGear = new ItemRequirement("Crush or ranged combat gear to fight the Golem guard", -1, -1); golemCombatGear.setDisplayItemId(BankSlotIcons.getCombatGear()); golemCombatGear.setConditionToHide(haveKilledGolem); arravCombatGear = new ItemRequirement("Ranged or melee combat gear for killing Arrav", -1, -1); - arravCombatGear.setTooltip("If you bring Melee gear, it's advisable to bring some ranged weapon swap for killing the Zombies as they spawn"); + arravCombatGear.setTooltip("If you bring Melee gear, it's advisable to bring some ranged weapon swap like darts for killing the Zombies as they spawn"); arravCombatGear.setDisplayItemId(BankSlotIcons.getRangedCombatGear()); food = new ItemRequirement("Food", ItemCollections.GOOD_EATING_FOOD, -1); twoFreeInventorySlots = new FreeInventorySlotRequirement(2); @@ -647,7 +647,7 @@ public List getGeneralRecommended() return List.of( twoFreeInventorySlots, new CombatLevelRequirement(85), - new SkillRequirement(Skill.PRAYER, 43, false, "43+ Prayer to use protection prayers") + new SkillRequirement(Skill.PRAYER, 43, false, "43 Prayer to use Protect from Melee") ); } From 8e262dcc8277fbb4ba4ea055c1ce421ca24136d1 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 17:09:07 +0100 Subject: [PATCH 24/60] refactor: make `finishedTilePuzzle` a class member --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 25baa4168b..b0d9e1c3b7 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -158,6 +158,7 @@ public class TheCurseOfArrav extends BasicQuestHelper private ObjectStep enterZemouregalsBase; private DetailedQuestStep getToBackOfZemouregalsBase; private QuestRequirement haveKilledGolem; + private VarbitRequirement finishedTilePuzzle; private QuestRequirement haveMadeCanopicJar; private QuestRequirement haveMinedAFullPath; private QuestRequirement haveUsedPlans; @@ -243,6 +244,7 @@ protected void setupZones() protected void setupRequirements() { haveKilledGolem = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 12); + finishedTilePuzzle = new VarbitRequirement(11483, 1); haveMadeCanopicJar = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 18); haveMinedAFullPath = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 30); haveUsedPlans = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 38); @@ -364,7 +366,6 @@ public void setupSteps() var inspectMurals = new ObjectStep(this, ObjectID.MURAL_55790, new WorldPoint(3852, 4687, 0), "Inspect the murals in the room to the south.", oilFilledCanopicJar); - var finishedTilePuzzle = new VarbitRequirement(11483, 1); unsortedStep12 = new ConditionalStep(this, todo); unsortedStep12.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); unsortedStep12.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), todo); From 11ea4e70147c2cf672811587403726abc4190445 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 17:14:16 +0100 Subject: [PATCH 25/60] refactor: Clean up step 12 --- .../thecurseofarrav/TheCurseOfArrav.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index b0d9e1c3b7..c8383714a6 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -128,7 +128,8 @@ public class TheCurseOfArrav extends BasicQuestHelper private ConditionalStep unsortedStep6; private ConditionalStep unsortedStep10; private PuzzleWrapperStep solveTilePuzzle; - private ConditionalStep unsortedStep12; + private ObjectStep searchShelvesForUrn; + private ConditionalStep finishTilePuzzleAndGetCanopicJar; private ConditionalStep unsortedStep16; private ConditionalStep unsortedStep18; private ConditionalStep unsortedStep20; @@ -188,8 +189,8 @@ public Map loadSteps() steps.put(6, unsortedStep6); steps.put(8, unsortedStep6); steps.put(10, unsortedStep10); - steps.put(12, unsortedStep12); - steps.put(14, unsortedStep12); + steps.put(12, finishTilePuzzleAndGetCanopicJar); + steps.put(14, finishTilePuzzleAndGetCanopicJar); steps.put(16, unsortedStep16); steps.put(18, unsortedStep18); steps.put(20, unsortedStep20); @@ -360,20 +361,18 @@ public void setupSteps() solveTilePuzzle = new TilePuzzleSolver(this).puzzleWrapStep("Move across the floor tile puzzle."); - - var searchShelvesForUrn = new ObjectStep(this, ObjectID.SHELVES_55796, new WorldPoint(3854, 4722, 0), "Search the shelves to the west for an oil-filled canopic jar."); + searchShelvesForUrn = new ObjectStep(this, ObjectID.SHELVES_55796, new WorldPoint(3854, 4722, 0), "Search the shelves to the west for an oil-filled canopic jar."); var oilFilledCanopicJar = new ItemRequirement("Oil-filled canopic jar", ItemID.CANOPIC_JAR_OIL); var inspectMurals = new ObjectStep(this, ObjectID.MURAL_55790, new WorldPoint(3852, 4687, 0), "Inspect the murals in the room to the south.", oilFilledCanopicJar); - unsortedStep12 = new ConditionalStep(this, todo); - unsortedStep12.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); - unsortedStep12.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), todo); - unsortedStep12.addStep(and(insideTombSecondFloor, finishedTilePuzzle), searchShelvesForUrn); - unsortedStep12.addStep(insideTombSecondFloor, solveTilePuzzle); - unsortedStep12.addStep(not(insideTomb), enterTomb); - unsortedStep12.addStep(and(insideTomb, insideGolenArena), enterTombBasement); - unsortedStep12.addStep(and(insideTomb), enterGolemArenaWithoutFight); + finishTilePuzzleAndGetCanopicJar = new ConditionalStep(this, enterTomb); + finishTilePuzzleAndGetCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); + finishTilePuzzleAndGetCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), todo); + finishTilePuzzleAndGetCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle), searchShelvesForUrn); + finishTilePuzzleAndGetCanopicJar.addStep(insideTombSecondFloor, solveTilePuzzle); + finishTilePuzzleAndGetCanopicJar.addStep(and(insideTomb, insideGolenArena), enterTombBasement); + finishTilePuzzleAndGetCanopicJar.addStep(and(insideTomb), enterGolemArenaWithoutFight); var oilAndBerryFilledCanopicJar = new ItemRequirement("Canopic jar (oil and berries)", ItemID.CANOPIC_JAR_OIL_AND_BERRIES); @@ -716,6 +715,7 @@ public List getPanels() fightGolemGuard, enterTombBasement, solveTilePuzzle, + searchShelvesForUrn, unsortedStep16, unsortedStep18 ), List.of( From cb474602f2bfd5486e121ea4d8c21dfab0e6d5dc Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 17:19:08 +0100 Subject: [PATCH 26/60] refactor: cleanup/clarify early tomb steps --- .../thecurseofarrav/TheCurseOfArrav.java | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index c8383714a6..af0f67cd30 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -116,20 +116,30 @@ public class TheCurseOfArrav extends BasicQuestHelper private ZoneRequirement inZemouregalsBaseSewer; // Steps + /// 0 + 2 private NpcStep startQuest; + + /// 4 private ObjectStep enterTomb; + + /// 6 + 8 + private ConditionalStep unsortedStep6; private ObjectStep getFirstKey; private ObjectStep getSecondKey; private ObjectStep pullSouthLever; private ObjectStep pullNorthLever; + + /// 10 + private ConditionalStep fightGolemCond; private ObjectStep enterGolemArena; private NpcStep fightGolemGuard; + + /// 12 + 14 + private ConditionalStep finishTilePuzzleAndGetCanopicJar; private ObjectStep enterTombBasement; - private ConditionalStep unsortedStep6; - private ConditionalStep unsortedStep10; private PuzzleWrapperStep solveTilePuzzle; private ObjectStep searchShelvesForUrn; - private ConditionalStep finishTilePuzzleAndGetCanopicJar; + private ObjectStep inspectMurals; private ConditionalStep unsortedStep16; private ConditionalStep unsortedStep18; private ConditionalStep unsortedStep20; @@ -188,7 +198,7 @@ public Map loadSteps() steps.put(4, enterTomb); steps.put(6, unsortedStep6); steps.put(8, unsortedStep6); - steps.put(10, unsortedStep10); + steps.put(10, fightGolemCond); steps.put(12, finishTilePuzzleAndGetCanopicJar); steps.put(14, finishTilePuzzleAndGetCanopicJar); steps.put(16, unsortedStep16); @@ -348,12 +358,12 @@ public void setupSteps() var insideGolenArena = new ZoneRequirement(golemArenaZone); enterGolemArena = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Open the imposing doors, ready to fight the Golem guard."); fightGolemGuard = new NpcStep(this, NpcID.GOLEM_GUARD, new WorldPoint(3860, 4595, 0), "Fight the Golem guard. It is weak to crush style weapons. Use Protect from Melee to avoid damage from his attacks. When the screen shakes, step away from him to avoid taking damage."); - unsortedStep10 = new ConditionalStep(this, enterGolemArena); + fightGolemCond = new ConditionalStep(this, enterGolemArena); // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? - unsortedStep10.addStep(not(insideTomb), enterTomb); - unsortedStep10.addStep(byNorthLeverReq, leaveNorthLever); - unsortedStep10.addStep(bySouthLeverReq, leaveSouthLever); - unsortedStep10.addStep(insideGolenArena, fightGolemGuard); + fightGolemCond.addStep(not(insideTomb), enterTomb); + fightGolemCond.addStep(byNorthLeverReq, leaveNorthLever); + fightGolemCond.addStep(bySouthLeverReq, leaveSouthLever); + fightGolemCond.addStep(insideGolenArena, fightGolemGuard); var enterGolemArenaWithoutFight = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Open the imposing doors to the north-east of the tomb."); enterTombBasement = new ObjectStep(this, ObjectID.STAIRS_55785, new WorldPoint(3860, 4596, 0), "Climb the stairs down the tomb basement."); @@ -364,7 +374,7 @@ public void setupSteps() searchShelvesForUrn = new ObjectStep(this, ObjectID.SHELVES_55796, new WorldPoint(3854, 4722, 0), "Search the shelves to the west for an oil-filled canopic jar."); var oilFilledCanopicJar = new ItemRequirement("Oil-filled canopic jar", ItemID.CANOPIC_JAR_OIL); - var inspectMurals = new ObjectStep(this, ObjectID.MURAL_55790, new WorldPoint(3852, 4687, 0), "Inspect the murals in the room to the south.", oilFilledCanopicJar); + inspectMurals = new ObjectStep(this, ObjectID.MURAL_55790, new WorldPoint(3852, 4687, 0), "Inspect the murals in the room to the south.", oilFilledCanopicJar); finishTilePuzzleAndGetCanopicJar = new ConditionalStep(this, enterTomb); finishTilePuzzleAndGetCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); @@ -716,6 +726,7 @@ public List getPanels() enterTombBasement, solveTilePuzzle, searchShelvesForUrn, + inspectMurals, unsortedStep16, unsortedStep18 ), List.of( From 325965aac919baf275084e0c8b1d19e57b56abe2 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 17:20:37 +0100 Subject: [PATCH 27/60] remove already-finished comment, remove never-reachable conditional step, and reorganize member variables --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index af0f67cd30..7d996a0528 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -100,6 +100,7 @@ public class TheCurseOfArrav extends BasicQuestHelper // 2 inv slots // Mid-quest item requirements + private ItemRequirement canopicJarFull; private ItemRequirement basePlans; private ItemRequirement baseKey; @@ -164,7 +165,6 @@ public class TheCurseOfArrav extends BasicQuestHelper private PuzzleWrapperStep rubbleMiner4; private PuzzleWrapperStep metalDoorSolver; private NpcStep returnToEliasWithBaseItems; - private ItemRequirement canopicJarFull; private NpcStep headToZemouregalsBaseAndTalkToElias; private ObjectStep enterZemouregalsBase; private DetailedQuestStep getToBackOfZemouregalsBase; @@ -298,7 +298,6 @@ public void setupSteps() startQuest.addDialogStep("Yes."); enterTomb = new ObjectStep(this, ObjectID.ENTRY_50201, new WorldPoint(3486, 3023, 0), "Enter the tomb south-west of Elias."); - // TODO: Ensure player can get hint to return var hasFirstKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY); getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton south of the entrance."); @@ -378,7 +377,6 @@ public void setupSteps() finishTilePuzzleAndGetCanopicJar = new ConditionalStep(this, enterTomb); finishTilePuzzleAndGetCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); - finishTilePuzzleAndGetCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), todo); finishTilePuzzleAndGetCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle), searchShelvesForUrn); finishTilePuzzleAndGetCanopicJar.addStep(insideTombSecondFloor, solveTilePuzzle); finishTilePuzzleAndGetCanopicJar.addStep(and(insideTomb, insideGolenArena), enterTombBasement); From dd7a23e2ef0b8712ecc8c5587ce54c595a1d5c46 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Tue, 12 Nov 2024 17:26:45 +0100 Subject: [PATCH 28/60] variable renames/rewording of canopic jar stuff --- .../thecurseofarrav/TheCurseOfArrav.java | 68 ++++++++++--------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 7d996a0528..8092383d9c 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -100,7 +100,9 @@ public class TheCurseOfArrav extends BasicQuestHelper // 2 inv slots // Mid-quest item requirements - private ItemRequirement canopicJarFull; + private ItemRequirement firstMastabaKey; + private ItemRequirement secondMastabaKey; + private ItemRequirement canopicJarFullForHeist; private ItemRequirement basePlans; private ItemRequirement baseKey; @@ -124,7 +126,7 @@ public class TheCurseOfArrav extends BasicQuestHelper private ObjectStep enterTomb; /// 6 + 8 - private ConditionalStep unsortedStep6; + private ConditionalStep unlockImposingDoors; private ObjectStep getFirstKey; private ObjectStep getSecondKey; private ObjectStep pullSouthLever; @@ -196,8 +198,8 @@ public Map loadSteps() steps.put(0, startQuest); steps.put(2, startQuest); steps.put(4, enterTomb); - steps.put(6, unsortedStep6); - steps.put(8, unsortedStep6); + steps.put(6, unlockImposingDoors); + steps.put(8, unlockImposingDoors); steps.put(10, fightGolemCond); steps.put(12, finishTilePuzzleAndGetCanopicJar); steps.put(14, finishTilePuzzleAndGetCanopicJar); @@ -287,6 +289,12 @@ protected void setupRequirements() arravCombatGear.setDisplayItemId(BankSlotIcons.getRangedCombatGear()); food = new ItemRequirement("Food", ItemCollections.GOOD_EATING_FOOD, -1); twoFreeInventorySlots = new FreeInventorySlotRequirement(2); + + // Mid-quest item requirements + firstMastabaKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY); + secondMastabaKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY_30309); + canopicJarFullForHeist = new ItemRequirement("Canopic jar (full)", ItemID.CANOPIC_JAR_FULL); + canopicJarFullForHeist.setTooltip("You can get a new one from Elias at the entrance of Zemouregal's base if you've lost it."); } public void setupSteps() @@ -299,13 +307,11 @@ public void setupSteps() enterTomb = new ObjectStep(this, ObjectID.ENTRY_50201, new WorldPoint(3486, 3023, 0), "Enter the tomb south-west of Elias."); - var hasFirstKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY); getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton south of the entrance."); - var hasSecondKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY_30309); getSecondKey = new ObjectStep(this, ObjectID.SKELETON_50353, new WorldPoint(3880, 4585, 0), "Get the second Mastaba key from the skeleton east of the entrance."); var bySouthLever = new Zone(new WorldPoint(3893, 4554, 0), new WorldPoint(3894, 4552, 0)); var bySouthLeverReq = new ZoneRequirement(bySouthLever); - pullSouthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4553, 0), "Pull the lever to the south-east.", hasSecondKey); + pullSouthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4553, 0), "Pull the lever to the south-east.", secondMastabaKey); pullSouthLever.addDialogStep("Yes."); var getToSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3891, 4554, 0), "Search the Odd markings to the south to get to the south lever. Search the markings again if you fail."); var needToInsertKeyInSouthLever = new VarbitRequirement(11482, 0); @@ -317,7 +323,7 @@ public void setupSteps() var byNorthLever = new Zone(new WorldPoint(3894, 4597, 0), new WorldPoint(3893, 4599, 0)); var byNorthLeverReq = new ZoneRequirement(byNorthLever); var getToNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3891, 4597, 0), "Search the Odd markings to the north to get to the north lever. Search the markings again if you fail."); - pullNorthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4598, 0), "Pull the lever to the north-east.", hasFirstKey); + pullNorthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4598, 0), "Pull the lever to the north-east.", firstMastabaKey); pullNorthLever.addDialogStep("Yes."); var needToInsertKeyInNorthLever = new VarbitRequirement(11481, 0); var needToFlipNorthLever = new VarbitRequirement(11481, 1); @@ -325,30 +331,30 @@ public void setupSteps() var leaveNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3892, 4597, 0), "Search the Odd markings next to you to get out."); pullNorthLever.addSubSteps(getToNorthLever, leaveNorthLever); - unsortedStep6 = new ConditionalStep(this, enterTomb); + unlockImposingDoors = new ConditionalStep(this, enterTomb); // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? - unsortedStep6.addStep(not(insideTomb), enterTomb); + unlockImposingDoors.addStep(not(insideTomb), enterTomb); // If the user has flipped the south lever & needs to get out of the little room - unsortedStep6.addStep(and(haveFlippedSouthLever, bySouthLeverReq), leaveSouthLever); + unlockImposingDoors.addStep(and(haveFlippedSouthLever, bySouthLeverReq), leaveSouthLever); // If the user has flipped the north lever & needs to get out of the little room - unsortedStep6.addStep(and(haveFlippedNorthLever, byNorthLeverReq), leaveNorthLever); + unlockImposingDoors.addStep(and(haveFlippedNorthLever, byNorthLeverReq), leaveNorthLever); // If the user has not already put the key in the south lever, and does not have the key - unsortedStep6.addStep(and(needToInsertKeyInSouthLever, not(hasSecondKey)), getSecondKey); + unlockImposingDoors.addStep(and(needToInsertKeyInSouthLever, not(secondMastabaKey)), getSecondKey); // If the user has not already put the key in the north lever, and does not have the key - unsortedStep6.addStep(and(needToInsertKeyInNorthLever, not(hasFirstKey)), getFirstKey); + unlockImposingDoors.addStep(and(needToInsertKeyInNorthLever, not(firstMastabaKey)), getFirstKey); // If the user has the key & stands by the south lever - unsortedStep6.addStep(and(needToFlipSouthLever, bySouthLeverReq), pullSouthLever); + unlockImposingDoors.addStep(and(needToFlipSouthLever, bySouthLeverReq), pullSouthLever); // If the user needs to flip the south lever, but is not inside the little room, get to the little room - unsortedStep6.addStep(not(haveFlippedSouthLever), getToSouthLever); + unlockImposingDoors.addStep(not(haveFlippedSouthLever), getToSouthLever); // If the user has the key & stands by the north lever - unsortedStep6.addStep(and(needToFlipNorthLever, byNorthLeverReq), pullNorthLever); + unlockImposingDoors.addStep(and(needToFlipNorthLever, byNorthLeverReq), pullNorthLever); // If the user needs to flip the north lever, but is not inside the little room, get to the little room - unsortedStep6.addStep(needToFlipNorthLever, getToNorthLever); + unlockImposingDoors.addStep(needToFlipNorthLever, getToNorthLever); // Once last lever was pulled, quest varbit changed from 6 to 8, then 8 to 10 at the same tick // This might have to do with which order you pulled the levers in @@ -384,8 +390,8 @@ public void setupSteps() var oilAndBerryFilledCanopicJar = new ItemRequirement("Canopic jar (oil and berries)", ItemID.CANOPIC_JAR_OIL_AND_BERRIES); - var combineJarWithDwellberries = new ItemStep(this, "Combine the Dwellberries with the Canopic jar.", oilFilledCanopicJar.highlighted(), dwellberries3.highlighted(), ringOfLife); - var combineJarWithRingOfLife = new ItemStep(this, "Combine the Dwellberries with the Ring of life.", oilAndBerryFilledCanopicJar.highlighted(), ringOfLife.highlighted()); + var combineJarWithDwellberries = new ItemStep(this, "Put the Dwellberries in the Canopic jar.", oilFilledCanopicJar.highlighted(), dwellberries3.highlighted(), ringOfLife); + var combineJarWithRingOfLife = new ItemStep(this, "Put the Ring of life in the Canopic jar.", oilAndBerryFilledCanopicJar.highlighted(), ringOfLife.highlighted()); unsortedStep16 = new ConditionalStep(this, todo); unsortedStep16.addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); @@ -505,29 +511,27 @@ public void setupSteps() // 40 -> 42 // 9658: 5 -> 6 - canopicJarFull = new ItemRequirement("Canopic jar (full)", ItemID.CANOPIC_JAR_FULL); - canopicJarFull.setTooltip("You can get a new one from Elias at the entrance of Zemouregal's base if you've lost it."); // this is at least true after the mining part // need 1 inventory slot free - headToZemouregalsBaseAndTalkToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3341, 3516, 0), "Head to Zemouregal's base east of Varrock's sawmill and talk to Elias.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFull, baseKey); // todo add teleport + headToZemouregalsBaseAndTalkToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3341, 3516, 0), "Head to Zemouregal's base east of Varrock's sawmill and talk to Elias.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); // todo add teleport headToZemouregalsBaseAndTalkToElias.addDialogStep("Ready when you are."); unsortedStep42 = new ConditionalStep(this, headToZemouregalsBaseAndTalkToElias); - enterZemouregalsBase = new ObjectStep(this, NullObjectID.NULL_50689, new WorldPoint(3343, 3515, 0), "Enter Zemouregal's base east of Varrock's sawmill.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFull, baseKey); // todo add teleport + enterZemouregalsBase = new ObjectStep(this, NullObjectID.NULL_50689, new WorldPoint(3343, 3515, 0), "Enter Zemouregal's base east of Varrock's sawmill.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); // todo add teleport getToBackOfZemouregalsBase = new DetailedQuestStep(this, "Make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage."); - var passZemouregalsBaseDoor1 = new ObjectStep(this, ObjectID.GATE_50149, new WorldPoint(3536, 4571, 0), "Open the gate and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFull, insulatedBoots); - var passZemouregalsBaseDoor2 = new ObjectStep(this, ObjectID.GATE_50150, new WorldPoint(3540, 4597, 0), "Open the gate and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFull, insulatedBoots); - var passZemouregalsBaseDoor3 = new ObjectStep(this, ObjectID.DOOR_50152, new WorldPoint(3576, 4604, 0), "Open the door and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFull, insulatedBoots); - var passZemouregalsBaseDoor4 = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3605, 4603, 0), "Open the gate and make your way to the back of Zemouregal's base.", canopicJarFull, insulatedBoots); + var passZemouregalsBaseDoor1 = new ObjectStep(this, ObjectID.GATE_50149, new WorldPoint(3536, 4571, 0), "Open the gate and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFullForHeist, insulatedBoots); + var passZemouregalsBaseDoor2 = new ObjectStep(this, ObjectID.GATE_50150, new WorldPoint(3540, 4597, 0), "Open the gate and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFullForHeist, insulatedBoots); + var passZemouregalsBaseDoor3 = new ObjectStep(this, ObjectID.DOOR_50152, new WorldPoint(3576, 4604, 0), "Open the door and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFullForHeist, insulatedBoots); + var passZemouregalsBaseDoor4 = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3605, 4603, 0), "Open the gate and make your way to the back of Zemouregal's base.", canopicJarFullForHeist, insulatedBoots); unsortedStep44 = new ConditionalStep(this, enterZemouregalsBase); unsortedStep44.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); unsortedStep44.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); unsortedStep44.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); - var enterZemouregalsBaseSewer = new ObjectStep(this, ObjectID.PIPE_50523, new WorldPoint(3609, 4598, 0), "Enter the sewers and make your way to the back of Zemouregal's base.", canopicJarFull, insulatedBoots.highlighted().equipped()); + var enterZemouregalsBaseSewer = new ObjectStep(this, ObjectID.PIPE_50523, new WorldPoint(3609, 4598, 0), "Enter the sewers and make your way to the back of Zemouregal's base.", canopicJarFullForHeist, insulatedBoots.highlighted().equipped()); - var exitZemouregalsBaseSewer = new ObjectStep(this, ObjectID.PIPE_50525, new WorldPoint(3741, 4573, 0), "Head south to exit the sewers and make your way to the back of Zemouregal's base.", canopicJarFull, insulatedBoots.highlighted().equipped()); + var exitZemouregalsBaseSewer = new ObjectStep(this, ObjectID.PIPE_50525, new WorldPoint(3741, 4573, 0), "Head south to exit the sewers and make your way to the back of Zemouregal's base.", canopicJarFullForHeist, insulatedBoots.highlighted().equipped()); getToBackOfZemouregalsBase.addSubSteps(passZemouregalsBaseDoor1, passZemouregalsBaseDoor2, passZemouregalsBaseDoor3, passZemouregalsBaseDoor4, enterZemouregalsBaseSewer, exitZemouregalsBaseSewer); @@ -573,7 +577,7 @@ public void setupSteps() unsortedStep48.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); unsortedStep48.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); - openMetalDoors = new ObjectStep(this, ObjectID.METAL_DOORS, new WorldPoint(3612, 4582, 0), "Step through through the metal doors.", canopicJarFull, anyGrappleableCrossbow, mithrilGrapple); + openMetalDoors = new ObjectStep(this, ObjectID.METAL_DOORS, new WorldPoint(3612, 4582, 0), "Step through through the metal doors.", canopicJarFullForHeist, anyGrappleableCrossbow, mithrilGrapple); var inGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3612, 4587, 0), new WorldPoint(3625, 4579, 0))); grappleAcross = new ObjectStep(this, ObjectID.PIPE_50542, new WorldPoint(3615, 4582, 0), "Grapple across the pipe", anyGrappleableCrossbow.highlighted().equipped(), mithrilGrapple.highlighted().equipped()); @@ -780,7 +784,7 @@ public List getPanels() mithrilGrapple, arravCombatGear, insulatedBoots, - canopicJarFull + canopicJarFullForHeist ), List.of( // Recommended new FreeInventorySlotRequirement(1), From a40a9e1a9140c8ac8d7b81babee9701386c71083 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 17:37:38 +0100 Subject: [PATCH 29/60] polish --- build.gradle | 1 + .../thecurseofarrav/MetalDoorSolver.java | 171 +++++++++- .../thecurseofarrav/TheCurseOfArrav.java | 189 ++++++----- .../thecurseofarrav/TilePuzzleSolver.java | 2 +- .../rubblesolvers/RubbleSolver.java | 57 +--- .../rubblesolvers/RubbleSolverFour.java | 48 +-- .../rubblesolvers/RubbleSolverThree.java | 14 +- .../rubblesolvers/RubbleSolverTwo.java | 36 +- .../rubblesolvers/RubbleType.java | 2 +- .../com/questhelper/panel/QuestStepPanel.java | 2 +- .../questhelpers/BasicQuestHelper.java | 19 +- .../questhelper/steps/DetailedQuestStep.java | 19 +- .../com/questhelper/steps/ObjectStep.java | 5 + .../java/com/questhelper/steps/QuestStep.java | 8 +- .../com/questhelper/steps/WidgetStep.java | 13 + src/test/java/com/questhelper/MockedTest.java | 27 ++ .../thecurseofarrav/KeysAndLeversTest.java | 313 ++++++++++++++++++ .../thecurseofarrav/MetalDoorSolverTest.java | 77 +++++ .../questhelpers/QuestHelperTest.java | 58 ++++ 19 files changed, 865 insertions(+), 196 deletions(-) create mode 100644 src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java diff --git a/build.gradle b/build.gradle index a56ad58040..62c4fb9a7d 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ dependencies { testImplementation group: "org.junit.jupiter", name: "junit-jupiter-engine", version: junitVersion testImplementation group: 'org.mockito', name:'mockito-core', version: "4.11.0" // runelite uses 3.1.0 + testImplementation group: 'org.mockito', name:'mockito-inline', version: "4.11.0" testImplementation(group: 'com.google.inject.extensions', name:'guice-testlib', version: "4.1.0") { exclude group: 'com.google.inject', module: 'guice' // already provided by runelite } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java index 782bbfd11b..052f020ee4 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java @@ -1,5 +1,8 @@ package com.questhelper.helpers.quests.thecurseofarrav; +import com.questhelper.QuestHelperPlugin; +import com.questhelper.requirements.ManualRequirement; +import com.questhelper.requirements.Requirement; import com.questhelper.requirements.item.ItemRequirement; import com.questhelper.requirements.widget.WidgetModelRequirement; import com.questhelper.requirements.widget.WidgetPresenceRequirement; @@ -10,8 +13,12 @@ import com.questhelper.steps.ItemStep; import com.questhelper.steps.ObjectStep; import com.questhelper.steps.QuestStep; +import java.awt.*; +import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.regex.Pattern; +import java.util.stream.IntStream; import javax.inject.Inject; import com.questhelper.steps.WidgetStep; import com.questhelper.steps.widget.WidgetDetails; @@ -23,6 +30,7 @@ import net.runelite.api.coords.WorldPoint; import net.runelite.api.events.GameTick; import net.runelite.client.eventbus.Subscribe; +import net.runelite.client.ui.FontManager; import static com.questhelper.requirements.util.LogicHelper.and; import static com.questhelper.requirements.util.LogicHelper.not; @@ -132,6 +140,10 @@ public class MetalDoorSolver extends DetailedOwnerStep private WidgetModelRequirement inputThirdCorrect; private WidgetModelRequirement inputFourthCorrect; + private int distanceUp = 69; + private int distanceDown = 69; + private ManualRequirement shouldClickDownInteadOfUp; + public MetalDoorSolver(TheCurseOfArrav theCurseOfArrav) { super(theCurseOfArrav, "Solve the Metal door puzzle by following the instructions in the overlay."); @@ -212,11 +224,105 @@ public static int[] calculate(String code) }; } + public static int calculateDistanceUp(int currentNumber, int targetNumber) + { + if (currentNumber == targetNumber) + { + return 0; + } + + if (currentNumber > targetNumber) + { + return targetNumber - currentNumber + 10; + } + else + { + return targetNumber - currentNumber; + } + } + + public static int calculateDistanceDown(int currentNumber, int targetNumber) + { + if (currentNumber == targetNumber) + { + return 0; + } + + if (currentNumber < targetNumber) + { + return currentNumber - targetNumber + 10; + } + else + { + return currentNumber - targetNumber; + } + } + @Subscribe public void onGameTick(GameTick event) { if (this.code != null) { + var currentNumberWidget = client.getWidget(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_CURRENT_CHILD_ID); + if (currentNumberWidget != null) + { + var currentNumberModel = currentNumberWidget.getModelId(); + var currentNumber = IntStream.range(0, PUZZLE_NUMBERS.length) + .filter(i -> PUZZLE_NUMBERS[i] == currentNumberModel) + .findFirst() + .orElse(-1); + + var input1 = client.getWidget(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_1_CHILD_ID); + var input2 = client.getWidget(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_2_CHILD_ID); + var input3 = client.getWidget(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_3_CHILD_ID); + var input4 = client.getWidget(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_4_CHILD_ID); + + if (input1 == null || input2 == null || input3 == null || input4 == null) + { + // something very wrong + this.distanceUp = -1; + this.distanceDown = -1; + return; + } + + var input1Text = input1.getText(); + var input2Text = input2.getText(); + var input3Text = input3.getText(); + var input4Text = input4.getText(); + + var targetNumber = -1; + + if (Objects.equals(input1Text, "-") || Integer.parseInt(input1.getText()) != this.doorPassword[0]) + { + targetNumber = this.doorPassword[0]; + } + else if (Objects.equals(input2Text, "-") || Integer.parseInt(input2.getText()) != this.doorPassword[1]) + { + targetNumber = this.doorPassword[1]; + } + else if (Objects.equals(input3Text, "-") || Integer.parseInt(input3.getText()) != this.doorPassword[2]) + { + targetNumber = this.doorPassword[2]; + } + else if (Objects.equals(input4Text, "-") || Integer.parseInt(input4.getText()) != this.doorPassword[3]) + { + targetNumber = this.doorPassword[3]; + } + + if (currentNumber == -1 || targetNumber == -1) + { + // something very wrong + this.distanceUp = -1; + this.distanceDown = -1; + } + else + { + this.distanceUp = calculateDistanceUp(currentNumber, targetNumber); + this.distanceDown = calculateDistanceDown(currentNumber, targetNumber); + + this.shouldClickDownInteadOfUp.setShouldPass(this.distanceDown < this.distanceUp); + } + } return; } @@ -231,7 +337,8 @@ public void onGameTick(GameTick event) { this.code = matcher.group(1); this.doorPassword = calculate(this.code); - if (this.doorPassword != null) { + if (this.doorPassword != null) + { firstNumberCorrect.setText(String.valueOf(this.doorPassword[0])); inputFirstCorrect.setId(PUZZLE_NUMBERS[this.doorPassword[0]]); secondNumberCorrect.setText(String.valueOf(this.doorPassword[1])); @@ -243,10 +350,7 @@ public void onGameTick(GameTick event) } updateSteps(); } - } - private void updatePuzzleSteps() - { } @Override @@ -258,11 +362,11 @@ public void startUp() @Override protected void setupSteps() { - var decoderStrips = new ItemRequirement("Decoder strips", ItemID.DECODER_STRIPS); + this.shouldClickDownInteadOfUp = new ManualRequirement(); var codeKey = new ItemRequirement("Code key", ItemID.CODE_KEY); - readCode = new ItemStep(getQuestHelper(), "Read the Code key in your inventory.", codeKey.highlighted(), decoderStrips); // TODO + readCode = new ItemStep(getQuestHelper(), "Read the Code key in your inventory.", codeKey.highlighted()); - clickMetalDoors = new ObjectStep(getQuestHelper(), ObjectID.METAL_DOORS, new WorldPoint(3612, 4582, 0), "Open the metal doors and solve the puzzle.", codeKey, decoderStrips); + clickMetalDoors = new ObjectStep(getQuestHelper(), ObjectID.METAL_DOORS, new WorldPoint(3612, 4582, 0), "Open the metal doors and solve the puzzle.", codeKey); var puzzleWidgetOpen = new WidgetPresenceRequirement(PUZZLE_GROUP_ID, PUZZLE_BTN_UP_CHILD_ID); @@ -283,20 +387,60 @@ protected void setupSteps() inputFourthCorrect = new WidgetModelRequirement(PUZZLE_GROUP_ID, PUZZLE_PASSWORD_CURRENT_CHILD_ID, -1); var clickUp = new WidgetStep(getQuestHelper(), "Click the Up button.", new WidgetDetails(PUZZLE_GROUP_ID, PUZZLE_BTN_UP_CHILD_ID)); + clickUp.addExtraWidgetOverlayHintFunction(this::drawDistanceUp); + var clickDown = new WidgetStep(getQuestHelper(), "Click the Down button.", new WidgetDetails(PUZZLE_GROUP_ID, PUZZLE_BTN_DOWN_CHILD_ID)); + clickDown.addExtraWidgetOverlayHintFunction(this::drawDistanceDown); var submitNumber = new WidgetStep(getQuestHelper(), "Click the Enter button.", new WidgetDetails(PUZZLE_GROUP_ID, PUZZLE_ENTER_CHILD_ID)); var pressBack = new WidgetStep(getQuestHelper(), "Click the Back button.", new WidgetDetails(PUZZLE_GROUP_ID, PUZZLE_BACK_CHILD_ID)); + var clickUpOrDown = new ConditionalStep(getQuestHelper(), clickUp); + clickUpOrDown.addStep(shouldClickDownInteadOfUp, clickDown); + solvePuzzle = new ConditionalStep(getQuestHelper(), pressBack); solvePuzzle.addStep(not(puzzleWidgetOpen), clickMetalDoors); solvePuzzle.addStep(and(fourthNumberCorrect, thirdNumberCorrect, secondNumberCorrect, firstNumberCorrect), submitNumber); solvePuzzle.addStep(and(fourthNumberEmpty, inputFourthCorrect, firstNumberCorrect, secondNumberCorrect, thirdNumberCorrect), submitNumber); - solvePuzzle.addStep(and(fourthNumberEmpty, firstNumberCorrect, secondNumberCorrect, thirdNumberCorrect), clickUp); + solvePuzzle.addStep(and(fourthNumberEmpty, firstNumberCorrect, secondNumberCorrect, thirdNumberCorrect), clickUpOrDown); solvePuzzle.addStep(and(thirdNumberEmpty, inputThirdCorrect, firstNumberCorrect, secondNumberCorrect), submitNumber); - solvePuzzle.addStep(and(thirdNumberEmpty, firstNumberCorrect, secondNumberCorrect), clickUp); + solvePuzzle.addStep(and(thirdNumberEmpty, firstNumberCorrect, secondNumberCorrect), clickUpOrDown); solvePuzzle.addStep(and(secondNumberEmpty, inputSecondCorrect, firstNumberCorrect), submitNumber); - solvePuzzle.addStep(and(secondNumberEmpty, firstNumberCorrect), clickUp); + solvePuzzle.addStep(and(secondNumberEmpty, firstNumberCorrect), clickUpOrDown); solvePuzzle.addStep(and(firstNumberEmpty, inputFirstCorrect), submitNumber); - solvePuzzle.addStep(firstNumberEmpty, clickUp); + solvePuzzle.addStep(firstNumberEmpty, clickUpOrDown); + } + + public void drawDistanceUp(Graphics2D graphics, QuestHelperPlugin plugin) + { + super.makeWidgetOverlayHint(graphics, plugin); + + var arrow = client.getWidget(PUZZLE_GROUP_ID, PUZZLE_BTN_DOWN_CHILD_ID); + if (arrow == null) + { + return; + } + + int widgetX = arrow.getCanvasLocation().getX() + (arrow.getWidth() / 2) - 30; + int widgetY = arrow.getCanvasLocation().getY() + (arrow.getHeight() / 2) + 4; + Font font = FontManager.getRunescapeFont().deriveFont(Font.BOLD, 16); + graphics.setFont(font); + graphics.drawString(Integer.toString(this.distanceUp), widgetX, widgetY); + } + + public void drawDistanceDown(Graphics2D graphics, QuestHelperPlugin plugin) + { + super.makeWidgetOverlayHint(graphics, plugin); + + var arrow = client.getWidget(PUZZLE_GROUP_ID, PUZZLE_BTN_DOWN_CHILD_ID); + if (arrow == null) + { + return; + } + + int widgetX = arrow.getCanvasLocation().getX() + (arrow.getWidth() / 2) - 30; + int widgetY = arrow.getCanvasLocation().getY() + (arrow.getHeight() / 2) + 4; + Font font = FontManager.getRunescapeFont().deriveFont(Font.BOLD, 16); + graphics.setFont(font); + graphics.drawString(Integer.toString(this.distanceDown), widgetX, widgetY); } protected void updateSteps() @@ -307,7 +451,8 @@ protected void updateSteps() return; } - if (this.doorPassword == null) { + if (this.doorPassword == null) + { startUpStep(solvePuzzleFallback); return; } @@ -323,6 +468,6 @@ public List getSteps() this.clickMetalDoors, this.solvePuzzleFallback, this.solvePuzzle - ); + ); } } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 8092383d9c..fb7fe31440 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -35,14 +35,17 @@ import com.questhelper.questinfo.QuestHelperQuest; import com.questhelper.requirements.Requirement; import com.questhelper.requirements.item.ItemRequirement; +import com.questhelper.requirements.item.ItemRequirements; import com.questhelper.requirements.item.TeleportItemRequirement; import com.questhelper.requirements.player.CombatLevelRequirement; import com.questhelper.requirements.player.FreeInventorySlotRequirement; import com.questhelper.requirements.player.SkillRequirement; import com.questhelper.requirements.quest.QuestRequirement; import static com.questhelper.requirements.util.LogicHelper.and; +import static com.questhelper.requirements.util.LogicHelper.nor; import static com.questhelper.requirements.util.LogicHelper.not; import static com.questhelper.requirements.util.LogicHelper.or; +import com.questhelper.requirements.util.Operation; import com.questhelper.requirements.var.VarbitRequirement; import com.questhelper.requirements.zone.Zone; import com.questhelper.requirements.zone.ZoneRequirement; @@ -79,16 +82,16 @@ public class TheCurseOfArrav extends BasicQuestHelper // Required items private ItemRequirement dwellberries3; private ItemRequirement ringOfLife; - private ItemRequirement anyPickaxe; + public ItemRequirement anyPickaxe; private ItemRequirement anyGrappleableCrossbow; private ItemRequirement mithrilGrapple; private ItemRequirement insulatedBoots; // Recommended items private TeleportItemRequirement fairyRingDLQ; + private TeleportItemRequirement lumberyardTeleport; // trollheim teleport / ghommal's hilt // antivenom - // lumberyard teleport // melee (crush) combat gear for golem // ranged combat gear for arrav private ItemRequirement golemCombatGear; @@ -120,22 +123,22 @@ public class TheCurseOfArrav extends BasicQuestHelper // Steps /// 0 + 2 - private NpcStep startQuest; + NpcStep startQuest; /// 4 - private ObjectStep enterTomb; + ObjectStep enterTomb; /// 6 + 8 - private ConditionalStep unlockImposingDoors; - private ObjectStep getFirstKey; - private ObjectStep getSecondKey; - private ObjectStep pullSouthLever; - private ObjectStep pullNorthLever; + ConditionalStep unlockImposingDoors; + ObjectStep getFirstKey; + ObjectStep getSecondKey; + ObjectStep pullSouthLever; + ObjectStep pullNorthLever; /// 10 - private ConditionalStep fightGolemCond; - private ObjectStep enterGolemArena; - private NpcStep fightGolemGuard; + ConditionalStep fightGolemCond; + ObjectStep enterGolemArena; + NpcStep fightGolemGuard; /// 12 + 14 private ConditionalStep finishTilePuzzleAndGetCanopicJar; @@ -185,6 +188,21 @@ public class TheCurseOfArrav extends BasicQuestHelper private ObjectStep enterBossRoom; private ObjectStep grappleAcross; private ObjectStep openMetalDoors; + ObjectStep getToSouthLever; + ObjectStep leaveSouthLever; + ObjectStep getToNorthLever; + ObjectStep leaveNorthLever; + ItemStep combineJarWithDwellberries; + ItemStep combineJarWithRingOfLife; + NpcStep returnToElias; + ObjectStep headToTrollheim; + ObjectStep continueThroughTrollheimCave; + ObjectStep enterTrollweissCave; + ItemRequirement canopicJarFull; + ObjectStep climbUpstairsAndTalkToArrav; + NpcStep talkToArrav; + ObjectStep goToNextRoom; + ObjectStep searchTapestry; @Override @@ -232,7 +250,7 @@ public Map loadSteps() @Override protected void setupZones() { - insideTomb = new ZoneRequirement(new Zone(new WorldPoint(3842, 4603, 0), new WorldPoint(3900, 4547, 0))); + insideTomb = new ZoneRequirement(new Zone(new WorldPoint(3842, 4547, 0), new WorldPoint(3900, 4603, 0))); insideTombSecondFloor = new ZoneRequirement( new Zone(new WorldPoint(3719, 4674, 0), new WorldPoint(3770, 4732, 0)), new Zone(new WorldPoint(3845, 4674, 0), new WorldPoint(3900, 4732, 0)) @@ -279,6 +297,7 @@ protected void setupRequirements() // Recommended items fairyRingDLQ = new TeleportItemRequirement("Fairy Ring [DLQ]", ItemCollections.FAIRY_STAFF); + lumberyardTeleport = new TeleportItemRequirement("Lumberyard teleport", ItemID.LUMBERYARD_TELEPORT); staminaPotion = new ItemRequirement("Stamina potion", ItemCollections.STAMINA_POTIONS, 1); prayerPotion = new ItemRequirement("Prayer potion", ItemCollections.PRAYER_POTIONS, 1); golemCombatGear = new ItemRequirement("Crush or ranged combat gear to fight the Golem guard", -1, -1); @@ -293,6 +312,7 @@ protected void setupRequirements() // Mid-quest item requirements firstMastabaKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY); secondMastabaKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY_30309); + canopicJarFull = new ItemRequirement("Canopic jar (full)", ItemID.CANOPIC_JAR_FULL); canopicJarFullForHeist = new ItemRequirement("Canopic jar (full)", ItemID.CANOPIC_JAR_FULL); canopicJarFullForHeist.setTooltip("You can get a new one from Elias at the entrance of Zemouregal's base if you've lost it."); } @@ -306,57 +326,65 @@ public void setupSteps() startQuest.addDialogStep("Yes."); enterTomb = new ObjectStep(this, ObjectID.ENTRY_50201, new WorldPoint(3486, 3023, 0), "Enter the tomb south-west of Elias."); + // TODO: Add item requirements to enterTomb step + // - 2 free inventory slots - getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton south of the entrance."); + var anyMastabaKey = new ItemRequirement("Mastaba Key", List.of(ItemID.MASTABA_KEY, ItemID.MASTABA_KEY_30309)); + + getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton in the cave south of the entrance."); getSecondKey = new ObjectStep(this, ObjectID.SKELETON_50353, new WorldPoint(3880, 4585, 0), "Get the second Mastaba key from the skeleton east of the entrance."); var bySouthLever = new Zone(new WorldPoint(3893, 4554, 0), new WorldPoint(3894, 4552, 0)); var bySouthLeverReq = new ZoneRequirement(bySouthLever); - pullSouthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4553, 0), "Pull the lever to the south-east.", secondMastabaKey); + pullSouthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4553, 0), "Pull the lever to the south-east."); pullSouthLever.addDialogStep("Yes."); - var getToSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3891, 4554, 0), "Search the Odd markings to the south to get to the south lever. Search the markings again if you fail."); + getToSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3891, 4554, 0), "Search the Odd markings to the south to get to the south lever. Search the markings again if you fail."); var needToInsertKeyInSouthLever = new VarbitRequirement(11482, 0); var needToFlipSouthLever = new VarbitRequirement(11482, 1); var haveFlippedSouthLever = new VarbitRequirement(11482, 2); - var leaveSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3892, 4554, 0), "Search the Odd markings next to you to get out."); + leaveSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3892, 4554, 0), "Search the Odd markings next to you to get out."); pullSouthLever.addSubSteps(getToSouthLever, leaveSouthLever); var byNorthLever = new Zone(new WorldPoint(3894, 4597, 0), new WorldPoint(3893, 4599, 0)); var byNorthLeverReq = new ZoneRequirement(byNorthLever); - var getToNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3891, 4597, 0), "Search the Odd markings to the north to get to the north lever. Search the markings again if you fail."); - pullNorthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4598, 0), "Pull the lever to the north-east.", firstMastabaKey); + getToNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3891, 4597, 0), "Search the Odd markings to the north to get to the north lever. Search the markings again if you fail."); + pullNorthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4598, 0), "Pull the lever to the north-east."); pullNorthLever.addDialogStep("Yes."); var needToInsertKeyInNorthLever = new VarbitRequirement(11481, 0); var needToFlipNorthLever = new VarbitRequirement(11481, 1); var haveFlippedNorthLever = new VarbitRequirement(11481, 2); - var leaveNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3892, 4597, 0), "Search the Odd markings next to you to get out."); + leaveNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3892, 4597, 0), "Search the Odd markings next to you to get out."); pullNorthLever.addSubSteps(getToNorthLever, leaveNorthLever); - unlockImposingDoors = new ConditionalStep(this, enterTomb); + // var anyMastabaKey = new ItemRequirements(firstMastabaKey, secondMastabaKey); + var bothMastabaKeys = and(firstMastabaKey, secondMastabaKey); + firstMastabaKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY); - // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? - unlockImposingDoors.addStep(not(insideTomb), enterTomb); + // ADDING THIS CONDITION TO HIDE BREAKS ALL ITEMREQUIREMENT CHECKS HERE?? + // firstMastabaKey.setConditionToHide(not(needToInsertKeyInSouthLever)); + // secondMastabaKey.setConditionToHide(not(needToInsertKeyInNorthLever)); - // If the user has flipped the south lever & needs to get out of the little room + // This step is complicated because you can use either key for either lever (I think). This could use some testing where the user does not follow instructions and: + // 1. Gets south key, pulls south lever, then what? + // 2. Gets north key, pulls south lever, then what? + // 3. Gets south key, pulls north lever, then what? + // 4. Gets north key, pulls north lever, then what? + // 5. Gets both keys, pulls north lever, then what? + unlockImposingDoors = new ConditionalStep(this, enterTomb); + unlockImposingDoors.addStep(not(insideTomb), enterTomb); unlockImposingDoors.addStep(and(haveFlippedSouthLever, bySouthLeverReq), leaveSouthLever); - // If the user has flipped the north lever & needs to get out of the little room unlockImposingDoors.addStep(and(haveFlippedNorthLever, byNorthLeverReq), leaveNorthLever); - - // If the user has not already put the key in the south lever, and does not have the key - unlockImposingDoors.addStep(and(needToInsertKeyInSouthLever, not(secondMastabaKey)), getSecondKey); - // If the user has not already put the key in the north lever, and does not have the key - unlockImposingDoors.addStep(and(needToInsertKeyInNorthLever, not(firstMastabaKey)), getFirstKey); - - // If the user has the key & stands by the south lever unlockImposingDoors.addStep(and(needToFlipSouthLever, bySouthLeverReq), pullSouthLever); - // If the user needs to flip the south lever, but is not inside the little room, get to the little room - unlockImposingDoors.addStep(not(haveFlippedSouthLever), getToSouthLever); - - // If the user has the key & stands by the north lever unlockImposingDoors.addStep(and(needToFlipNorthLever, byNorthLeverReq), pullNorthLever); - // If the user needs to flip the north lever, but is not inside the little room, get to the little room - unlockImposingDoors.addStep(needToFlipNorthLever, getToNorthLever); - - // Once last lever was pulled, quest varbit changed from 6 to 8, then 8 to 10 at the same tick + unlockImposingDoors.addStep(and(not(bySouthLeverReq), bothMastabaKeys, needToInsertKeyInSouthLever), getToSouthLever); + unlockImposingDoors.addStep(and(not(bySouthLeverReq), needToFlipSouthLever), getToSouthLever); + unlockImposingDoors.addStep(and(bySouthLeverReq, bothMastabaKeys, needToInsertKeyInSouthLever), pullSouthLever); + unlockImposingDoors.addStep(and(not(byNorthLeverReq), haveFlippedSouthLever, anyMastabaKey, needToInsertKeyInNorthLever), getToNorthLever); + unlockImposingDoors.addStep(and(not(byNorthLeverReq), haveFlippedSouthLever, needToFlipNorthLever), getToNorthLever); + unlockImposingDoors.addStep(and(haveFlippedSouthLever, anyMastabaKey, needToInsertKeyInNorthLever, byNorthLeverReq), pullNorthLever); + unlockImposingDoors.addStep(and(or(needToInsertKeyInNorthLever, needToInsertKeyInSouthLever), not(firstMastabaKey)), getFirstKey); + unlockImposingDoors.addStep(and(or(needToInsertKeyInNorthLever, needToInsertKeyInSouthLever), not(secondMastabaKey)), getSecondKey); + + // Once the north lever is pulled, quest varbit changed from 6 to 8, then 8 to 10 at the same tick // This might have to do with which order you pulled the levers in var golemArenaZone = new Zone(new WorldPoint(3856, 4592, 0), new WorldPoint(3884, 4599, 0)); @@ -390,8 +418,8 @@ public void setupSteps() var oilAndBerryFilledCanopicJar = new ItemRequirement("Canopic jar (oil and berries)", ItemID.CANOPIC_JAR_OIL_AND_BERRIES); - var combineJarWithDwellberries = new ItemStep(this, "Put the Dwellberries in the Canopic jar.", oilFilledCanopicJar.highlighted(), dwellberries3.highlighted(), ringOfLife); - var combineJarWithRingOfLife = new ItemStep(this, "Put the Ring of life in the Canopic jar.", oilAndBerryFilledCanopicJar.highlighted(), ringOfLife.highlighted()); + combineJarWithDwellberries = new ItemStep(this, "Put the Dwellberries in the Canopic jar.", oilFilledCanopicJar.highlighted(), dwellberries3.highlighted(), ringOfLife); + combineJarWithRingOfLife = new ItemStep(this, "Put the Ring of life in the Canopic jar.", oilAndBerryFilledCanopicJar.highlighted(), ringOfLife.highlighted()); unsortedStep16 = new ConditionalStep(this, todo); unsortedStep16.addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); @@ -402,7 +430,7 @@ public void setupSteps() unsortedStep16.addStep(and(insideTomb), enterGolemArenaWithoutFight); - var returnToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); + returnToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring.", canopicJarFull); returnToElias.addTeleport(fairyRingDLQ); var returnToEliasByWalking = new ObjectStep(this, ObjectID.STAIRS_55786, new WorldPoint(3894, 4714, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring."); returnToEliasByWalking.addTeleport(fairyRingDLQ); @@ -421,26 +449,32 @@ public void setupSteps() var trollheimTeleport = new TeleportItemRequirement("Trollheim Teleport", ItemID.TROLLHEIM_TELEPORT); trollheimTeleport.addAlternates(ItemCollections.GHOMMALS_HILT); - var headToTrollheim = new ObjectStep(this, ObjectID.CAVE_ENTRANCE_5007, new WorldPoint(2821, 3744, 0), "Enter the cave next to Trollheim. You can use a Trollheim teleport tablet or the GWD Ghommal's Hilt teleport to get close."); + headToTrollheim = new ObjectStep(this, ObjectID.CAVE_ENTRANCE_5007, new WorldPoint(2821, 3744, 0), "Enter the cave next to Trollheim. You can use a Trollheim teleport tablet or the GWD Ghommal's Hilt teleport to get close.", anyPickaxe); headToTrollheim.addTeleport(trollheimTeleport); var trollheimCave = new Zone(11167); var inTrollheimCave = new ZoneRequirement(trollheimCave); - var continueThroughTrollheimCave = new ObjectStep(this, ObjectID.CREVASSE, new WorldPoint(2772, 10233, 0), "Continue through the Trollheim cave, exiting at the Crevasse to the north-west. Use Protect from Melee to avoid taking damage from the Ice Trolls."); + continueThroughTrollheimCave = new ObjectStep(this, ObjectID.CREVASSE, new WorldPoint(2772, 10233, 0), "Continue through the Trollheim cave, exiting at the Crevasse to the north-west. Use Protect from Melee to avoid taking damage from the Ice Trolls.", anyPickaxe); var trollweissMountain = new Zone(11068); var onTrollweissMountain = new ZoneRequirement(trollweissMountain); - var enterTrollweissCave = new ObjectStep(this, ObjectID.CAVE_55779, new WorldPoint(2809, 3861, 0), "Enter the Trollweiss cave to the east."); + enterTrollweissCave = new ObjectStep(this, ObjectID.CAVE_55779, new WorldPoint(2809, 3861, 0), "Enter the Trollweiss cave to the east.", anyPickaxe); var trollweissCave1 = new Zone(11168); var inTrollweissCave = new ZoneRequirement(trollweissCave1); - rubbleMiner1 = new RubbleSolverOne(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); - rubbleMiner2 = new RubbleSolverTwo(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); - rubbleMiner3 = new RubbleSolverThree(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); - rubbleMiner4 = new RubbleSolverFour(this).puzzleWrapStep("Mine the rubble and make your way through the cave."); + var rubbleMiner1Real = new RubbleSolverOne(this); + var rubbleMiner2Real = new RubbleSolverTwo(this); + var rubbleMiner3Real = new RubbleSolverThree(this); + var rubbleMiner4Real = new RubbleSolverFour(this); + + rubbleMiner1 = rubbleMiner1Real.puzzleWrapStep("Mine the rubble and make your way through the cave."); + rubbleMiner2 = rubbleMiner2Real.puzzleWrapStep("Mine the rubble and make your way through the cave."); + rubbleMiner3 = rubbleMiner3Real.puzzleWrapStep("Mine the rubble and make your way through the cave."); + rubbleMiner4 = rubbleMiner4Real.puzzleWrapStep("Mine the rubble and make your way through the cave."); + + rubbleMiner1Real.addSubSteps(rubbleMiner2, rubbleMiner3, rubbleMiner4); - rubbleMiner1.addSubSteps(rubbleMiner2, rubbleMiner3, rubbleMiner4); unsortedStep20 = new ConditionalStep(this, headToTrollheim); unsortedStep20.addStep(inTrollweissCave, rubbleMiner1); @@ -463,7 +497,7 @@ public void setupSteps() unsortedStep28.addStep(inTrollheimCave, continueThroughTrollheimCave); - var climbUpstairsAndTalkToArrav = new ObjectStep(this, ObjectID.STAIRS_50508, new WorldPoint(2811, 10267, 0), "Climb up the stairs in the room with the red tile floor and talk to Arrav."); + climbUpstairsAndTalkToArrav = new ObjectStep(this, ObjectID.STAIRS_50508, new WorldPoint(2811, 10267, 0), "Climb up the stairs in the room with the red tile floor and talk to Arrav."); unsortedStep30 = new ConditionalStep(this, headToTrollheim); unsortedStep30.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); unsortedStep30.addStep(onTrollweissMountain, enterTrollweissCave); @@ -471,7 +505,7 @@ public void setupSteps() var arravHouseFirstRoom = new Zone(new WorldPoint(2848, 3868, 0), new WorldPoint(2858, 3873, 0)); var inArravHouseFirstRoom = new ZoneRequirement(arravHouseFirstRoom); - var talkToArrav = new NpcStep(this, NpcID.ARRAV_14129, new WorldPoint(2856, 3871, 0), "Talk to Arrav."); + talkToArrav = new NpcStep(this, NpcID.ARRAV_14129, new WorldPoint(2856, 3871, 0), "Talk to Arrav."); unsortedStep32 = new ConditionalStep(this, headToTrollheim); unsortedStep32.addStep(inArravHouseFirstRoom, talkToArrav); @@ -482,8 +516,8 @@ public void setupSteps() var arravHouseSecondRoom = new Zone(new WorldPoint(2863, 3865, 0), new WorldPoint(2859, 3873, 0)); var inArravHouseSecondRoom = new ZoneRequirement(arravHouseSecondRoom); - var goToNextRoom = new ObjectStep(this, ObjectID.DOOR_50514, new WorldPoint(2859, 3870, 0), "Enter the room to your east and search the tapestry for ?."); - var searchTapestry = new ObjectStep(this, ObjectID.TAPESTRY_50516, new WorldPoint(2861, 3865, 0), "Search the tapestry in the south of the room."); + goToNextRoom = new ObjectStep(this, ObjectID.DOOR_50514, new WorldPoint(2859, 3870, 0), "Enter the room to your east and search the tapestry for something to help you with your heist."); + searchTapestry = new ObjectStep(this, ObjectID.TAPESTRY_50516, new WorldPoint(2861, 3865, 0), "Search the tapestry in the south of the room."); unsortedStep34 = new ConditionalStep(this, headToTrollheim); unsortedStep34.addStep(inArravHouseSecondRoom, searchTapestry); unsortedStep34.addStep(inArravHouseFirstRoom, goToNextRoom); @@ -514,6 +548,7 @@ public void setupSteps() // need 1 inventory slot free headToZemouregalsBaseAndTalkToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3341, 3516, 0), "Head to Zemouregal's base east of Varrock's sawmill and talk to Elias.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); // todo add teleport headToZemouregalsBaseAndTalkToElias.addDialogStep("Ready when you are."); + headToZemouregalsBaseAndTalkToElias.addTeleport(lumberyardTeleport); unsortedStep42 = new ConditionalStep(this, headToZemouregalsBaseAndTalkToElias); enterZemouregalsBase = new ObjectStep(this, NullObjectID.NULL_50689, new WorldPoint(3343, 3515, 0), "Enter Zemouregal's base east of Varrock's sawmill.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); // todo add teleport @@ -563,13 +598,10 @@ public void setupSteps() // also used for 50 unsortedStep48 = new ConditionalStep(this, enterZemouregalsBase); - // TODO: DECODER STRIPS ARE NOT NECESSARY. REMOVE THEM :) - unsortedStep48.addStep(and(inSecondPart, not(inStorageRoom), decoderStrips, codeKey), metalDoorSolver); - unsortedStep48.addStep(and(inStorageRoom, not(decoderStrips)), searchTableForDecoderStrips); - unsortedStep48.addStep(and(inStorageRoom, not(codeKey)), openChestForCodeKey); - unsortedStep48.addStep(and(inStorageRoom, decoderStrips), exitStorageRoom); + unsortedStep48.addStep(and(inSecondPart, not(inStorageRoom), codeKey), metalDoorSolver); + unsortedStep48.addStep(and(inStorageRoom, codeKey), exitStorageRoom); + unsortedStep48.addStep(and(inStorageRoom), openChestForCodeKey); unsortedStep48.addStep(and(inSecondPart, not(codeKey)), enterStorageRoom); - unsortedStep48.addStep(and(inSecondPart, not(decoderStrips)), enterStorageRoom); unsortedStep48.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); unsortedStep48.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); unsortedStep48.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); @@ -579,12 +611,13 @@ public void setupSteps() openMetalDoors = new ObjectStep(this, ObjectID.METAL_DOORS, new WorldPoint(3612, 4582, 0), "Step through through the metal doors.", canopicJarFullForHeist, anyGrappleableCrossbow, mithrilGrapple); - var inGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3612, 4587, 0), new WorldPoint(3625, 4579, 0))); - grappleAcross = new ObjectStep(this, ObjectID.PIPE_50542, new WorldPoint(3615, 4582, 0), "Grapple across the pipe", anyGrappleableCrossbow.highlighted().equipped(), mithrilGrapple.highlighted().equipped()); + var inGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3613, 4587, 0), new WorldPoint(3625, 4579, 0))); + grappleAcross = new ObjectStep(this, ObjectID.PIPE_50542, new WorldPoint(3615, 4582, 0), "Grapple across the pipe", canopicJarFullForHeist, anyGrappleableCrossbow.highlighted().equipped(), mithrilGrapple.highlighted().equipped()); var pastGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3621, 4589, 0), new WorldPoint(3645, 4578, 0))); - enterBossRoom = new ObjectStep(this, ObjectID.PEDESTAL_50539, new WorldPoint(3638, 4582, 0), "Attempt to take Arrav's heart from the pedestal, ready for a fight. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid some of the incoming damage. When Arrav throws an axe towards you, step to the side or behind him.", arravCombatGear); + enterBossRoom = new ObjectStep(this, ObjectID.PEDESTAL_50539, new WorldPoint(3638, 4582, 0), "Attempt to take Arrav's heart from the pedestal, ready for a fight with Arrav. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid some of the incoming damage. When Arrav throws an axe towards you, step to the side or behind him.", canopicJarFullForHeist, arravCombatGear); + enterBossRoom.setOverlayText("Attempt to take Arrav's heart from the pedestal, ready for a fight with Arrav. Some hints are available in the sidebar."); unsortedStep52 = new ConditionalStep(this, enterZemouregalsBase); unsortedStep52.addStep(pastGrapplePuzzleRoom, enterBossRoom); @@ -599,7 +632,8 @@ public void setupSteps() // User has engaged Arrav - fightArrav = new NpcStep(this, NpcID.ARRAV_14132, new WorldPoint(3635, 4582, 0), "fight arrav xd"); + fightArrav = new NpcStep(this, NpcID.ARRAV_14132, new WorldPoint(3635, 4582, 0), "Fight Arrav. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid some of the incoming damage. When Arrav throws an axe towards you, step to the side or behind him.", canopicJarFullForHeist); + fightArrav.setOverlayText("Fight Arrav. Some hints are available in the sidebar."); unsortedStep54 = new ConditionalStep(this, enterZemouregalsBase); unsortedStep54.addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), fightArrav); unsortedStep54.addStep(inSecondPart, openMetalDoors); @@ -649,7 +683,9 @@ public List getItemRecommended() prayerPotion, golemCombatGear, arravCombatGear, - food + food, + lumberyardTeleport, + fairyRingDLQ ); } @@ -729,8 +765,9 @@ public List getPanels() solveTilePuzzle, searchShelvesForUrn, inspectMurals, - unsortedStep16, - unsortedStep18 + combineJarWithDwellberries, + combineJarWithRingOfLife, + returnToElias ), List.of( dwellberries3, ringOfLife, @@ -744,15 +781,14 @@ public List getPanels() food ))); panels.add(new PanelDetails("Fort Invasion", List.of( - unsortedStep20, + headToTrollheim, + continueThroughTrollheimCave, + enterTrollweissCave, rubbleMiner1, - rubbleMiner2, - rubbleMiner3, - rubbleMiner4, - unsortedStep30, - unsortedStep32, - unsortedStep34 - // TODO + climbUpstairsAndTalkToArrav, + talkToArrav, + goToNextRoom, + searchTapestry ), List.of( // Requirements anyPickaxe @@ -787,7 +823,6 @@ public List getPanels() canopicJarFullForHeist ), List.of( // Recommended - new FreeInventorySlotRequirement(1), staminaPotion, prayerPotion, food diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java index 07c0a56328..2d799b7364 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java @@ -363,7 +363,7 @@ protected void updateSteps() } } else { log.debug("player is outside of puzzle: {} / {} / {}/{}", playerWp, localPoint, xInPuzzle, yInPuzzle); - var userIsPastPuzzle = localPoint.getX() <= baseX; // TODO: If the user walks to the cave to the south, we might tell the user to just click the lever. I need to figure out the correct zone here. polish pass! + var userIsPastPuzzle = localPoint.getX() <= 3730 || (localPoint.getX() <= baseX && localPoint.getY() >= 4701); if (userIsPastPuzzle) { // highlight lever startUpStep(finishPuzzleStep); diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java index 437e1ca4c7..69e845c12e 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java @@ -30,7 +30,7 @@ public abstract class RubbleSolver extends DetailedOwnerStep { private int stepCounter; public RubbleSolver(TheCurseOfArrav theCurseOfArrav, String number) { - super(theCurseOfArrav, "Make your way through the Trollweiss cave, mining rubble with your pickaxe. " + number); + super(theCurseOfArrav, "Make your way through the Trollweiss cave, mining rubble with your pickaxe from the direction indicated. Rubble can only be mined from the same direction once."); } protected void addMineRubbleStep(int x, int y, RubbleType rubbleType, Direction direction) { @@ -40,10 +40,11 @@ protected void addMineRubbleStep(int x, int y, RubbleType rubbleType, Direction var validIDSet = new HashSet<>(validObjectIDs); var wp = new WorldPoint(x, y, 0); - var stepCounter = this.stepCounter++; - var text = String.format("[%d] Mine the rubble from the %s side", stepCounter, direction.toString().toLowerCase()); + // Useful for debugging + // var stepCounter = this.stepCounter++; + var text = String.format("Mine the rubble from the %s side", direction.toString().toLowerCase()); var mainObjectID = validObjectIDs.get(0); - var step = new ObjectStep(getQuestHelper(), mainObjectID, wp, text); + var step = new ObjectStep(getQuestHelper(), mainObjectID, wp, text, ((TheCurseOfArrav) getQuestHelper()).anyPickaxe); var offsetX = x; var offsetY = y; switch (direction) { @@ -67,8 +68,8 @@ protected void addMineRubbleStep(int x, int y, RubbleType rubbleType, Direction step.addAlternateObjects(alternateIDs); } - var conditionText = String.format("[%d] Rubble mined from the %s side", stepCounter, direction.toString().toLowerCase()); - var inverseConditionText = String.format("[%d] Rubble needs to be mined from the %s side", stepCounter, direction.toString().toLowerCase()); + var conditionText = String.format("Rubble mined from the %s side", direction.toString().toLowerCase()); + var inverseConditionText = String.format("Rubble needs to be mined from the %s side", direction.toString().toLowerCase()); var conditionThatRubbleIsStillThere = new ObjectCondition(validIDSet, wp); var conditionThatRubbleHasBeenMined = new Conditions(true, LogicType.NAND, conditionThatRubbleIsStillThere); conditionThatRubbleIsStillThere.setText(inverseConditionText); @@ -102,56 +103,22 @@ protected void setupSteps() { this.setupRubbleSteps(); - // after reversing - // mineStep 0: mine C - // mineStep 1: mine B - // mineStep 2: mine A - - // condition 0: A is mined - // condition 1: B is mined - // condition 2: C is mined - - // i = 0: Mine C, if B and A are mined, and C is not mined - // i = 1: Mine B, if A is mined - // i = 2: Mine A, with no condition - conditionalStep = new ConditionalStep(getQuestHelper(), todo); - // Collections.reverse(this.mineSteps); - // Collections.reverse(this.inverseConditions); assert this.mineSteps.size() == this.conditions.size(); assert this.mineSteps.size() == this.inverseConditions.size(); - // { - // var allDone = new DetailedQuestStep(getQuestHelper(), "you are all done lol"); - // var conditionList = new ArrayList(); - // for (var condition : this.conditions) { - // allDone.addRequirement(condition); - // } - // var xd = new Conditions(LogicType.AND, conditionList); - // conditionalStep.addStep(xd, allDone); - // } for (var i = 0; i < mineSteps.size(); i++) { var mineStep = mineSteps.get(i); var inverseCondition = this.inverseConditions.get(i); - // var conditionList = new ArrayList(); - - mineStep.addRequirement(inverseCondition); - // conditionList.add(this.inverseConditions.get(i)); - - // StringBuilder text = new StringBuilder(); - // for (var j = 0; j < this.conditions.size() - i - 1; j++) { - // var condition = this.conditions.get(j); - // conditionList.add(condition); - // text.append(this.conditions.get(j).getDisplayText()); - // mineStep.addRequirement(condition); - // } + // Useful for debugging + // mineStep.addRequirement(inverseCondition); - var xd = new Conditions(LogicType.AND, inverseCondition); - xd.setText(inverseCondition.getDisplayText()); + // var xd = new Conditions(LogicType.AND, inverseCondition); + // xd.setText(inverseCondition.getDisplayText()); - conditionalStep.addStep(xd, mineStep); + conditionalStep.addStep(inverseCondition, mineStep); } } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java index 1f2f21f969..85002a855e 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java @@ -5,7 +5,7 @@ import net.runelite.api.coords.Direction; /** - * This class describes the rubble mining steps required for Roadblock 3 (when quest state varbit is 26) + * This class describes the rubble mining steps required for Roadblock 4 (when quest state varbit is 28) */ @Slf4j public class RubbleSolverFour extends RubbleSolver @@ -16,34 +16,34 @@ public RubbleSolverFour(TheCurseOfArrav theCurseOfArrav) { @Override protected void setupRubbleSteps() { - this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 1 - this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 2 - this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 3 - this.addMineRubbleStep(2788, 10267, RubbleType.Two, Direction.NORTH); // 4 - this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 5 - this.addMineRubbleStep(2788, 10267, RubbleType.One, Direction.WEST); // 6 + this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); + this.addMineRubbleStep(2788, 10267, RubbleType.Two, Direction.NORTH); + this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2788, 10267, RubbleType.One, Direction.WEST); // Last part from south - this.addMineRubbleStep(2803, 10264, RubbleType.Three, Direction.SOUTH); // 7 - this.addMineRubbleStep(2803, 10265, RubbleType.Two, Direction.SOUTH); // 8 + this.addMineRubbleStep(2803, 10264, RubbleType.Three, Direction.SOUTH); + this.addMineRubbleStep(2803, 10265, RubbleType.Two, Direction.SOUTH); // Last part from north - this.addMineRubbleStep(2803, 10267, RubbleType.One, Direction.NORTH); // 9 - this.addMineRubbleStep(2803, 10266, RubbleType.Three, Direction.NORTH); // 10 - this.addMineRubbleStep(2804, 10266, RubbleType.Two, Direction.NORTH); // 11 + this.addMineRubbleStep(2803, 10267, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2803, 10266, RubbleType.Three, Direction.NORTH); + this.addMineRubbleStep(2804, 10266, RubbleType.Two, Direction.NORTH); // Last part from west - this.addMineRubbleStep(2802, 10266, RubbleType.Two, Direction.WEST); // 12 - this.addMineRubbleStep(2801, 10265, RubbleType.One, Direction.NORTH); // 13 - this.addMineRubbleStep(2802, 10265, RubbleType.One, Direction.WEST); // 14 - this.addMineRubbleStep(2803, 10265, RubbleType.One, Direction.WEST); // 15 - this.addMineRubbleStep(2802, 10266, RubbleType.One, Direction.SOUTH); // 16 - this.addMineRubbleStep(2803, 10266, RubbleType.Two, Direction.WEST); // 17 - this.addMineRubbleStep(2804, 10265, RubbleType.Two, Direction.WEST); // 18 - this.addMineRubbleStep(2803, 10266, RubbleType.One, Direction.SOUTH); // 19 - this.addMineRubbleStep(2804, 10266, RubbleType.One, Direction.WEST); // 20 - this.addMineRubbleStep(2804, 10265, RubbleType.One, Direction.NORTH); // 21 - this.addMineRubbleStep(2805, 10265, RubbleType.One, Direction.WEST); // 22 - this.addMineRubbleStep(2806, 10265, RubbleType.One, Direction.WEST); // 23 + this.addMineRubbleStep(2802, 10266, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2801, 10265, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2802, 10265, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2803, 10265, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2802, 10266, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2804, 10265, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2803, 10266, RubbleType.Two, Direction.SOUTH); + this.addMineRubbleStep(2803, 10266, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2804, 10266, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2804, 10265, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2805, 10265, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2806, 10265, RubbleType.One, Direction.WEST); } } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java index 43697f6927..9b1f823655 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java @@ -17,13 +17,13 @@ public RubbleSolverThree(TheCurseOfArrav theCurseOfArrav) { @Override protected void setupRubbleSteps() { // These 3 steps are technically part of the next solver, but it's better to get these done asap - this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); // 1 - this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); // 2 - this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); // 3 + this.addMineRubbleStep(2787, 10267, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2787, 10266, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2787, 10267, RubbleType.Two, Direction.SOUTH); - this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); // 4 - this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); // 5 - this.addMineRubbleStep(2789, 10285, RubbleType.Two, Direction.WEST); // 6 + this.addMineRubbleStep(2789, 10286, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2789, 10285, RubbleType.Three, Direction.NORTH); + this.addMineRubbleStep(2789, 10285, RubbleType.Two, Direction.WEST); this.addMineRubbleStep(2789, 10283, RubbleType.Two, Direction.WEST); this.addMineRubbleStep(2789, 10284, RubbleType.Three, Direction.WEST); @@ -41,6 +41,6 @@ protected void setupRubbleSteps() { this.addMineRubbleStep(2792, 10285, RubbleType.One, Direction.WEST); this.addMineRubbleStep(2793, 10285, RubbleType.One, Direction.WEST); - this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); // 26 (or when??) + this.addMineRubbleStep(2787, 10267, RubbleType.One, Direction.NORTH); } } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java index c65e280dde..177ab888aa 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java @@ -16,23 +16,23 @@ public RubbleSolverTwo(TheCurseOfArrav theCurseOfArrav) { @Override protected void setupRubbleSteps() { - this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); // 5 - this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); // 6 - this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); // 7 - this.addMineRubbleStep(2766, 10279, RubbleType.Two, Direction.NORTH); // 8 - this.addMineRubbleStep(2766, 10278, RubbleType.Two, Direction.WEST); // 9 - this.addMineRubbleStep(2766, 10278, RubbleType.One, Direction.SOUTH); // 10 - this.addMineRubbleStep(2766, 10279, RubbleType.One, Direction.SOUTH); // 11 - this.addMineRubbleStep(2767, 10278, RubbleType.One, Direction.WEST); // 12 - this.addMineRubbleStep(2767, 10279, RubbleType.Two, Direction.WEST); // 13 - this.addMineRubbleStep(2768, 10279, RubbleType.One, Direction.WEST); // 14 - this.addMineRubbleStep(2767, 10279, RubbleType.One, Direction.SOUTH); // 15 - this.addMineRubbleStep(2768, 10280, RubbleType.Three, Direction.SOUTH); // 16: THIS TRIGGERS A STONE FALL OR SOMETHING :) - this.addMineRubbleStep(2768, 10281, RubbleType.One, Direction.SOUTH); // 17 - this.addMineRubbleStep(2769, 10281, RubbleType.Two, Direction.WEST); // 18 - this.addMineRubbleStep(2767, 10281, RubbleType.One, Direction.EAST); // 19 - this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); // 20 - this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); // 21 - this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); // 22 + this.addMineRubbleStep(2766, 10279, RubbleType.Three, Direction.WEST); + this.addMineRubbleStep(2766, 10280, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2767, 10281, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2766, 10279, RubbleType.Two, Direction.NORTH); + this.addMineRubbleStep(2766, 10278, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2766, 10278, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2766, 10279, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2767, 10278, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2767, 10279, RubbleType.Two, Direction.SOUTH); + this.addMineRubbleStep(2767, 10279, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2768, 10279, RubbleType.One, Direction.WEST); + this.addMineRubbleStep(2768, 10280, RubbleType.Three, Direction.SOUTH); + this.addMineRubbleStep(2768, 10281, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2769, 10281, RubbleType.Two, Direction.WEST); + this.addMineRubbleStep(2767, 10281, RubbleType.One, Direction.EAST); + this.addMineRubbleStep(2767, 10282, RubbleType.One, Direction.SOUTH); + this.addMineRubbleStep(2769, 10281, RubbleType.One, Direction.NORTH); + this.addMineRubbleStep(2770, 10281, RubbleType.One, Direction.WEST); } } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java index 4350f47e76..6715b77c19 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java @@ -10,7 +10,7 @@ public enum RubbleType { Three(ObjectID.RUBBLE_50603, ObjectID.RUBBLE_50604), Two(ObjectID.RUBBLE_50598, ObjectID.RUBBLE_50602, ObjectID.RUBBLE_50601, ObjectID.RUBBLE_50599), - One(ObjectID.RUBBLE_50587, ObjectID.RUBBLE_50589, ObjectID.RUBBLE_50590, ObjectID.RUBBLE_50594, ObjectID.RUBBLE_50597, ObjectID.RUBBLE_50588); + One(ObjectID.RUBBLE_50587, ObjectID.RUBBLE_50589, ObjectID.RUBBLE_50590, ObjectID.RUBBLE_50594, ObjectID.RUBBLE_50597, ObjectID.RUBBLE_50588, ObjectID.RUBBLE_50593); private final List objectIDs; diff --git a/src/main/java/com/questhelper/panel/QuestStepPanel.java b/src/main/java/com/questhelper/panel/QuestStepPanel.java index 211db88e75..b1952b7a39 100644 --- a/src/main/java/com/questhelper/panel/QuestStepPanel.java +++ b/src/main/java/com/questhelper/panel/QuestStepPanel.java @@ -223,7 +223,7 @@ public void updateHighlightCheck(Client client, QuestStep newStep, QuestHelper c for (QuestStep step : getSteps()) { if (step.getConditionToHide() != null && step.getConditionToHide().check(client)) continue; - if (step == newStep || step.getSubsteps().contains(newStep)) + if (step == newStep || step.hasOtherStepAsSubstep(newStep)) { highlighted = true; updateHighlight(step); diff --git a/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java b/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java index 879ff9c4ba..59cbaa6c64 100644 --- a/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java +++ b/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java @@ -33,14 +33,21 @@ import java.util.Map; import com.questhelper.panel.PanelDetails; import com.questhelper.steps.QuestStep; +import lombok.Getter; public abstract class BasicQuestHelper extends QuestHelper { protected Map steps; protected int var; - @Override - public void init() + public Map getStepList() { + return this.steps; + } + + /** + * Attempt to load steps from the quest if steps have not yet been loaded + */ + private void tryLoadSteps() { if (steps == null) { @@ -48,9 +55,17 @@ public void init() } } + @Override + public void init() + { + this.tryLoadSteps(); + } + @Override public void startUp(QuestHelperConfig config) { + // this.tryLoadSteps(); + // TODO: THIS SHOULD USE tryLoadSteps steps = loadSteps(); this.config = config; instantiateSteps(steps.values()); diff --git a/src/main/java/com/questhelper/steps/DetailedQuestStep.java b/src/main/java/com/questhelper/steps/DetailedQuestStep.java index b2b65b977f..cdbd8b1002 100644 --- a/src/main/java/com/questhelper/steps/DetailedQuestStep.java +++ b/src/main/java/com/questhelper/steps/DetailedQuestStep.java @@ -672,6 +672,9 @@ protected void addItemTiles(Collection requirements) { return; } + var scene = client.getScene(); + var tilesxd = scene.getTiles(); + var plane = client.getPlane(); Tile[][] squareOfTiles = client.getScene().getTiles()[client.getPlane()]; // Reduce the two-dimensional array into a single list for processing. @@ -910,12 +913,16 @@ public void setShortestPath() { if (worldPoint != null) { - WorldPoint playerWp = client.getLocalPlayer().getWorldLocation(); - if (getQuestHelper().getConfig().useShortestPath() && playerWp != null) { - Map data = new HashMap<>(); - data.put("start", playerWp); - data.put("target", worldPoint); - eventBus.post(new PluginMessage("shortestpath", "path", data)); + if (getQuestHelper().getConfig().useShortestPath()) + { + WorldPoint playerWp = client.getLocalPlayer().getWorldLocation(); + if (getQuestHelper().getConfig().useShortestPath() && playerWp != null) + { + Map data = new HashMap<>(); + data.put("start", playerWp); + data.put("target", worldPoint); + eventBus.post(new PluginMessage("shortestpath", "path", data)); + } } } } diff --git a/src/main/java/com/questhelper/steps/ObjectStep.java b/src/main/java/com/questhelper/steps/ObjectStep.java index 58424a60b2..3eaa37ddec 100644 --- a/src/main/java/com/questhelper/steps/ObjectStep.java +++ b/src/main/java/com/questhelper/steps/ObjectStep.java @@ -499,4 +499,9 @@ private Zone objZone(GameObject obj) bottomLeftCorner.getPlane()) ); } + + @Override + public String toString() { + return super.toString() + "(" + this.getText() + ")"; + } } diff --git a/src/main/java/com/questhelper/steps/QuestStep.java b/src/main/java/com/questhelper/steps/QuestStep.java index 74ae932c5f..bc12e42aaa 100644 --- a/src/main/java/com/questhelper/steps/QuestStep.java +++ b/src/main/java/com/questhelper/steps/QuestStep.java @@ -45,13 +45,15 @@ import com.questhelper.steps.choice.WidgetChoiceStep; import com.questhelper.steps.choice.WidgetChoiceSteps; import com.questhelper.steps.overlay.IconOverlay; -import java.awt.Graphics2D; +import java.awt.*; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; import java.util.regex.Pattern; import lombok.Getter; @@ -594,4 +596,8 @@ public PuzzleWrapperStep puzzleWrapStep(String alternateText) { return new PuzzleWrapperStep(getQuestHelper(), this, alternateText); } + + public boolean hasOtherStepAsSubstep(QuestStep otherStep) { + return this.getSubsteps().contains(otherStep); + } } diff --git a/src/main/java/com/questhelper/steps/WidgetStep.java b/src/main/java/com/questhelper/steps/WidgetStep.java index 83398da076..d78a103893 100644 --- a/src/main/java/com/questhelper/steps/WidgetStep.java +++ b/src/main/java/com/questhelper/steps/WidgetStep.java @@ -30,6 +30,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Function; import lombok.Setter; import net.runelite.api.widgets.Widget; import com.questhelper.QuestHelperPlugin; @@ -40,6 +43,8 @@ public class WidgetStep extends DetailedQuestStep @Setter protected List widgetDetails = new ArrayList<>(); + protected List> extraWidgetOverlayHintFunctions = new ArrayList<>(); + public WidgetStep(QuestHelper questHelper, String text, int groupID, int childID) { super(questHelper, text); @@ -52,6 +57,10 @@ public WidgetStep(QuestHelper questHelper, String text, WidgetDetails... widgetD this.widgetDetails.addAll(Arrays.asList(widgetDetails)); } + public void addExtraWidgetOverlayHintFunction(BiConsumer function) { + this.extraWidgetOverlayHintFunctions.add(function); + } + @Override public void makeWidgetOverlayHint(Graphics2D graphics, QuestHelperPlugin plugin) { @@ -79,5 +88,9 @@ public void makeWidgetOverlayHint(Graphics2D graphics, QuestHelperPlugin plugin) graphics.setColor(questHelper.getConfig().targetOverlayColor()); graphics.draw(widget.getBounds()); } + + for (var extraWidgetOverlayHintFunction : extraWidgetOverlayHintFunctions) { + extraWidgetOverlayHintFunction.accept(graphics, plugin); + } } } diff --git a/src/test/java/com/questhelper/MockedTest.java b/src/test/java/com/questhelper/MockedTest.java index 048f8461de..139eded7e3 100644 --- a/src/test/java/com/questhelper/MockedTest.java +++ b/src/test/java/com/questhelper/MockedTest.java @@ -32,18 +32,26 @@ import com.questhelper.statemanagement.AchievementDiaryStepManager; import com.questhelper.statemanagement.PlayerStateManager; import net.runelite.api.Client; +import net.runelite.api.SpriteID; import net.runelite.client.callback.ClientThread; import net.runelite.client.callback.Hooks; import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.config.ConfigManager; +import net.runelite.client.config.RuneLiteConfig; import net.runelite.client.eventbus.EventBus; import net.runelite.client.game.ItemManager; +import net.runelite.client.game.SpriteManager; import net.runelite.client.ui.ClientToolbar; import net.runelite.client.ui.overlay.OverlayManager; import org.junit.jupiter.api.BeforeEach; import org.mockito.Mockito; import javax.inject.Named; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.Random; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadLocalRandom; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; /** @@ -69,9 +77,15 @@ public abstract class MockedTest extends MockedTestBase @Bind protected QuestHelperConfig questHelperConfig = Mockito.mock(QuestHelperConfig.class); + @Bind + protected RuneLiteConfig runeLiteConfig = Mockito.mock(RuneLiteConfig.class); + @Bind protected QuestOverlayManager questOverlayManager = Mockito.mock(QuestOverlayManager.class); + @Bind + protected SpriteManager spriteManager = Mockito.mock(SpriteManager.class); + @Bind protected RuneliteObjectManager runeliteObjectManager = Mockito.mock(RuneliteObjectManager.class); @@ -99,6 +113,18 @@ public abstract class MockedTest extends MockedTestBase @Bind @Named("developerMode") private boolean developerMode; + + public BufferedImage random(final int width, final int height) { + Random rand = ThreadLocalRandom.current(); + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + image.setRGB(x, y, new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat()).getRGB()); + } + } + return image; + } + @Override @BeforeEach @@ -110,6 +136,7 @@ protected void setUp() when(playerStateManager.getAccountType()).thenReturn(AccountType.NORMAL); when(client.getIntStack()).thenReturn(new int[] { 1, 1, 1, 1 }); when(questHelperConfig.solvePuzzles()).thenReturn(true); + when(spriteManager.getSprite(SpriteID.TAB_QUESTS, 0)).thenReturn(new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB)); AchievementDiaryStepManager.setup(configManager); } diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java new file mode 100644 index 0000000000..c5585d195e --- /dev/null +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java @@ -0,0 +1,313 @@ +package com.questhelper.helpers.quests.thecurseofarrav; + +import com.questhelper.MockedTest; +import com.questhelper.domain.AccountType; +import com.questhelper.questinfo.QuestHelperQuest; +import com.questhelper.statemanagement.AchievementDiaryStepManager; +import com.questhelper.steps.ConditionalStep; +import com.questhelper.steps.tools.QuestPerspective; +import net.runelite.api.InventoryID; +import net.runelite.api.Item; +import net.runelite.api.ItemContainer; +import net.runelite.api.ItemID; +import net.runelite.api.Node; +import net.runelite.api.Player; +import net.runelite.api.Scene; +import net.runelite.api.Skill; +import net.runelite.api.SpriteID; +import net.runelite.api.Tile; +import net.runelite.api.coords.LocalPoint; +import net.runelite.api.coords.WorldPoint; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.awt.image.BufferedImage; +import java.util.ArrayList; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +public class KeysAndLeversTest extends MockedTest +{ + private MockedStatic questPerspectiveMockedStatic; + private MockedStatic worldPointMockedStatic; + private TheCurseOfArrav helper; + + @BeforeEach + protected void lol() + { + when(playerStateManager.getAccountType()).thenReturn(AccountType.NORMAL); + + var mockedPlayer = Mockito.mock(Player.class); + // when(mockedPlayer.getLocalLocation()).thenReturn(new LocalPoint(1, 1, 1)); + when(client.getLocalPlayer()).thenReturn(mockedPlayer); + + questPerspectiveMockedStatic = Mockito.mockStatic(QuestPerspective.class); + + worldPointMockedStatic = Mockito.mockStatic(WorldPoint.class); + + questPerspectiveMockedStatic.when(() -> QuestPerspective.getInstanceLocalPointFromReal(any(), any())) + .thenReturn(null); + + helper = new TheCurseOfArrav(); + + } + + @AfterEach + protected void lel() + { + questPerspectiveMockedStatic.close(); + worldPointMockedStatic.close(); + } + + private ConditionalStep init(WorldPoint playerLocation) + { + return this.init(playerLocation, null); + } + + private ConditionalStep init(WorldPoint playerLocation, Item[] mockedItems) + { + worldPointMockedStatic.when(() -> WorldPoint.fromLocalInstance(any(), any())) + .thenReturn(playerLocation); + + var mockedItemContainer = Mockito.mock(ItemContainer.class); + if (mockedItems != null) { + when(mockedItemContainer.getItems()).thenReturn(mockedItems); + when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(mockedItemContainer); + } + + when(client.getPlane()).thenReturn(0); + + var mockedScene = Mockito.mock(Scene.class); + when(mockedScene.getTiles()).thenReturn(new Tile[][][]{ + {} + }); + when(client.getScene()).thenReturn(mockedScene); + + this.injector.injectMembers(helper); + helper.setInjector(injector); + helper.setQuest(QuestHelperQuest.THE_CURSE_OF_ARRAV); + helper.setQuestHelperPlugin(questHelperPlugin); + helper.setConfig(questHelperConfig); + helper.init(); + + helper.startUp(questHelperConfig); + var conditionalStep = helper.unlockImposingDoors; + conditionalStep.startUp(); + return conditionalStep; + } + + @Test + void ensureOutsideTomb() + { + var conditionalStep = this.init(new WorldPoint(3305, 3037, 0)); + + assertEquals(this.helper.enterTomb, conditionalStep.getActiveStep()); + } + + @Test + void getFirstKey() + { + var conditionalStep = this.init(new WorldPoint(3845, 4547, 0)); + + assertEquals(this.helper.getFirstKey, conditionalStep.getActiveStep()); + } + + @Test + void getSecondKey() + { + var mockedItems = new Item[]{new Item(ItemID.MASTABA_KEY, 1)}; + var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); + + assertEquals(this.helper.getSecondKey, conditionalStep.getActiveStep()); + } + + @Test + void getToSouthLever() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY, 1), + new Item(ItemID.MASTABA_KEY_30309, 1), + }; + var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); + + assertEquals(this.helper.getToSouthLever, conditionalStep.getActiveStep()); + } + + @Test + void insertKeyIntoSouthLever() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY, 1), + new Item(ItemID.MASTABA_KEY_30309, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(0); + var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); + + assertEquals(this.helper.pullSouthLever, conditionalStep.getActiveStep()); + } + + @Test + void getToSouthLeverAfterInsertingKey1() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(1); + var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); + + assertEquals(this.helper.getToSouthLever, conditionalStep.getActiveStep()); + } + + @Test + void getToSouthLeverAfterInsertingKey2() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY_30309, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(1); + var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); + + assertEquals(this.helper.getToSouthLever, conditionalStep.getActiveStep()); + } + + @Test + void pullSouthLeverAfterInsertingKey1() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(1); + var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); + + assertEquals(this.helper.pullSouthLever, conditionalStep.getActiveStep()); + } + + @Test + void pullSouthLeverAfterInsertingKey2() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY_30309, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(1); + var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); + + assertEquals(this.helper.pullSouthLever, conditionalStep.getActiveStep()); + } + + @Test + void leaveSouthLeverAfterInsertingKey1() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(2); + var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); + + assertEquals(this.helper.leaveSouthLever, conditionalStep.getActiveStep()); + } + + @Test + void leaveSouthLeverAfterInsertingKey2() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY_30309, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(2); + var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); + + assertEquals(this.helper.leaveSouthLever, conditionalStep.getActiveStep()); + } + + @Test + void goToNorthLeverAfterPullingSouthLeverKey1() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(2); + var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); + + assertEquals(this.helper.getToNorthLever, conditionalStep.getActiveStep()); + } + + @Test + void goToNorthLeverAfterPullingSouthLeverKey2() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY_30309, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(2); + var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); + + assertEquals(this.helper.getToNorthLever, conditionalStep.getActiveStep()); + } + + @Test + void insertKeyIntoNorthLeverAfterPullingSouthLeverKey1() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(2); + var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); + + assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); + } + + @Test + void insertKeyIntoNorthLeverAfterPullingSouthLeverKey2() + { + var mockedItems = new Item[]{ + new Item(ItemID.MASTABA_KEY_30309, 1), + }; + when(client.getVarbitValue(11482)).thenReturn(2); + var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); + + assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); + } + + @Test + void getToSouthLeverAfterInsertingKey() + { + var mockedItems = new Item[]{ + }; + when(client.getVarbitValue(11482)).thenReturn(2); + when(client.getVarbitValue(11481)).thenReturn(1); + var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); + + assertEquals(this.helper.getToNorthLever, conditionalStep.getActiveStep()); + } + + @Test + void pullNorthLeverAfterPullingSouthLeverKey1() + { + var mockedItems = new Item[]{ + }; + when(client.getVarbitValue(11482)).thenReturn(2); + when(client.getVarbitValue(11481)).thenReturn(1); + var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); + + assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); + } + + @Test + void pullNorthLeverAfterPullingSouthLeverKey2() + { + var mockedItems = new Item[]{ + }; + when(client.getVarbitValue(11482)).thenReturn(2); + when(client.getVarbitValue(11481)).thenReturn(1); + var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); + + assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); + } +} diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java index e3f2cd1b4d..f361a4a3bb 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java @@ -26,6 +26,9 @@ public void testValidCodes() // from Zoinkwiz assertArrayEquals(new int[]{6, 3, 6, 4}, MetalDoorSolver.calculate("AEGH")); + + // from pajdank + assertArrayEquals(new int[]{1, 3, 4, 2}, MetalDoorSolver.calculate("BIAF")); } @Test @@ -70,4 +73,78 @@ public void testCodeIsNull() { assertNull(MetalDoorSolver.calculate(null)); } + + @Test + public void testDistanceUp() + { + assertEquals(0, MetalDoorSolver.calculateDistanceUp(0, 0)); + assertEquals(0, MetalDoorSolver.calculateDistanceUp(1, 1)); + assertEquals(0, MetalDoorSolver.calculateDistanceUp(2, 2)); + assertEquals(0, MetalDoorSolver.calculateDistanceUp(3, 3)); + assertEquals(0, MetalDoorSolver.calculateDistanceUp(4, 4)); + assertEquals(0, MetalDoorSolver.calculateDistanceUp(5, 5)); + assertEquals(0, MetalDoorSolver.calculateDistanceUp(6, 6)); + assertEquals(0, MetalDoorSolver.calculateDistanceUp(7, 7)); + assertEquals(0, MetalDoorSolver.calculateDistanceUp(8, 8)); + assertEquals(0, MetalDoorSolver.calculateDistanceUp(9, 9)); + + assertEquals(1, MetalDoorSolver.calculateDistanceUp(0, 1)); + assertEquals(1, MetalDoorSolver.calculateDistanceUp(1, 2)); + assertEquals(1, MetalDoorSolver.calculateDistanceUp(2, 3)); + assertEquals(1, MetalDoorSolver.calculateDistanceUp(3, 4)); + assertEquals(1, MetalDoorSolver.calculateDistanceUp(4, 5)); + assertEquals(1, MetalDoorSolver.calculateDistanceUp(5, 6)); + assertEquals(1, MetalDoorSolver.calculateDistanceUp(6, 7)); + assertEquals(1, MetalDoorSolver.calculateDistanceUp(7, 8)); + assertEquals(1, MetalDoorSolver.calculateDistanceUp(8, 9)); + assertEquals(1, MetalDoorSolver.calculateDistanceUp(9, 0)); + + assertEquals(9, MetalDoorSolver.calculateDistanceUp(0, 9)); + assertEquals(9, MetalDoorSolver.calculateDistanceUp(1, 0)); + assertEquals(9, MetalDoorSolver.calculateDistanceUp(2, 1)); + assertEquals(9, MetalDoorSolver.calculateDistanceUp(3, 2)); + assertEquals(9, MetalDoorSolver.calculateDistanceUp(4, 3)); + assertEquals(9, MetalDoorSolver.calculateDistanceUp(5, 4)); + assertEquals(9, MetalDoorSolver.calculateDistanceUp(6, 5)); + assertEquals(9, MetalDoorSolver.calculateDistanceUp(7, 6)); + assertEquals(9, MetalDoorSolver.calculateDistanceUp(8, 7)); + assertEquals(9, MetalDoorSolver.calculateDistanceUp(9, 8)); + } + + @Test + public void testDistanceDown() + { + assertEquals(0, MetalDoorSolver.calculateDistanceDown(0, 0)); + assertEquals(0, MetalDoorSolver.calculateDistanceDown(1, 1)); + assertEquals(0, MetalDoorSolver.calculateDistanceDown(2, 2)); + assertEquals(0, MetalDoorSolver.calculateDistanceDown(3, 3)); + assertEquals(0, MetalDoorSolver.calculateDistanceDown(4, 4)); + assertEquals(0, MetalDoorSolver.calculateDistanceDown(5, 5)); + assertEquals(0, MetalDoorSolver.calculateDistanceDown(6, 6)); + assertEquals(0, MetalDoorSolver.calculateDistanceDown(7, 7)); + assertEquals(0, MetalDoorSolver.calculateDistanceDown(8, 8)); + assertEquals(0, MetalDoorSolver.calculateDistanceDown(9, 9)); + + assertEquals(1, MetalDoorSolver.calculateDistanceDown(0, 9)); + assertEquals(1, MetalDoorSolver.calculateDistanceDown(1, 0)); + assertEquals(1, MetalDoorSolver.calculateDistanceDown(2, 1)); + assertEquals(1, MetalDoorSolver.calculateDistanceDown(3, 2)); + assertEquals(1, MetalDoorSolver.calculateDistanceDown(4, 3)); + assertEquals(1, MetalDoorSolver.calculateDistanceDown(5, 4)); + assertEquals(1, MetalDoorSolver.calculateDistanceDown(6, 5)); + assertEquals(1, MetalDoorSolver.calculateDistanceDown(7, 6)); + assertEquals(1, MetalDoorSolver.calculateDistanceDown(8, 7)); + assertEquals(1, MetalDoorSolver.calculateDistanceDown(9, 8)); + + assertEquals(9, MetalDoorSolver.calculateDistanceDown(0, 1)); + assertEquals(9, MetalDoorSolver.calculateDistanceDown(1, 2)); + assertEquals(9, MetalDoorSolver.calculateDistanceDown(2, 3)); + assertEquals(9, MetalDoorSolver.calculateDistanceDown(3, 4)); + assertEquals(9, MetalDoorSolver.calculateDistanceDown(4, 5)); + assertEquals(9, MetalDoorSolver.calculateDistanceDown(5, 6)); + assertEquals(9, MetalDoorSolver.calculateDistanceDown(6, 7)); + assertEquals(9, MetalDoorSolver.calculateDistanceDown(7, 8)); + assertEquals(9, MetalDoorSolver.calculateDistanceDown(8, 9)); + assertEquals(9, MetalDoorSolver.calculateDistanceDown(9, 0)); + } } diff --git a/src/test/java/com/questhelper/questhelpers/QuestHelperTest.java b/src/test/java/com/questhelper/questhelpers/QuestHelperTest.java index 7cbc628dd0..8414b98e6c 100644 --- a/src/test/java/com/questhelper/questhelpers/QuestHelperTest.java +++ b/src/test/java/com/questhelper/questhelpers/QuestHelperTest.java @@ -2,15 +2,19 @@ import com.questhelper.MockedTest; import com.questhelper.domain.AccountType; +import com.questhelper.panel.PanelDetails; import com.questhelper.questinfo.QuestHelperQuest; import com.questhelper.requirements.Requirement; import com.questhelper.requirements.item.ItemRequirement; import com.questhelper.requirements.zone.ZoneRequirement; import com.questhelper.statemanagement.AchievementDiaryStepManager; import java.lang.reflect.Field; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertFalse; +import com.questhelper.steps.ConditionalStep; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @@ -169,4 +173,58 @@ void ensureAllVariablesCorrectlySet() } } } + + @Test + void ensureAllStepsHaveSidebarLink() + { + when(questHelperConfig.solvePuzzles()).thenReturn(true); + + AchievementDiaryStepManager.setup(configManager); + + for (var quest : QuestHelperQuest.values()) + { + var helper = quest.getQuestHelper(); + helper.setQuest(quest); + if (quest.getPlayerQuests() != null) + { + continue; + } + + this.injector.injectMembers(helper); + helper.setQuestHelperPlugin(questHelperPlugin); + helper.setConfig(questHelperConfig); + helper.init(); + + if (quest != QuestHelperQuest.THE_CURSE_OF_ARRAV) { + continue; + } + + if (helper instanceof BasicQuestHelper) { + var basicHelper = (BasicQuestHelper) helper; + var panels = helper.getPanels(); + var panelSteps = panels.stream().flatMap(panelDetails -> panelDetails.getSteps().stream()).collect(Collectors.toList()); + var steps = basicHelper.getStepList().values(); + for (var step : steps) { + assertNotNull(step); + var rawText = step.getText(); + var text = rawText == null ? "" : String.join("\n", step.getText()); + if (step instanceof ConditionalStep) { + // + } else { + var isInPanelSteps = panelSteps.contains(step); + /* TODO + var isSubstepOf = steps.stream().filter(questStep -> { + if (questStep instanceof BasicQuest) { + return questStep.getSubSteps(); + } + return null; + }); + */ + var isInAnyStepSubStepsThatIsInPanelSteps = true; // todo + assertTrue(isInPanelSteps); + } + } + } + } + } } From ee9f88fbdec458534e23b6c3e58d5e8e7c24c80d Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 17:41:42 +0100 Subject: [PATCH 30/60] tiny code polish --- .../quests/thecurseofarrav/MetalDoorSolver.java | 2 -- .../quests/thecurseofarrav/TheCurseOfArrav.java | 4 ---- .../quests/thecurseofarrav/TilePuzzleSolver.java | 11 ----------- .../thecurseofarrav/rubblesolvers/RubbleSolver.java | 12 ++++-------- .../rubblesolvers/RubbleSolverOne.java | 12 ------------ .../thecurseofarrav/rubblesolvers/RubbleType.java | 8 +++----- 6 files changed, 7 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java index 052f020ee4..c3954f5dba 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java @@ -2,7 +2,6 @@ import com.questhelper.QuestHelperPlugin; import com.questhelper.requirements.ManualRequirement; -import com.questhelper.requirements.Requirement; import com.questhelper.requirements.item.ItemRequirement; import com.questhelper.requirements.widget.WidgetModelRequirement; import com.questhelper.requirements.widget.WidgetPresenceRequirement; @@ -14,7 +13,6 @@ import com.questhelper.steps.ObjectStep; import com.questhelper.steps.QuestStep; import java.awt.*; -import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.regex.Pattern; diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index fb7fe31440..7ceb1168f7 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -35,17 +35,14 @@ import com.questhelper.questinfo.QuestHelperQuest; import com.questhelper.requirements.Requirement; import com.questhelper.requirements.item.ItemRequirement; -import com.questhelper.requirements.item.ItemRequirements; import com.questhelper.requirements.item.TeleportItemRequirement; import com.questhelper.requirements.player.CombatLevelRequirement; import com.questhelper.requirements.player.FreeInventorySlotRequirement; import com.questhelper.requirements.player.SkillRequirement; import com.questhelper.requirements.quest.QuestRequirement; import static com.questhelper.requirements.util.LogicHelper.and; -import static com.questhelper.requirements.util.LogicHelper.nor; import static com.questhelper.requirements.util.LogicHelper.not; import static com.questhelper.requirements.util.LogicHelper.or; -import com.questhelper.requirements.util.Operation; import com.questhelper.requirements.var.VarbitRequirement; import com.questhelper.requirements.zone.Zone; import com.questhelper.requirements.zone.ZoneRequirement; @@ -582,7 +579,6 @@ public void setupSteps() var inSecondPart = new ZoneRequirement(new Zone(new WorldPoint(3590, 4538, 0), new WorldPoint(3622, 4597, 0))); var inStorageRoom = new ZoneRequirement(new Zone(new WorldPoint(3614, 4571, 0), new WorldPoint(3605, 4563, 0))); - var decoderStrips = new ItemRequirement("Decoder strips", ItemID.DECODER_STRIPS); searchTableForDecoderStrips = new ObjectStep(this, ObjectID.TABLE_50533, "Search the table for some decoder strips."); enterStorageRoom = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3609, 4572, 0), "Enter the storage room to the south-east."); var exitStorageRoom = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3609, 4572, 0), "Exit the storage room."); diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java index 2d799b7364..9edc133148 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java @@ -255,16 +255,6 @@ public void onGameTick(GameTick event) this.shortestPath = possiblePath; } } - - if (this.shortestPath == null) - { - // TODO: tell user to just find a way to solve it lol - } - else - { - // TODO: figure out how to highlight this? make object steps? - // How do I get the correct world points? maybe check objectstep to see if we offset it somewhere with instance points or something - } } updateSteps(); @@ -359,7 +349,6 @@ protected void updateSteps() { log.debug("user stepped off the path, lead them back"); startUpStep(this.mostRecentStep); - return; } } else { log.debug("player is outside of puzzle: {} / {} / {}/{}", playerWp, localPoint, xInPuzzle, yInPuzzle); diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java index 69e845c12e..7c721db57c 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java @@ -27,9 +27,10 @@ public abstract class RubbleSolver extends DetailedOwnerStep { private List inverseConditions; private ConditionalStep conditionalStep; - private int stepCounter; + @SuppressWarnings({"unused", "FieldCanBeLocal"}) + private int stepCounter; - public RubbleSolver(TheCurseOfArrav theCurseOfArrav, String number) { + public RubbleSolver(TheCurseOfArrav theCurseOfArrav, @SuppressWarnings("unused") String number) { super(theCurseOfArrav, "Make your way through the Trollweiss cave, mining rubble with your pickaxe from the direction indicated. Rubble can only be mined from the same direction once."); } @@ -115,9 +116,6 @@ protected void setupSteps() { // Useful for debugging // mineStep.addRequirement(inverseCondition); - // var xd = new Conditions(LogicType.AND, inverseCondition); - // xd.setText(inverseCondition.getDisplayText()); - conditionalStep.addStep(inverseCondition, mineStep); } } @@ -131,9 +129,7 @@ public List getSteps() { var steps = new ArrayList(); steps.add(this.conditionalStep); - for (var step : this.mineSteps) { - steps.add(step); - } + steps.addAll(this.mineSteps); return steps; } diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java index 5ea75dda5e..56033e0884 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java @@ -1,21 +1,9 @@ package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; -import com.questhelper.requirements.Requirement; -import com.questhelper.requirements.conditional.Conditions; -import com.questhelper.requirements.conditional.ObjectCondition; -import com.questhelper.requirements.util.LogicType; -import com.questhelper.steps.*; -import java.util.*; - -import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import net.runelite.api.*; import net.runelite.api.coords.Direction; -import net.runelite.api.coords.WorldPoint; -import net.runelite.api.events.GameTick; -import net.runelite.client.eventbus.Subscribe; /** * This class describes the rubble mining steps required for Roadblock 1 (when quest state varbit is 22) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java index 6715b77c19..ee92da77a4 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java @@ -3,6 +3,7 @@ import lombok.Getter; import net.runelite.api.ObjectID; import java.util.ArrayList; +import java.util.Collections; import java.util.List; @Getter @@ -15,10 +16,7 @@ public enum RubbleType private final List objectIDs; RubbleType(Integer... possibleObjectIDs) { - this.objectIDs = new ArrayList(); - for (var xd : possibleObjectIDs) { - this.objectIDs.add(xd); - } - // Collections.addAll(this.objectIDs, possibleObjectIDs); + this.objectIDs = new ArrayList<>(); + Collections.addAll(this.objectIDs, possibleObjectIDs); } } From 44af4ad6198850e1a2e62a5aea7135dd0042820d Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:13:14 +0100 Subject: [PATCH 31/60] disable new sidebar step --- .../questhelpers/QuestHelperTest.java | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/src/test/java/com/questhelper/questhelpers/QuestHelperTest.java b/src/test/java/com/questhelper/questhelpers/QuestHelperTest.java index 8414b98e6c..0d7a260193 100644 --- a/src/test/java/com/questhelper/questhelpers/QuestHelperTest.java +++ b/src/test/java/com/questhelper/questhelpers/QuestHelperTest.java @@ -174,57 +174,57 @@ void ensureAllVariablesCorrectlySet() } } - @Test - void ensureAllStepsHaveSidebarLink() - { - when(questHelperConfig.solvePuzzles()).thenReturn(true); - - AchievementDiaryStepManager.setup(configManager); - - for (var quest : QuestHelperQuest.values()) - { - var helper = quest.getQuestHelper(); - helper.setQuest(quest); - if (quest.getPlayerQuests() != null) - { - continue; - } - - this.injector.injectMembers(helper); - helper.setQuestHelperPlugin(questHelperPlugin); - helper.setConfig(questHelperConfig); - helper.init(); - - if (quest != QuestHelperQuest.THE_CURSE_OF_ARRAV) { - continue; - } - - if (helper instanceof BasicQuestHelper) { - var basicHelper = (BasicQuestHelper) helper; - var panels = helper.getPanels(); - var panelSteps = panels.stream().flatMap(panelDetails -> panelDetails.getSteps().stream()).collect(Collectors.toList()); - var steps = basicHelper.getStepList().values(); - for (var step : steps) { - assertNotNull(step); - var rawText = step.getText(); - var text = rawText == null ? "" : String.join("\n", step.getText()); - if (step instanceof ConditionalStep) { - // - } else { - var isInPanelSteps = panelSteps.contains(step); - /* TODO - var isSubstepOf = steps.stream().filter(questStep -> { - if (questStep instanceof BasicQuest) { - return questStep.getSubSteps(); - } - return null; - }); - */ - var isInAnyStepSubStepsThatIsInPanelSteps = true; // todo - assertTrue(isInPanelSteps); - } - } - } - } - } + // @Test + // void ensureAllStepsHaveSidebarLink() + // { + // when(questHelperConfig.solvePuzzles()).thenReturn(true); + + // AchievementDiaryStepManager.setup(configManager); + + // for (var quest : QuestHelperQuest.values()) + // { + // var helper = quest.getQuestHelper(); + // helper.setQuest(quest); + // if (quest.getPlayerQuests() != null) + // { + // continue; + // } + + // this.injector.injectMembers(helper); + // helper.setQuestHelperPlugin(questHelperPlugin); + // helper.setConfig(questHelperConfig); + // helper.init(); + + // if (quest != QuestHelperQuest.THE_CURSE_OF_ARRAV) { + // continue; + // } + + // if (helper instanceof BasicQuestHelper) { + // var basicHelper = (BasicQuestHelper) helper; + // var panels = helper.getPanels(); + // var panelSteps = panels.stream().flatMap(panelDetails -> panelDetails.getSteps().stream()).collect(Collectors.toList()); + // var steps = basicHelper.getStepList().values(); + // for (var step : steps) { + // assertNotNull(step); + // var rawText = step.getText(); + // var text = rawText == null ? "" : String.join("\n", step.getText()); + // if (step instanceof ConditionalStep) { + // // + // } else { + // var isInPanelSteps = panelSteps.contains(step); + // /* TODO + // var isSubstepOf = steps.stream().filter(questStep -> { + // if (questStep instanceof BasicQuest) { + // return questStep.getSubSteps(); + // } + // return null; + // }); + // */ + // var isInAnyStepSubStepsThatIsInPanelSteps = true; // todo + // assertTrue(isInPanelSteps); + // } + // } + // } + // } + // } } From 3e9c07c8c178c7cab287ae68e0381e8adaebb0b8 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:15:57 +0100 Subject: [PATCH 32/60] add copyright block to all newly added files --- .../thecurseofarrav/MetalDoorSolver.java | 24 +++++++++++++++++++ .../thecurseofarrav/TilePuzzleSolver.java | 24 +++++++++++++++++++ .../rubblesolvers/RubbleSolver.java | 24 +++++++++++++++++++ .../rubblesolvers/RubbleSolverFour.java | 24 +++++++++++++++++++ .../rubblesolvers/RubbleSolverOne.java | 24 +++++++++++++++++++ .../rubblesolvers/RubbleSolverThree.java | 24 +++++++++++++++++++ .../rubblesolvers/RubbleSolverTwo.java | 24 +++++++++++++++++++ .../rubblesolvers/RubbleType.java | 24 +++++++++++++++++++ .../thecurseofarrav/KeysAndLeversTest.java | 24 +++++++++++++++++++ .../thecurseofarrav/MetalDoorSolverTest.java | 24 +++++++++++++++++++ 10 files changed, 240 insertions(+) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java index c3954f5dba..53339034ed 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolver.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav; import com.questhelper.QuestHelperPlugin; diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java index 9edc133148..4909427b2c 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav; import com.questhelper.steps.DetailedOwnerStep; diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java index 7c721db57c..0174e2399d 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolver.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java index 85002a855e..bb51d450e1 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverFour.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java index 56033e0884..74dfd7e873 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverOne.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java index 9b1f823655..719c4cfd46 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverThree.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java index 177ab888aa..0aa0ae2f44 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleSolverTwo.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; import com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav; diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java index ee92da77a4..75b276cad5 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/rubblesolvers/RubbleType.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav.rubblesolvers; import lombok.Getter; diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java index c5585d195e..9c2942a974 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav; import com.questhelper.MockedTest; diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java index f361a4a3bb..1b9e0c4181 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2024, pajlada + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package com.questhelper.helpers.quests.thecurseofarrav; import net.runelite.api.coords.WorldPoint; From 96d981d9092a072ac89c12867f1bec5c34b25e5a Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:16:14 +0100 Subject: [PATCH 33/60] remove some more unused imports --- .../quests/thecurseofarrav/KeysAndLeversTest.java | 13 ------------- .../quests/thecurseofarrav/MetalDoorSolverTest.java | 4 ---- 2 files changed, 17 deletions(-) diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java index 9c2942a974..a2e55c1245 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java @@ -27,35 +27,22 @@ import com.questhelper.MockedTest; import com.questhelper.domain.AccountType; import com.questhelper.questinfo.QuestHelperQuest; -import com.questhelper.statemanagement.AchievementDiaryStepManager; import com.questhelper.steps.ConditionalStep; import com.questhelper.steps.tools.QuestPerspective; import net.runelite.api.InventoryID; import net.runelite.api.Item; import net.runelite.api.ItemContainer; import net.runelite.api.ItemID; -import net.runelite.api.Node; import net.runelite.api.Player; import net.runelite.api.Scene; -import net.runelite.api.Skill; -import net.runelite.api.SpriteID; import net.runelite.api.Tile; -import net.runelite.api.coords.LocalPoint; import net.runelite.api.coords.WorldPoint; -import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.awt.image.BufferedImage; -import java.util.ArrayList; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java index 1b9e0c4181..c3d79e91a1 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java @@ -24,13 +24,9 @@ */ package com.questhelper.helpers.quests.thecurseofarrav; -import net.runelite.api.coords.WorldPoint; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.List; import org.junit.jupiter.api.Test; From 15653a7be290d11dd38e0d274b08392e95e248fb Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:20:01 +0100 Subject: [PATCH 34/60] better document BasicQuestHelper's setupStep --- .../java/com/questhelper/questhelpers/BasicQuestHelper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java b/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java index 59cbaa6c64..fe65cd4c76 100644 --- a/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java +++ b/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java @@ -65,7 +65,8 @@ public void init() public void startUp(QuestHelperConfig config) { // this.tryLoadSteps(); - // TODO: THIS SHOULD USE tryLoadSteps + // TODO: This should use `tryLoadSteps` but when it is being more careful to be initialized, it doesn't handle + // highlighting in sidebars properly steps = loadSteps(); this.config = config; instantiateSteps(steps.values()); From 45eb9a120bc5476f1b4d01afd42e6cb8d769074e Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:20:14 +0100 Subject: [PATCH 35/60] Remove conditionforstep comment for getDisplayText --- .../questhelper/requirements/conditional/ConditionForStep.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/requirements/conditional/ConditionForStep.java b/src/main/java/com/questhelper/requirements/conditional/ConditionForStep.java index 3183b16ec0..5d5359c031 100644 --- a/src/main/java/com/questhelper/requirements/conditional/ConditionForStep.java +++ b/src/main/java/com/questhelper/requirements/conditional/ConditionForStep.java @@ -68,7 +68,7 @@ public void updateHandler() @Nonnull @Override - public String getDisplayText() // conditions don't need display text (yet?) + public String getDisplayText() { return this.text; } From 6031038d98acc8b2e04c73fb9bcabfef11ca1871 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:21:34 +0100 Subject: [PATCH 36/60] undo step-highlight-checker --- src/main/java/com/questhelper/panel/QuestStepPanel.java | 2 +- src/main/java/com/questhelper/steps/QuestStep.java | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/com/questhelper/panel/QuestStepPanel.java b/src/main/java/com/questhelper/panel/QuestStepPanel.java index b1952b7a39..211db88e75 100644 --- a/src/main/java/com/questhelper/panel/QuestStepPanel.java +++ b/src/main/java/com/questhelper/panel/QuestStepPanel.java @@ -223,7 +223,7 @@ public void updateHighlightCheck(Client client, QuestStep newStep, QuestHelper c for (QuestStep step : getSteps()) { if (step.getConditionToHide() != null && step.getConditionToHide().check(client)) continue; - if (step == newStep || step.hasOtherStepAsSubstep(newStep)) + if (step == newStep || step.getSubsteps().contains(newStep)) { highlighted = true; updateHighlight(step); diff --git a/src/main/java/com/questhelper/steps/QuestStep.java b/src/main/java/com/questhelper/steps/QuestStep.java index bc12e42aaa..5f1d7b2065 100644 --- a/src/main/java/com/questhelper/steps/QuestStep.java +++ b/src/main/java/com/questhelper/steps/QuestStep.java @@ -596,8 +596,4 @@ public PuzzleWrapperStep puzzleWrapStep(String alternateText) { return new PuzzleWrapperStep(getQuestHelper(), this, alternateText); } - - public boolean hasOtherStepAsSubstep(QuestStep otherStep) { - return this.getSubsteps().contains(otherStep); - } } From c0e1e2822621a049377f8a35f6881c80bb096c02 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:25:02 +0100 Subject: [PATCH 37/60] Remove unused imports from BasicQuestHelper --- .../java/com/questhelper/questhelpers/BasicQuestHelper.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java b/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java index fe65cd4c76..b5e8c703a9 100644 --- a/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java +++ b/src/main/java/com/questhelper/questhelpers/BasicQuestHelper.java @@ -25,15 +25,11 @@ package com.questhelper.questhelpers; import com.questhelper.QuestHelperConfig; -import com.questhelper.requirements.Requirement; -import com.questhelper.requirements.conditional.Conditions; -import com.questhelper.requirements.util.LogicType; import java.util.ArrayList; import java.util.List; import java.util.Map; import com.questhelper.panel.PanelDetails; import com.questhelper.steps.QuestStep; -import lombok.Getter; public abstract class BasicQuestHelper extends QuestHelper { From 86d93ecb41376f379c18c1ed0bec265ece32355d Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:31:26 +0100 Subject: [PATCH 38/60] Add optimal quest order, optimal ironman order, and release order --- .../com/questhelper/panel/questorders/OptimalQuestGuide.java | 1 + src/main/java/com/questhelper/panel/questorders/QuestOrders.java | 1 + src/main/java/com/questhelper/panel/questorders/ReleaseDate.java | 1 + 3 files changed, 3 insertions(+) diff --git a/src/main/java/com/questhelper/panel/questorders/OptimalQuestGuide.java b/src/main/java/com/questhelper/panel/questorders/OptimalQuestGuide.java index d7dc2baa68..1d741e90fc 100644 --- a/src/main/java/com/questhelper/panel/questorders/OptimalQuestGuide.java +++ b/src/main/java/com/questhelper/panel/questorders/OptimalQuestGuide.java @@ -250,6 +250,7 @@ public class OptimalQuestGuide //QuestHelperQuest.INTO_THE_TOMBS, - Placeholder for future addition. QuestHelperQuest.A_NIGHT_AT_THE_THEATRE, QuestHelperQuest.DRAGON_SLAYER_II, + QuestHelperQuest.THE_CURSE_OF_ARRAV, QuestHelperQuest.MAKING_FRIENDS_WITH_MY_ARM, QuestHelperQuest.SECRETS_OF_THE_NORTH, QuestHelperQuest.WHILE_GUTHIX_SLEEPS, diff --git a/src/main/java/com/questhelper/panel/questorders/QuestOrders.java b/src/main/java/com/questhelper/panel/questorders/QuestOrders.java index 8c111ca844..9106358f80 100644 --- a/src/main/java/com/questhelper/panel/questorders/QuestOrders.java +++ b/src/main/java/com/questhelper/panel/questorders/QuestOrders.java @@ -249,6 +249,7 @@ public class QuestOrders QuestHelperQuest.SECRETS_OF_THE_NORTH, QuestHelperQuest.SONG_OF_THE_ELVES, QuestHelperQuest.DESERT_TREASURE_II, + QuestHelperQuest.THE_CURSE_OF_ARRAV, // Not from wiki QuestHelperQuest.WHILE_GUTHIX_SLEEPS, // Remaining section is unordered as not part of list on https://oldschool.runescape.wiki/w/Optimal_quest_guide/Ironman diff --git a/src/main/java/com/questhelper/panel/questorders/ReleaseDate.java b/src/main/java/com/questhelper/panel/questorders/ReleaseDate.java index 13b1afae50..0df0ea19df 100644 --- a/src/main/java/com/questhelper/panel/questorders/ReleaseDate.java +++ b/src/main/java/com/questhelper/panel/questorders/ReleaseDate.java @@ -217,6 +217,7 @@ public class ReleaseDate QuestHelperQuest.DEATH_ON_THE_ISLE, QuestHelperQuest.MEAT_AND_GREET, QuestHelperQuest.ETHICALLY_ACQUIRED_ANTIQUITIES, + QuestHelperQuest.THE_CURSE_OF_ARRAV, // Miniquests QuestHelperQuest.ALFRED_GRIMHANDS_BARCRAWL, QuestHelperQuest.THE_MAGE_ARENA, From 8b21fcb40c7ede34def7488609288c754dde670b Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:34:41 +0100 Subject: [PATCH 39/60] wiki link now works without a redirect --- .../java/com/questhelper/questinfo/ExternalQuestResources.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/questhelper/questinfo/ExternalQuestResources.java b/src/main/java/com/questhelper/questinfo/ExternalQuestResources.java index 2487e22566..a8251c179d 100644 --- a/src/main/java/com/questhelper/questinfo/ExternalQuestResources.java +++ b/src/main/java/com/questhelper/questinfo/ExternalQuestResources.java @@ -203,6 +203,7 @@ public enum ExternalQuestResources IN_SEARCH_OF_KNOWLEDGE("https://oldschool.runescape.wiki/w/In_Search_of_Knowledge"), DADDYS_HOME("https://oldschool.runescape.wiki/w/Daddy%27s_Home"), HOPESPEARS_WILL("https://oldschool.runescape.wiki/w/Hopespear%27s_Will"), + THE_CURSE_OF_ARRAV("https://oldschool.runescape.wiki/w/The_Curse_of_Arrav"), // Fake miniquests KNIGHT_WAVES_TRAINING_GROUNDS("https://oldschool.runescape.wiki/w/Camelot_training_room"), From 58d8c9649acd3a841691105b249f83e34e4e70e2 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:36:20 +0100 Subject: [PATCH 40/60] remove previously-added-but-now-unused Conditions ctor --- .../questhelper/requirements/conditional/Conditions.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/com/questhelper/requirements/conditional/Conditions.java b/src/main/java/com/questhelper/requirements/conditional/Conditions.java index 9bf414947e..0ef0b1f94e 100644 --- a/src/main/java/com/questhelper/requirements/conditional/Conditions.java +++ b/src/main/java/com/questhelper/requirements/conditional/Conditions.java @@ -131,15 +131,6 @@ public Conditions(boolean onlyNeedToPassOnce, Requirement... conditions) this.logicType = LogicType.AND; } - public Conditions(boolean onlyNeedToPassOnce, LogicType logicType, ArrayList conditions) - { - assert(conditions.stream().noneMatch(Objects::isNull)); - - this.conditions = new ArrayList<>(conditions); - this.logicType = logicType; - this.onlyNeedToPassOnce = onlyNeedToPassOnce; - } - @Override @Nonnull public String getDisplayText() From ecf59f5dddd09d72649960fcb73db559e31216db Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:37:45 +0100 Subject: [PATCH 41/60] more asserts for new ObjectCondition ctor --- .../questhelper/requirements/conditional/ObjectCondition.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java b/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java index 0ae8a4d552..ee780486be 100644 --- a/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java +++ b/src/main/java/com/questhelper/requirements/conditional/ObjectCondition.java @@ -32,7 +32,7 @@ import net.runelite.api.Tile; import net.runelite.api.TileObject; import net.runelite.api.coords.WorldPoint; -import java.util.List; +import java.util.Objects; import java.util.Set; public class ObjectCondition extends ConditionForStep @@ -71,6 +71,8 @@ public ObjectCondition(int objectID, Zone zone) public ObjectCondition(Set objectIDs, WorldPoint worldPoint) { assert(worldPoint != null); + assert(objectIDs != null); + assert(objectIDs.stream().noneMatch(Objects::isNull)); this.objectIDs = objectIDs; this.zone = new Zone(worldPoint); From 9420028216feb8260c31f4f8e2d1b5c7140c1cad Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:41:52 +0100 Subject: [PATCH 42/60] remove some test declarations --- src/main/java/com/questhelper/steps/DetailedQuestStep.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/com/questhelper/steps/DetailedQuestStep.java b/src/main/java/com/questhelper/steps/DetailedQuestStep.java index cdbd8b1002..1a7a438efd 100644 --- a/src/main/java/com/questhelper/steps/DetailedQuestStep.java +++ b/src/main/java/com/questhelper/steps/DetailedQuestStep.java @@ -672,9 +672,6 @@ protected void addItemTiles(Collection requirements) { return; } - var scene = client.getScene(); - var tilesxd = scene.getTiles(); - var plane = client.getPlane(); Tile[][] squareOfTiles = client.getScene().getTiles()[client.getPlane()]; // Reduce the two-dimensional array into a single list for processing. From 7bdcdebd3a8538ae7eb616444afeab8d4ea9888e Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:42:55 +0100 Subject: [PATCH 43/60] Undo change to the shortestPath logic --- .../com/questhelper/steps/DetailedQuestStep.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/questhelper/steps/DetailedQuestStep.java b/src/main/java/com/questhelper/steps/DetailedQuestStep.java index 1a7a438efd..d0eb1796d4 100644 --- a/src/main/java/com/questhelper/steps/DetailedQuestStep.java +++ b/src/main/java/com/questhelper/steps/DetailedQuestStep.java @@ -910,16 +910,13 @@ public void setShortestPath() { if (worldPoint != null) { - if (getQuestHelper().getConfig().useShortestPath()) + WorldPoint playerWp = client.getLocalPlayer().getWorldLocation(); + if (getQuestHelper().getConfig().useShortestPath() && playerWp != null) { - WorldPoint playerWp = client.getLocalPlayer().getWorldLocation(); - if (getQuestHelper().getConfig().useShortestPath() && playerWp != null) - { - Map data = new HashMap<>(); - data.put("start", playerWp); - data.put("target", worldPoint); - eventBus.post(new PluginMessage("shortestpath", "path", data)); - } + Map data = new HashMap<>(); + data.put("start", playerWp); + data.put("target", worldPoint); + eventBus.post(new PluginMessage("shortestpath", "path", data)); } } } From 57a085c4553c78d05005220fc142a626996cf5aa Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:43:23 +0100 Subject: [PATCH 44/60] remove custom ObjectStep toString function --- src/main/java/com/questhelper/steps/ObjectStep.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/com/questhelper/steps/ObjectStep.java b/src/main/java/com/questhelper/steps/ObjectStep.java index 3eaa37ddec..58424a60b2 100644 --- a/src/main/java/com/questhelper/steps/ObjectStep.java +++ b/src/main/java/com/questhelper/steps/ObjectStep.java @@ -499,9 +499,4 @@ private Zone objZone(GameObject obj) bottomLeftCorner.getPlane()) ); } - - @Override - public String toString() { - return super.toString() + "(" + this.getText() + ")"; - } } From 9da19c124f0076983d6a825cc2fade0d290f2613 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:43:42 +0100 Subject: [PATCH 45/60] undo reformat --- src/main/java/com/questhelper/steps/DetailedQuestStep.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/questhelper/steps/DetailedQuestStep.java b/src/main/java/com/questhelper/steps/DetailedQuestStep.java index d0eb1796d4..b2b65b977f 100644 --- a/src/main/java/com/questhelper/steps/DetailedQuestStep.java +++ b/src/main/java/com/questhelper/steps/DetailedQuestStep.java @@ -911,8 +911,7 @@ public void setShortestPath() if (worldPoint != null) { WorldPoint playerWp = client.getLocalPlayer().getWorldLocation(); - if (getQuestHelper().getConfig().useShortestPath() && playerWp != null) - { + if (getQuestHelper().getConfig().useShortestPath() && playerWp != null) { Map data = new HashMap<>(); data.put("start", playerWp); data.put("target", worldPoint); From 9fcc422da3f940a75ed8a7f555660b9856b8f8d7 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:44:07 +0100 Subject: [PATCH 46/60] Undo import changes to QuestStep --- src/main/java/com/questhelper/steps/QuestStep.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/questhelper/steps/QuestStep.java b/src/main/java/com/questhelper/steps/QuestStep.java index 5f1d7b2065..74ae932c5f 100644 --- a/src/main/java/com/questhelper/steps/QuestStep.java +++ b/src/main/java/com/questhelper/steps/QuestStep.java @@ -45,15 +45,13 @@ import com.questhelper.steps.choice.WidgetChoiceStep; import com.questhelper.steps.choice.WidgetChoiceSteps; import com.questhelper.steps.overlay.IconOverlay; -import java.awt.*; +import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; import java.util.regex.Pattern; import lombok.Getter; From d54e418ca916b7a456415eb0efecd227fe09e3af Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:46:10 +0100 Subject: [PATCH 47/60] remove unused imports, function & did some formatting in tests --- .../java/com/questhelper/steps/WidgetStep.java | 2 -- src/test/java/com/questhelper/MockedTest.java | 17 +---------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/main/java/com/questhelper/steps/WidgetStep.java b/src/main/java/com/questhelper/steps/WidgetStep.java index d78a103893..203bfbc957 100644 --- a/src/main/java/com/questhelper/steps/WidgetStep.java +++ b/src/main/java/com/questhelper/steps/WidgetStep.java @@ -31,8 +31,6 @@ import java.util.Arrays; import java.util.List; import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; import lombok.Setter; import net.runelite.api.widgets.Widget; import com.questhelper.QuestHelperPlugin; diff --git a/src/test/java/com/questhelper/MockedTest.java b/src/test/java/com/questhelper/MockedTest.java index 139eded7e3..501da5301c 100644 --- a/src/test/java/com/questhelper/MockedTest.java +++ b/src/test/java/com/questhelper/MockedTest.java @@ -46,12 +46,8 @@ import org.junit.jupiter.api.BeforeEach; import org.mockito.Mockito; import javax.inject.Named; -import java.awt.*; import java.awt.image.BufferedImage; -import java.util.Random; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadLocalRandom; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; /** @@ -113,17 +109,6 @@ public abstract class MockedTest extends MockedTestBase @Bind @Named("developerMode") private boolean developerMode; - - public BufferedImage random(final int width, final int height) { - Random rand = ThreadLocalRandom.current(); - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - image.setRGB(x, y, new Color(rand.nextFloat(), rand.nextFloat(), rand.nextFloat()).getRGB()); - } - } - return image; - } @Override @@ -134,7 +119,7 @@ protected void setUp() when(questHelperPlugin.getPlayerStateManager()).thenReturn(playerStateManager); when(playerStateManager.getAccountType()).thenReturn(AccountType.NORMAL); - when(client.getIntStack()).thenReturn(new int[] { 1, 1, 1, 1 }); + when(client.getIntStack()).thenReturn(new int[] {1, 1, 1, 1}); when(questHelperConfig.solvePuzzles()).thenReturn(true); when(spriteManager.getSprite(SpriteID.TAB_QUESTS, 0)).thenReturn(new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB)); From 9b574dd8e8881aab720c3470ff10526815389349 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:49:52 +0100 Subject: [PATCH 48/60] add antivenom recommendation --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 7ceb1168f7..565d69cc8f 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -96,6 +96,7 @@ public class TheCurseOfArrav extends BasicQuestHelper private ItemRequirement food; private ItemRequirement staminaPotion; private ItemRequirement prayerPotion; + private ItemRequirement antiVenom; private FreeInventorySlotRequirement twoFreeInventorySlots; // 2 inv slots @@ -297,6 +298,7 @@ protected void setupRequirements() lumberyardTeleport = new TeleportItemRequirement("Lumberyard teleport", ItemID.LUMBERYARD_TELEPORT); staminaPotion = new ItemRequirement("Stamina potion", ItemCollections.STAMINA_POTIONS, 1); prayerPotion = new ItemRequirement("Prayer potion", ItemCollections.PRAYER_POTIONS, 1); + antiVenom = new ItemRequirement("Anti-venom", ItemCollections.ANTIVENOMS, 1); golemCombatGear = new ItemRequirement("Crush or ranged combat gear to fight the Golem guard", -1, -1); golemCombatGear.setDisplayItemId(BankSlotIcons.getCombatGear()); golemCombatGear.setConditionToHide(haveKilledGolem); @@ -677,6 +679,7 @@ public List getItemRecommended() return List.of( staminaPotion, prayerPotion, + antiVenom, golemCombatGear, arravCombatGear, food, @@ -821,6 +824,7 @@ public List getPanels() // Recommended staminaPotion, prayerPotion, + antiVenom, food ))); From 9fe58c49738daf5011e4ca4726c93464b2cf8962 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:50:34 +0100 Subject: [PATCH 49/60] remove some comments --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 565d69cc8f..d95481d0ea 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -87,10 +87,6 @@ public class TheCurseOfArrav extends BasicQuestHelper // Recommended items private TeleportItemRequirement fairyRingDLQ; private TeleportItemRequirement lumberyardTeleport; - // trollheim teleport / ghommal's hilt - // antivenom - // melee (crush) combat gear for golem - // ranged combat gear for arrav private ItemRequirement golemCombatGear; private ItemRequirement arravCombatGear; private ItemRequirement food; @@ -98,7 +94,6 @@ public class TheCurseOfArrav extends BasicQuestHelper private ItemRequirement prayerPotion; private ItemRequirement antiVenom; private FreeInventorySlotRequirement twoFreeInventorySlots; - // 2 inv slots // Mid-quest item requirements private ItemRequirement firstMastabaKey; From 353358eb59191ae6e049eaffc18c27659815e7e9 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:53:19 +0100 Subject: [PATCH 50/60] make varbit constant for lever states (since it's used in tests) --- .../thecurseofarrav/TheCurseOfArrav.java | 16 +++++---- .../thecurseofarrav/KeysAndLeversTest.java | 36 ++++++++++--------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index d95481d0ea..90e2661c16 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -66,6 +66,7 @@ import net.runelite.api.ObjectID; import net.runelite.api.QuestState; import net.runelite.api.Skill; +import net.runelite.api.annotations.Varbit; import net.runelite.api.coords.WorldPoint; /** @@ -76,6 +77,9 @@ @SuppressWarnings("FieldCanBeLocal") public class TheCurseOfArrav extends BasicQuestHelper { + static final @Varbit int VARBIT_SOUTH_LEVER_STATE = 11482; + static final @Varbit int VARBIT_NORTH_LEVER_STATE = 11481; + // Required items private ItemRequirement dwellberries3; private ItemRequirement ringOfLife; @@ -332,9 +336,9 @@ public void setupSteps() pullSouthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4553, 0), "Pull the lever to the south-east."); pullSouthLever.addDialogStep("Yes."); getToSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3891, 4554, 0), "Search the Odd markings to the south to get to the south lever. Search the markings again if you fail."); - var needToInsertKeyInSouthLever = new VarbitRequirement(11482, 0); - var needToFlipSouthLever = new VarbitRequirement(11482, 1); - var haveFlippedSouthLever = new VarbitRequirement(11482, 2); + var needToInsertKeyInSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 0); + var needToFlipSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 1); + var haveFlippedSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 2); leaveSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3892, 4554, 0), "Search the Odd markings next to you to get out."); pullSouthLever.addSubSteps(getToSouthLever, leaveSouthLever); @@ -343,9 +347,9 @@ public void setupSteps() getToNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3891, 4597, 0), "Search the Odd markings to the north to get to the north lever. Search the markings again if you fail."); pullNorthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4598, 0), "Pull the lever to the north-east."); pullNorthLever.addDialogStep("Yes."); - var needToInsertKeyInNorthLever = new VarbitRequirement(11481, 0); - var needToFlipNorthLever = new VarbitRequirement(11481, 1); - var haveFlippedNorthLever = new VarbitRequirement(11481, 2); + var needToInsertKeyInNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 0); + var needToFlipNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 1); + var haveFlippedNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 2); leaveNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3892, 4597, 0), "Search the Odd markings next to you to get out."); pullNorthLever.addSubSteps(getToNorthLever, leaveNorthLever); diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java index a2e55c1245..b2f521e0e2 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java @@ -42,6 +42,8 @@ import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; +import static com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav.VARBIT_NORTH_LEVER_STATE; +import static com.questhelper.helpers.quests.thecurseofarrav.TheCurseOfArrav.VARBIT_SOUTH_LEVER_STATE; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @@ -160,7 +162,7 @@ void insertKeyIntoSouthLever() new Item(ItemID.MASTABA_KEY, 1), new Item(ItemID.MASTABA_KEY_30309, 1), }; - when(client.getVarbitValue(11482)).thenReturn(0); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(0); var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); assertEquals(this.helper.pullSouthLever, conditionalStep.getActiveStep()); @@ -172,7 +174,7 @@ void getToSouthLeverAfterInsertingKey1() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY, 1), }; - when(client.getVarbitValue(11482)).thenReturn(1); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(1); var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); assertEquals(this.helper.getToSouthLever, conditionalStep.getActiveStep()); @@ -184,7 +186,7 @@ void getToSouthLeverAfterInsertingKey2() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY_30309, 1), }; - when(client.getVarbitValue(11482)).thenReturn(1); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(1); var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); assertEquals(this.helper.getToSouthLever, conditionalStep.getActiveStep()); @@ -196,7 +198,7 @@ void pullSouthLeverAfterInsertingKey1() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY, 1), }; - when(client.getVarbitValue(11482)).thenReturn(1); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(1); var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); assertEquals(this.helper.pullSouthLever, conditionalStep.getActiveStep()); @@ -208,7 +210,7 @@ void pullSouthLeverAfterInsertingKey2() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY_30309, 1), }; - when(client.getVarbitValue(11482)).thenReturn(1); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(1); var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); assertEquals(this.helper.pullSouthLever, conditionalStep.getActiveStep()); @@ -220,7 +222,7 @@ void leaveSouthLeverAfterInsertingKey1() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY, 1), }; - when(client.getVarbitValue(11482)).thenReturn(2); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); assertEquals(this.helper.leaveSouthLever, conditionalStep.getActiveStep()); @@ -232,7 +234,7 @@ void leaveSouthLeverAfterInsertingKey2() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY_30309, 1), }; - when(client.getVarbitValue(11482)).thenReturn(2); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); assertEquals(this.helper.leaveSouthLever, conditionalStep.getActiveStep()); @@ -244,7 +246,7 @@ void goToNorthLeverAfterPullingSouthLeverKey1() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY, 1), }; - when(client.getVarbitValue(11482)).thenReturn(2); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); assertEquals(this.helper.getToNorthLever, conditionalStep.getActiveStep()); @@ -256,7 +258,7 @@ void goToNorthLeverAfterPullingSouthLeverKey2() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY_30309, 1), }; - when(client.getVarbitValue(11482)).thenReturn(2); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); assertEquals(this.helper.getToNorthLever, conditionalStep.getActiveStep()); @@ -268,7 +270,7 @@ void insertKeyIntoNorthLeverAfterPullingSouthLeverKey1() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY, 1), }; - when(client.getVarbitValue(11482)).thenReturn(2); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); @@ -280,7 +282,7 @@ void insertKeyIntoNorthLeverAfterPullingSouthLeverKey2() var mockedItems = new Item[]{ new Item(ItemID.MASTABA_KEY_30309, 1), }; - when(client.getVarbitValue(11482)).thenReturn(2); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); @@ -291,8 +293,8 @@ void getToSouthLeverAfterInsertingKey() { var mockedItems = new Item[]{ }; - when(client.getVarbitValue(11482)).thenReturn(2); - when(client.getVarbitValue(11481)).thenReturn(1); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); + when(client.getVarbitValue(VARBIT_NORTH_LEVER_STATE)).thenReturn(1); var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); assertEquals(this.helper.getToNorthLever, conditionalStep.getActiveStep()); @@ -303,8 +305,8 @@ void pullNorthLeverAfterPullingSouthLeverKey1() { var mockedItems = new Item[]{ }; - when(client.getVarbitValue(11482)).thenReturn(2); - when(client.getVarbitValue(11481)).thenReturn(1); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); + when(client.getVarbitValue(VARBIT_NORTH_LEVER_STATE)).thenReturn(1); var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); @@ -315,8 +317,8 @@ void pullNorthLeverAfterPullingSouthLeverKey2() { var mockedItems = new Item[]{ }; - when(client.getVarbitValue(11482)).thenReturn(2); - when(client.getVarbitValue(11481)).thenReturn(1); + when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); + when(client.getVarbitValue(VARBIT_NORTH_LEVER_STATE)).thenReturn(1); var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); From 3afeccfcc2b89870d87b75dbd3441037529f46e4 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:53:31 +0100 Subject: [PATCH 51/60] clean up KeysAndLevers test --- .../helpers/quests/thecurseofarrav/KeysAndLeversTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java index b2f521e0e2..09977609b6 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java @@ -55,7 +55,7 @@ public class KeysAndLeversTest extends MockedTest private TheCurseOfArrav helper; @BeforeEach - protected void lol() + protected void preTest() { when(playerStateManager.getAccountType()).thenReturn(AccountType.NORMAL); @@ -75,7 +75,7 @@ protected void lol() } @AfterEach - protected void lel() + protected void postTest() { questPerspectiveMockedStatic.close(); worldPointMockedStatic.close(); From 1241f54d71b8aab613a7d769094d7357799eaa2a Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 18:56:21 +0100 Subject: [PATCH 52/60] reformat tests --- .../helpers/quests/thecurseofarrav/KeysAndLeversTest.java | 3 ++- .../helpers/quests/thecurseofarrav/MetalDoorSolverTest.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java index 09977609b6..279db4a5fe 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java @@ -92,7 +92,8 @@ private ConditionalStep init(WorldPoint playerLocation, Item[] mockedItems) .thenReturn(playerLocation); var mockedItemContainer = Mockito.mock(ItemContainer.class); - if (mockedItems != null) { + if (mockedItems != null) + { when(mockedItemContainer.getItems()).thenReturn(mockedItems); when(client.getItemContainer(InventoryID.INVENTORY)).thenReturn(mockedItemContainer); } diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java index c3d79e91a1..d392301a71 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/MetalDoorSolverTest.java @@ -36,7 +36,7 @@ public class MetalDoorSolverTest public void testValidCodes() { // from pajdonk - assertArrayEquals(new int[]{0, 2, 3, 5},MetalDoorSolver.calculate("IFCB")); + assertArrayEquals(new int[]{0, 2, 3, 5}, MetalDoorSolver.calculate("IFCB")); // from Gupinic assertArrayEquals(new int[]{1, 3, 7, 2}, MetalDoorSolver.calculate("FBDG")); @@ -55,7 +55,7 @@ public void testValidCodes() public void testLowercaseValidCodes() { // from pajdonk - assertArrayEquals(new int[]{0, 2, 3, 5},MetalDoorSolver.calculate("ifcb")); + assertArrayEquals(new int[]{0, 2, 3, 5}, MetalDoorSolver.calculate("ifcb")); // from Gupinic assertArrayEquals(new int[]{1, 3, 7, 2}, MetalDoorSolver.calculate("fbdg")); From 207fcb289dde105340e11bc2a9a428272de8ab51 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sat, 16 Nov 2024 19:01:48 +0100 Subject: [PATCH 53/60] last refactors/requirement polishes --- .../quests/thecurseofarrav/TheCurseOfArrav.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 90e2661c16..b6ae083f1e 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -317,15 +317,13 @@ protected void setupRequirements() public void setupSteps() { - var todo = new NpcStep(this, 5, "TODO XD"); + var unreachableState = new DetailedQuestStep(this, "This state should not be reachable, please make a report with a screenshot in the Quest Helper discord."); startQuest = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Talk to Elias south of Ruins of Uzer to start the quest."); startQuest.addTeleport(fairyRingDLQ); startQuest.addDialogStep("Yes."); - enterTomb = new ObjectStep(this, ObjectID.ENTRY_50201, new WorldPoint(3486, 3023, 0), "Enter the tomb south-west of Elias."); - // TODO: Add item requirements to enterTomb step - // - 2 free inventory slots + enterTomb = new ObjectStep(this, ObjectID.ENTRY_50201, new WorldPoint(3486, 3023, 0), "Enter the tomb south-west of Elias.", dwellberries3, ringOfLife, twoFreeInventorySlots, golemCombatGear); var anyMastabaKey = new ItemRequirement("Mastaba Key", List.of(ItemID.MASTABA_KEY, ItemID.MASTABA_KEY_30309)); @@ -419,7 +417,7 @@ public void setupSteps() combineJarWithDwellberries = new ItemStep(this, "Put the Dwellberries in the Canopic jar.", oilFilledCanopicJar.highlighted(), dwellberries3.highlighted(), ringOfLife); combineJarWithRingOfLife = new ItemStep(this, "Put the Ring of life in the Canopic jar.", oilAndBerryFilledCanopicJar.highlighted(), ringOfLife.highlighted()); - unsortedStep16 = new ConditionalStep(this, todo); + unsortedStep16 = new ConditionalStep(this, unreachableState); unsortedStep16.addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); unsortedStep16.addStep(oilFilledCanopicJar, combineJarWithDwellberries); unsortedStep16.addStep(and(insideTombSecondFloor, finishedTilePuzzle), searchShelvesForUrn); @@ -544,11 +542,12 @@ public void setupSteps() // 9658: 5 -> 6 // need 1 inventory slot free - headToZemouregalsBaseAndTalkToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3341, 3516, 0), "Head to Zemouregal's base east of Varrock's sawmill and talk to Elias.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); // todo add teleport + headToZemouregalsBaseAndTalkToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3341, 3516, 0), "Head to Zemouregal's base east of Varrock's sawmill and talk to Elias.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); headToZemouregalsBaseAndTalkToElias.addDialogStep("Ready when you are."); headToZemouregalsBaseAndTalkToElias.addTeleport(lumberyardTeleport); unsortedStep42 = new ConditionalStep(this, headToZemouregalsBaseAndTalkToElias); - enterZemouregalsBase = new ObjectStep(this, NullObjectID.NULL_50689, new WorldPoint(3343, 3515, 0), "Enter Zemouregal's base east of Varrock's sawmill.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); // todo add teleport + enterZemouregalsBase = new ObjectStep(this, NullObjectID.NULL_50689, new WorldPoint(3343, 3515, 0), "Enter Zemouregal's base east of Varrock's sawmill.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); + enterZemouregalsBase.addTeleport(lumberyardTeleport); getToBackOfZemouregalsBase = new DetailedQuestStep(this, "Make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage."); @@ -809,7 +808,6 @@ public List getPanels() enterBossRoom, fightArrav, finishQuest - // TODO ), List.of( // Requirements basePlans, From c7a457b468f1c25ed6c7fb625885964a0c8829da Mon Sep 17 00:00:00 2001 From: Zoinkwiz Date: Sun, 17 Nov 2024 14:33:06 +0000 Subject: [PATCH 54/60] fix: Simplify mastaba door solution The new solution assumes that the key 30308 always goes with lever 50204, and 30309 goes with 50205. This makes the conditional logic a lot simpler. --- .../thecurseofarrav/TheCurseOfArrav.java | 55 ++++++++----------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index b6ae083f1e..5dcd530e5f 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -43,6 +43,8 @@ import static com.questhelper.requirements.util.LogicHelper.and; import static com.questhelper.requirements.util.LogicHelper.not; import static com.questhelper.requirements.util.LogicHelper.or; + +import com.questhelper.requirements.util.Operation; import com.questhelper.requirements.var.VarbitRequirement; import com.questhelper.requirements.zone.Zone; import com.questhelper.requirements.zone.ZoneRequirement; @@ -325,17 +327,15 @@ public void setupSteps() enterTomb = new ObjectStep(this, ObjectID.ENTRY_50201, new WorldPoint(3486, 3023, 0), "Enter the tomb south-west of Elias.", dwellberries3, ringOfLife, twoFreeInventorySlots, golemCombatGear); - var anyMastabaKey = new ItemRequirement("Mastaba Key", List.of(ItemID.MASTABA_KEY, ItemID.MASTABA_KEY_30309)); - getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton in the cave south of the entrance."); getSecondKey = new ObjectStep(this, ObjectID.SKELETON_50353, new WorldPoint(3880, 4585, 0), "Get the second Mastaba key from the skeleton east of the entrance."); var bySouthLever = new Zone(new WorldPoint(3893, 4554, 0), new WorldPoint(3894, 4552, 0)); var bySouthLeverReq = new ZoneRequirement(bySouthLever); - pullSouthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4553, 0), "Pull the lever to the south-east."); - pullSouthLever.addDialogStep("Yes."); getToSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3891, 4554, 0), "Search the Odd markings to the south to get to the south lever. Search the markings again if you fail."); - var needToInsertKeyInSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 0); - var needToFlipSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 1); + var haveUsedKeyOnSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 1, Operation.GREATER_EQUAL); + pullSouthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4553, 0), "Pull the lever to the south-east.", + secondMastabaKey.hideConditioned(haveUsedKeyOnSouthLever)); + pullSouthLever.addDialogStep("Yes."); var haveFlippedSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 2); leaveSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3892, 4554, 0), "Search the Odd markings next to you to get out."); pullSouthLever.addSubSteps(getToSouthLever, leaveSouthLever); @@ -343,42 +343,31 @@ public void setupSteps() var byNorthLever = new Zone(new WorldPoint(3894, 4597, 0), new WorldPoint(3893, 4599, 0)); var byNorthLeverReq = new ZoneRequirement(byNorthLever); getToNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3891, 4597, 0), "Search the Odd markings to the north to get to the north lever. Search the markings again if you fail."); - pullNorthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4598, 0), "Pull the lever to the north-east."); + var haveUsedKeyOnNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 1, Operation.GREATER_EQUAL); + pullNorthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4598, 0), "Pull the lever to the north-east.", firstMastabaKey.hideConditioned(haveUsedKeyOnNorthLever)); pullNorthLever.addDialogStep("Yes."); - var needToInsertKeyInNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 0); - var needToFlipNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 1); var haveFlippedNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 2); leaveNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3892, 4597, 0), "Search the Odd markings next to you to get out."); pullNorthLever.addSubSteps(getToNorthLever, leaveNorthLever); - // var anyMastabaKey = new ItemRequirements(firstMastabaKey, secondMastabaKey); - var bothMastabaKeys = and(firstMastabaKey, secondMastabaKey); - firstMastabaKey = new ItemRequirement("Mastaba Key", ItemID.MASTABA_KEY); + var haveOrUsedFirstKey = or(firstMastabaKey, haveUsedKeyOnNorthLever); + var haveOrUsedSecondKey = or(secondMastabaKey, haveUsedKeyOnSouthLever); + var haveOrUsedBothKeys = and(haveOrUsedFirstKey, haveOrUsedSecondKey); + + var stepsNearNorthLever = new ConditionalStep(this, leaveNorthLever); + stepsNearNorthLever.addStep(and(haveOrUsedFirstKey, not(haveFlippedNorthLever)), pullNorthLever); - // ADDING THIS CONDITION TO HIDE BREAKS ALL ITEMREQUIREMENT CHECKS HERE?? - // firstMastabaKey.setConditionToHide(not(needToInsertKeyInSouthLever)); - // secondMastabaKey.setConditionToHide(not(needToInsertKeyInNorthLever)); + var stepsNearSouthLever = new ConditionalStep(this, leaveSouthLever); + stepsNearSouthLever.addStep(and(haveOrUsedSecondKey, not(haveFlippedSouthLever)), pullSouthLever); - // This step is complicated because you can use either key for either lever (I think). This could use some testing where the user does not follow instructions and: - // 1. Gets south key, pulls south lever, then what? - // 2. Gets north key, pulls south lever, then what? - // 3. Gets south key, pulls north lever, then what? - // 4. Gets north key, pulls north lever, then what? - // 5. Gets both keys, pulls north lever, then what? unlockImposingDoors = new ConditionalStep(this, enterTomb); unlockImposingDoors.addStep(not(insideTomb), enterTomb); - unlockImposingDoors.addStep(and(haveFlippedSouthLever, bySouthLeverReq), leaveSouthLever); - unlockImposingDoors.addStep(and(haveFlippedNorthLever, byNorthLeverReq), leaveNorthLever); - unlockImposingDoors.addStep(and(needToFlipSouthLever, bySouthLeverReq), pullSouthLever); - unlockImposingDoors.addStep(and(needToFlipNorthLever, byNorthLeverReq), pullNorthLever); - unlockImposingDoors.addStep(and(not(bySouthLeverReq), bothMastabaKeys, needToInsertKeyInSouthLever), getToSouthLever); - unlockImposingDoors.addStep(and(not(bySouthLeverReq), needToFlipSouthLever), getToSouthLever); - unlockImposingDoors.addStep(and(bySouthLeverReq, bothMastabaKeys, needToInsertKeyInSouthLever), pullSouthLever); - unlockImposingDoors.addStep(and(not(byNorthLeverReq), haveFlippedSouthLever, anyMastabaKey, needToInsertKeyInNorthLever), getToNorthLever); - unlockImposingDoors.addStep(and(not(byNorthLeverReq), haveFlippedSouthLever, needToFlipNorthLever), getToNorthLever); - unlockImposingDoors.addStep(and(haveFlippedSouthLever, anyMastabaKey, needToInsertKeyInNorthLever, byNorthLeverReq), pullNorthLever); - unlockImposingDoors.addStep(and(or(needToInsertKeyInNorthLever, needToInsertKeyInSouthLever), not(firstMastabaKey)), getFirstKey); - unlockImposingDoors.addStep(and(or(needToInsertKeyInNorthLever, needToInsertKeyInSouthLever), not(secondMastabaKey)), getSecondKey); + unlockImposingDoors.addStep(bySouthLeverReq, stepsNearSouthLever); + unlockImposingDoors.addStep(byNorthLeverReq, stepsNearNorthLever); + unlockImposingDoors.addStep(and(haveOrUsedBothKeys, not(haveFlippedSouthLever)), getToSouthLever); + unlockImposingDoors.addStep(and(haveOrUsedBothKeys, not(haveFlippedNorthLever)), getToNorthLever); + unlockImposingDoors.addStep(not(haveOrUsedFirstKey), getFirstKey); + unlockImposingDoors.addStep(not(haveOrUsedSecondKey), getSecondKey); // Once the north lever is pulled, quest varbit changed from 6 to 8, then 8 to 10 at the same tick // This might have to do with which order you pulled the levers in From 99891dd09992a02bf237321168e14ba12d69aa27 Mon Sep 17 00:00:00 2001 From: Zoinkwiz Date: Sun, 17 Nov 2024 22:09:01 +0000 Subject: [PATCH 55/60] fix: Simplify tile puzzle in CoA --- .../thecurseofarrav/TilePuzzleSolver.java | 89 +++++-------------- 1 file changed, 22 insertions(+), 67 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java index 4909427b2c..1e8d263eb6 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java @@ -73,13 +73,11 @@ public class TilePuzzleSolver extends DetailedOwnerStep * True if they have had their object IDs filled in. */ private boolean tilesConfigured = false; - private ObjectStep firstObjectStepXD; - private ObjectStep[][] objectSteps; - List shortestPath = null; + List shortestPath = null; private DetailedQuestStep fallbackStep; private QuestStep finishPuzzleStep; - private ObjectStep mostRecentStep = null; + private DetailedQuestStep pathStep; public TilePuzzleSolver(TheCurseOfArrav theCurseOfArrav) { @@ -87,13 +85,13 @@ public TilePuzzleSolver(TheCurseOfArrav theCurseOfArrav) } /** - * @param startX local X coordinate of the tiles array for where to start searching * @param startY local Y coordinate of the tiles array for where to start searching * @return A list of local X/Y coordinates if a path to the end was found */ - private @Nullable List findPath(int startX, int startY) + private @Nullable List findPath(int startY) { - assert (startX >= 0 && startX < SIZE); + int startX = 11; + assert (startY >= 0 && startY < SIZE); assert (this.tilesConfigured); @@ -264,7 +262,7 @@ public void onGameTick(GameTick event) var possiblePaths = new ArrayList>(); for (int y = 0; y < 12; y++) { - var path = this.findPath(11, y); + var path = this.findPath(y); if (path != null) { log.debug("Found possible path starting at {}/{}. Length {}", 11, y, path.size()); @@ -272,11 +270,21 @@ public void onGameTick(GameTick event) } } + var baseX = 3737; + var baseY = 4709; + for (var possiblePath : possiblePaths) { if (this.shortestPath == null || possiblePath.size() < this.shortestPath.size()) { - this.shortestPath = possiblePath; + List line = new ArrayList<>(); + for (int[] tileXY : possiblePath) + { + var wp = new WorldPoint(baseX + tileXY[0], baseY + tileXY[1], 0); + line.add(wp); + } + this.shortestPath = line; + this.pathStep.setLinePoints(this.shortestPath); } } } @@ -293,27 +301,7 @@ public void startUp() @Override protected void setupSteps() { - objectSteps = new ObjectStep[SIZE][SIZE]; - var baseX = 3737; - var baseY = 4709; - var plane = 0; - for (int x = 0; x < SIZE; ++x) - { - var objectText = "Click the tile to pass through the puzzle."; - if (x == 11) { - objectText = "Click the tile to start the puzzle."; - } - for (int y = 0; y < SIZE; ++y) - { - var wp = new WorldPoint(baseX + x, baseY + y, plane); - var objectStep = new ObjectStep(getQuestHelper(), GREEN_TILE, wp, objectText); - objectStep.addAlternateObjects(BLUE_TILE, RED_TILE, YELLOW_TILE); - if (firstObjectStepXD == null) { - firstObjectStepXD = objectStep; - } - objectSteps[x][y] = objectStep; - } - } + pathStep = new DetailedQuestStep(getQuestHelper(), new WorldPoint(3734, 4714, 0), "Click the tiles to pass through the puzzle."); fallbackStep = new DetailedQuestStep(getQuestHelper(), new WorldPoint(3734, 4714, 0), "Unable to figure out a path, click your way across lol"); // TODO @@ -347,33 +335,9 @@ protected void updateSteps() var xInPuzzle = localPoint.getX() - baseX; var yInPuzzle = localPoint.getY() - baseY; - var puzzleStartX = this.shortestPath.get(0)[0]; - var puzzleStartY = this.shortestPath.get(0)[1]; - - if (xInPuzzle >= 0 && xInPuzzle < SIZE && yInPuzzle >= 0 && yInPuzzle < SIZE) { + if (xInPuzzle > 0 && xInPuzzle < SIZE && yInPuzzle >= 0 && yInPuzzle < SIZE) { log.info("Player is in the puzzle, at {}/{}", xInPuzzle, yInPuzzle); - boolean nextIsOurCoolStep = false; - for (var pathPos : this.shortestPath) { - if (nextIsOurCoolStep) { - startUpStep(objectSteps[pathPos[0]][pathPos[1]]); - return; - } - if (pathPos[0] == xInPuzzle && pathPos[1] == yInPuzzle) { - nextIsOurCoolStep = true; - this.mostRecentStep = objectSteps[pathPos[0]][pathPos[1]]; - } - } - if (nextIsOurCoolStep) { - log.info("user is at end"); - startUpStep(finishPuzzleStep); - return; - } - - if (this.mostRecentStep != null) - { - log.debug("user stepped off the path, lead them back"); - startUpStep(this.mostRecentStep); - } + startUpStep(pathStep); } else { log.debug("player is outside of puzzle: {} / {} / {}/{}", playerWp, localPoint, xInPuzzle, yInPuzzle); var userIsPastPuzzle = localPoint.getX() <= 3730 || (localPoint.getX() <= baseX && localPoint.getY() >= 4701); @@ -382,7 +346,7 @@ protected void updateSteps() startUpStep(finishPuzzleStep); } else { // highlight puzzle start - startUpStep(objectSteps[puzzleStartX][puzzleStartY]); + startUpStep(pathStep); } } } @@ -392,16 +356,7 @@ public List getSteps() { var steps = new ArrayList(); steps.add(fallbackStep); - steps.add(firstObjectStepXD); - - for (int x = 0; x < SIZE; ++x) - { - for (int y = 0; y < SIZE; ++y) - { - steps.add(objectSteps[x][y]); - } - } - + steps.add(pathStep); steps.add(finishPuzzleStep); return steps; From cc16c1f1713c9ab624f902e33f58eccc190516f3 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 17 Nov 2024 23:48:22 +0100 Subject: [PATCH 56/60] Remove now-unused tests in KeysAndLeversTest.java --- .../thecurseofarrav/KeysAndLeversTest.java | 72 ------------------- 1 file changed, 72 deletions(-) diff --git a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java index 279db4a5fe..86986ebe6b 100644 --- a/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java +++ b/src/test/java/com/questhelper/helpers/quests/thecurseofarrav/KeysAndLeversTest.java @@ -181,18 +181,6 @@ void getToSouthLeverAfterInsertingKey1() assertEquals(this.helper.getToSouthLever, conditionalStep.getActiveStep()); } - @Test - void getToSouthLeverAfterInsertingKey2() - { - var mockedItems = new Item[]{ - new Item(ItemID.MASTABA_KEY_30309, 1), - }; - when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(1); - var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); - - assertEquals(this.helper.getToSouthLever, conditionalStep.getActiveStep()); - } - @Test void pullSouthLeverAfterInsertingKey1() { @@ -205,18 +193,6 @@ void pullSouthLeverAfterInsertingKey1() assertEquals(this.helper.pullSouthLever, conditionalStep.getActiveStep()); } - @Test - void pullSouthLeverAfterInsertingKey2() - { - var mockedItems = new Item[]{ - new Item(ItemID.MASTABA_KEY_30309, 1), - }; - when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(1); - var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); - - assertEquals(this.helper.pullSouthLever, conditionalStep.getActiveStep()); - } - @Test void leaveSouthLeverAfterInsertingKey1() { @@ -229,18 +205,6 @@ void leaveSouthLeverAfterInsertingKey1() assertEquals(this.helper.leaveSouthLever, conditionalStep.getActiveStep()); } - @Test - void leaveSouthLeverAfterInsertingKey2() - { - var mockedItems = new Item[]{ - new Item(ItemID.MASTABA_KEY_30309, 1), - }; - when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); - var conditionalStep = this.init(new WorldPoint(3893, 4552, 0), mockedItems); - - assertEquals(this.helper.leaveSouthLever, conditionalStep.getActiveStep()); - } - @Test void goToNorthLeverAfterPullingSouthLeverKey1() { @@ -253,18 +217,6 @@ void goToNorthLeverAfterPullingSouthLeverKey1() assertEquals(this.helper.getToNorthLever, conditionalStep.getActiveStep()); } - @Test - void goToNorthLeverAfterPullingSouthLeverKey2() - { - var mockedItems = new Item[]{ - new Item(ItemID.MASTABA_KEY_30309, 1), - }; - when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); - var conditionalStep = this.init(new WorldPoint(3845, 4547, 0), mockedItems); - - assertEquals(this.helper.getToNorthLever, conditionalStep.getActiveStep()); - } - @Test void insertKeyIntoNorthLeverAfterPullingSouthLeverKey1() { @@ -277,18 +229,6 @@ void insertKeyIntoNorthLeverAfterPullingSouthLeverKey1() assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); } - @Test - void insertKeyIntoNorthLeverAfterPullingSouthLeverKey2() - { - var mockedItems = new Item[]{ - new Item(ItemID.MASTABA_KEY_30309, 1), - }; - when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); - var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); - - assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); - } - @Test void getToSouthLeverAfterInsertingKey() { @@ -312,16 +252,4 @@ void pullNorthLeverAfterPullingSouthLeverKey1() assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); } - - @Test - void pullNorthLeverAfterPullingSouthLeverKey2() - { - var mockedItems = new Item[]{ - }; - when(client.getVarbitValue(VARBIT_SOUTH_LEVER_STATE)).thenReturn(2); - when(client.getVarbitValue(VARBIT_NORTH_LEVER_STATE)).thenReturn(1); - var conditionalStep = this.init(new WorldPoint(3894, 4597, 0), mockedItems); - - assertEquals(this.helper.pullNorthLever, conditionalStep.getActiveStep()); - } } From 598a17a91f822940b13dd090e96f4bebd21ed942 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Sun, 17 Nov 2024 23:50:51 +0100 Subject: [PATCH 57/60] replace log.info with log.debug --- .../helpers/quests/thecurseofarrav/TilePuzzleSolver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java index 1e8d263eb6..58705801d1 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TilePuzzleSolver.java @@ -336,7 +336,7 @@ protected void updateSteps() var yInPuzzle = localPoint.getY() - baseY; if (xInPuzzle > 0 && xInPuzzle < SIZE && yInPuzzle >= 0 && yInPuzzle < SIZE) { - log.info("Player is in the puzzle, at {}/{}", xInPuzzle, yInPuzzle); + log.debug("Player is in the puzzle, at {}/{}", xInPuzzle, yInPuzzle); startUpStep(pathStep); } else { log.debug("player is outside of puzzle: {} / {} / {}/{}", playerWp, localPoint, xInPuzzle, yInPuzzle); From f8723320d271302a97189f93b2e9afca05ed6fbd Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Mon, 18 Nov 2024 22:59:29 +0100 Subject: [PATCH 58/60] Clean up teleport recommendations in sections --- .../quests/thecurseofarrav/TheCurseOfArrav.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 5dcd530e5f..59b95b8fbe 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -93,6 +93,7 @@ public class TheCurseOfArrav extends BasicQuestHelper // Recommended items private TeleportItemRequirement fairyRingDLQ; private TeleportItemRequirement lumberyardTeleport; + private TeleportItemRequirement trollheimTeleport; private ItemRequirement golemCombatGear; private ItemRequirement arravCombatGear; private ItemRequirement food; @@ -432,7 +433,7 @@ public void setupSteps() unsortedStep18.addStep(insideTomb, returnToEliasByWalkingMidway); // ardy cloak + fairy ring takes 50s, walking takes 1m12s - var trollheimTeleport = new TeleportItemRequirement("Trollheim Teleport", ItemID.TROLLHEIM_TELEPORT); + trollheimTeleport = new TeleportItemRequirement("Trollheim Teleport", ItemID.TROLLHEIM_TELEPORT); trollheimTeleport.addAlternates(ItemCollections.GHOMMALS_HILT); headToTrollheim = new ObjectStep(this, ObjectID.CAVE_ENTRANCE_5007, new WorldPoint(2821, 3744, 0), "Enter the cave next to Trollheim. You can use a Trollheim teleport tablet or the GWD Ghommal's Hilt teleport to get close.", anyPickaxe); headToTrollheim.addTeleport(trollheimTeleport); @@ -670,8 +671,9 @@ public List getItemRecommended() golemCombatGear, arravCombatGear, food, - lumberyardTeleport, - fairyRingDLQ + fairyRingDLQ, + trollheimTeleport, + lumberyardTeleport ); } @@ -762,6 +764,7 @@ public List getPanels() ), List.of( // Recommended twoFreeInventorySlots, + fairyRingDLQ, staminaPotion, prayerPotion, food @@ -774,17 +777,19 @@ public List getPanels() climbUpstairsAndTalkToArrav, talkToArrav, goToNextRoom, - searchTapestry + searchTapestry, + returnToEliasWithBaseItems ), List.of( // Requirements anyPickaxe ), List.of( // Recommended + fairyRingDLQ, + trollheimTeleport, staminaPotion ))); panels.add(new PanelDetails("Hearty Heist", List.of( // Steps - returnToEliasWithBaseItems, headToZemouregalsBaseAndTalkToElias, enterZemouregalsBase, getToBackOfZemouregalsBase, @@ -808,6 +813,7 @@ public List getPanels() canopicJarFullForHeist ), List.of( // Recommended + lumberyardTeleport, staminaPotion, prayerPotion, antiVenom, From 0977c73f2a080bf5c53ac4f74bc5c045b6793a77 Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Mon, 18 Nov 2024 23:09:43 +0100 Subject: [PATCH 59/60] fix NPE on launch --- .../helpers/quests/thecurseofarrav/TheCurseOfArrav.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index 59b95b8fbe..f04eaad1fd 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -92,8 +92,8 @@ public class TheCurseOfArrav extends BasicQuestHelper // Recommended items private TeleportItemRequirement fairyRingDLQ; - private TeleportItemRequirement lumberyardTeleport; private TeleportItemRequirement trollheimTeleport; + private TeleportItemRequirement lumberyardTeleport; private ItemRequirement golemCombatGear; private ItemRequirement arravCombatGear; private ItemRequirement food; @@ -297,6 +297,8 @@ protected void setupRequirements() // Recommended items fairyRingDLQ = new TeleportItemRequirement("Fairy Ring [DLQ]", ItemCollections.FAIRY_STAFF); + trollheimTeleport = new TeleportItemRequirement("Trollheim Teleport", ItemID.TROLLHEIM_TELEPORT); + trollheimTeleport.addAlternates(ItemCollections.GHOMMALS_HILT); lumberyardTeleport = new TeleportItemRequirement("Lumberyard teleport", ItemID.LUMBERYARD_TELEPORT); staminaPotion = new ItemRequirement("Stamina potion", ItemCollections.STAMINA_POTIONS, 1); prayerPotion = new ItemRequirement("Prayer potion", ItemCollections.PRAYER_POTIONS, 1); @@ -433,8 +435,6 @@ public void setupSteps() unsortedStep18.addStep(insideTomb, returnToEliasByWalkingMidway); // ardy cloak + fairy ring takes 50s, walking takes 1m12s - trollheimTeleport = new TeleportItemRequirement("Trollheim Teleport", ItemID.TROLLHEIM_TELEPORT); - trollheimTeleport.addAlternates(ItemCollections.GHOMMALS_HILT); headToTrollheim = new ObjectStep(this, ObjectID.CAVE_ENTRANCE_5007, new WorldPoint(2821, 3744, 0), "Enter the cave next to Trollheim. You can use a Trollheim teleport tablet or the GWD Ghommal's Hilt teleport to get close.", anyPickaxe); headToTrollheim.addTeleport(trollheimTeleport); From 18b2d0038e1e0016b7e1ae091a675bf052c84b8c Mon Sep 17 00:00:00 2001 From: Rasmus Karlsson Date: Mon, 18 Nov 2024 23:56:57 +0100 Subject: [PATCH 60/60] final polish --- .../thecurseofarrav/TheCurseOfArrav.java | 334 +++++++++--------- 1 file changed, 172 insertions(+), 162 deletions(-) diff --git a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java index f04eaad1fd..5db2c36fab 100644 --- a/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java +++ b/src/main/java/com/questhelper/helpers/quests/thecurseofarrav/TheCurseOfArrav.java @@ -112,14 +112,33 @@ public class TheCurseOfArrav extends BasicQuestHelper // Zones & their requirements /// Top floor of the tomb (Uzer Mastaba) private ZoneRequirement insideTomb; + /// Top floor of the tomb (Uzer Mastaba) by the south lever + ZoneRequirement bySouthLever; + /// Top floor of the tomb (Uzer Mastaba) by the north lever + ZoneRequirement byNorthLever; + /// Top floor of the tomb (Uzer Mastaba) in the room with the Golem guard + ZoneRequirement insideGolemArena; /// Second floor of the tomb (Uzer Mastaba) private ZoneRequirement insideTombSecondFloor; + ZoneRequirement inTrollheimCave; + ZoneRequirement onTrollweissMountain; + ZoneRequirement inTrollweissCave; + ZoneRequirement inArravHouseFirstRoom; + ZoneRequirement inArravHouseSecondRoom; private ZoneRequirement inZemouregalsBaseSection1; private ZoneRequirement inZemouregalsBaseSection2; private ZoneRequirement inZemouregalsBaseSection3; private ZoneRequirement inZemouregalsBaseSection4; private ZoneRequirement inZemouregalsBaseKitchen; private ZoneRequirement inZemouregalsBaseSewer; + /// After exiting the sewer of Zemouregal's base + ZoneRequirement inZemouregalsBaseSecondPart; + /// In the storage room after exiting the sewer of Zemouregal's base + ZoneRequirement inStorageRoom; + /// Past the Metal door in Zemouregal's base + ZoneRequirement inGrapplePuzzleRoom; + /// Past the Grapple puzzle in Zemouregal's base + ZoneRequirement pastGrapplePuzzleRoom; // Steps /// 0 + 2 @@ -146,22 +165,21 @@ public class TheCurseOfArrav extends BasicQuestHelper private PuzzleWrapperStep solveTilePuzzle; private ObjectStep searchShelvesForUrn; private ObjectStep inspectMurals; - private ConditionalStep unsortedStep16; - private ConditionalStep unsortedStep18; - private ConditionalStep unsortedStep20; - private ConditionalStep unsortedStep24; - private ConditionalStep unsortedStep26; - private ConditionalStep unsortedStep28; - private ConditionalStep unsortedStep30; - private ConditionalStep unsortedStep32; - private ConditionalStep unsortedStep34; - private ConditionalStep unsortedStep42; - private ConditionalStep unsortedStep44; - private ConditionalStep unsortedStep46; - private ConditionalStep unsortedStep48; - private ConditionalStep unsortedStep52; - private ConditionalStep unsortedStep54; - private ConditionalStep unsortedStep56; + private ConditionalStep fillCanopicJar; + private ConditionalStep showCanopicJarToElias; + private ConditionalStep goThroughTrollweissCave1; + private ConditionalStep goThroughTrollweissCave2; + private ConditionalStep goThroughTrollweissCave3; + private ConditionalStep goThroughTrollweissCave4; + private ConditionalStep climbUpToZemouregalsFort; + private ConditionalStep confrontArravInZemouregalsFort; + private ConditionalStep stealBaseKeyForHeist; + private ConditionalStep unlockDoorInZemouregalsBase; + private ConditionalStep getToBackroomsOfZemouregalsBase; + private ConditionalStep unlockMetalDoor; + private ConditionalStep attemptToStealHeart; + private ConditionalStep actuallyConfrontArrav; + private ConditionalStep watchYourVictoryDialog; private NpcStep finishQuest; private PuzzleWrapperStep rubbleMiner1; @@ -203,6 +221,10 @@ public class TheCurseOfArrav extends BasicQuestHelper NpcStep talkToArrav; ObjectStep goToNextRoom; ObjectStep searchTapestry; + VarbitRequirement haveUsedKeyOnSouthLever; + VarbitRequirement haveFlippedSouthLever; + VarbitRequirement haveUsedKeyOnNorthLever; + VarbitRequirement haveFlippedNorthLever; @Override @@ -221,27 +243,27 @@ public Map loadSteps() steps.put(10, fightGolemCond); steps.put(12, finishTilePuzzleAndGetCanopicJar); steps.put(14, finishTilePuzzleAndGetCanopicJar); - steps.put(16, unsortedStep16); - steps.put(18, unsortedStep18); - steps.put(20, unsortedStep20); - steps.put(22, unsortedStep20); - steps.put(24, unsortedStep24); - steps.put(26, unsortedStep26); - steps.put(28, unsortedStep28); - steps.put(30, unsortedStep30); - steps.put(32, unsortedStep32); - steps.put(34, unsortedStep34); + steps.put(16, fillCanopicJar); + steps.put(18, showCanopicJarToElias); + steps.put(20, goThroughTrollweissCave1); + steps.put(22, goThroughTrollweissCave1); + steps.put(24, goThroughTrollweissCave2); + steps.put(26, goThroughTrollweissCave3); + steps.put(28, goThroughTrollweissCave4); + steps.put(30, climbUpToZemouregalsFort); + steps.put(32, confrontArravInZemouregalsFort); + steps.put(34, stealBaseKeyForHeist); steps.put(36, returnToEliasWithBaseItems); steps.put(38, interpretPlansWithElias); steps.put(40, interpretPlansWithElias); - steps.put(42, unsortedStep42); - steps.put(44, unsortedStep44); - steps.put(46, unsortedStep46); - steps.put(48, unsortedStep48); - steps.put(50, unsortedStep48); - steps.put(52, unsortedStep52); - steps.put(54, unsortedStep54); - steps.put(56, unsortedStep56); + steps.put(42, headToZemouregalsBaseAndTalkToElias); + steps.put(44, unlockDoorInZemouregalsBase); + steps.put(46, getToBackroomsOfZemouregalsBase); + steps.put(48, unlockMetalDoor); + steps.put(50, unlockMetalDoor); + steps.put(52, attemptToStealHeart); + steps.put(54, actuallyConfrontArrav); + steps.put(56, watchYourVictoryDialog); steps.put(58, finishQuest); return steps; @@ -251,11 +273,20 @@ public Map loadSteps() protected void setupZones() { insideTomb = new ZoneRequirement(new Zone(new WorldPoint(3842, 4547, 0), new WorldPoint(3900, 4603, 0))); + bySouthLever = new ZoneRequirement(new Zone(new WorldPoint(3893, 4554, 0), new WorldPoint(3894, 4552, 0))); + byNorthLever = new ZoneRequirement(new Zone(new WorldPoint(3894, 4597, 0), new WorldPoint(3893, 4599, 0))); + insideGolemArena = new ZoneRequirement(new Zone(new WorldPoint(3856, 4592, 0), new WorldPoint(3884, 4599, 0))); insideTombSecondFloor = new ZoneRequirement( new Zone(new WorldPoint(3719, 4674, 0), new WorldPoint(3770, 4732, 0)), new Zone(new WorldPoint(3845, 4674, 0), new WorldPoint(3900, 4732, 0)) ); + inTrollheimCave = new ZoneRequirement(new Zone(11167)); + onTrollweissMountain = new ZoneRequirement(new Zone(11068)); + inTrollweissCave = new ZoneRequirement(new Zone(11168)); + inArravHouseFirstRoom = new ZoneRequirement(new Zone(new WorldPoint(2848, 3868, 0), new WorldPoint(2858, 3873, 0))); + inArravHouseSecondRoom = new ZoneRequirement(new Zone(new WorldPoint(2863, 3865, 0), new WorldPoint(2859, 3873, 0))); + // Right as you head into the base inZemouregalsBaseSection1 = new ZoneRequirement(new Zone(new WorldPoint(3536, 4577, 0), new WorldPoint(3564, 4547, 0))); // After you've passed the first door @@ -269,11 +300,20 @@ protected void setupZones() inZemouregalsBaseSection4 = new ZoneRequirement(new Zone(new WorldPoint(3577, 4615, 0), new WorldPoint(3605, 4592, 0))); inZemouregalsBaseKitchen = new ZoneRequirement(new Zone(new WorldPoint(3613, 4604, 0), new WorldPoint(3606, 4598, 0))); inZemouregalsBaseSewer = new ZoneRequirement(new Zone(14919)); + + inZemouregalsBaseSecondPart = new ZoneRequirement(new Zone(new WorldPoint(3590, 4538, 0), new WorldPoint(3622, 4597, 0))); + inStorageRoom = new ZoneRequirement(new Zone(new WorldPoint(3614, 4571, 0), new WorldPoint(3605, 4563, 0))); + inGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3613, 4587, 0), new WorldPoint(3625, 4579, 0))); + pastGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3621, 4589, 0), new WorldPoint(3645, 4578, 0))); } @Override protected void setupRequirements() { + haveUsedKeyOnSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 1, Operation.GREATER_EQUAL); + haveFlippedSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 2); + haveUsedKeyOnNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 1, Operation.GREATER_EQUAL); + haveFlippedNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 2); haveKilledGolem = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 12); finishedTilePuzzle = new VarbitRequirement(11483, 1); haveMadeCanopicJar = new QuestRequirement(QuestHelperQuest.THE_CURSE_OF_ARRAV, 18); @@ -332,24 +372,16 @@ public void setupSteps() getFirstKey = new ObjectStep(this, ObjectID.SKELETON_50350, new WorldPoint(3875, 4554, 0), "Get the first Mastaba key from the skeleton in the cave south of the entrance."); getSecondKey = new ObjectStep(this, ObjectID.SKELETON_50353, new WorldPoint(3880, 4585, 0), "Get the second Mastaba key from the skeleton east of the entrance."); - var bySouthLever = new Zone(new WorldPoint(3893, 4554, 0), new WorldPoint(3894, 4552, 0)); - var bySouthLeverReq = new ZoneRequirement(bySouthLever); getToSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3891, 4554, 0), "Search the Odd markings to the south to get to the south lever. Search the markings again if you fail."); - var haveUsedKeyOnSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 1, Operation.GREATER_EQUAL); pullSouthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4553, 0), "Pull the lever to the south-east.", secondMastabaKey.hideConditioned(haveUsedKeyOnSouthLever)); pullSouthLever.addDialogStep("Yes."); - var haveFlippedSouthLever = new VarbitRequirement(VARBIT_SOUTH_LEVER_STATE, 2); leaveSouthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3892, 4554, 0), "Search the Odd markings next to you to get out."); pullSouthLever.addSubSteps(getToSouthLever, leaveSouthLever); - var byNorthLever = new Zone(new WorldPoint(3894, 4597, 0), new WorldPoint(3893, 4599, 0)); - var byNorthLeverReq = new ZoneRequirement(byNorthLever); getToNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50208, new WorldPoint(3891, 4597, 0), "Search the Odd markings to the north to get to the north lever. Search the markings again if you fail."); - var haveUsedKeyOnNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 1, Operation.GREATER_EQUAL); pullNorthLever = new ObjectStep(this, ObjectID.LEVER_50205, new WorldPoint(3894, 4598, 0), "Pull the lever to the north-east.", firstMastabaKey.hideConditioned(haveUsedKeyOnNorthLever)); pullNorthLever.addDialogStep("Yes."); - var haveFlippedNorthLever = new VarbitRequirement(VARBIT_NORTH_LEVER_STATE, 2); leaveNorthLever = new ObjectStep(this, ObjectID.ODD_MARKINGS_50207, new WorldPoint(3892, 4597, 0), "Search the Odd markings next to you to get out."); pullNorthLever.addSubSteps(getToNorthLever, leaveNorthLever); @@ -365,8 +397,8 @@ public void setupSteps() unlockImposingDoors = new ConditionalStep(this, enterTomb); unlockImposingDoors.addStep(not(insideTomb), enterTomb); - unlockImposingDoors.addStep(bySouthLeverReq, stepsNearSouthLever); - unlockImposingDoors.addStep(byNorthLeverReq, stepsNearNorthLever); + unlockImposingDoors.addStep(bySouthLever, stepsNearSouthLever); + unlockImposingDoors.addStep(byNorthLever, stepsNearNorthLever); unlockImposingDoors.addStep(and(haveOrUsedBothKeys, not(haveFlippedSouthLever)), getToSouthLever); unlockImposingDoors.addStep(and(haveOrUsedBothKeys, not(haveFlippedNorthLever)), getToNorthLever); unlockImposingDoors.addStep(not(haveOrUsedFirstKey), getFirstKey); @@ -375,16 +407,14 @@ public void setupSteps() // Once the north lever is pulled, quest varbit changed from 6 to 8, then 8 to 10 at the same tick // This might have to do with which order you pulled the levers in - var golemArenaZone = new Zone(new WorldPoint(3856, 4592, 0), new WorldPoint(3884, 4599, 0)); - var insideGolenArena = new ZoneRequirement(golemArenaZone); enterGolemArena = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Open the imposing doors, ready to fight the Golem guard."); fightGolemGuard = new NpcStep(this, NpcID.GOLEM_GUARD, new WorldPoint(3860, 4595, 0), "Fight the Golem guard. It is weak to crush style weapons. Use Protect from Melee to avoid damage from his attacks. When the screen shakes, step away from him to avoid taking damage."); fightGolemCond = new ConditionalStep(this, enterGolemArena); // Get inside the tomb if you're not already inside. In case the user has teleported out or died to golem? fightGolemCond.addStep(not(insideTomb), enterTomb); - fightGolemCond.addStep(byNorthLeverReq, leaveNorthLever); - fightGolemCond.addStep(bySouthLeverReq, leaveSouthLever); - fightGolemCond.addStep(insideGolenArena, fightGolemGuard); + fightGolemCond.addStep(byNorthLever, leaveNorthLever); + fightGolemCond.addStep(bySouthLever, leaveSouthLever); + fightGolemCond.addStep(insideGolemArena, fightGolemGuard); var enterGolemArenaWithoutFight = new ObjectStep(this, ObjectID.IMPOSING_DOORS_50211, new WorldPoint(3885, 4597, 0), "Open the imposing doors to the north-east of the tomb."); enterTombBasement = new ObjectStep(this, ObjectID.STAIRS_55785, new WorldPoint(3860, 4596, 0), "Climb the stairs down the tomb basement."); @@ -401,7 +431,7 @@ public void setupSteps() finishTilePuzzleAndGetCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle, oilFilledCanopicJar), inspectMurals); finishTilePuzzleAndGetCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle), searchShelvesForUrn); finishTilePuzzleAndGetCanopicJar.addStep(insideTombSecondFloor, solveTilePuzzle); - finishTilePuzzleAndGetCanopicJar.addStep(and(insideTomb, insideGolenArena), enterTombBasement); + finishTilePuzzleAndGetCanopicJar.addStep(and(insideTomb, insideGolemArena), enterTombBasement); finishTilePuzzleAndGetCanopicJar.addStep(and(insideTomb), enterGolemArenaWithoutFight); var oilAndBerryFilledCanopicJar = new ItemRequirement("Canopic jar (oil and berries)", ItemID.CANOPIC_JAR_OIL_AND_BERRIES); @@ -409,13 +439,13 @@ public void setupSteps() combineJarWithDwellberries = new ItemStep(this, "Put the Dwellberries in the Canopic jar.", oilFilledCanopicJar.highlighted(), dwellberries3.highlighted(), ringOfLife); combineJarWithRingOfLife = new ItemStep(this, "Put the Ring of life in the Canopic jar.", oilAndBerryFilledCanopicJar.highlighted(), ringOfLife.highlighted()); - unsortedStep16 = new ConditionalStep(this, unreachableState); - unsortedStep16.addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); - unsortedStep16.addStep(oilFilledCanopicJar, combineJarWithDwellberries); - unsortedStep16.addStep(and(insideTombSecondFloor, finishedTilePuzzle), searchShelvesForUrn); - unsortedStep16.addStep(not(insideTomb), enterTomb); - unsortedStep16.addStep(and(insideTomb, insideGolenArena), enterTombBasement); - unsortedStep16.addStep(and(insideTomb), enterGolemArenaWithoutFight); + fillCanopicJar = new ConditionalStep(this, unreachableState); + fillCanopicJar.addStep(oilAndBerryFilledCanopicJar, combineJarWithRingOfLife); + fillCanopicJar.addStep(oilFilledCanopicJar, combineJarWithDwellberries); + fillCanopicJar.addStep(and(insideTombSecondFloor, finishedTilePuzzle), searchShelvesForUrn); + fillCanopicJar.addStep(not(insideTomb), enterTomb); + fillCanopicJar.addStep(and(insideTomb, insideGolemArena), enterTombBasement); + fillCanopicJar.addStep(and(insideTomb), enterGolemArenaWithoutFight); returnToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Return to Elias south of Ruins of Uzer, either by walking out of the tomb or using the fairy ring.", canopicJarFull); @@ -429,26 +459,19 @@ public void setupSteps() returnToElias.addSubSteps(returnToEliasByWalking, returnToEliasByWalkingMidway, returnToEliasByWalkingMidwayGolem); - unsortedStep18 = new ConditionalStep(this, returnToElias); - unsortedStep18.addStep(insideTombSecondFloor, returnToEliasByWalking); - unsortedStep18.addStep(insideGolenArena, returnToEliasByWalkingMidwayGolem); - unsortedStep18.addStep(insideTomb, returnToEliasByWalkingMidway); + showCanopicJarToElias = new ConditionalStep(this, returnToElias); + showCanopicJarToElias.addStep(insideTombSecondFloor, returnToEliasByWalking); + showCanopicJarToElias.addStep(insideGolemArena, returnToEliasByWalkingMidwayGolem); + showCanopicJarToElias.addStep(insideTomb, returnToEliasByWalkingMidway); // ardy cloak + fairy ring takes 50s, walking takes 1m12s headToTrollheim = new ObjectStep(this, ObjectID.CAVE_ENTRANCE_5007, new WorldPoint(2821, 3744, 0), "Enter the cave next to Trollheim. You can use a Trollheim teleport tablet or the GWD Ghommal's Hilt teleport to get close.", anyPickaxe); headToTrollheim.addTeleport(trollheimTeleport); - var trollheimCave = new Zone(11167); - var inTrollheimCave = new ZoneRequirement(trollheimCave); continueThroughTrollheimCave = new ObjectStep(this, ObjectID.CREVASSE, new WorldPoint(2772, 10233, 0), "Continue through the Trollheim cave, exiting at the Crevasse to the north-west. Use Protect from Melee to avoid taking damage from the Ice Trolls.", anyPickaxe); - var trollweissMountain = new Zone(11068); - var onTrollweissMountain = new ZoneRequirement(trollweissMountain); enterTrollweissCave = new ObjectStep(this, ObjectID.CAVE_55779, new WorldPoint(2809, 3861, 0), "Enter the Trollweiss cave to the east.", anyPickaxe); - var trollweissCave1 = new Zone(11168); - var inTrollweissCave = new ZoneRequirement(trollweissCave1); - var rubbleMiner1Real = new RubbleSolverOne(this); var rubbleMiner2Real = new RubbleSolverTwo(this); var rubbleMiner3Real = new RubbleSolverThree(this); @@ -462,55 +485,48 @@ public void setupSteps() rubbleMiner1Real.addSubSteps(rubbleMiner2, rubbleMiner3, rubbleMiner4); - unsortedStep20 = new ConditionalStep(this, headToTrollheim); - unsortedStep20.addStep(inTrollweissCave, rubbleMiner1); - unsortedStep20.addStep(onTrollweissMountain, enterTrollweissCave); - unsortedStep20.addStep(inTrollheimCave, continueThroughTrollheimCave); + goThroughTrollweissCave1 = new ConditionalStep(this, headToTrollheim); + goThroughTrollweissCave1.addStep(inTrollweissCave, rubbleMiner1); + goThroughTrollweissCave1.addStep(onTrollweissMountain, enterTrollweissCave); + goThroughTrollweissCave1.addStep(inTrollheimCave, continueThroughTrollheimCave); - unsortedStep24 = new ConditionalStep(this, headToTrollheim); - unsortedStep24.addStep(inTrollweissCave, rubbleMiner2); - unsortedStep24.addStep(onTrollweissMountain, enterTrollweissCave); - unsortedStep24.addStep(inTrollheimCave, continueThroughTrollheimCave); + goThroughTrollweissCave2 = new ConditionalStep(this, headToTrollheim); + goThroughTrollweissCave2.addStep(inTrollweissCave, rubbleMiner2); + goThroughTrollweissCave2.addStep(onTrollweissMountain, enterTrollweissCave); + goThroughTrollweissCave2.addStep(inTrollheimCave, continueThroughTrollheimCave); - unsortedStep26 = new ConditionalStep(this, headToTrollheim); - unsortedStep26.addStep(inTrollweissCave, rubbleMiner3); - unsortedStep26.addStep(onTrollweissMountain, enterTrollweissCave); - unsortedStep26.addStep(inTrollheimCave, continueThroughTrollheimCave); - - unsortedStep28 = new ConditionalStep(this, headToTrollheim); - unsortedStep28.addStep(inTrollweissCave, rubbleMiner4); - unsortedStep28.addStep(onTrollweissMountain, enterTrollweissCave); - unsortedStep28.addStep(inTrollheimCave, continueThroughTrollheimCave); + goThroughTrollweissCave3 = new ConditionalStep(this, headToTrollheim); + goThroughTrollweissCave3.addStep(inTrollweissCave, rubbleMiner3); + goThroughTrollweissCave3.addStep(onTrollweissMountain, enterTrollweissCave); + goThroughTrollweissCave3.addStep(inTrollheimCave, continueThroughTrollheimCave); + goThroughTrollweissCave4 = new ConditionalStep(this, headToTrollheim); + goThroughTrollweissCave4.addStep(inTrollweissCave, rubbleMiner4); + goThroughTrollweissCave4.addStep(onTrollweissMountain, enterTrollweissCave); + goThroughTrollweissCave4.addStep(inTrollheimCave, continueThroughTrollheimCave); climbUpstairsAndTalkToArrav = new ObjectStep(this, ObjectID.STAIRS_50508, new WorldPoint(2811, 10267, 0), "Climb up the stairs in the room with the red tile floor and talk to Arrav."); - unsortedStep30 = new ConditionalStep(this, headToTrollheim); - unsortedStep30.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); - unsortedStep30.addStep(onTrollweissMountain, enterTrollweissCave); - unsortedStep30.addStep(inTrollheimCave, continueThroughTrollheimCave); + climbUpToZemouregalsFort = new ConditionalStep(this, headToTrollheim); + climbUpToZemouregalsFort.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); + climbUpToZemouregalsFort.addStep(onTrollweissMountain, enterTrollweissCave); + climbUpToZemouregalsFort.addStep(inTrollheimCave, continueThroughTrollheimCave); - var arravHouseFirstRoom = new Zone(new WorldPoint(2848, 3868, 0), new WorldPoint(2858, 3873, 0)); - var inArravHouseFirstRoom = new ZoneRequirement(arravHouseFirstRoom); talkToArrav = new NpcStep(this, NpcID.ARRAV_14129, new WorldPoint(2856, 3871, 0), "Talk to Arrav."); - unsortedStep32 = new ConditionalStep(this, headToTrollheim); - unsortedStep32.addStep(inArravHouseFirstRoom, talkToArrav); - unsortedStep32.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); - unsortedStep32.addStep(onTrollweissMountain, enterTrollweissCave); - unsortedStep32.addStep(inTrollheimCave, continueThroughTrollheimCave); - - var arravHouseSecondRoom = new Zone(new WorldPoint(2863, 3865, 0), new WorldPoint(2859, 3873, 0)); - var inArravHouseSecondRoom = new ZoneRequirement(arravHouseSecondRoom); + confrontArravInZemouregalsFort = new ConditionalStep(this, headToTrollheim); + confrontArravInZemouregalsFort.addStep(inArravHouseFirstRoom, talkToArrav); + confrontArravInZemouregalsFort.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); + confrontArravInZemouregalsFort.addStep(onTrollweissMountain, enterTrollweissCave); + confrontArravInZemouregalsFort.addStep(inTrollheimCave, continueThroughTrollheimCave); goToNextRoom = new ObjectStep(this, ObjectID.DOOR_50514, new WorldPoint(2859, 3870, 0), "Enter the room to your east and search the tapestry for something to help you with your heist."); searchTapestry = new ObjectStep(this, ObjectID.TAPESTRY_50516, new WorldPoint(2861, 3865, 0), "Search the tapestry in the south of the room."); - unsortedStep34 = new ConditionalStep(this, headToTrollheim); - unsortedStep34.addStep(inArravHouseSecondRoom, searchTapestry); - unsortedStep34.addStep(inArravHouseFirstRoom, goToNextRoom); - unsortedStep34.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); - unsortedStep34.addStep(onTrollweissMountain, enterTrollweissCave); - unsortedStep34.addStep(inTrollheimCave, continueThroughTrollheimCave); - + stealBaseKeyForHeist = new ConditionalStep(this, headToTrollheim); + stealBaseKeyForHeist.addStep(inArravHouseSecondRoom, searchTapestry); + stealBaseKeyForHeist.addStep(inArravHouseFirstRoom, goToNextRoom); + stealBaseKeyForHeist.addStep(inTrollweissCave, climbUpstairsAndTalkToArrav); + stealBaseKeyForHeist.addStep(onTrollweissMountain, enterTrollweissCave); + stealBaseKeyForHeist.addStep(inTrollheimCave, continueThroughTrollheimCave); var tapestryFindText = "Can be acquired by heading back to Zemouregal's Fort past the Trollweiss mining dungeon and searching the tapestry."; basePlans = new ItemRequirement("Base plans", ItemID.BASE_PLANS); @@ -531,11 +547,9 @@ public void setupSteps() // 40 -> 42 // 9658: 5 -> 6 - // need 1 inventory slot free headToZemouregalsBaseAndTalkToElias = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3341, 3516, 0), "Head to Zemouregal's base east of Varrock's sawmill and talk to Elias.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); headToZemouregalsBaseAndTalkToElias.addDialogStep("Ready when you are."); headToZemouregalsBaseAndTalkToElias.addTeleport(lumberyardTeleport); - unsortedStep42 = new ConditionalStep(this, headToZemouregalsBaseAndTalkToElias); enterZemouregalsBase = new ObjectStep(this, NullObjectID.NULL_50689, new WorldPoint(3343, 3515, 0), "Enter Zemouregal's base east of Varrock's sawmill.", anyGrappleableCrossbow, mithrilGrapple, arravCombatGear, insulatedBoots, canopicJarFullForHeist, baseKey); enterZemouregalsBase.addTeleport(lumberyardTeleport); @@ -546,10 +560,10 @@ public void setupSteps() var passZemouregalsBaseDoor3 = new ObjectStep(this, ObjectID.DOOR_50152, new WorldPoint(3576, 4604, 0), "Open the door and make your way to the back of Zemouregal's base. Protect from Melee against the zombies to avoid most damage.", baseKey, canopicJarFullForHeist, insulatedBoots); var passZemouregalsBaseDoor4 = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3605, 4603, 0), "Open the gate and make your way to the back of Zemouregal's base.", canopicJarFullForHeist, insulatedBoots); - unsortedStep44 = new ConditionalStep(this, enterZemouregalsBase); - unsortedStep44.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - unsortedStep44.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - unsortedStep44.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + unlockDoorInZemouregalsBase = new ConditionalStep(this, enterZemouregalsBase); + unlockDoorInZemouregalsBase.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + unlockDoorInZemouregalsBase.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + unlockDoorInZemouregalsBase.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); var enterZemouregalsBaseSewer = new ObjectStep(this, ObjectID.PIPE_50523, new WorldPoint(3609, 4598, 0), "Enter the sewers and make your way to the back of Zemouregal's base.", canopicJarFullForHeist, insulatedBoots.highlighted().equipped()); @@ -559,16 +573,14 @@ public void setupSteps() // 44 -> 46 when opening door, consuming the base key - unsortedStep46 = new ConditionalStep(this, enterZemouregalsBase); - unsortedStep46.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - unsortedStep46.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - unsortedStep46.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - unsortedStep46.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - unsortedStep46.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - unsortedStep46.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + getToBackroomsOfZemouregalsBase = new ConditionalStep(this, enterZemouregalsBase); + getToBackroomsOfZemouregalsBase.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + getToBackroomsOfZemouregalsBase.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + getToBackroomsOfZemouregalsBase.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + getToBackroomsOfZemouregalsBase.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + getToBackroomsOfZemouregalsBase.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + getToBackroomsOfZemouregalsBase.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); - var inSecondPart = new ZoneRequirement(new Zone(new WorldPoint(3590, 4538, 0), new WorldPoint(3622, 4597, 0))); - var inStorageRoom = new ZoneRequirement(new Zone(new WorldPoint(3614, 4571, 0), new WorldPoint(3605, 4563, 0))); searchTableForDecoderStrips = new ObjectStep(this, ObjectID.TABLE_50533, "Search the table for some decoder strips."); enterStorageRoom = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3609, 4572, 0), "Enter the storage room to the south-east."); var exitStorageRoom = new ObjectStep(this, ObjectID.GATE_50537, new WorldPoint(3609, 4572, 0), "Exit the storage room."); @@ -583,67 +595,65 @@ public void setupSteps() // also used for 50 - unsortedStep48 = new ConditionalStep(this, enterZemouregalsBase); - unsortedStep48.addStep(and(inSecondPart, not(inStorageRoom), codeKey), metalDoorSolver); - unsortedStep48.addStep(and(inStorageRoom, codeKey), exitStorageRoom); - unsortedStep48.addStep(and(inStorageRoom), openChestForCodeKey); - unsortedStep48.addStep(and(inSecondPart, not(codeKey)), enterStorageRoom); - unsortedStep48.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - unsortedStep48.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - unsortedStep48.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - unsortedStep48.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - unsortedStep48.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - unsortedStep48.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + unlockMetalDoor = new ConditionalStep(this, enterZemouregalsBase); + unlockMetalDoor.addStep(and(inZemouregalsBaseSecondPart, not(inStorageRoom), codeKey), metalDoorSolver); + unlockMetalDoor.addStep(and(inStorageRoom, codeKey), exitStorageRoom); + unlockMetalDoor.addStep(and(inStorageRoom), openChestForCodeKey); + unlockMetalDoor.addStep(and(inZemouregalsBaseSecondPart, not(codeKey)), enterStorageRoom); + unlockMetalDoor.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + unlockMetalDoor.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + unlockMetalDoor.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + unlockMetalDoor.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + unlockMetalDoor.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + unlockMetalDoor.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); openMetalDoors = new ObjectStep(this, ObjectID.METAL_DOORS, new WorldPoint(3612, 4582, 0), "Step through through the metal doors.", canopicJarFullForHeist, anyGrappleableCrossbow, mithrilGrapple); - var inGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3613, 4587, 0), new WorldPoint(3625, 4579, 0))); grappleAcross = new ObjectStep(this, ObjectID.PIPE_50542, new WorldPoint(3615, 4582, 0), "Grapple across the pipe", canopicJarFullForHeist, anyGrappleableCrossbow.highlighted().equipped(), mithrilGrapple.highlighted().equipped()); - var pastGrapplePuzzleRoom = new ZoneRequirement(new Zone(new WorldPoint(3621, 4589, 0), new WorldPoint(3645, 4578, 0))); enterBossRoom = new ObjectStep(this, ObjectID.PEDESTAL_50539, new WorldPoint(3638, 4582, 0), "Attempt to take Arrav's heart from the pedestal, ready for a fight with Arrav. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid some of the incoming damage. When Arrav throws an axe towards you, step to the side or behind him.", canopicJarFullForHeist, arravCombatGear); enterBossRoom.setOverlayText("Attempt to take Arrav's heart from the pedestal, ready for a fight with Arrav. Some hints are available in the sidebar."); - unsortedStep52 = new ConditionalStep(this, enterZemouregalsBase); - unsortedStep52.addStep(pastGrapplePuzzleRoom, enterBossRoom); - unsortedStep52.addStep(inGrapplePuzzleRoom, grappleAcross); - unsortedStep52.addStep(inSecondPart, openMetalDoors); - unsortedStep52.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - unsortedStep52.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - unsortedStep52.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - unsortedStep52.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - unsortedStep52.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - unsortedStep52.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + attemptToStealHeart = new ConditionalStep(this, enterZemouregalsBase); + attemptToStealHeart.addStep(pastGrapplePuzzleRoom, enterBossRoom); + attemptToStealHeart.addStep(inGrapplePuzzleRoom, grappleAcross); + attemptToStealHeart.addStep(inZemouregalsBaseSecondPart, openMetalDoors); + attemptToStealHeart.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + attemptToStealHeart.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + attemptToStealHeart.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + attemptToStealHeart.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + attemptToStealHeart.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + attemptToStealHeart.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); // User has engaged Arrav fightArrav = new NpcStep(this, NpcID.ARRAV_14132, new WorldPoint(3635, 4582, 0), "Fight Arrav. Kill zombies as they appear (ranged weapons are handy here). Avoid the venom pools they spawn. Use Protect from Melee to avoid some of the incoming damage. When Arrav throws an axe towards you, step to the side or behind him.", canopicJarFullForHeist); fightArrav.setOverlayText("Fight Arrav. Some hints are available in the sidebar."); - unsortedStep54 = new ConditionalStep(this, enterZemouregalsBase); - unsortedStep54.addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), fightArrav); - unsortedStep54.addStep(inSecondPart, openMetalDoors); - unsortedStep54.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - unsortedStep54.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - unsortedStep54.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - unsortedStep54.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - unsortedStep54.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - unsortedStep54.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + actuallyConfrontArrav = new ConditionalStep(this, enterZemouregalsBase); + actuallyConfrontArrav.addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), fightArrav); + actuallyConfrontArrav.addStep(inZemouregalsBaseSecondPart, openMetalDoors); + actuallyConfrontArrav.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + actuallyConfrontArrav.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + actuallyConfrontArrav.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + actuallyConfrontArrav.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + actuallyConfrontArrav.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + actuallyConfrontArrav.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); // 54 -> 56 when beating arrav var watchTheDialog = new DetailedQuestStep(this, "Watch the dialog."); fightArrav.addSubSteps(watchTheDialog); - unsortedStep56 = new ConditionalStep(this, enterZemouregalsBase); - unsortedStep56.addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), watchTheDialog); - unsortedStep56.addStep(inSecondPart, openMetalDoors); - unsortedStep56.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); - unsortedStep56.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); - unsortedStep56.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); - unsortedStep56.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); - unsortedStep56.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); - unsortedStep56.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); + watchYourVictoryDialog = new ConditionalStep(this, enterZemouregalsBase); + watchYourVictoryDialog.addStep(or(pastGrapplePuzzleRoom, inGrapplePuzzleRoom), watchTheDialog); + watchYourVictoryDialog.addStep(inZemouregalsBaseSecondPart, openMetalDoors); + watchYourVictoryDialog.addStep(inZemouregalsBaseSewer, exitZemouregalsBaseSewer); + watchYourVictoryDialog.addStep(inZemouregalsBaseKitchen, enterZemouregalsBaseSewer); + watchYourVictoryDialog.addStep(inZemouregalsBaseSection4, passZemouregalsBaseDoor4); + watchYourVictoryDialog.addStep(inZemouregalsBaseSection3, passZemouregalsBaseDoor3); + watchYourVictoryDialog.addStep(inZemouregalsBaseSection2, passZemouregalsBaseDoor2); + watchYourVictoryDialog.addStep(inZemouregalsBaseSection1, passZemouregalsBaseDoor1); finishQuest = new NpcStep(this, NpcID.ELIAS_WHITE, new WorldPoint(3505, 3037, 0), "Talk to Elias to finish the quest."); }