diff --git a/Server/data/configs/door_configs.json b/Server/data/configs/door_configs.json index 37011ac53..19083ed5d 100644 --- a/Server/data/configs/door_configs.json +++ b/Server/data/configs/door_configs.json @@ -1983,7 +1983,9 @@ "id": "20391", "replaceId": "28518", "fence": "false", - "metal": "true" + "metal": "true", + "autowalk": "true", + "questRequirement": "Icthlarin's Little Helper" }, { "id": "21065", diff --git a/Server/data/configs/drop_tables.json b/Server/data/configs/drop_tables.json index 56c44d15f..3505d0957 100644 --- a/Server/data/configs/drop_tables.json +++ b/Server/data/configs/drop_tables.json @@ -11979,7 +11979,7 @@ "maxAmount": "1" } ], - "ids": "490,1958,1959,1961,1962,1963,1964,1965,1966,1967,1968,2015,2016,2017,2018,2019,6753,6754,6755,6756,6757,6758,6759,6760", + "ids": "490,1959,1962,1963,1964,1965,1966,1967,1968,2015,2016,2017,2018,2019,6753,6754,6755,6756,6757,6758,6759,6760", "description": "", "main": [ { @@ -28422,7 +28422,7 @@ "maxAmount": "1" } ], - "ids": "1960,5360", + "ids": "1958,1961,1960,5360", "description": "", "main": [ { @@ -28439,7 +28439,7 @@ }, { "minAmount": "1", - "weight": "5.0", + "weight": "2.0", "id": "4675", "maxAmount": "1" }, diff --git a/Server/data/configs/npc_spawns.json b/Server/data/configs/npc_spawns.json index 3c78c4c44..59c300c9d 100644 --- a/Server/data/configs/npc_spawns.json +++ b/Server/data/configs/npc_spawns.json @@ -3301,7 +3301,7 @@ }, { "npc_id": "1369", - "loc_data": "{2165,3276,0,1,0}" + "loc_data": "{2527,5876,0,1,0}" }, { "npc_id": "1373", diff --git a/Server/detekt.yml b/Server/detekt.yml index 3a3977905..706aec911 100644 --- a/Server/detekt.yml +++ b/Server/detekt.yml @@ -609,7 +609,7 @@ style: ObjectLiteralToLambda: active: true OptionalAbstractKeyword: - active: true + active: false OptionalUnit: active: false OptionalWhenBraces: diff --git a/Server/src/main/content/data/GodBook.java b/Server/src/main/content/data/GodBook.java index 37e0adae8..314e61773 100644 --- a/Server/src/main/content/data/GodBook.java +++ b/Server/src/main/content/data/GodBook.java @@ -3,6 +3,8 @@ package content.data; import core.game.node.entity.player.Player; import core.game.node.item.Item; +import static core.api.ContentAPIKt.hasRequirement; + /** * A god book. * @author Vexia @@ -98,6 +100,8 @@ public enum GodBook { * @param page the page. */ public void insertPage(Player player, Item book, Item page) { + if (!hasRequirement(player, "Horror from the Deep")) + return; if (hasPage(player, book, page)) { player.sendMessage("The book already has that page."); return; diff --git a/Server/src/main/content/global/handlers/iface/PrayerTabInterface.java b/Server/src/main/content/global/handlers/iface/PrayerTabInterface.java index b1c9de0db..2d0932e89 100644 --- a/Server/src/main/content/global/handlers/iface/PrayerTabInterface.java +++ b/Server/src/main/content/global/handlers/iface/PrayerTabInterface.java @@ -8,6 +8,8 @@ import core.game.node.entity.player.link.prayer.PrayerType; import core.plugin.Initializable; import core.plugin.Plugin; +import static core.api.ContentAPIKt.hasRequirement; + /** * Represents the prayer interface. * @author 'Vexia @@ -24,6 +26,9 @@ public final class PrayerTabInterface extends ComponentPlugin { @Override public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) { final PrayerType type = PrayerType.get(button); + if (type == PrayerType.CHIVALRY || type == PrayerType.PIETY) + if (!hasRequirement(player, "King's Ransom")) + return true; if (type == null) { return true; } diff --git a/Server/src/main/content/global/handlers/iface/QuestTabInterface.java b/Server/src/main/content/global/handlers/iface/QuestTabInterface.java index 82839f982..90d580af2 100644 --- a/Server/src/main/content/global/handlers/iface/QuestTabInterface.java +++ b/Server/src/main/content/global/handlers/iface/QuestTabInterface.java @@ -47,7 +47,7 @@ public class QuestTabInterface extends ComponentPlugin { p.getInterfaceManager().open(new Component(275)); quest.drawJournal(p, quest.getStage(p)); return true; - } + } else QuestTabUtils.showRequirementsInterface(p, button); // } return false; } @@ -68,4 +68,4 @@ public class QuestTabInterface extends ComponentPlugin { return true; } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/handlers/iface/QuestTabUtils.kt b/Server/src/main/content/global/handlers/iface/QuestTabUtils.kt new file mode 100644 index 000000000..187669bd6 --- /dev/null +++ b/Server/src/main/content/global/handlers/iface/QuestTabUtils.kt @@ -0,0 +1,244 @@ +package content.global.handlers.iface + +import core.game.requirement.* +import core.api.* +import core.tools.* +import core.game.node.entity.player.Player +import core.game.node.entity.skill.Skills + +import kotlin.math.* +import java.util.* + +import org.rs09.consts.* + +object QuestTabUtils { + @JvmStatic + fun showRequirementsInterface (player: Player, button: Int) { + val questName = getNameForButton (button) + val questReq = QuestRequirements.values().filter { it.questName.equals(questName, true) }.firstOrNull() ?: return + var (isMet, unmetReqs) = QuestReq(questReq).evaluate(player) + + var messageList = ArrayList() + + val statMap = HashMap() + val questList = HashSet() + var maxQpReq = 0 + var qpPenalty = 0 + + for (req in unmetReqs) { + if (req is QuestReq) + questList.add(req.questReq.questName) + else if (req is SkillReq) { + if (statMap[req.skillId] == null || (statMap[req.skillId] != null && statMap[req.skillId]!! < req.level)) + statMap[req.skillId] = req.level + } + else if (req is QPReq && req.amount > maxQpReq) + maxQpReq = req.amount + else if (req is QPCumulative) + qpPenalty += req.amount + } + + messageList.add(colorize("%B[Quests Needed]")) + messageList.addAll(questList.map { "Completion of $it" }) + + messageList.add(" ") + messageList.add(colorize("%B[Skills Needed]")) + + for ((skillId, level) in statMap) { + val name = Skills.SKILL_NAME[skillId] + messageList.add("$level $name") + } + + messageList.add(" ") + messageList.add(colorize("%B[Other Reqs]")) + + val totalQpRequirement = QPReq(min(max(maxQpReq, qpPenalty), player.questRepository.getAvailablePoints())) + val (meetsQp, _) = totalQpRequirement.evaluate(player) + isMet = isMet && meetsQp + + if (isMet) + messageList.add(colorize("%GCongratulations! You've earned this one.")) + + if (!meetsQp) messageList.add("A total of ${totalQpRequirement.amount} Quest Points.") + + messageList.add("") + messageList.add(colorize("%BDISCLAIMER: If you're seeing this screen, this quest is not")) + messageList.add(colorize("%Bimplemented yet. These are the requirements that you need in order")) + messageList.add(colorize("%Bto access implemented content that would normally require this quest")) + messageList.add("") + messageList.add("If you want to see more quests enter the game, consider") + messageList.add("contributing dialogue transcripts!") + + + setInterfaceText(player, questName, Components.QUESTJOURNAL_SCROLL_275, 2) + var lineId = 11 + for(i in 0..299) { + val entry = messageList.elementAtOrNull(i) + if (entry != null) + setInterfaceText(player, entry, Components.QUESTJOURNAL_SCROLL_275, lineId++) + else + setInterfaceText(player, "", Components.QUESTJOURNAL_SCROLL_275, lineId++) + } + openInterface(player, Components.QUESTJOURNAL_SCROLL_275) + } + + fun getNameForButton (button: Int) : String { + val name = when (button) { + 10 -> "Myths of the White Lands" + 11 -> "Myths of the White Lands" + 12 -> "Free Quests" + 13 -> "Black Knights' Fortress" + 14 -> "Cook's Assistant" + 15 -> "Demon Slayer" + 16 -> "Doric's Quest" + 17 -> "Dragon Slayer" + 18 -> "Ernest the Chicken" + 19 -> "Goblin Diplomacy" + 20 -> "Imp Catcher" + 21 -> "The Knight's Sword" + 22 -> "Pirate's Treasure" + 23 -> "Prince Ali Rescue" + 24 -> "The Restless Ghost" + 25 -> "Romeo & Juliet" + 26 -> "Rune Mysteries" + 27 -> "Sheep Shearer" + 28 -> "Shield of Arrav" + 29 -> "Vampire Slayer" + 30 -> "Witch's Potion" + 31 -> "Members' Quests" + 32 -> "Animal Magnetism" + 33 -> "Between a Rock..." + 34 -> "Big Chompy Bird Hunting" + 35 -> "Biohazard" + 36 -> "Cabin Fever" + 37 -> "Clock Tower" + 38 -> "Contact!" + 39 -> "Zogre Flesh Eaters" + 40 -> "Creature of Fenkenstrain" + 41 -> "Darkness of Hallowvale" + 42 -> "Death to the Dorgeshuun" + 43 -> "Death Plateau" + 44 -> "Desert Treasure" + 45 -> "Devious Minds" + 46 -> "The Dig Site" + 47 -> "Druidic Ritual" + 48 -> "Dwarf Cannon" + 49 -> "Eadgar's Ruse" + 50 -> "Eagles' Peak" + 51 -> "Elemental Workshop I" + 52 -> "Elemental Workshop II" + 53 -> "Enakhra's Lament" + 54 -> "Enlightened Journey" + 55 -> "The Eyes of Glouphrie" + 56 -> "Fairytale I - Growing Pains" + 57 -> "Fairytale II - Cure a Queen" + 58 -> "Family Crest" + 59 -> "The Feud" + 60 -> "Fight Arena" + 61 -> "Fishing Contest" + 62 -> "Forgettable Tale..." + 63 -> "The Fremennik Trials" + 64 -> "Waterfall Quest" + 65 -> "Garden of Tranquillity" + 66 -> "Gertrude's Cat" + 67 -> "Ghosts Ahoy" + 68 -> "The Giant Dwarf" + 69 -> "The Golem" + 70 -> "The Grand Tree" + 71 -> "The Hand in the Sand" + 72 -> "Haunted Mine" + 73 -> "Hazeel Cult" + 74 -> "Heroes' Quest" + 75 -> "Holy Grail" + 76 -> "Horror from the Deep" + 77 -> "Icthlarin's Little Helper" + 78 -> "In Aid of the Myreque" + 79 -> "In Search of the Myreque" + 80 -> "Jungle Potion" + 81 -> "Legend's Quest" + 82 -> "Lost City" + 83 -> "The Lost Tribe" + 84 -> "Lunar Diplomacy" + 85 -> "Making History" + 86 -> "Merlin's Crystal" + 87 -> "Monkey Madness" + 88 -> "Monk's Friend" + 89 -> "Mountain Daughter" + 90 -> "Mourning's End Part I" + 91 -> "Mourning's End Part II" + 92 -> "Murder Mystery" + 93 -> "My Arm's Big Adventure" + 94 -> "Nature Spirit" + 95 -> "Observatory Quest" + 96 -> "One Small Favour" + 97 -> "Plague City" + 98 -> "Priest in Peril" + 99 -> "Rag and Bone Man" + 100 -> "Ratcatchers" + 101 -> "Recipe for Disaster" + 102 -> "Recruitment Drive" + 103 -> "Regicide" + 104 -> "Roving Elves" + 105 -> "Royal Trouble" + 106 -> "Rum Deal" + 107 -> "Scorpion Catcher" + 108 -> "Sea Slug" + 109 -> "The Slug Menace" + 110 -> "Shades of Mort'ton" + 111 -> "Shadow of the Storm" + 112 -> "Sheep Herder" + 113 -> "Shilo Village" + 114 -> "A Soul's Bane" + 115 -> "Spirits of the Elid" + 116 -> "Swan Song" + 117 -> "Tai Bwo Wannai Trio" + 118 -> "A Tail of Two Cats" + 119 -> "Tears of Guthix" + 120 -> "Temple of Ikov" + 121 -> "Throne of Miscellania" + 122 -> "The Tourist Trap" + 123 -> "Witch's House" + 124 -> "Tree Gnome Village" + 125 -> "Tribal Totem" + 126 -> "Troll Romance" + 127 -> "Troll Stronghold" + 128 -> "Underground Pass" + 129 -> "Wanted!" + 130 -> "Watchtower" + 131 -> "Cold War" + 132 -> "The Fremennik Isles" + 133 -> "Tower of Life" + 134 -> "The Great Brain Robbery" + 135 -> "What Lies Below" + 136 -> "Olaf's Quest" + 137 -> "Another Slice of H.A.M" + 138 -> "Dream Mentor" + 139 -> "Grim Tales" + 140 -> "King's Ransom" + 141 -> "The Path of Glouphrie" + 142 -> "Back to my Roots" + 143 -> "Land of the Goblins" + 144 -> "Dealing with Scabaras" + 145 -> "Wolf Whistle" + 146 -> "As a First Resort..." + 147 -> "Catapult Construction" + 148 -> "Kennith's Concerns" + 149 -> "Legacy of Seergaze" + 150 -> "Perils of Ice Mountain" + 151 -> "TokTz-Ket-Dill" + 152 -> "Smoking Kills" + 153 -> "Rocking Out" + 154 -> "Spirit of Summer" + 155 -> "Meeting History" + 156 -> "All Fired Up" + 157 -> "Summer's End" + 158 -> "Defender of Varrock" + 159 -> "Swept Away" + 160 -> "While Guthix Sleeps" + 161 -> "In Pyre Need" + 162 -> "Myths of the White Lands" + else -> "" + } + return name + } +} diff --git a/Server/src/main/content/global/handlers/item/ItemQuestRequirementListener.kt b/Server/src/main/content/global/handlers/item/ItemQuestRequirementListener.kt index f02f0ca02..4dd960bad 100644 --- a/Server/src/main/content/global/handlers/item/ItemQuestRequirementListener.kt +++ b/Server/src/main/content/global/handlers/item/ItemQuestRequirementListener.kt @@ -89,6 +89,19 @@ class ItemQuestRequirementListener : InteractionListener { private val questCapes = intArrayOf(9813,9814) + private val godBooks = intArrayOf ( + Items.HOLY_BOOK_3840, + Items.UNHOLY_BOOK_3842 + ) + + private val pharaohScepters = (9044..9051).toIntArray() + + private val initiateArmour = (5574..5576).toIntArray() + + private val proselyteArmour = (9672..9678).toIntArray() + + private val spiritShields = (13734..13745).toIntArray() + override fun defineListeners() { /* @@ -109,20 +122,24 @@ class ItemQuestRequirementListener : InteractionListener { } */ - onEquip(fremennikTrialsEquipment.plus(fremennikIslesEquipment)) { player, _ -> - return@onEquip requireQuest(player, "Fremennik Trials", "to equip this.") + onEquip(fremennikTrialsEquipment) { player, _ -> + return@onEquip hasRequirement(player, "Fremennik Trials") + } + + onEquip(fremennikIslesEquipment) {player, _ -> + return@onEquip hasRequirement(player, "The Fremennik Isles") } onEquip(avasBackpacks){ player, _ -> - return@onEquip requireQuest(player, "Animal Magnetism", "to equip this.") + return@onEquip hasRequirement(player, "Animal Magnetism") } onEquip(lostCityWeapons){ player, _ -> - return@onEquip requireQuest(player, "Lost City", "to equip this.") + return@onEquip hasRequirement(player, "Lost City") } onEquip(Items.CAPE_OF_LEGENDS_1052) { player, _ -> - return@onEquip requireQuest(player, "Legends' Quest", "to equip this.") + return@onEquip hasRequirement(player, "Legend's Quest") } onEquip(questCapes) { player, _ -> @@ -135,27 +152,84 @@ class ItemQuestRequirementListener : InteractionListener { } onEquip(Items.WOLFBANE_2952){ player, _ -> - return@onEquip requireQuest(player, "Priest in Peril", "to equip this.") + return@onEquip hasRequirement(player, "Priest in Peril") } onEquip(Items.ANCIENT_MACE_11061){ player, _ -> - return@onEquip requireQuest(player, "Another Slice of H.A.M.", "to equip this.") + return@onEquip hasRequirement(player, "Another Slice of H.A.M") } onEquip(Items.ANCIENT_STAFF_4675){ player, _ -> - return@onEquip requireQuest(player, "Desert Treasure", "to equip this.") + return@onEquip hasRequirement(player, "Desert Treasure") } onEquip(Items.ELEMENTAL_SHIELD_2890) { player, _ -> - return@onEquip requireQuest(player, "Elemental Workshop I", "to equip this.") + return@onEquip hasRequirement(player, "Elemental Workshop I") } onEquip(crystalEquipment){ player, _ -> - return@onEquip requireQuest(player, "Roving Elves", "to equip this.") + return@onEquip hasRequirement(player, "Roving Elves") } onEquip(dragonSlayerEquipment) {player, _ -> - return@onEquip requireQuest(player, "Dragon Slayer", "to equip this.") + return@onEquip hasRequirement(player, "Dragon Slayer") + } + + onEquip(Items.DRAGON_SCIMITAR_4587) {player, _ -> + return@onEquip hasRequirement(player, "Monkey Madness") + } + + onEquip(Items.GLOVES_7462) {player, _ -> + return@onEquip hasRequirement(player, "Recipe for Disaster") + } + + onEquip(Items.SLAYER_HELMET_13263) {player, _ -> + return@onEquip hasRequirement(player, "Smoking Kills") + } + + onEquip (Items.DRAGON_HALBERD_3204) {player, _ -> + return@onEquip hasRequirement(player, "Regicide") + } + + onEquip (Items.CLIMBING_BOOTS_3105) {player, _ -> + return@onEquip hasRequirement(player, "Death Plateau") + } + + onEquip (godBooks) {player, _ -> + return@onEquip hasRequirement(player, "Horror from the Deep") + } + + onEquip (pharaohScepters) {player, _ -> + return@onEquip hasRequirement(player, "Icthlarin's Little Helper") + } + + onEquip (Items.DRAGON_SQ_SHIELD_1187) {player, _ -> + //because I know people won't believe it: https://runescape.wiki/w/Dragon_sq_shield?oldid=899636 + return@onEquip hasRequirement(player, "Legend's Quest") + } + + onEquip (initiateArmour) {player, _ -> + return@onEquip hasRequirement(player, "Recruitment Drive") + } + + onEquip (proselyteArmour) {player, _ -> + return@onEquip hasRequirement(player, "The Slug Menace") + } + + onEquip (spiritShields) {player, _ -> + return@onEquip hasRequirement(player, "Summer's End") + } + + onEquip (Items.DRAGON_MACE_1434) {player, _ -> + return@onEquip hasRequirement(player, "Heroes' Quest") + } + + onEquip (Items.DRAGON_BATTLEAXE_1377) {player, _ -> + return@onEquip hasRequirement(player, "Heroes' Quest") + } + + onEquip (Items.DARKLIGHT_6746) {player, _ -> + return@onEquip hasRequirement(player, "Shadow of the Storm") } } } diff --git a/Server/src/main/content/global/handlers/item/TeleportCrystalPlugin.java b/Server/src/main/content/global/handlers/item/TeleportCrystalPlugin.java index dc779e885..94c3b4eb7 100644 --- a/Server/src/main/content/global/handlers/item/TeleportCrystalPlugin.java +++ b/Server/src/main/content/global/handlers/item/TeleportCrystalPlugin.java @@ -13,6 +13,8 @@ import core.game.world.map.Location; import core.game.world.map.zone.impl.WildernessZone; import core.plugin.Plugin; +import static core.api.ContentAPIKt.hasRequirement; + /** * Represents the rotten potato plugin. * @author 'Vexia @@ -32,6 +34,8 @@ public final class TeleportCrystalPlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { + if (!hasRequirement(player, "Mourning's End Part I")) + return true; if (!WildernessZone.checkTeleport(player, 20)) { player.getPacketDispatch().sendMessage("The crystal is unresponsive."); return true; diff --git a/Server/src/main/content/global/skill/agility/shortcuts/TunnelShortcut.java b/Server/src/main/content/global/skill/agility/shortcuts/TunnelShortcut.java index 529c32366..7388fde01 100644 --- a/Server/src/main/content/global/skill/agility/shortcuts/TunnelShortcut.java +++ b/Server/src/main/content/global/skill/agility/shortcuts/TunnelShortcut.java @@ -14,6 +14,8 @@ import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles a tunnel shortcut. * @author Vexia @@ -70,6 +72,10 @@ public class TunnelShortcut extends AgilityShortcut { @Override public void run(final Player player, Scenery object, String option, boolean failed) { + if (object.getId() == 14922) { + if (!hasRequirement(player, "Swan Song")) + return; + } player.lock(6); final Scenery o = object; final Location start = player.getLocation(); diff --git a/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt b/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt index 9c3341cf2..c0eeb7a4b 100644 --- a/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt +++ b/Server/src/main/content/global/skill/farming/UseWithPatchHandler.kt @@ -33,6 +33,11 @@ class UseWithPatchHandler : InteractionListener { val patch = FarmingPatch.forObject(with.asScenery()) ?: return@onUseWith true val usedItem = used.asItem() + if (patch == FarmingPatch.TROLL_STRONGHOLD_HERB) { + if (!hasRequirement(player, "My Arm's Big Adventure")) + return@onUseWith true + } + player.faceLocation(with.location) when(usedItem.id){ RAKE -> PatchRaker.rake(player,patch) diff --git a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt index 30d40ad92..4277651a9 100644 --- a/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt +++ b/Server/src/main/content/global/skill/magic/modern/ModernListeners.kt @@ -92,21 +92,29 @@ class ModernListeners : SpellListener("modern"){ } onCast(Modern.ARDOUGNE_TELEPORT, NONE){ player, _ -> + if (!hasRequirement(player, "Plague City")) + return@onCast requires(player,51, arrayOf(Item(Items.WATER_RUNE_555,2),Item(Items.LAW_RUNE_563,2))) sendTeleport(player,61.0, Location.create(2662, 3307, 0)) } onCast(Modern.WATCHTOWER_TELEPORT, NONE){ player, _ -> + if (!hasRequirement(player, "Watchtower")) + return@onCast requires(player,58, arrayOf(Item(Items.EARTH_RUNE_557,2),Item(Items.LAW_RUNE_563,2))) sendTeleport(player,68.0, Location.create(2549, 3112, 0)) } onCast(Modern.TROLLHEIM_TELEPORT, NONE){ player, _ -> + if (!hasRequirement(player, "Eadgar's Ruse")) + return@onCast requires(player,61, arrayOf(Item(Items.FIRE_RUNE_554,2),Item(Items.LAW_RUNE_563,2))) sendTeleport(player,68.0, Location.create(2891, 3678, 0)) } onCast(Modern.APE_ATOLL_TELEPORT, NONE){ player, _ -> + if (!hasRequirement(player, "Monkey Madness")) + return@onCast requires(player,64, arrayOf(Item(Items.FIRE_RUNE_554,2),Item(Items.WATER_RUNE_555,2),Item(Items.LAW_RUNE_563,2),Item(Items.BANANA_1963))) sendTeleport(player,74.0, Location.create(2754, 2784, 0)) } diff --git a/Server/src/main/content/global/skill/prayer/PrayerAltarPlugin.java b/Server/src/main/content/global/skill/prayer/PrayerAltarPlugin.java index 56d413546..68b7c7add 100644 --- a/Server/src/main/content/global/skill/prayer/PrayerAltarPlugin.java +++ b/Server/src/main/content/global/skill/prayer/PrayerAltarPlugin.java @@ -16,6 +16,8 @@ import core.game.world.map.Location; import core.game.world.update.flag.context.Animation; import core.plugin.Plugin; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles the praying at an alter. * @author Vexia @@ -104,6 +106,8 @@ public class PrayerAltarPlugin extends OptionHandler { ANCIENT(6552, SpellBook.ANCIENT.getInterfaceId(), "You feel a strange wisdom fill your mind...", "You feel a strange drain upon your memory...") { @Override public void pray(Player player) { + if (!hasRequirement(player, "Desert Treasure")) + return; if (player.getSkills().getStaticLevel(Skills.MAGIC) < 50) { player.sendMessage("You need a Magic level of at least 50 in order to do this."); return; @@ -121,6 +125,8 @@ public class PrayerAltarPlugin extends OptionHandler { LUNAR(17010, SpellBook.LUNAR.getInterfaceId(), "Lunar spells activated!", "Modern spells activated!") { @Override public void pray(Player player) { + if (!hasRequirement(player, "Lunar Diplomacy")) + return; if (player.getSkills().getStaticLevel(Skills.MAGIC) < 65) { player.sendMessage("You need a Magic level of at least 65 in order to do this."); return; diff --git a/Server/src/main/content/global/skill/runecrafting/Altar.java b/Server/src/main/content/global/skill/runecrafting/Altar.java index 698116728..29cc03953 100644 --- a/Server/src/main/content/global/skill/runecrafting/Altar.java +++ b/Server/src/main/content/global/skill/runecrafting/Altar.java @@ -4,6 +4,8 @@ import core.cache.def.impl.ItemDefinition; import core.game.node.entity.player.Player; import core.game.node.scenery.Scenery; +import static core.api.ContentAPIKt.hasRequirement; + /** * Represents an altar an it's relative information(corresponding ruin, etc) * @author 'Vexia @@ -69,6 +71,18 @@ public enum Altar { * @param player the player. */ public void enterRift(Player player) { + if (this == ASTRAL) { + if (!hasRequirement(player, "Lunar Diplomacy")) + return; + } + if (this == DEATH) { + if (!hasRequirement(player, "Mourning's End Part II")) + return; + } + if (this == BLOOD) { + if (!hasRequirement(player, "Legacy of Seergaze")) + return; + } if (this == LAW) { if (!ItemDefinition.canEnterEntrana(player)) { player.sendMessage("You can't take weapons and armour into the law rift."); diff --git a/Server/src/main/content/global/skill/runecrafting/MysteriousRuin.java b/Server/src/main/content/global/skill/runecrafting/MysteriousRuin.java index 55a42ce9a..82c124337 100644 --- a/Server/src/main/content/global/skill/runecrafting/MysteriousRuin.java +++ b/Server/src/main/content/global/skill/runecrafting/MysteriousRuin.java @@ -5,6 +5,8 @@ import core.game.node.entity.player.Player; import core.game.node.scenery.Scenery; import core.game.world.map.Location; +import static core.api.ContentAPIKt.hasRequirement; + /** * Represents a mysterious ruin. * @author 'Vexia @@ -70,6 +72,14 @@ public enum MysteriousRuin { * @param player the player. */ public void enter(Player player) { + if (this == DEATH) { + if (!hasRequirement(player, "Mourning's End Part II")) + return; + } + if (this == BLOOD) { + if (!hasRequirement(player, "Legacy of Seergaze")) + return; + } if (player.getEquipment().get(EquipmentContainer.SLOT_HAT) == null) { return; } diff --git a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java index 4c6558770..311d023e5 100644 --- a/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java +++ b/Server/src/main/content/global/skill/runecrafting/RuneCraftPulse.java @@ -15,6 +15,7 @@ import core.tools.RandomFunction; import static core.api.ContentAPIKt.inEquipment; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_BASE; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_RC; +import static core.api.ContentAPIKt.hasRequirement; import core.game.world.GameWorld; import org.rs09.consts.Items; @@ -96,6 +97,18 @@ public final class RuneCraftPulse extends SkillPulse { @Override public boolean checkRequirements() { + if (altar == Altar.ASTRAL) { + if (!hasRequirement(player, "Lunar Diplomacy")) + return false; + } + if (altar == Altar.DEATH) { + if (!hasRequirement(player, "Mourning's End Part II")) + return false; + } + if (altar == Altar.BLOOD) { + if (!hasRequirement(player, "Legacy of Seergaze")) + return false; + } if (!altar.isOurania() && player.getSkills().getLevel(Skills.RUNECRAFTING) < rune.getLevel()) { player.getPacketDispatch().sendMessage("You need a Runecrafting level of at least " + rune.getLevel() + " to craft this rune."); return false; diff --git a/Server/src/main/content/global/skill/runecrafting/RunecraftingPlugin.java b/Server/src/main/content/global/skill/runecrafting/RunecraftingPlugin.java index 903503992..31185326d 100644 --- a/Server/src/main/content/global/skill/runecrafting/RunecraftingPlugin.java +++ b/Server/src/main/content/global/skill/runecrafting/RunecraftingPlugin.java @@ -23,6 +23,8 @@ import content.global.travel.EssenceTeleport; import core.game.world.GameWorld; import core.plugin.ClassScanner; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles runecraftign related options. * @author Vexia @@ -94,7 +96,12 @@ public class RunecraftingPlugin extends OptionHandler { player.sendMessage("You can only craft Astral runes on Lunar Isle."); return true; } - player.getPulseManager().run(new RuneCraftPulse(player, null, Altar.forObject(((Scenery) node)), false, null)); + Altar a = Altar.forObject(((Scenery) node)); + if (a == Altar.ASTRAL) { + if (!hasRequirement(player, "Lunar Diplomacy")) + return true; + } + player.getPulseManager().run(new RuneCraftPulse(player, null, a, false, null)); break; case "locate": final Talisman talisman = Talisman.forItem(((Item) node)); diff --git a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt index b30636136..63808540d 100644 --- a/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt +++ b/Server/src/main/content/global/skill/skillcapeperks/SkillcapePerks.kt @@ -5,12 +5,14 @@ import core.game.node.entity.player.Player import core.game.node.entity.player.link.SpellBookManager import core.game.node.entity.player.link.TeleportManager import content.global.skill.runecrafting.Altar +import core.game.world.map.Location import core.game.world.map.zone.impl.DarkZone import core.plugin.Initializable import core.game.world.GameWorld import content.global.skill.farming.* import core.api.getAttribute import core.api.sendDialogue +import core.api.hasRequirement enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? = null) { BAREFISTED_SMITHING("cape_perks:barefisted-smithing"), @@ -184,12 +186,20 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? else -> null } + end() if(spellbook != null){ + if (spellbook == SpellBookManager.SpellBook.ANCIENT) { + if (!hasRequirement(player, "Desert Treasure")) + return true + } + else if (spellbook == SpellBookManager.SpellBook.LUNAR) { + if (!hasRequirement(player, "Lunar Diplomacy")) + return true + } player.spellBookManager.setSpellBook(spellbook) player.interfaceManager.openTab(Component(spellbook.interfaceId)) player.incrementAttribute("/save:cape_perks:librarian-magus-charges",-1) } - end() return true } @@ -244,7 +254,16 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? fun sendAltar(player: Player,altar: Altar){ end() - player.teleporter.send(altar.ruin.end,TeleportManager.TeleportType.TELE_OTHER) + if (altar == Altar.DEATH && !hasRequirement(player, "Mourning's End Part II")) + return + else if (altar == Altar.ASTRAL && !hasRequirement(player, "Lunar Diplomacy")) + return + else if (altar == Altar.BLOOD && !hasRequirement(player, "Legacy of Seergaze")) + return + + var endLoc = if (altar == Altar.ASTRAL) Location.create(2151, 3864, 0) else altar.ruin.end + + player.teleporter.send(endLoc, TeleportManager.TeleportType.TELE_OTHER) player.incrementAttribute("/save:cape_perks:abyssal_warp",-1) } diff --git a/Server/src/main/content/global/skill/slayer/Master.java b/Server/src/main/content/global/skill/slayer/Master.java index 9f0727cb0..0a3d3619d 100644 --- a/Server/src/main/content/global/skill/slayer/Master.java +++ b/Server/src/main/content/global/skill/slayer/Master.java @@ -242,7 +242,7 @@ public enum Master { new Task(Tasks.SPIRTUAL_RANGERS,2), new Task(Tasks.SPIRTUAL_WARRIORS,2), new Task(Tasks.STEEL_DRAGONS,7), - //new Task(Tasks.SUQAHS,8), + new Task(Tasks.SUQAHS,8), new Task(Tasks.TROLLS,6), new Task(Tasks.TZHAAR, 10), new Task(Tasks.VAMPIRES,8), @@ -306,4 +306,4 @@ public enum Master { this.weight = weight; } } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/skill/slayer/SlayerPlugin.java b/Server/src/main/content/global/skill/slayer/SlayerPlugin.java index ec6940b15..35d6a4544 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerPlugin.java +++ b/Server/src/main/content/global/skill/slayer/SlayerPlugin.java @@ -11,6 +11,8 @@ import core.game.world.map.Location; import core.plugin.Initializable; import core.plugin.Plugin; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles related slayer nodes. * @author Vexia @@ -61,6 +63,8 @@ public class SlayerPlugin extends OptionHandler { player.teleport(new Location(2729, 3733, 0)); break; case 15767: + if (!hasRequirement(player, "Cabin Fever")) + return true; player.teleport(new Location(3748, 9373, 0)); break; case 15811: diff --git a/Server/src/main/content/global/skill/slayer/SlayerRewardPlugin.java b/Server/src/main/content/global/skill/slayer/SlayerRewardPlugin.java index d8231167e..84d54b18d 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerRewardPlugin.java +++ b/Server/src/main/content/global/skill/slayer/SlayerRewardPlugin.java @@ -16,6 +16,8 @@ import core.plugin.Initializable; import core.plugin.Plugin; import core.plugin.ClassScanner; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles the slayer reward interface plugin. * @author Vexia @@ -307,6 +309,8 @@ public class SlayerRewardPlugin extends ComponentPlugin { @Override public boolean handle(Player player, Node node, String option) { + if (!hasRequirement(player, "Smoking Kills")) + return true; openTab(player, BUY); return true; } diff --git a/Server/src/main/content/global/skill/slayer/SlayerUtils.kt b/Server/src/main/content/global/skill/slayer/SlayerUtils.kt index 14b00d7f3..789486a8e 100644 --- a/Server/src/main/content/global/skill/slayer/SlayerUtils.kt +++ b/Server/src/main/content/global/skill/slayer/SlayerUtils.kt @@ -31,7 +31,7 @@ object SlayerUtils { fun canBeAssigned(player: Player, task: Tasks): Boolean { - return player.getSkills().getLevel(Skills.SLAYER) >= task.levelReq && !SlayerManager.getInstance(player).flags.removed.contains(task) + return player.getSkills().getLevel(Skills.SLAYER) >= task.levelReq && !SlayerManager.getInstance(player).flags.removed.contains(task) && task.hasQuestRequirements(player) } fun assign(player: Player, task: Tasks, master: Master) @@ -56,4 +56,4 @@ object SlayerUtils { .spellBook == SpellBook.MODERN.interfaceId ) } -} \ No newline at end of file +} diff --git a/Server/src/main/content/global/skill/slayer/Tasks.java b/Server/src/main/content/global/skill/slayer/Tasks.java index e7a95d0a7..19d726f22 100644 --- a/Server/src/main/content/global/skill/slayer/Tasks.java +++ b/Server/src/main/content/global/skill/slayer/Tasks.java @@ -5,6 +5,9 @@ import core.cache.def.impl.NPCDefinition; import java.util.Arrays; import java.util.HashMap; +import core.game.node.entity.player.Player; + +import static core.api.ContentAPIKt.hasRequirement; /** * A non-garbage way of representing tasks @@ -29,7 +32,7 @@ public enum Tasks { CATABLEPONS(35, new int[] { 4397, 4398, 4399, }, new String[] { "They use the magic spell Weaken to drain up to 15% of their", "opponent's maximum Strength level." }, 1, false, false), CAVE_BUG(1, new int[] { 1832, 5750, }, new String[] { "It regenerates life points quickly and seems to be a good", "herblore monster." }, 7, false, false), CAVE_CRAWLERS(10, new int[] { 1600, 1601, 1602, 1603, }, new String[] { "The poisonous parts of them are presumably removed." }, 10, false, false), - CAVE_HORRORS(85, new int[] { 4353, 4354, 4355, 4356, 4357, }, new String[] { "A Cave horror wears a creepy mask, it is", "prefered to wear a witchwood icon." }, 58, false, false), + CAVE_HORRORS(85, new int[] { 4353, 4354, 4355, 4356, 4357, }, new String[] { "A Cave horror wears a creepy mask, it is", "prefered to wear a witchwood icon." }, 58, "Cabin Fever"), CAVE_SLIMES(15, new int[] { 1831 }, new String[] { "These are lesser versions of jellies, watch out they can poison you." }, 17, false, false), COCKATRICES(25, new int[] { 1620, 1621, 4227, }, new String[] { "A Mirror shield is necessary when fighting these monsters." }, 25, false, false), COWS(5, new int[] { 1766, 1768, 2310, 81, 397, 955, 1767, 3309 }, new String[] { "Cow's may seem stupid, however they know more then", "you think. Don't under estimate them." }, 1, false, false), @@ -88,6 +91,7 @@ public enum Tasks { TROLLS(60, new int[] { 72, 3584, 1098, 1096, 1097, 1095, 1101, 1105, 1102, 1103, 1104, 1130, 1131, 1132, 1133, 1134, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1138, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 3840, 3841, 3842, 3843, 3845, 1933, 1934, }, new String[] { "Trolls have a crushing attack, it's bets to wear a high crushing defence." }, 1, false, false), TUROTHS(60, new int[] { 1626, 1627, 1628, 1629, 1630 }, new String[] { "Turoths are Slayer monsters that require a Slayer level of 55 to kill" }, 55, false, false), TZHAAR(45, new int[] { 2591, 2592, 2593, 2745, 2594, 2595, 2596, 2597, 2604, 2605, 2606, 2607, 2608, 2609, 7755, 7753, 2598, 2599, 2600, 2601, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2624, 2617, 2618, 2625, 2602, 2603, 7754, 7767, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2624, 2625, 2627, 2628, 2629, 2630, 2631, 2632, 7746, 7747, 7748, 7749, 7750, 7751, 7752, 7753, 7754, 7755, 7756, 7757, 7758, 7759, 7760, 7761, 7762, 7763, 7764, 7765, 7766, 7767, 7768, 7769, 7770, 7771, 7747, 7747, 7748, 7749, 7750, 7751, 7752, 7753, 7757, 7765, 7769, 7768 }, new String[] { "Young Tzhaar's of the century are furious with your kind." }, 1, false, false), + SUQAHS (65, new int[] { 4527, 4528, 4529, 4530, 4531, 4532, 4533 }, new String[] { "Suquah are big, angry folk that inhabit Lunar Isle." }, 1, "Lunar Diplomacy"), VAMPIRES(35, new int[] { 1023, 1220, 1223, 1225, 6214 }, new String[] { "Vampies arr equiped with large fangs", "they can do serious damage." }, 1, false, false), WATERFIENDS(75, new int[] { 5361 }, new String[] { "A waterfiend takes no damage from fire!" }, 1, false, false), WEREWOLFS(60, new int[] { 1665, 6006, 6007, 6008, 6009, 6010, 6011, 6012, 6013, 6014, 6015, 6016, 6017, 6018, 6019, 6020, 6021, 6022, 6023, 6024, 6025, 6212, 6213, 6607, 6609, 6614, 6617, 6625, 6632, 6644, 6663, 6675, 6686, 6701, 6712, 6724, 6728, }, new String[] { "There temper is alot more nasty then a regular wolf!" }, 1, false, false), @@ -111,9 +115,10 @@ public enum Tasks { public final int combatCheck; public final String[] info; public final int[] ids; - public final boolean undead; - public final boolean dragon; + public boolean undead = false; + public boolean dragon = false; public int amtHash; + public String questReq = ""; Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead, boolean dragon){ this.levelReq = levelReq; this.ids = ids; @@ -133,6 +138,14 @@ public enum Tasks { this.combatCheck = combatCheck; } + Tasks (int combatCheck, int[] ids, String[] info, int levelReq, String questReq) { + this.combatCheck = combatCheck; + this.ids = ids; + this.info = info; + this.levelReq = levelReq; + this.questReq = questReq; + } + public int[] getNpcs(){ return ids; } @@ -141,6 +154,10 @@ public enum Tasks { return info; } + public boolean hasQuestRequirements (Player player) { + return questReq.equals("") || hasRequirement(player, questReq, false); + } + public static Tasks forId(int id){ return taskMap.get(id); } diff --git a/Server/src/main/content/minigame/pyramidplunder/PharaohSceptre.kt b/Server/src/main/content/minigame/pyramidplunder/PharaohSceptre.kt index 5627fd664..b54f8dd36 100644 --- a/Server/src/main/content/minigame/pyramidplunder/PharaohSceptre.kt +++ b/Server/src/main/content/minigame/pyramidplunder/PharaohSceptre.kt @@ -1,8 +1,6 @@ package content.minigame.pyramidplunder -import core.api.EquipmentSlot -import core.api.openDialogue -import core.api.sendMessage +import core.api.* import core.game.world.GameWorld.Pulser import content.minigame.pyramidplunder.PyramidPlunderMinigame.Companion.GUARDIAN_ROOM import core.game.node.entity.player.Player @@ -25,6 +23,9 @@ class PharaohSceptre : InteractionListener { val SCEPTRES = intArrayOf(Items.PHARAOHS_SCEPTRE_9044, Items.PHARAOHS_SCEPTRE_9046, Items.PHARAOHS_SCEPTRE_9048, Items.PHARAOHS_SCEPTRE_9050) on(SCEPTRES, IntType.ITEM, "teleport", "operate"){ player, node -> + if (!hasRequirement(player, "Icthlarin's Little Helper")) + return@on true + val sceptre = node.asItem() if(sceptre.id == SCEPTRES.last()) @@ -121,4 +122,4 @@ class PharaohSceptre : InteractionListener { private val GRAPHICS = Graphics(715) private val ANIMATION = Animation(714) } -} \ No newline at end of file +} diff --git a/Server/src/main/content/minigame/sorceress/SorceressApprenticeDialogue.java b/Server/src/main/content/minigame/sorceress/SorceressApprenticeDialogue.java index 5e19d4503..4e6be91c4 100644 --- a/Server/src/main/content/minigame/sorceress/SorceressApprenticeDialogue.java +++ b/Server/src/main/content/minigame/sorceress/SorceressApprenticeDialogue.java @@ -10,6 +10,8 @@ import core.game.world.GameWorld; import core.game.world.map.Location; import core.game.world.update.flag.context.Graphics; +import static core.api.ContentAPIKt.hasRequirement; + /** * Dialogue for Sorceress Apprentice * @author SonicForce41 @@ -236,6 +238,8 @@ public class SorceressApprenticeDialogue extends DialoguePlugin { } public static void teleport(final NPC npc, final Player player) { + if (!hasRequirement(player, "Prince Ali Rescue")) + return; npc.faceTemporary(player, 4); npc.graphics(new Graphics(108)); player.lock(); diff --git a/Server/src/main/content/region/asgarnia/burthorpe/handlers/HeroGuildPlugin.java b/Server/src/main/content/region/asgarnia/burthorpe/handlers/HeroGuildPlugin.java index 2cb15bbb8..5c3900341 100644 --- a/Server/src/main/content/region/asgarnia/burthorpe/handlers/HeroGuildPlugin.java +++ b/Server/src/main/content/region/asgarnia/burthorpe/handlers/HeroGuildPlugin.java @@ -17,6 +17,8 @@ import core.plugin.Plugin; import core.plugin.Initializable; import core.plugin.ClassScanner; +import static core.api.ContentAPIKt.hasRequirement; + /** * Represents the hero guild. * @author Vexia @@ -40,7 +42,8 @@ public final class HeroGuildPlugin extends OptionHandler { switch (id) { case 2624: case 2625: - // player.getPacketDispatch().sendMessage("You need to complete the Heroes' Quest."); + if (!hasRequirement(player, "Heroes' Quest")) + return true; DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); break; } @@ -79,9 +82,16 @@ public final class HeroGuildPlugin extends OptionHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); + if (!hasRequirement(player, "Heroes' Quest")) + return true; final EnchantedJewellery jewellery; assert event.getUsedItem() != null; jewellery = EnchantedJewellery.Companion.getIdMap().get(event.getUsedItem().getId()); + if (!hasRequirement(player, "Heroes' Quest")) + return true; + if (jewellery == EnchantedJewellery.COMBAT_BRACELET || jewellery == EnchantedJewellery.SKILLS_NECKLACE) + if (!hasRequirement(player, "Legend's Quest")) + return true; if (jewellery == null && event.getUsedItem().getId() != 2572) { return true; } diff --git a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodwarsEntranceHandler.java b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodwarsEntranceHandler.java index a794f2289..4960e215e 100644 --- a/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodwarsEntranceHandler.java +++ b/Server/src/main/content/region/asgarnia/trollheim/handlers/gwd/GodwarsEntranceHandler.java @@ -17,6 +17,8 @@ import core.game.world.map.RegionManager; import core.game.world.update.flag.context.Animation; import core.plugin.Plugin; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles the entrance hole to the godwars dungeon. * @author Emperor @@ -66,6 +68,8 @@ public final class GodwarsEntranceHandler extends OptionHandler { }); return true; case 26338: + if (!hasRequirement(player, "Troll Stronghold")) + return true; if (player.getSkills().getStaticLevel(Skills.STRENGTH) < 60) { player.getPacketDispatch().sendMessage("You need a Strength level of 60 to move this boulder."); return true; diff --git a/Server/src/main/content/region/desert/alkharid/dialogue/AliMorrisaneDialogue.kt b/Server/src/main/content/region/desert/alkharid/dialogue/AliMorrisaneDialogue.kt index 0550e8579..50f351f37 100644 --- a/Server/src/main/content/region/desert/alkharid/dialogue/AliMorrisaneDialogue.kt +++ b/Server/src/main/content/region/desert/alkharid/dialogue/AliMorrisaneDialogue.kt @@ -7,6 +7,8 @@ import core.game.node.entity.player.Player import core.plugin.Initializable import org.rs09.consts.NPCs +import core.api.* + /** * Represents the ali morrisane dialogue. * @author 'Vexia @@ -34,6 +36,8 @@ class AliMorrisaneDialogue(player: Player? = null) : DialoguePlugin(player) { 1 -> playerl(FacialExpression.ASKING, "If you are, then why are you still selling goods from a stall?").also { stage = 10 } 2 -> { end() + if (!hasRequirement(player, "The Feud")) + return true npc.openShop(player) } } @@ -55,6 +59,8 @@ class AliMorrisaneDialogue(player: Player? = null) : DialoguePlugin(player) { } 2 -> { end() + if (!hasRequirement(player, "The Feud")) + return true npc.openShop(player) } } diff --git a/Server/src/main/content/region/desert/dialogue/EblisDialogue.java b/Server/src/main/content/region/desert/dialogue/EblisDialogue.java deleted file mode 100644 index 1ea4b0216..000000000 --- a/Server/src/main/content/region/desert/dialogue/EblisDialogue.java +++ /dev/null @@ -1,107 +0,0 @@ -package content.region.desert.dialogue; - -import core.game.dialogue.DialoguePlugin; -import core.game.node.entity.npc.NPC; -import core.game.node.item.Item; -import core.plugin.Initializable; -import core.game.node.entity.player.Player; -import org.rs09.consts.Items; - -/** - * Handles Eblis's dialogue. - * @author ceik - * @version 1.0 - */ -@Initializable -public class EblisDialogue extends DialoguePlugin { - - /** - * Constructs a new {@code EblisDialogue} {@code Object}. - */ - public EblisDialogue() { - /** - * Empty - */ - } - - /** - * Constructs a new {@code EblisDialogue} {@code Object}. - * @param player The player to construct the class for. - */ - public EblisDialogue(final Player player) { - super(player); - } - - @Override - public DialoguePlugin newInstance(Player player) { - return new EblisDialogue(player); - } - - @Override - public boolean open(Object... args) { - //TODO: Add proper dialogue once DT is implemented - npc = (NPC) args[0]; - if(!player.getAttribute("DT:staff-bought",false)) { - player("Hey."); - stage = 0; - } else { - player("Say, what's up with your dialogue?"); - stage = 20; - } - return true; - } - - @Override - public boolean handle(int interfaceId, int buttonId) { - //TODO: Add proper dialogue once DT is implemented - switch(stage){ - case 0: - npc("Hey, you wanna buy this funny stick thing?"); - stage = 1; - break; - case 1: - options("Yes please.","No thanks."); - stage = 2; - break; - case 2: - switch(buttonId){ - case 1: - npc("Alright, that'll be 80,000 golden shekels."); - stage = 10; - break; - case 2: - player("Nah, I'm good, homie."); - stage = 30; - break; - } - break; - case 10: - player("Hmm.... ok."); - stage = 11; - break; - case 11: - if(!player.getInventory().contains(Items.COINS_995,80000)){ - npc("Oi vey... you dont have enough.."); - } else { - player.getInventory().remove(new Item(Items.COINS_995,80000)); - player.getInventory().add(new Item(Items.ANCIENT_STAFF_4675)); - } - stage = 30; - break; - case 20: - npc("Well I don't have me bloody quest yet, mate","so I needed SOMETHING to say,","oi vey."); - stage = 30; - break; - case 30: - end(); - break; - } - return true; - } - - @Override - public int[] getIds() { - return new int[] { 1923 }; - } - -} diff --git a/Server/src/main/content/region/desert/dialogue/RugMerchantDialogue.java b/Server/src/main/content/region/desert/dialogue/RugMerchantDialogue.java index a82cd69b2..00d0c5be7 100644 --- a/Server/src/main/content/region/desert/dialogue/RugMerchantDialogue.java +++ b/Server/src/main/content/region/desert/dialogue/RugMerchantDialogue.java @@ -156,7 +156,14 @@ public final class RugMerchantDialogue extends DialoguePlugin { stage = 20; return; } + end(); destination = options.length == 1 ? options[0] : options[buttonId - 1]; + if (destination == RugDestination.UZER && !hasRequirement(player, "The Golem")) + break; + else if (destination == RugDestination.BEDABIN_CAMP && !hasRequirement(player, "The Tourist Trap")) + break; + else if (destination == RugDestination.SOPHANEM && !hasRequirement(player, "Icthlarin's Little Helper")) + break; if(player.getEquipment().get(EquipmentContainer.SLOT_WEAPON) != null){ player.sendMessage(colorize("%RYou must unequip all your weapons before you can fly on a carpet.")); } else { @@ -164,7 +171,6 @@ public final class RugMerchantDialogue extends DialoguePlugin { destination.travel(current, player); } } - end(); break; case 20: end(); diff --git a/Server/src/main/content/region/desert/sophanem/handlers/SophanemPlugin.java b/Server/src/main/content/region/desert/sophanem/handlers/SophanemPlugin.java index 2b03f8923..776b39973 100644 --- a/Server/src/main/content/region/desert/sophanem/handlers/SophanemPlugin.java +++ b/Server/src/main/content/region/desert/sophanem/handlers/SophanemPlugin.java @@ -12,6 +12,8 @@ import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; +import static core.api.ContentAPIKt.hasRequirement; + /** * The plugin for handling stuff in Sophanem. * @author jamix77 @@ -32,6 +34,8 @@ public class SophanemPlugin extends OptionHandler { final int id = node instanceof Scenery ? ((Scenery) node).getId() : ((Item) node).getId(); switch (id) { case 20275: + if (!hasRequirement(player, "Contact!")) + break; ClimbActionHandler.climb(player, new Animation(827), Location.create(2799, 5160, 0)); break; case 20277: diff --git a/Server/src/main/content/region/fremennik/dialogue/LokarSearunnerDialogue.java b/Server/src/main/content/region/fremennik/dialogue/LokarSearunnerDialogue.java index 4d192382e..ab283041c 100644 --- a/Server/src/main/content/region/fremennik/dialogue/LokarSearunnerDialogue.java +++ b/Server/src/main/content/region/fremennik/dialogue/LokarSearunnerDialogue.java @@ -11,6 +11,7 @@ import core.net.packet.PacketRepository; import core.net.packet.context.MinimapStateContext; import core.plugin.Initializable; import core.net.packet.out.MinimapState; +import static core.api.ContentAPIKt.hasRequirement; /** * Handles the lokar searunner dialogue. @@ -109,6 +110,8 @@ public class LokarSearunnerDialogue extends DialoguePlugin { * @param location the location. */ private void travel(final Player player, final Location location) { + if (!hasRequirement(player, "Lunar Diplomacy")) + return; player.lock(); GameWorld.getPulser().submit(new Pulse(1, player) { int counter; diff --git a/Server/src/main/content/region/fremennik/jatizso/dialogue/MordGunnarsDialogue.kt b/Server/src/main/content/region/fremennik/jatizso/dialogue/MordGunnarsDialogue.kt index 8cc1eb110..b4e2b45bf 100644 --- a/Server/src/main/content/region/fremennik/jatizso/dialogue/MordGunnarsDialogue.kt +++ b/Server/src/main/content/region/fremennik/jatizso/dialogue/MordGunnarsDialogue.kt @@ -7,6 +7,7 @@ import org.rs09.consts.NPCs import content.region.fremennik.rellekka.handlers.RellekkaDestination import content.region.fremennik.rellekka.handlers.RellekkaUtils import core.tools.END_DIALOGUE +import core.api.* @Initializable class MordGunnarsDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { @@ -34,6 +35,8 @@ class MordGunnarsDialogue(player: Player? = null) : core.game.dialogue.DialogueP 2 -> { end() + if (!hasRequirement(player, "Fremennik Trials")) + return true RellekkaUtils.sail(player, if(npc.id == NPCs.MORD_GUNNARS_5481) RellekkaDestination.RELLEKKA_TO_JATIZSO else RellekkaDestination.JATIZSO_TO_RELLEKKA) } } @@ -44,4 +47,4 @@ class MordGunnarsDialogue(player: Player? = null) : core.game.dialogue.DialogueP return intArrayOf(NPCs.MORD_GUNNARS_5482, NPCs.MORD_GUNNARS_5481) } -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/fremennik/rellekka/dialogue/MariaGunnarsDialogue.java b/Server/src/main/content/region/fremennik/rellekka/dialogue/MariaGunnarsDialogue.java index e29283ccf..766227b3a 100644 --- a/Server/src/main/content/region/fremennik/rellekka/dialogue/MariaGunnarsDialogue.java +++ b/Server/src/main/content/region/fremennik/rellekka/dialogue/MariaGunnarsDialogue.java @@ -6,6 +6,8 @@ import core.game.node.entity.player.Player; import content.region.fremennik.rellekka.handlers.RellekkaDestination; import content.region.fremennik.rellekka.handlers.RellekkaUtils; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles the maria gunnars dialogue. * @author Vexia @@ -62,12 +64,14 @@ public class MariaGunnarsDialogue extends DialoguePlugin { stage++; break; case 3: + end(); + if (!hasRequirement(player, "Fremennik Trials")) + break; if (npc.getId() == 5508) { RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_NEITIZNOT); } else { RellekkaUtils.sail(player, RellekkaDestination.NEITIZNOT_TO_RELLEKKA); } - end(); break; case 4: npc("Thanks!"); diff --git a/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaListeners.kt b/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaListeners.kt index ddb16861c..92f0a0ce1 100644 --- a/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaListeners.kt +++ b/Server/src/main/content/region/fremennik/rellekka/handlers/RellekkaListeners.kt @@ -1,5 +1,6 @@ package content.region.fremennik.rellekka.handlers +import core.api.* import core.game.world.map.Location import org.rs09.consts.NPCs import core.game.interaction.InteractionListener @@ -47,6 +48,8 @@ class RellekkaListeners : InteractionListener { } on(NPCs.MARIA_GUNNARS_5508, IntType.NPC, "ferry-neitiznot"){ player, _ -> + if (!hasRequirement(player, "Fremennik Trials")) + return@on true RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_NEITIZNOT) return@on true } @@ -57,6 +60,8 @@ class RellekkaListeners : InteractionListener { } on(NPCs.MORD_GUNNARS_5481, IntType.NPC, "ferry-jatizso"){ player, node -> + if (!hasRequirement(player, "Fremennik Trials")) + return@on true RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_JATIZSO) return@on true } @@ -66,4 +71,4 @@ class RellekkaListeners : InteractionListener { return@on true } } -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt index e2e1e289a..835153a26 100644 --- a/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt +++ b/Server/src/main/content/region/fremennik/rellekka/quest/thefremenniktrials/ChieftanBrundtDialogue.kt @@ -1,7 +1,7 @@ package content.region.fremennik.rellekka.quest.thefremenniktrials -import core.api.addItem -import core.api.removeItem +import core.api.* +import core.game.node.item.Item import core.game.node.entity.player.Player import core.plugin.Initializable import core.game.dialogue.DialoguePlugin @@ -9,6 +9,8 @@ import core.game.dialogue.FacialExpression import core.tools.END_DIALOGUE import kotlin.random.Random +import org.rs09.consts.* + @Initializable class ChieftanBrundt(player: Player? = null) : core.game.dialogue.DialoguePlugin(player){ val gender = if (player?.isMale == true){"brother"} else "sister" @@ -16,52 +18,52 @@ class ChieftanBrundt(player: Player? = null) : core.game.dialogue.DialoguePlugin override fun open(vararg args: Any?): Boolean { if(player?.inventory?.contains(3701,1) == true){ - playerl(core.game.dialogue.FacialExpression.HAPPY,"I got Sigli's hunting map for you.") + playerl(FacialExpression.HAPPY,"I got Sigli's hunting map for you.") stage = 515 return true } else if(player?.inventory?.contains(3708,1) == true){ - playerl(core.game.dialogue.FacialExpression.ASKING,"So cutting sales tax isn't going to ruin your economy here or anything?") + playerl(FacialExpression.ASKING,"So cutting sales tax isn't going to ruin your economy here or anything?") stage = 520 return true } else if(player?.getAttribute("sigmundreturning",false) == true){ - playerl(core.game.dialogue.FacialExpression.ASKING,"I've got this trade item. Is it for you?") + playerl(FacialExpression.ASKING,"I've got this trade item. Is it for you?") stage = 525 return true } if(player?.getAttribute("sigmund-steps",0) == 5){ - playerl(core.game.dialogue.FacialExpression.ASKING,"I don't suppose you have any idea where I could find a map to unspoiled hunting grounds, do you?") + playerl(FacialExpression.ASKING,"I don't suppose you have any idea where I could find a map to unspoiled hunting grounds, do you?") stage = 510 return true } else if(player?.getAttribute("sigmund-steps",0) == 4){ - playerl(core.game.dialogue.FacialExpression.ASKING,"I don't suppose you have any idea where I could find a guarantee of a reduction on sales taxes, do you?") + playerl(FacialExpression.ASKING,"I don't suppose you have any idea where I could find a guarantee of a reduction on sales taxes, do you?") stage = 500 return true } else if(player.getAttribute("fremtrials:votes",0) >= 7){ - npcl(core.game.dialogue.FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") + npcl(FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") stage = 545 return true } else if(player.getAttribute("fremtrials:votes",0) in 3..6){ - npcl(core.game.dialogue.FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") + npcl(FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") stage = 540 return true } else if(player.getAttribute("fremtrials:votes",0) == 1){ - npcl(core.game.dialogue.FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") + npcl(FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") stage = 535 return true } else if(player.getAttribute("fremtrials:votes",-1) == 0){ - npcl(core.game.dialogue.FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") + npcl(FacialExpression.HAPPY," Greetings again outerlander! How goes your attempts to gain votes with the council of elders?") stage = 530 return true } else if(player.questRepository.isComplete("Fremennik Trials")){ - npcl(core.game.dialogue.FacialExpression.HAPPY,"Hello again, $gender $fName. I hope your travels have brought you wealth and joy! What compels you to visit me on this day?") + npcl(FacialExpression.HAPPY,"Hello again, $gender $fName. I hope your travels have brought you wealth and joy! What compels you to visit me on this day?") stage = 600 return true } @@ -77,23 +79,23 @@ class ChieftanBrundt(player: Player? = null) : core.game.dialogue.DialoguePlugin //Pre-Quest 0 -> { options("What is this place?", "Why will no-one talk to me?", "Do you have any quests?", "Nice hat!");stage++} 1 -> when(buttonId){ - 1 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"What is this place?").also { stage ++ } - 2 -> playerl(core.game.dialogue.FacialExpression.ASKING,"Why will no-one talk to me?").also { stage = 5 } + 1 -> playerl(FacialExpression.HAPPY,"What is this place?").also { stage ++ } + 2 -> playerl(FacialExpression.ASKING,"Why will no-one talk to me?").also { stage = 5 } 3 -> player("Do you have any quests?").also {stage = 300} - 4 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Nice hat!").also { stage = 15 } + 4 -> playerl(FacialExpression.HAPPY,"Nice hat!").also { stage = 15 } } - 2 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"This place? Why, this is Relleka! Homeland of all Fremennik! I do not recognise your face outerlander; Where do you come from?").also { stage++ } - 3 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Hmmm... I will not press the issue then outerlander. How may my tribe and I help you?").also { stage = 0 } + 2 -> npcl(FacialExpression.HAPPY,"This place? Why, this is Relleka! Homeland of all Fremennik! I do not recognise your face outerlander; Where do you come from?").also { stage++ } + 3 -> playerl(FacialExpression.HAPPY,"Hmmm... I will not press the issue then outerlander. How may my tribe and I help you?").also { stage = 0 } - 5 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Do not take it personally, outerlander! We are a simple people, and it is our experience that keeping ourselves to ourselves is best.").also { stage++ } - 6 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"This is why speaking to outerlanders is forbidden.").also { stage++ } - 7 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"We do not wish to enter war with the outerlanders and their strange magics, so we limit all unauthorised communication.").also { stage++ } - 8 -> playerl(core.game.dialogue.FacialExpression.ASKING,"Then how come you're talking to me?").also { stage++ } - 9 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Ah, this is because I am the chieftan. I am the one who authorised contact. You will not find many of my tribe so forthcoming with you, as I.").also { stage++ } - 10 -> playerl(core.game.dialogue.FacialExpression.ASKING,"Is there a way for you to authorise your tribe to talk to me then?").also { stage++ } - 11 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Well, there is one way... but I doubt it is of any interest to you.").also { stage = 0 } + 5 -> npcl(FacialExpression.HAPPY,"Do not take it personally, outerlander! We are a simple people, and it is our experience that keeping ourselves to ourselves is best.").also { stage++ } + 6 -> npcl(FacialExpression.HAPPY,"This is why speaking to outerlanders is forbidden.").also { stage++ } + 7 -> npcl(FacialExpression.HAPPY,"We do not wish to enter war with the outerlanders and their strange magics, so we limit all unauthorised communication.").also { stage++ } + 8 -> playerl(FacialExpression.ASKING,"Then how come you're talking to me?").also { stage++ } + 9 -> npcl(FacialExpression.HAPPY,"Ah, this is because I am the chieftan. I am the one who authorised contact. You will not find many of my tribe so forthcoming with you, as I.").also { stage++ } + 10 -> playerl(FacialExpression.ASKING,"Is there a way for you to authorise your tribe to talk to me then?").also { stage++ } + 11 -> npcl(FacialExpression.HAPPY,"Well, there is one way... but I doubt it is of any interest to you.").also { stage = 0 } - 15 -> npcl(core.game.dialogue.FacialExpression.ANNOYED,"Don't mock me outerlander; this helm has saved my life more times than I care to recall right now.").also { stage = 1000 } + 15 -> npcl(FacialExpression.ANNOYED,"Don't mock me outerlander; this helm has saved my life more times than I care to recall right now.").also { stage = 1000 } //Do you have any quests? @@ -130,46 +132,46 @@ class ChieftanBrundt(player: Player? = null) : core.game.dialogue.DialoguePlugin //No, I'm not interested 340 -> TODO("Not implemented yet") - 500 -> npcl(core.game.dialogue.FacialExpression.THINKING,"A reduction on sales taxes? Why, I am the only one in the Fremennik who may authorise such a thing. What does an outerlander want with that?").also { stage++ } - 501 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Actually, it's not for me. I need to get it as part of my trials").also { stage++ } - 502 -> npcl(core.game.dialogue.FacialExpression.THINKING,"Hmmm. Interesting. Your trials seem to be very different to those I took as a young lad.").also { stage++ } - 503 -> npcl(core.game.dialogue.FacialExpression.NEUTRAL,"Well, I am not adverse in principle to giving a slight tax break to our shops.").also { stage++ } - 504 -> npcl(core.game.dialogue.FacialExpression.THINKING,"There will of course be a shortfall in the tribe's income, that will need to be made up for elsewhere, however.").also { stage++ } - 505 -> npcl(core.game.dialogue.FacialExpression.ASKING,"How about this. For many years Sigli has been the only one in the tribe who knows the locations of the best hunting grounds where game is easiest to catch.").also { stage++ } - 506 -> npcl(core.game.dialogue.FacialExpression.ASKING,"If you can persuade him to let the entire tribe know these hunting grounds, then we can increase productivity within the tribe, and any shortfall caused by lowering sales taxes will be covered.").also { stage++ } - 507 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"I think this is a more than fair arrangement to make, dont you?").also { stage++ } - 508 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Yeah, that sounds very fair.").also { stage++ } - 509 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Speak to Sigli then, and you may have my promise to reduce our sales taxes. And best of luck with the rest of your trials.").also { + 500 -> npcl(FacialExpression.THINKING,"A reduction on sales taxes? Why, I am the only one in the Fremennik who may authorise such a thing. What does an outerlander want with that?").also { stage++ } + 501 -> playerl(FacialExpression.HAPPY,"Actually, it's not for me. I need to get it as part of my trials").also { stage++ } + 502 -> npcl(FacialExpression.THINKING,"Hmmm. Interesting. Your trials seem to be very different to those I took as a young lad.").also { stage++ } + 503 -> npcl(FacialExpression.NEUTRAL,"Well, I am not adverse in principle to giving a slight tax break to our shops.").also { stage++ } + 504 -> npcl(FacialExpression.THINKING,"There will of course be a shortfall in the tribe's income, that will need to be made up for elsewhere, however.").also { stage++ } + 505 -> npcl(FacialExpression.ASKING,"How about this. For many years Sigli has been the only one in the tribe who knows the locations of the best hunting grounds where game is easiest to catch.").also { stage++ } + 506 -> npcl(FacialExpression.ASKING,"If you can persuade him to let the entire tribe know these hunting grounds, then we can increase productivity within the tribe, and any shortfall caused by lowering sales taxes will be covered.").also { stage++ } + 507 -> npcl(FacialExpression.HAPPY,"I think this is a more than fair arrangement to make, dont you?").also { stage++ } + 508 -> playerl(FacialExpression.HAPPY,"Yeah, that sounds very fair.").also { stage++ } + 509 -> npcl(FacialExpression.HAPPY,"Speak to Sigli then, and you may have my promise to reduce our sales taxes. And best of luck with the rest of your trials.").also { player?.incrementAttribute("sigmund-steps",1) stage = 1000 } - 510 -> npcl(core.game.dialogue.FacialExpression.ANNOYED,"Ah, outerlander... if you wish to become a Fremennik you should try and pay more attention to what people tell you... ").also { stage++ } - 511 -> npcl(core.game.dialogue.FacialExpression.ANNOYED,"Sigli the hunter is the only one who knows of such hunting grounds. Go and request his knowledge.").also { stage = 1000 } + 510 -> npcl(FacialExpression.ANNOYED,"Ah, outerlander... if you wish to become a Fremennik you should try and pay more attention to what people tell you... ").also { stage++ } + 511 -> npcl(FacialExpression.ANNOYED,"Sigli the hunter is the only one who knows of such hunting grounds. Go and request his knowledge.").also { stage = 1000 } - 515 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Excellent work outerlander! And so quickly, too! Here, you may take my financial report promising reduced sales taxes on all goods.").also { + 515 -> npcl(FacialExpression.HAPPY,"Excellent work outerlander! And so quickly, too! Here, you may take my financial report promising reduced sales taxes on all goods.").also { removeItem(player,3701) addItem(player,3708) stage = 1000 } - 520 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Not at all outerlander; now that we have Sigli's map we can increase the amount of hunts we run, and make up any shortfall that way.").also { stage = 1000 } + 520 -> npcl(FacialExpression.HAPPY,"Not at all outerlander; now that we have Sigli's map we can increase the amount of hunts we run, and make up any shortfall that way.").also { stage = 1000 } - 525 -> npcl(core.game.dialogue.FacialExpression.ANNOYED,"Not unless it's a map of the hunting grounds.").also { stage = 1000 } + 525 -> npcl(FacialExpression.ANNOYED,"Not unless it's a map of the hunting grounds.").also { stage = 1000 } - 530 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"I don't have any votes yet.").also { stage++ } - 531 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Go and speak to the twelve members of the council of elders who live in this village. I am sure at least a few will be prepared to vote for you.").also { stage = 550 } + 530 -> playerl(FacialExpression.HAPPY,"I don't have any votes yet.").also { stage++ } + 531 -> npcl(FacialExpression.HAPPY,"Go and speak to the twelve members of the council of elders who live in this village. I am sure at least a few will be prepared to vote for you.").also { stage = 550 } - 535 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"I only have one vote so far.").also { stage++ } - 536 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Hmmm... well that is certainly a good start I would say. Keep up the good work!").also { stage++ } - 537 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Remember: You need to get at least seven council votes to be accepted as a member of the Fremennik.").also { stage = 550 } + 535 -> playerl(FacialExpression.HAPPY,"I only have one vote so far.").also { stage++ } + 536 -> npcl(FacialExpression.HAPPY,"Hmmm... well that is certainly a good start I would say. Keep up the good work!").also { stage++ } + 537 -> npcl(FacialExpression.HAPPY,"Remember: You need to get at least seven council votes to be accepted as a member of the Fremennik.").also { stage = 550 } - 540 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"I only have ${player.getAttribute("fremtrials:votes",0)} votes so far.").also { stage++ } - 541 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Hmmm... you are doing very well so far, outerlander. Keep up the good work!").also { stage = 537 } + 540 -> playerl(FacialExpression.HAPPY,"I only have ${player.getAttribute("fremtrials:votes",0)} votes so far.").also { stage++ } + 541 -> npcl(FacialExpression.HAPPY,"Hmmm... you are doing very well so far, outerlander. Keep up the good work!").also { stage = 537 } - 545 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"I have seven members of the council prepared to vote in my favour now!").also { stage++ } - 546 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"I know outerlander, for I have been closely monitoring your progress so far!").also {stage++} - 547 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Then let us put the formality aside, and let me personally welcome you into the Fremennik! May you bring us honour!").also { + 545 -> playerl(FacialExpression.HAPPY,"I have seven members of the council prepared to vote in my favour now!").also { stage++ } + 546 -> npcl(FacialExpression.HAPPY,"I know outerlander, for I have been closely monitoring your progress so far!").also {stage++} + 547 -> npcl(FacialExpression.HAPPY,"Then let us put the formality aside, and let me personally welcome you into the Fremennik! May you bring us honour!").also { if(player.inventory.freeSlots() >= 10){ println(GenerateFremennikName()) player.setAttribute("/save:fremennikname", GenerateFremennikName()) @@ -180,82 +182,98 @@ class ChieftanBrundt(player: Player? = null) : core.game.dialogue.DialoguePlugin } 548 -> sendDialogue("You require 10 free spaces in your backpack to claim your reward.").also { stage = 1000 } - 550 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"If you need any help with your trials, I suggest you speak to Askeladden. He is currently doing his own trials of manhood to become a true Fremennik.") + 550 -> npcl(FacialExpression.HAPPY,"If you need any help with your trials, I suggest you speak to Askeladden. He is currently doing his own trials of manhood to become a true Fremennik.") - 560 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"From this day onward, you are outerlander no more! In honour of your acceptance into the Fremennik, you gain a new name: ${player.getAttribute("fremennikname","how did u break this")}.").also { + 560 -> npcl(FacialExpression.HAPPY,"From this day onward, you are outerlander no more! In honour of your acceptance into the Fremennik, you gain a new name: ${player.getAttribute("fremennikname","how did u break this")}.").also { cleanupAttributes(player) player.questRepository.getQuest("Fremennik Trials").finish(player) stage = 1000 } - 600 -> options("I just came to say hello.","Do you have any quests?","Nice hat!","Can I hear the history of your people?").also { stage++ } + 600 -> options("I just came to say hello.","Do you have any quests?","Nice hat!","Can I hear the history of your people?", "Can I have a seal of passage?").also { stage++ } 601 -> when(buttonId){ - 1 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"I just came by to say hello.").also { stage++ } - 2 -> playerl(core.game.dialogue.FacialExpression.ASKING,"Do you have any quests?").also { stage = 605 } - 3 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Nice hat!").also { stage = 610 } - 4 -> playerl(core.game.dialogue.FacialExpression.ASKING,"Can I hear the history of your people?").also { stage = 615 } + 1 -> playerl(FacialExpression.HAPPY,"I just came by to say hello.").also { stage++ } + 2 -> playerl(FacialExpression.ASKING,"Do you have any quests?").also { stage = 605 } + 3 -> playerl(FacialExpression.HAPPY,"Nice hat!").also { stage = 610 } + 4 -> playerl(FacialExpression.ASKING,"Can I hear the history of your people?").also { stage = 615 } + 5 -> playerl(FacialExpression.HAPPY, "Can I have a seal of passage?").also { stage = 1200 } } - 602 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Well met, $gender $fName. it is always good to see your face in glorious Rellekka once more!").also { stage = 1000 } + 602 -> npcl(FacialExpression.HAPPY,"Well met, $gender $fName. it is always good to see your face in glorious Rellekka once more!").also { stage = 1000 } - 605 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Not at the moment, $fName. Rest assured, should your services to the Fremennik be required, I will call upon you").also { stage = 1000 } + 605 -> npcl(FacialExpression.HAPPY,"Not at the moment, $fName. Rest assured, should your services to the Fremennik be required, I will call upon you").also { stage = 1000 } - 610 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Aye that it is, $gender $fName. Should you desire one of your own, you should go to Skulgrimen's shop and see what they have available!").also { stage = 1000 } + 610 -> npcl(FacialExpression.HAPPY,"Aye that it is, $gender $fName. Should you desire one of your own, you should go to Skulgrimen's shop and see what they have available!").also { stage = 1000 } - 615 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Why, of course, $fName! Do not say 'your people' like that, for you are now a Fremennik yourself! What did you want to hear of?").also { stage++ } + 615 -> npcl(FacialExpression.HAPPY,"Why, of course, $fName! Do not say 'your people' like that, for you are now a Fremennik yourself! What did you want to hear of?").also { stage++ } 616 -> options("Tell me of the finding of Koschei","Tell me of the lands to the North","Tell me of the outerlanders","Don't tell me anything").also { stage++ } 617 -> when(buttonId){ - 1 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"I'm interested in finding out about that mysterious warrior I fought as part of Thorvalds' combat trial. His name is Koschei I believe.").also { stage++ } - 2 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"I would like to hear of the lands across the ocean to the North.").also { stage = 635 } - 3 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"I would like to hear a little of the history between the Fremenniks and the outerlanders.").also { stage = 645 } - 4 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Actually, history isn't really my thing.").also { stage = 665 } + 1 -> playerl(FacialExpression.HAPPY,"I'm interested in finding out about that mysterious warrior I fought as part of Thorvalds' combat trial. His name is Koschei I believe.").also { stage++ } + 2 -> playerl(FacialExpression.HAPPY,"I would like to hear of the lands across the ocean to the North.").also { stage = 635 } + 3 -> playerl(FacialExpression.HAPPY,"I would like to hear a little of the history between the Fremenniks and the outerlanders.").also { stage = 645 } + 4 -> playerl(FacialExpression.HAPPY,"Actually, history isn't really my thing.").also { stage = 665 } } - 618 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Ah... the deathless one... We do not even know if Koschei is his name, when we found him he had no memory,").also { stage++ } - 619 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"he was simply repeating that single word. Whatever happened to him must have rattled his soul so hard that his memory ran away from him,").also { stage++ } - 620 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"and he has not yet found its hiding place.").also { stage++ } - 621 -> playerl(core.game.dialogue.FacialExpression.ASKING,"So how exactly did you find him?").also { stage++ } - 622 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Well, it was a raiding party like any other. We had just struck one of the smaller northern islands to harvest supplies by combat, as our laws allow,").also { stage++ } - 623 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"when we saw a figure in the icey waters. As we were at least a 3 week sail from any port, and saw no other ships nearby, he must have been there some time.").also { stage++ } - 624 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"We could not leave someone to the cold death of the ocean, even an outerlander, so we fished him aboard. He muttered continually, but his words made no sense.").also { stage++ } - 625 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"He had no clothes or possessions with him, and seemed to have been burnt somehow before he had landed in the water. I cannot help but wonder what burnt him,").also { stage++ } - 626 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"for as you may have seen, he is incredibly powerful and resistant to damage by any means I know of! Anyway, we decided to bring him back to Rellekka,").also { stage++ } - 627 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"for he did not seem of good health or sound mind, and simply repeated the word Koschei over and over. Yrsa tended to him for many weeks, until one day it was as though a new soul had entered his burnt and broken body.").also { stage++ } - 628 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"He suddenly left her house one day, fully healed, and able to speak to us as though nothing had happened to him.").also { stage++ } - 629 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"He still had no recollection of how he had come to be in the icey ocean, or of who he was, or where he had come from, but this did not matter to us or him.").also { stage++ } - 630 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"He took his trials of adulthood, as you did, and has been a boon to our clan ever since. Someday I fear he may regain his memory, and leave us for his past...").also { stage++ } - 631 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"But I will always respect any decision he decides to make should that day ever come upon us. Until then, he is more than welcome to stay here.").also { stage++ } - 632 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"So, $fName, was there anything more you wished to hear?").also { stage = 616 } + 618 -> npcl(FacialExpression.HAPPY,"Ah... the deathless one... We do not even know if Koschei is his name, when we found him he had no memory,").also { stage++ } + 619 -> npcl(FacialExpression.HAPPY,"he was simply repeating that single word. Whatever happened to him must have rattled his soul so hard that his memory ran away from him,").also { stage++ } + 620 -> npcl(FacialExpression.HAPPY,"and he has not yet found its hiding place.").also { stage++ } + 621 -> playerl(FacialExpression.ASKING,"So how exactly did you find him?").also { stage++ } + 622 -> npcl(FacialExpression.HAPPY,"Well, it was a raiding party like any other. We had just struck one of the smaller northern islands to harvest supplies by combat, as our laws allow,").also { stage++ } + 623 -> npcl(FacialExpression.HAPPY,"when we saw a figure in the icey waters. As we were at least a 3 week sail from any port, and saw no other ships nearby, he must have been there some time.").also { stage++ } + 624 -> npcl(FacialExpression.HAPPY,"We could not leave someone to the cold death of the ocean, even an outerlander, so we fished him aboard. He muttered continually, but his words made no sense.").also { stage++ } + 625 -> npcl(FacialExpression.HAPPY,"He had no clothes or possessions with him, and seemed to have been burnt somehow before he had landed in the water. I cannot help but wonder what burnt him,").also { stage++ } + 626 -> npcl(FacialExpression.HAPPY,"for as you may have seen, he is incredibly powerful and resistant to damage by any means I know of! Anyway, we decided to bring him back to Rellekka,").also { stage++ } + 627 -> npcl(FacialExpression.HAPPY,"for he did not seem of good health or sound mind, and simply repeated the word Koschei over and over. Yrsa tended to him for many weeks, until one day it was as though a new soul had entered his burnt and broken body.").also { stage++ } + 628 -> npcl(FacialExpression.HAPPY,"He suddenly left her house one day, fully healed, and able to speak to us as though nothing had happened to him.").also { stage++ } + 629 -> npcl(FacialExpression.HAPPY,"He still had no recollection of how he had come to be in the icey ocean, or of who he was, or where he had come from, but this did not matter to us or him.").also { stage++ } + 630 -> npcl(FacialExpression.HAPPY,"He took his trials of adulthood, as you did, and has been a boon to our clan ever since. Someday I fear he may regain his memory, and leave us for his past...").also { stage++ } + 631 -> npcl(FacialExpression.HAPPY,"But I will always respect any decision he decides to make should that day ever come upon us. Until then, he is more than welcome to stay here.").also { stage++ } + 632 -> npcl(FacialExpression.HAPPY,"So, $fName, was there anything more you wished to hear?").also { stage = 616 } - 635 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Well, I think the best thing for you would be to go to the docks and ask to join one of our longboats on a journey. My affairs are concentrated mostly on Rellekka,").also { stage++ } - 636 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"So my knowledge is not great, but I will happily share what little I do know with you, $fName. North of this town the atmosphere becomes bitterly cold.").also { stage++ } - 637 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"There are a number of small inhabited islands that we have sea routes with. The largest of these is possibly Miscellania,").also { stage++ } - 638 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Although I hear that there has been some recent incident with their monarch, but I don't know the details.").also { stage++ } - 639 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"There is also of course the island of the moon clan, who change with the tides. They are our bitterest enemies, and we are currently at war with them.").also { stage++ } - 640 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"They are an evil people, equally cursed and blessed by the magic in their blood. Beyond those islands, there is the large frozen wasteland we call Acheron.").also { stage++ } - 641 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"It is an inhospitable land, and you will need an agile and sturdy body just to keep alive in its perils.").also { stage++ } - 642 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"As I say, my knowledge outside of this town is rather limited, and I know no more than this.").also { stage++ } - 643 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Was there anything else you wished to hear tell of?").also { stage = 616 } + 635 -> npcl(FacialExpression.HAPPY,"Well, I think the best thing for you would be to go to the docks and ask to join one of our longboats on a journey. My affairs are concentrated mostly on Rellekka,").also { stage++ } + 636 -> npcl(FacialExpression.HAPPY,"So my knowledge is not great, but I will happily share what little I do know with you, $fName. North of this town the atmosphere becomes bitterly cold.").also { stage++ } + 637 -> npcl(FacialExpression.HAPPY,"There are a number of small inhabited islands that we have sea routes with. The largest of these is possibly Miscellania,").also { stage++ } + 638 -> npcl(FacialExpression.HAPPY,"Although I hear that there has been some recent incident with their monarch, but I don't know the details.").also { stage++ } + 639 -> npcl(FacialExpression.HAPPY,"There is also of course the island of the moon clan, who change with the tides. They are our bitterest enemies, and we are currently at war with them.").also { stage++ } + 640 -> npcl(FacialExpression.HAPPY,"They are an evil people, equally cursed and blessed by the magic in their blood. Beyond those islands, there is the large frozen wasteland we call Acheron.").also { stage++ } + 641 -> npcl(FacialExpression.HAPPY,"It is an inhospitable land, and you will need an agile and sturdy body just to keep alive in its perils.").also { stage++ } + 642 -> npcl(FacialExpression.HAPPY,"As I say, my knowledge outside of this town is rather limited, and I know no more than this.").also { stage++ } + 643 -> npcl(FacialExpression.HAPPY,"Was there anything else you wished to hear tell of?").also { stage = 616 } - 645 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Ah, now that is something I know a great deal about. Believe it or not, all outerlanders were once orginally Fremenniks.").also { stage++ } - 646 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"When first man came to these lands all were Fremenniks, and followed our ways. We lived a happy life, and never settled in one place for long.").also { stage++ } - 647 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"We travelled by boat along the coastlines, never taking more from the land than could be regrown by the same time in the following year.").also { stage++ } - 648 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"However, many moons past, some of our tribesmen were weary of constantly travelling the lands, and decided to build themselves permanent homes.").also { stage++ } - 649 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Unfortunately, the other races that had also migrated here did not like this. They waged war against us at every opportunity.").also { stage++ } - 650 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"We were driven mostly to the coastlines, where we could escape by boat when attacked. Remember, at this time we had no real way to defend against constant attack.").also { stage++ } - 651 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Then one day one of our Seers, whose full name has been lost in the telling of this tale, discovered a cave full of strange rocks.").also { stage++ } - 652 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"This rock would never be consumed, no matter how much we took, and sparkled at its peak, and broke off in small and regular sized chunks when mined.").also { stage++ } - 653 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Stranger than this, we found that these rocks would become filled with power when taken to certain places across this land! There was a terrible argument in our tribe!").also { stage++ } - 654 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Some said that we should take as many of these rocks as we could, and use them in defending against our enemies' attacks!").also { stage++ } - 655 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Others said that we had found a place that belonged only to the gods, and that should we steal what was not ours we would find only torment and misery.").also { stage++ } - 656 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"We voted on this, and decided that it was in the best interests of the tribe to leave these strange rocks where they lay, for the gods can be spiteful and cruel,").also { stage++ } - 657 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"especially to those who do not treat them with the respect they desire. Some of our number refused to accept this ruling by our council however.").also { stage++ } - 658 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"They began to mine these rocks, and set up transport systems to the various places of power that enchanted them. They even created temples at each of these places!").also { stage++ } - 659 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"This was going too far! We had no choice, but to expel them from our tribe forever!").also { stage++ } - 660 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"We turned our backs upon them, and let them know they would never be welcome back to our tribes until they had released themselves from the rocks.").also { stage++ } - 661 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"This is the tale of how the outerlanders came about; through stealing from the gods, and from betraying our ideals. This is why we show them no trust.").also { stage++ } - 662 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Was there something else you wished to hear?").also { stage = 616 } + 645 -> npcl(FacialExpression.HAPPY,"Ah, now that is something I know a great deal about. Believe it or not, all outerlanders were once orginally Fremenniks.").also { stage++ } + 646 -> npcl(FacialExpression.HAPPY,"When first man came to these lands all were Fremenniks, and followed our ways. We lived a happy life, and never settled in one place for long.").also { stage++ } + 647 -> npcl(FacialExpression.HAPPY,"We travelled by boat along the coastlines, never taking more from the land than could be regrown by the same time in the following year.").also { stage++ } + 648 -> npcl(FacialExpression.HAPPY,"However, many moons past, some of our tribesmen were weary of constantly travelling the lands, and decided to build themselves permanent homes.").also { stage++ } + 649 -> npcl(FacialExpression.HAPPY,"Unfortunately, the other races that had also migrated here did not like this. They waged war against us at every opportunity.").also { stage++ } + 650 -> npcl(FacialExpression.HAPPY,"We were driven mostly to the coastlines, where we could escape by boat when attacked. Remember, at this time we had no real way to defend against constant attack.").also { stage++ } + 651 -> npcl(FacialExpression.HAPPY,"Then one day one of our Seers, whose full name has been lost in the telling of this tale, discovered a cave full of strange rocks.").also { stage++ } + 652 -> npcl(FacialExpression.HAPPY,"This rock would never be consumed, no matter how much we took, and sparkled at its peak, and broke off in small and regular sized chunks when mined.").also { stage++ } + 653 -> npcl(FacialExpression.HAPPY,"Stranger than this, we found that these rocks would become filled with power when taken to certain places across this land! There was a terrible argument in our tribe!").also { stage++ } + 654 -> npcl(FacialExpression.HAPPY,"Some said that we should take as many of these rocks as we could, and use them in defending against our enemies' attacks!").also { stage++ } + 655 -> npcl(FacialExpression.HAPPY,"Others said that we had found a place that belonged only to the gods, and that should we steal what was not ours we would find only torment and misery.").also { stage++ } + 656 -> npcl(FacialExpression.HAPPY,"We voted on this, and decided that it was in the best interests of the tribe to leave these strange rocks where they lay, for the gods can be spiteful and cruel,").also { stage++ } + 657 -> npcl(FacialExpression.HAPPY,"especially to those who do not treat them with the respect they desire. Some of our number refused to accept this ruling by our council however.").also { stage++ } + 658 -> npcl(FacialExpression.HAPPY,"They began to mine these rocks, and set up transport systems to the various places of power that enchanted them. They even created temples at each of these places!").also { stage++ } + 659 -> npcl(FacialExpression.HAPPY,"This was going too far! We had no choice, but to expel them from our tribe forever!").also { stage++ } + 660 -> npcl(FacialExpression.HAPPY,"We turned our backs upon them, and let them know they would never be welcome back to our tribes until they had released themselves from the rocks.").also { stage++ } + 661 -> npcl(FacialExpression.HAPPY,"This is the tale of how the outerlanders came about; through stealing from the gods, and from betraying our ideals. This is why we show them no trust.").also { stage++ } + 662 -> npcl(FacialExpression.HAPPY,"Was there something else you wished to hear?").also { stage = 616 } - 665 -> npcl(core.game.dialogue.FacialExpression.HAPPY,"Well let me know should you wish to hear our lore and histories. We value them highly.").also { stage = 1000 } + 665 -> npcl(FacialExpression.HAPPY,"Well let me know should you wish to hear our lore and histories. We value them highly.").also { stage = 1000 } + + 1200 -> npcl(FacialExpression.HALF_THINKING, "Well, I ought not to give you such things lightly...").also { stage++ } + 1201 -> npcl(FacialExpression.HALF_THINKING, "I suppose I can grant you one temporarily, provided you meet certain requirements.").also { stage++ } + 1202 -> npcl(FacialExpression.HAPPY, "Very well, $fName! Let me look you over and see if you're strong enough for this boon.").also { stage++ } + 1203 -> { + if (!hasRequirement(player, "Lunar Diplomacy") || player!!.hasItem(Item(Items.SEAL_OF_PASSAGE_9083))) + npcl(FacialExpression.HALF_GUILTY, "I'm sorry, $fName. You just don't have the experience needed for this gift. Please come back when you've learned more.").also { stage = END_DIALOGUE } + else + npcl(FacialExpression.HAPPY, "Yes, yes... I see it. You've got the strength and wisdom for this gift. Please, take this. For now.").also { stage++ } + } + 1204 -> { + sendItemDialogue (player, Items.SEAL_OF_PASSAGE_9083, "Chieftan Brundt hands you a Seal of Passage.") + addItem(player, Items.SEAL_OF_PASSAGE_9083) + stage = END_DIALOGUE + } 1000 -> end() } @@ -335,4 +353,4 @@ fun cleanupAttributes(player: Player){ player.removeAttribute("fremtrials:thorvald-vote") player.removeAttribute("fremtrials:sigli-vote") player.removeAttribute("riddlesolved") -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/karamja/shilo/handlers/BrokenCartBypass.java b/Server/src/main/content/region/karamja/shilo/handlers/BrokenCartBypass.java index 7011a44ca..5176ad97b 100644 --- a/Server/src/main/content/region/karamja/shilo/handlers/BrokenCartBypass.java +++ b/Server/src/main/content/region/karamja/shilo/handlers/BrokenCartBypass.java @@ -11,6 +11,8 @@ import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; +import static core.api.ContentAPIKt.hasRequirement; + /** * Temporarily fix to allow people into shilo village by foot until the Shilo Village quest is added @@ -39,6 +41,8 @@ public class BrokenCartBypass extends OptionHandler { }); } public final boolean handle(Player player, Node node, String options){ + if (!hasRequirement(player, "Shilo Village")) + return true; Location location = new Location(0,0); Location playerloc = new Location(player.getLocation().getX(),player.getLocation().getY()); if(options.equals("look-at")) { diff --git a/Server/src/main/content/region/karamja/shilo/handlers/ShiloVillagePlugin.java b/Server/src/main/content/region/karamja/shilo/handlers/ShiloVillagePlugin.java index afb1c65a4..6dc4d101e 100644 --- a/Server/src/main/content/region/karamja/shilo/handlers/ShiloVillagePlugin.java +++ b/Server/src/main/content/region/karamja/shilo/handlers/ShiloVillagePlugin.java @@ -15,6 +15,8 @@ import core.game.world.map.RegionManager; import core.plugin.Plugin; import core.plugin.ClassScanner; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles shilo village interactions. * @author Vexia @@ -40,6 +42,8 @@ public final class ShiloVillagePlugin extends OptionHandler { @Override public boolean handle(Player player, Node node, String option) { + if (!hasRequirement(player, "Shilo Village")) + return true; switch (node.getId()) { case 511: case 510: @@ -91,6 +95,10 @@ public final class ShiloVillagePlugin extends OptionHandler { npc = (NPC) args[0]; shilo = npc.getId() == 510; npc("Hello Bwana!"); + if (!hasRequirement(player, "Shilo Village")) { + end(); + return true; + } return true; } diff --git a/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimCartMethods.kt b/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimCartMethods.kt index 0fb6f4cf8..06dcb2ac5 100644 --- a/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimCartMethods.kt +++ b/Server/src/main/content/region/misc/keldagrim/handlers/KeldagrimCartMethods.kt @@ -8,15 +8,20 @@ import core.game.world.map.Direction import core.game.world.map.Location import org.rs09.consts.Components import core.game.world.GameWorld +import core.api.* object KeldagrimCartMethods { @JvmStatic fun goToKeldagrim(player: Player){ + if (!hasRequirement(player, "The Giant Dwarf")) + return GameWorld.Pulser.submit(TravelToKeldagrimPulse(player)) } @JvmStatic fun leaveKeldagrimTo(player: Player, dest: Location){ + if (!hasRequirement(player, "The Giant Dwarf")) + return GameWorld.Pulser.submit(TravelFromKeldagrimPulse(player,dest)) } } @@ -90,4 +95,4 @@ class TravelToKeldagrimPulse(val player: Player) : Pulse(){ } return false } -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt b/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt index 01f468038..c8bbff281 100644 --- a/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt +++ b/Server/src/main/content/region/misc/zanaris/handlers/FairyRingPlugin.kt @@ -1,7 +1,6 @@ package content.region.misc.zanaris.handlers -import core.api.anyInEquipment -import core.api.isQuestComplete +import core.api.* import core.game.component.Component import core.game.node.entity.player.Player import core.game.node.entity.player.link.TeleportManager.TeleportType @@ -42,7 +41,7 @@ class FairyRingPlugin : InteractionListener { } private fun fairyMagic(player: Player) : Boolean { - if (!isQuestComplete(player,"Lost City")) { // should be converted to a FTP2 stage requirement once FTP2 is implemented + if (!hasRequirement(player, "Fairytale I - Growing Pains")) { // should be converted to a FTP2 stage requirement once FTP2 is implemented player.sendMessage("The fairy ring is inert.") return false } diff --git a/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetismPlugin.java b/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetismPlugin.java index 3e77bcd3b..57032bcf0 100644 --- a/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetismPlugin.java +++ b/Server/src/main/content/region/misthalin/draynor/quest/anma/AnimalMagnetismPlugin.java @@ -35,6 +35,7 @@ import core.plugin.ClassScanner; import core.tools.RandomFunction; import static core.api.ContentAPIKt.teleport; +import static core.api.ContentAPIKt.hasRequirement; /** * Handles the animal magnetism plugin. @@ -61,6 +62,8 @@ public final class AnimalMagnetismPlugin extends OptionHandler { public boolean handle(Player player, Node node, String option) { switch (node.getId()) { case 5167: + if (!hasRequirement(player, "Creature of Fenkenstrain")) + break; player.teleport(new Location(3577, 9927)); break; case 5198: @@ -76,6 +79,8 @@ public final class AnimalMagnetismPlugin extends OptionHandler { break; case 4251: case 4252: + if (!hasRequirement(player, "Ghosts Ahoy")) + return true; if (option.equalsIgnoreCase("empty")) { handleEctophial(player, (Item) node); } else { diff --git a/Server/src/main/content/region/misthalin/lumbridge/handlers/CulinomancerShop.kt b/Server/src/main/content/region/misthalin/lumbridge/handlers/CulinomancerShop.kt index b867ca67d..5417f18b8 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/handlers/CulinomancerShop.kt +++ b/Server/src/main/content/region/misthalin/lumbridge/handlers/CulinomancerShop.kt @@ -92,6 +92,7 @@ class CulinomancerShop : LoginListener { stock[i].amount = 30 stock[i + 10].amount = 5 } + stock[9].amount = 1 return stock } diff --git a/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java b/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java index ec7831b24..ecdbd5bed 100644 --- a/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java +++ b/Server/src/main/content/region/misthalin/lumbridge/handlers/LumbridgeBasementPlugin.java @@ -21,6 +21,8 @@ import core.plugin.ClassScanner; import core.plugin.Initializable; import core.tools.RandomFunction; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles the lumbridge basement. * @author Vexia @@ -191,6 +193,8 @@ public class LumbridgeBasementPlugin extends OptionHandler { @Override public boolean handle(NodeUsageEvent event) { final Player player = event.getPlayer(); + if (!hasRequirement(player, "While Guthix Sleeps")) + return true; player.lock(2); player.teleport(Location.create(2538, 5881, 0)); return true; diff --git a/Server/src/main/content/region/morytania/quest/naturespirit/NSListeners.kt b/Server/src/main/content/region/morytania/quest/naturespirit/NSListeners.kt index 4fe37592f..c8e5a1b4a 100644 --- a/Server/src/main/content/region/morytania/quest/naturespirit/NSListeners.kt +++ b/Server/src/main/content/region/morytania/quest/naturespirit/NSListeners.kt @@ -182,6 +182,20 @@ class NSListeners : InteractionListener { NSUtils.activatePouch(player, with as MortMyreGhastNPC) } + onUseWith(IntType.NPC, Items.SECATEURS_5329, NPCs.NATURE_SPIRIT_1051) {player, used, with -> + if (!hasRequirement(player, "Fairytale I - Growing Pains")) + return@onUseWith true + if (amountInInventory(player, Items.COINS_995) < 40000) { + sendDialogue(player, "You need 40,000 coins to do this.") + return@onUseWith true + } + if (removeItem(player, used) && removeItem(player, Item(Items.COINS_995, 40000))) { + sendItemDialogue(player, Items.MAGIC_SECATEURS_7409, "Your secateurs are enchanted into magic secateurs") + addItem(player, Items.MAGIC_SECATEURS_7409) + } + return@onUseWith true + } + onUseWith(IntType.SCENERY, items, *stones) { player, used, with -> when (used.id) { USED_SPELLCARD -> { diff --git a/Server/src/main/content/region/tirranwn/dialogue/QuarterMasterDialogue.java b/Server/src/main/content/region/tirranwn/dialogue/QuarterMasterDialogue.java index 3bee089c1..844cc01c2 100644 --- a/Server/src/main/content/region/tirranwn/dialogue/QuarterMasterDialogue.java +++ b/Server/src/main/content/region/tirranwn/dialogue/QuarterMasterDialogue.java @@ -5,6 +5,8 @@ import core.game.node.entity.npc.NPC; import core.plugin.Initializable; import core.game.node.entity.player.Player; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles the quarter master dialogue. * @author Vexia @@ -40,6 +42,10 @@ public final class QuarterMasterDialogue extends DialoguePlugin { public boolean open(Object... args) { npc = (NPC) args[0]; npc("Hi, would you like to see my wares?"); + if (!hasRequirement(player, "Regicide")) { + end(); + return true; + } return true; } diff --git a/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesObstacles.java b/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesObstacles.java index d14ff7bc3..e24874c99 100644 --- a/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesObstacles.java +++ b/Server/src/main/content/region/tirranwn/quest/rovingelves/RovingElvesObstacles.java @@ -14,6 +14,8 @@ import core.plugin.Plugin; import java.util.Arrays; import java.util.List; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles all the agility obstacles for Roving Elves. * @authors Splinter & downthecrop @@ -94,6 +96,8 @@ public final class RovingElvesObstacles extends OptionHandler { switch (node.getId()) { case 8742: + if (!hasRequirement(player, "Mourning's End Part I")) + return true; player.teleport(player.getLocation().transform(EAST_WEST, 2)); break; case 3999: diff --git a/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java b/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java index 0dbabb18b..0681c9806 100644 --- a/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java +++ b/Server/src/main/content/region/wilderness/handlers/ChaosTunnelZone.java @@ -27,6 +27,8 @@ import core.plugin.Plugin; import core.plugin.ClassScanner; import core.tools.RandomFunction; +import static core.api.ContentAPIKt.hasRequirement; + /** * Handles the chaos tunnels. * @author Vexia @@ -230,8 +232,9 @@ public final class ChaosTunnelZone extends MapZone implements Plugin { * @param player the player. */ private void teleport(Player player, Scenery object) { - if (object.getLocation().getX() == 3142 || object.getLocation().getY() == 5545) { - commenceBorkBattle(player); + if (object.getLocation().getX() == 3142 && object.getLocation().getY() == 5545) { + if (hasRequirement(player, "What Lies Below")) + commenceBorkBattle(player); return; } Location loc = getLocation(object.getLocation()); diff --git a/Server/src/main/content/region/wilderness/handlers/CorporealBeastWarningInterface.kt b/Server/src/main/content/region/wilderness/handlers/CorporealBeastWarningInterface.kt index fe4fceb46..83b64acc2 100644 --- a/Server/src/main/content/region/wilderness/handlers/CorporealBeastWarningInterface.kt +++ b/Server/src/main/content/region/wilderness/handlers/CorporealBeastWarningInterface.kt @@ -4,6 +4,7 @@ import core.game.component.Component import core.game.node.entity.player.Player import core.game.interaction.InterfaceListener import core.game.world.GameWorld +import core.api.* /** * Handles the corporeal beast warning interface @@ -15,6 +16,8 @@ class CorporealBeastWarningInterface : InterfaceListener { override fun defineInterfaceListeners() { on(COMPONENT_ID,17){player,component,_,_,_,_ -> + if (!hasRequirement(player, "Summer's End")) + return@on true if(player.getAttribute("corp-beast-cave-delay",0) <= GameWorld.ticks) { player.properties.teleportLocation = player.location.transform(4, 0, 0).also { close(player,component) } player.setAttribute("corp-beast-cave-delay", GameWorld.ticks + 5) @@ -33,4 +36,4 @@ class CorporealBeastWarningInterface : InterfaceListener { fun close(player: Player,component: Component){ player.interfaceManager.close(component) } -} \ No newline at end of file +} diff --git a/Server/src/main/content/region/wilderness/handlers/WildernessPlugin.java b/Server/src/main/content/region/wilderness/handlers/WildernessPlugin.java index 45543b45e..2f9a764a6 100644 --- a/Server/src/main/content/region/wilderness/handlers/WildernessPlugin.java +++ b/Server/src/main/content/region/wilderness/handlers/WildernessPlugin.java @@ -13,6 +13,8 @@ import core.game.world.update.flag.context.Animation; import core.plugin.Initializable; import core.plugin.Plugin; +import static core.api.ContentAPIKt.hasRequirement; + /** * Represents a plugin used to handle wilderness nodes. * @@ -45,6 +47,8 @@ public final class WildernessPlugin extends OptionHandler { ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, Location.create(3239, 3606, 0), "You climb up the ladder to the surface."); break; case 39188: + if (!hasRequirement(player, "Defender of Varrock")) + break; ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_DOWN, Location.create(3241, 9991, 0), "You descend into the cavern below."); break; case 37928: diff --git a/Server/src/main/core/api/ContentAPI.kt b/Server/src/main/core/api/ContentAPI.kt index 3c9e6b0cd..93977d81b 100644 --- a/Server/src/main/core/api/ContentAPI.kt +++ b/Server/src/main/core/api/ContentAPI.kt @@ -69,6 +69,7 @@ import core.api.utils.Vector import core.tools.* import core.game.world.update.flag.* import core.game.world.update.flag.context.* +import core.game.requirement.* import java.util.regex.* import java.io.* import kotlin.math.* @@ -1697,6 +1698,46 @@ fun announceIfRare(player: Player, item: Item) { } } +fun hasRequirement (player: Player, req: QuestReq, message: Boolean = true) : Boolean { + var (isMet, unmetReqs) = req.evaluate(player) + val messageList = ArrayList() + + var totalSoftQp = 0 + var totalHardQp = 0 + + for (req in unmetReqs) { + when (req) { + is QPCumulative -> totalSoftQp += req.amount + is QPReq -> if (req.amount > totalHardQp) totalHardQp = req.amount + } + } + + var neededQp = min(max(totalSoftQp, totalHardQp), player.questRepository.getAvailablePoints()) + + isMet = isMet && neededQp < player.questRepository.getPoints() + + if (isMet) return true + + if (unmetReqs.size == 2 && unmetReqs[0] is QuestReq) { + messageList.add ("This requires completion of ${(unmetReqs[0] as QuestReq).questReq.questName} to access.") + } else { + messageList.add ("You need the pre-reqs for ${req.questReq.questName} to access this.") + messageList.add ("Please check the page in your quest journal for more info.") + } + + if (message) + for (message in messageList) + sendMessage(player, message) + + return false +} + +@JvmOverloads +fun hasRequirement (player: Player, quest: String, message: Boolean = true) : Boolean { + val questReq = QuestRequirements.values().filter { it.questName.equals(quest, true) }.firstOrNull() ?: return false + return hasRequirement(player, QuestReq(questReq), message) +} + /** * Generates a list of skill names which the player has mastered * @param player the player diff --git a/Server/src/main/core/game/global/action/DoorActionHandler.java b/Server/src/main/core/game/global/action/DoorActionHandler.java index 5c51ea0d5..dcbda6940 100644 --- a/Server/src/main/core/game/global/action/DoorActionHandler.java +++ b/Server/src/main/core/game/global/action/DoorActionHandler.java @@ -16,6 +16,8 @@ import kotlin.Unit; import core.game.system.config.DoorConfigLoader; import core.game.world.GameWorld; +import static core.api.ContentAPIKt.hasRequirement; + import java.awt.*; /** @@ -65,7 +67,11 @@ public final class DoorActionHandler { return; } DoorConfigLoader.Door d = DoorConfigLoader.Companion.forId(object.getId()); - if (d == null) { + if (d != null && !d.getQuestRequirement().equals("")) { + if (!hasRequirement(player, d.getQuestRequirement())) + return; + } + if (d == null || d.isAutoWalk()) { handleAutowalkDoor(player, object); return; } @@ -512,4 +518,4 @@ public final class DoorActionHandler { } return rotations; } -} \ No newline at end of file +} diff --git a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java index e35124a1b..0d31d81d2 100644 --- a/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java +++ b/Server/src/main/core/game/node/entity/player/info/login/LoginConfiguration.java @@ -18,6 +18,8 @@ import core.tools.SystemLogger; import core.game.world.GameWorld; import core.game.world.repository.Repository; import core.game.world.update.UpdateSequence; +import core.game.node.entity.player.link.SpellBookManager; +import core.game.node.item.GroundItemManager; import java.util.ArrayList; import java.util.Date; @@ -27,6 +29,8 @@ import java.util.concurrent.TimeUnit; import java.util.stream.IntStream; import static core.api.ContentAPIKt.log; +import static core.api.ContentAPIKt.hasRequirement; +import static core.tools.GlobalsKt.colorize; /** @@ -148,8 +152,31 @@ public final class LoginConfiguration { //We should have already been doing this. //Frankly, I don't even want to imagine the number of bugs us *not* doing this has caused. if (item == null) continue; - InteractionListeners.run(item.getId(), player, item, true); + player.getEquipment().remove(item); + if (!InteractionListeners.run(item.getId(), player, item, true) || !player.getEquipment().add(item, true, false)) { + if (player.getInventory().add(item)) + player.sendMessage (colorize("%RAs you can no longer wear " + item.getName() + ", it has been unequipped.")); + else if (player.getBankPrimary().add(item)) + player.sendMessage (colorize("%RAs you can no longer wear " + item.getName() + ", it has been sent to your bank.")); + else if (player.getBankSecondary().add(item)) + player.sendMessage (colorize("%RAs you can no longer wear " + item.getName() + ", it has been sent to your secondary bank.")); + else { + player.sendMessage (colorize("%RAs you can no longer wear " + item.getName() + ", and your inventory and both banks are full,")); + player.sendMessage (colorize("%RIt has been placed on the ground under your feet. Don't forget to grab it.")); + player.sendMessage ("(Also, consider cleaning out your banks maybe? I mean jesus.)"); + GroundItemManager.create (item, player); + } + } } + SpellBookManager.SpellBook currentSpellBook = SpellBookManager.SpellBook.forInterface(player.getSpellBookManager().getSpellBook()); + if (currentSpellBook == SpellBookManager.SpellBook.ANCIENT && !hasRequirement(player, "Desert Treasure")) { + player.sendMessage(colorize("%RAs you can no longer use Ancient Magic, you have been set back to Modern.")); + player.getSpellBookManager().setSpellBook(SpellBookManager.SpellBook.MODERN); + } else if (currentSpellBook == SpellBookManager.SpellBook.LUNAR && !hasRequirement(player, "Lunar Diplomacy")) { + player.sendMessage(colorize("%RAs you can no longer use Lunar Magic, you have been set back to Modern.")); + player.getSpellBookManager().setSpellBook(SpellBookManager.SpellBook.MODERN); + } + player.getSpellBookManager().update(player); if(ServerConstants.RULES_AND_INFO_ENABLED) RulesAndInfo.openFor(player); /*if (GameWorld.getSettings().isPvp()) { diff --git a/Server/src/main/core/game/requirement/Requirement.kt b/Server/src/main/core/game/requirement/Requirement.kt new file mode 100644 index 000000000..862ed6ca4 --- /dev/null +++ b/Server/src/main/core/game/requirement/Requirement.kt @@ -0,0 +1,199 @@ +package core.game.requirement + +import core.api.* +import core.game.node.entity.player.Player +import core.game.node.entity.player.link.quest.QuestRepository +import core.game.node.entity.skill.Skills +import kotlin.math.min + +import java.util.ArrayList + +interface Requirement { + abstract fun evaluate (player: Player) : Pair> +} + +open class SkillReq (val skillId: Int, val level: Int, val soft: Boolean = false) : Requirement { + override fun evaluate (player: Player) : Pair> { + val hasLevelRequirement = if (soft) getDynLevel(player, skillId) >= level else getStatLevel(player, skillId) >= level + if (hasLevelRequirement) return Pair (true, listOf()) + else return Pair(false, listOf(this)) + } +} + +open class QuestReq (val questReq: QuestRequirements, val stageRequired: Int = 100) : Requirement { + override fun evaluate (player: Player) : Pair> { + val quest = QuestRepository.getQuests()[questReq.questName] + val unmetRequirements = ArrayList() + var isMet = true + if (quest == null) { + for (req in questReq.requirements) { + val (met, reqs) = req.evaluate(player) + isMet = isMet && met + unmetRequirements.addAll(reqs) + } + unmetRequirements.add (QPCumulative(5)) + } else { + isMet = quest.getStage(player) >= stageRequired + if (!isMet) unmetRequirements.add(this) + unmetRequirements.add (QPCumulative(quest.getQuestPoints())) + } + + return Pair (isMet, unmetRequirements) + } +} + +open class QPReq (val amount: Int) : Requirement { + override fun evaluate (player: Player) : Pair> { + val needed = min(amount, player.questRepository.getAvailablePoints()) + val hasNeeded = player.questRepository.getPoints() >= needed + + return Pair (hasNeeded, if (hasNeeded) listOf() else listOf(this)) + } +} + +open class QPCumulative (val amount: Int) : Requirement { + override fun evaluate (player: Player) : Pair> { + return Pair (false, listOf(this)) + } +} + +enum class QuestRequirements (val questName: String, vararg val requirements: Requirement) { + COOK_ASSIST ("Cook's Assistant"), + DEMON_SLAYER ("Demon Slayer"), + DORIC_QUEST ("Doric's Quest"), + DRAGON_SLAYER ("Dragon Slayer", QPReq(32)), + ERNEST ("Ernest the Chicken"), + GOBLIN_DIP ("Goblin Diplomacy"), + IMP_CATCHER ("Imp Catcher"), + KNIGHT_SWORD ("The Knight's Sword", SkillReq(Skills.MINING, 10, true)), + PIRATE_T ("Pirate's Treasure"), + ALI_RESCUE ("Prince Ali Rescue"), + RESTLESS_GHOST ("The Restless Ghost"), + ROMEO ("Romeo & Juliet"), + RUNE_MYST ("Rune Mysteries"), + SHEEP ("Sheep Shearer"), + ARRAV ("Shield of Arrav"), + VAMPIRE ("Vampire Slayer"), + DORIC ("Doric's Quest"), + RUNE_MYSTERIES("Rune Mysteries"), + BLACK_KNIGHT("Black Knights' Fortress", QPReq(12)), + WITCH_POTION ("Witch's Potion"), + DRUIDIC_RITUAL ("Druidic Ritual"), + LOST_CITY ("Lost City", SkillReq(Skills.CRAFTING, 31, true), SkillReq(Skills.WOODCUTTING, 36, true)), + WITCH_HOUSE ("Witch's House"), + MERLIN ("Merlin's Crystal"), + HERO ("Heroes' Quest", QPReq(55), SkillReq(Skills.COOKING, 53, true), SkillReq(Skills.FISHING, 53, true), SkillReq(Skills.HERBLORE, 25, true), SkillReq(Skills.MINING, 50, true), QuestReq(ARRAV), QuestReq(LOST_CITY), QuestReq(MERLIN), QuestReq(DRAGON_SLAYER)), + SCORP_CATCHER ("Scorpion Catcher", SkillReq(Skills.PRAYER, 31)), + FAMILY_CREST ("Family Crest", SkillReq(Skills.MINING, 40, true), SkillReq(Skills.SMITHING, 40, true), SkillReq(Skills.MAGIC, 59, true), SkillReq(Skills.CRAFTING, 40, true)), + FISHING_CONTEST ("Fishing Contest", SkillReq(Skills.FISHING, 10)), + TOTEM ("Tribal Totem", SkillReq(Skills.THIEVING, 21)), + MONK ("Monk's Friend"), + IKOV ("Temple of Ikov", SkillReq(Skills.THIEVING, 42, true), SkillReq(Skills.RANGE, 40)), + CLOCK_TOWER ("Clock Tower"), + GRAIL ("Holy Grail", QuestReq (MERLIN), SkillReq (Skills.ATTACK, 20)), + GNOME_VILLAGE ("Tree Gnome Village"), + FIGHT_ARENA ("Fight Arena"), + HAZEEL ("Hazeel Cult"), + SHEEP_HERDER ("Sheep Herder"), + PLAGUE_CITY ("Plague City"), + SEA_SLUG ("Sea Slug", SkillReq(Skills.FIREMAKING, 30, true)), + WATERFALL ("Waterfall Quest"), + POTION ("Jungle Potion", SkillReq(Skills.HERBLORE, 3, true), QuestReq(DRUIDIC_RITUAL)), + GRAND_TREE ("The Grand Tree", SkillReq(Skills.AGILITY, 25, true)), + BIOHAZARD ("Biohazard", QuestReq(PLAGUE_CITY)), + UNDERGROUND_PASS ("Underground Pass", SkillReq (Skills.RANGE, 25), QuestReq(BIOHAZARD), QuestReq(PLAGUE_CITY)), + OBSERVATORY ("Observatory Quest"), + TOURIST ("The Tourist Trap", SkillReq (Skills.FLETCHING, 10, true), SkillReq(Skills.SMITHING, 20, true)), + WATCHTOWER ("Watchtower", SkillReq (Skills.MAGIC, 14, true), SkillReq(Skills.THIEVING, 15, true), SkillReq (Skills.AGILITY, 25, true), SkillReq (Skills.HERBLORE, 14, true), SkillReq(Skills.MINING, 40, true)), + DWARF_CANNON ("Dwarf Cannon"), + MURDER_MYS ("Murder Mystery"), + DIG_SITE ("Dig Site", SkillReq(Skills.AGILITY, 10, true), SkillReq (Skills.HERBLORE, 10, true), SkillReq (Skills.THIEVING, 25, true)), + GERTRUDE ("Gertrude's Cat"), + SHILO ("Shilo Village", QuestReq(POTION), SkillReq(Skills.CRAFTING, 20, true), SkillReq(Skills.AGILITY, 32, true)), + LEGEND ("Legend's Quest", QPReq(107), SkillReq(Skills.AGILITY, 50, true), SkillReq(Skills.CRAFTING, 50, true), SkillReq(Skills.HERBLORE, 45, true), SkillReq(Skills.MAGIC, 56, true), SkillReq(Skills.MINING, 52, true), SkillReq(Skills.PRAYER, 42, true), SkillReq(Skills.SMITHING, 50, true), SkillReq(Skills.STRENGTH, 50, true), SkillReq(Skills.THIEVING, 50, true), SkillReq(Skills.WOODCUTTING, 50, true), QuestReq(FAMILY_CREST), QuestReq(HERO), QuestReq(SHILO), QuestReq(UNDERGROUND_PASS), QuestReq(WATERFALL)), + DEATH_PLATEAU ("Death Plateau"), + TROLL_STRONGHOLD ("Troll Stronghold", QuestReq(DEATH_PLATEAU), SkillReq(Skills.AGILITY, 15, true)), + EADGAR ("Eadgar's Ruse", QuestReq (DRUIDIC_RITUAL), QuestReq (TROLL_STRONGHOLD), SkillReq(Skills.HERBLORE, 31, true)), + CHOMPY ("Big Chompy Bird Hunting", SkillReq (Skills.FLETCHING, 5, true), SkillReq (Skills.COOKING, 30, true), SkillReq(Skills.RANGE, 30, false)), + ELEMENTAL_W1 ("Elemental Workshop I", SkillReq(Skills.MINING, 20, true), SkillReq(Skills.SMITHING, 20, true), SkillReq(Skills.CRAFTING, 20, true)), + PRIEST ("Priest in Peril"), + NATURE_SPIRIT ("Nature Spirit", QuestReq(PRIEST), QuestReq(RESTLESS_GHOST)), + REGICIDE ("Regicide", QuestReq (UNDERGROUND_PASS), SkillReq (Skills.CRAFTING, 10), SkillReq(Skills.AGILITY, 56, true)), + TAI_BWO ("Tai Bwo Wannai Trio", SkillReq (Skills.AGILITY, 15, true), SkillReq(Skills.COOKING, 30), SkillReq(Skills.FISHING, 65, true), QuestReq(POTION)), + SHADES ("Shades of Mort'ton", QuestReq(PRIEST), SkillReq(Skills.CRAFTING, 20, true), SkillReq(Skills.HERBLORE, 15, true), SkillReq(Skills.FIREMAKING, 5, true)), + FREM_TRIALS ("Fremennik Trials", SkillReq(Skills.FLETCHING, 25, true), SkillReq(Skills.WOODCUTTING, 40, true), SkillReq(Skills.CRAFTING, 40, true)), + HORROR_DEEP ("Horror from the Deep", SkillReq(Skills.AGILITY, 35, true)), + THRONE ("Throne of Miscellania", QuestReq(HERO), QuestReq(FREM_TRIALS)), + MONKEY ("Monkey Madness", QuestReq(GRAND_TREE), QuestReq(GNOME_VILLAGE)), + MINE ("Haunted Mine", QuestReq(PRIEST), SkillReq(Skills.CRAFTING, 35, true)), + TROLL_ROMANCE ("Troll Romance", QuestReq(TROLL_STRONGHOLD), SkillReq(Skills.AGILITY, 28, true)), + SEARCH_MYREQUE ("In Search of the Myreque", QuestReq(NATURE_SPIRIT), SkillReq(Skills.AGILITY, 25, true)), + FENKENSTRAIN ("Creature of Fenkenstrain", QuestReq(PRIEST), QuestReq(RESTLESS_GHOST), SkillReq(Skills.THIEVING, 25, true), SkillReq(Skills.CRAFTING, 20, true)), + ROVING_ELVES ("Roving Elves", QuestReq(REGICIDE), QuestReq(WATERFALL), SkillReq(Skills.AGILITY, 56, true)), + GHOSTS_AHOY ("Ghosts Ahoy", QuestReq(PRIEST), QuestReq(RESTLESS_GHOST), SkillReq(Skills.AGILITY, 25, true), SkillReq(Skills.COOKING, 20, true)), + FAVOR ("One Small Favor", QuestReq(RUNE_MYSTERIES), QuestReq(SHILO), SkillReq(Skills.AGILITY, 36, true), SkillReq(Skills.CRAFTING, 25, true), SkillReq(Skills.HERBLORE, 18, true), SkillReq(Skills.SMITHING, 30, true)), + MOUNTAIN_DAUGHTER ("Mountain Daughter", SkillReq(Skills.AGILITY, 20, true)), + BETWEEN_ROCK ("Between a Rock...", QuestReq(DWARF_CANNON), QuestReq(FISHING_CONTEST), SkillReq(Skills.DEFENCE, 30, true), SkillReq(Skills.MINING, 40, true), SkillReq(Skills.SMITHING, 50, true)), + FEUD ("The Feud", SkillReq(Skills.THIEVING, 30)), + GOLEM ("The Golem", SkillReq(Skills.CRAFTING, 20, true), SkillReq(Skills.THIEVING, 25, true)), + DESERT ("Desert Treasure", QuestReq (DIG_SITE), QuestReq (IKOV), QuestReq(TOURIST), QuestReq(TROLL_STRONGHOLD), QuestReq(PRIEST), QuestReq(WATERFALL), SkillReq(Skills.THIEVING, 53), SkillReq(Skills.MAGIC, 50), SkillReq(Skills.FIREMAKING, 50, true), SkillReq(Skills.SLAYER, 10)), + ICTHLARIN ("Icthlarin's Little Helper", QuestReq (GERTRUDE)), + TEARS_OF_GUTHIX ("Tears of Guthix", QPReq(43), SkillReq(Skills.FIREMAKING, 49, true), SkillReq(Skills.CRAFTING, 20, true), SkillReq(Skills.MINING, 20, true)), + LOST_TRIBE ("Lost Tribe", QuestReq(GOBLIN_DIP), QuestReq(RUNE_MYSTERIES), SkillReq(Skills.AGILITY, 13, true), SkillReq(Skills.THIEVING, 13, true), SkillReq(Skills.MINING, 17, true)), + GIANT_DWARF ("The Giant Dwarf", SkillReq(Skills.CRAFTING, 12, true), SkillReq(Skills.FIREMAKING, 16, true), SkillReq(Skills.MAGIC, 33, true), SkillReq(Skills.THIEVING, 14, true)), + RECRUITMENT_DRIVE ("Recruitment Drive", QuestReq (BLACK_KNIGHT), QuestReq(DRUIDIC_RITUAL)), + MEP_1 ("Mourning's End Part I", SkillReq(Skills.RANGE, 60), SkillReq(Skills.THIEVING, 50), QuestReq(ROVING_ELVES), QuestReq(CHOMPY), QuestReq(SHEEP_HERDER)), + FORGETTABLE ("Forgettable Tale of a Drunken Dwarf", SkillReq (Skills.COOKING, 22, true), SkillReq(Skills.FARMING, 17, true), QuestReq(GIANT_DWARF), QuestReq(FISHING_CONTEST)), + GARDEN ("Garden of Tranquility", QuestReq(FENKENSTRAIN), SkillReq(Skills.FARMING, 25)), + TWO_CATS ("A Tale of Two Cats", QuestReq(ICTHLARIN)), + WANTED ("Wanted!", QPReq(32), QuestReq(RECRUITMENT_DRIVE), QuestReq(LOST_TRIBE), QuestReq(PRIEST)), + MEP_2 ("Mourning's End Part II", QuestReq(MEP_1)), + ZOGRE ("Zogre Flesh Eaters", QuestReq(CHOMPY), QuestReq(POTION), SkillReq(Skills.SMITHING, 4, true), SkillReq(Skills.HERBLORE, 8, true), SkillReq(Skills.RANGE, 30)), + RUM_DEAL ("Rum Deal", QuestReq(ZOGRE), QuestReq(PRIEST), SkillReq(Skills.CRAFTING, 42, true), SkillReq(Skills.FISHING, 50, true), SkillReq(Skills.FARMING, 40, true), SkillReq(Skills.PRAYER, 47, true), SkillReq(Skills.SLAYER, 42)), + SHADOW ("Shadow of the Storm", SkillReq(Skills.CRAFTING, 30, true), QuestReq(GOLEM), QuestReq(DEMON_SLAYER)), + HISTORY ("Making History", QuestReq(PRIEST), QuestReq(RESTLESS_GHOST)), + RATCATCHERS ("Ratcatchers", QuestReq(ICTHLARIN), QuestReq(GIANT_DWARF)), + SPIRITS_ELID ("Spirits of the Elid", SkillReq(Skills.MAGIC, 33, true), SkillReq(Skills.RANGE, 37, true), SkillReq(Skills.MINING, 37, true), SkillReq(Skills.THIEVING, 37, true)), + DEVIOUS ("Devious Minds", SkillReq(Skills.SMITHING, 65, true), SkillReq(Skills.RUNECRAFTING, 50, true), SkillReq(Skills.FLETCHING, 50, true), QuestReq(WANTED), QuestReq(TROLL_STRONGHOLD), QuestReq(DORIC)), + SAND ("The Hand in the Sand", SkillReq(Skills.THIEVING, 17, true), SkillReq(Skills.CRAFTING, 49, true)), + ENAKHRA ("Enakhra's Lament", SkillReq(Skills.CRAFTING, 50, true), SkillReq(Skills.FIREMAKING, 45, true), SkillReq(Skills.PRAYER, 43, true), SkillReq(Skills.MAGIC, 39, true)), + CABIN_FEVER ("Cabin Fever", QuestReq(PIRATE_T), QuestReq(RUM_DEAL), SkillReq(Skills.AGILITY, 42), SkillReq(Skills.CRAFTING, 45), SkillReq(Skills.SMITHING, 50), SkillReq(Skills.RANGE, 40)), + FAIRYTALE_1 ("Fairytale I - Growing Pains", QuestReq(LOST_CITY), QuestReq(NATURE_SPIRIT)), + RFD ("Recipe for Disaster", QPReq(175), QuestReq(COOK_ASSIST), SkillReq(Skills.COOKING, 70, true), SkillReq(Skills.AGILITY, 48, true), SkillReq(Skills.MINING, 50, true), SkillReq(Skills.FISHING, 53, true), SkillReq(Skills.THIEVING, 53, true), SkillReq(Skills.HERBLORE, 25, true), SkillReq(Skills.MAGIC, 59, true), SkillReq(Skills.SMITHING, 40, true), SkillReq(Skills.FIREMAKING, 50, true), SkillReq(Skills.RANGE, 40), SkillReq(Skills.CRAFTING, 40, true), SkillReq(Skills.FLETCHING, 10, true), SkillReq(Skills.WOODCUTTING, 36, true), QuestReq(FISHING_CONTEST), QuestReq(GOBLIN_DIP), QuestReq(CHOMPY), QuestReq(MURDER_MYS), QuestReq(NATURE_SPIRIT), QuestReq(WITCH_HOUSE), QuestReq(GERTRUDE), QuestReq(SHADOW), QuestReq(LEGEND), QuestReq(MONKEY), QuestReq(DESERT), QuestReq(HORROR_DEEP)), + AID_MYREQUE ("In Aid of the Myreque", QuestReq(SEARCH_MYREQUE), SkillReq(Skills.AGILITY, 25, true), SkillReq(Skills.CRAFTING, 25), SkillReq(Skills.MINING, 15), SkillReq(Skills.MAGIC, 7, true)), + SOUL_BANE ("A Soul's Bane"), + BONE_MAN_1 ("Rag and Bone Man I"), + SWAN ("Swan Song", QPReq(100), SkillReq(Skills.MAGIC, 66, true), SkillReq(Skills.COOKING, 62, true), SkillReq(Skills.FISHING, 62, true), SkillReq(Skills.SMITHING, 45, true), SkillReq(Skills.FIREMAKING, 42, true), SkillReq(Skills.CRAFTING, 40, true), QuestReq(FAVOR), QuestReq(GARDEN)), + ROYAL_TROUBLE ("Royal Trouble", SkillReq(Skills.AGILITY, 40, true), SkillReq(Skills.SLAYER, 40, true), QuestReq(THRONE)), + DEATH_DORGESHUUN ("Death to the Dorgeshuun", QuestReq(LOST_TRIBE), SkillReq(Skills.AGILITY, 23, true), SkillReq(Skills.THIEVING, 23, true)), + FAIRYTALE_2 ("Fairytale II - Cure a Queen", QuestReq(FAIRYTALE_1), SkillReq(Skills.THIEVING, 40), SkillReq(Skills.FARMING, 49, true), SkillReq(Skills.HERBLORE, 57, true)), + LUNAR_DIPLOMACY ("Lunar Diplomacy", QuestReq(FREM_TRIALS), QuestReq(LOST_CITY), QuestReq(RUNE_MYSTERIES), QuestReq(SHILO), SkillReq(Skills.HERBLORE, 5), SkillReq(Skills.CRAFTING, 61), SkillReq(Skills.DEFENCE, 40), SkillReq(Skills.FIREMAKING, 49), SkillReq(Skills.MAGIC, 65), SkillReq(Skills.MINING, 60), SkillReq(Skills.WOODCUTTING, 55)), + GLOUPHRIE ("The Eyes of Glouphrie", QuestReq(GRAND_TREE), SkillReq(Skills.CONSTRUCTION, 5), SkillReq(Skills.MAGIC, 46)), + HALLOWVALE ("Darkness of Hallowvale", QuestReq(AID_MYREQUE), SkillReq(Skills.CONSTRUCTION, 5, true), SkillReq(Skills.MINING, 20), SkillReq(Skills.THIEVING, 22), SkillReq(Skills.AGILITY, 26, true), SkillReq(Skills.CRAFTING, 32), SkillReq(Skills.MAGIC, 33, true), SkillReq(Skills.STRENGTH, 40)), + SLUG_MENACE ("The Slug Menace", QuestReq(WANTED), QuestReq(SEA_SLUG), SkillReq(Skills.CRAFTING, 30), SkillReq(Skills.RUNECRAFTING, 30), SkillReq(Skills.SLAYER, 30), SkillReq(Skills.THIEVING, 30)), + ELEMENTAL_W2 ("Elemental Workshop II", QuestReq(ELEMENTAL_W1), SkillReq(Skills.MAGIC, 20, true), SkillReq(Skills.SMITHING, 30, true)), + ARM_ADVENTURE ("My Arm's Big Adventure", SkillReq(Skills.FARMING, 29, true), SkillReq(Skills.WOODCUTTING, 10), QuestReq(EADGAR), QuestReq(FEUD), QuestReq(POTION)), + ENL_JOURNEY ("Enlightened Journey", QPReq(20), SkillReq(Skills.FIREMAKING, 20, true), SkillReq(Skills.FARMING, 30, true), SkillReq(Skills.CRAFTING, 36, true)), + EAGLE ("Eagles' Peak", SkillReq(Skills.HUNTER, 27, true)), + ANMA ("Animal Magnetism", QuestReq(RESTLESS_GHOST), QuestReq(ERNEST), QuestReq(PRIEST), SkillReq(Skills.SLAYER, 18), SkillReq(Skills.CRAFTING, 19), SkillReq(Skills.RANGE, 30), SkillReq(Skills.WOODCUTTING, 35)), + CONTACT ("Contact!", QuestReq(ALI_RESCUE), QuestReq(ICTHLARIN)), + COLD_WAR ("Cold War", SkillReq(Skills.HUNTER, 10), SkillReq(Skills.AGILITY, 30, true), SkillReq(Skills.CRAFTING, 30), SkillReq(Skills.CONSTRUCTION, 34), SkillReq(Skills.THIEVING, 15)), + FREM_ISLES ("The Fremennik Isles", QuestReq(FREM_TRIALS), SkillReq(Skills.CONSTRUCTION, 20, true)), + BRAIN_ROBBERY ("The Great Brain Robbery", SkillReq(Skills.CRAFTING, 16), SkillReq(Skills.CONSTRUCTION, 30), SkillReq(Skills.PRAYER, 50), QuestReq(FENKENSTRAIN), QuestReq(CABIN_FEVER), QuestReq(RFD)), + WHAT_LIES_BELOW ("What Lies Below", QuestReq(RUNE_MYSTERIES), SkillReq(Skills.RUNECRAFTING, 35)), + OLAF ("Olaf's Quest", QuestReq(FREM_TRIALS), SkillReq(Skills.FIREMAKING, 40, true), SkillReq(Skills.WOODCUTTING, 50, true)), + ANOTHER_SLICE ("Another Slice of H.A.M", SkillReq(Skills.ATTACK, 15), SkillReq(Skills.PRAYER, 25), QuestReq(DEATH_DORGESHUUN), QuestReq(GIANT_DWARF), QuestReq(DIG_SITE)), + DREAM_MENTOR ("Dream Mentor", QuestReq(LUNAR_DIPLOMACY), QuestReq(EADGAR)), + GRIM_TALES ("Grim Tales", QuestReq(WITCH_HOUSE), SkillReq(Skills.FARMING, 45, true), SkillReq(Skills.HERBLORE, 52, true), SkillReq(Skills.THIEVING, 58, true), SkillReq(Skills.AGILITY, 59, true), SkillReq(Skills.WOODCUTTING, 71, true)), + KINGS_RANSOM ("King's Ransom", SkillReq(Skills.MAGIC, 45), SkillReq(Skills.MINING, 45, true), SkillReq(Skills.DEFENCE, 65), QuestReq(BLACK_KNIGHT), QuestReq(GRAIL), QuestReq(MURDER_MYS), QuestReq(FAVOR)), + TOWER_OF_LIFE ("Tower of Life", SkillReq(Skills.CONSTRUCTION, 10)), + BONE_MAN_2 ("Rag and Bone Man II", SkillReq(Skills.SLAYER, 40, true), SkillReq(Skills.DEFENCE, 20), QuestReq(BONE_MAN_1), QuestReq(FREM_TRIALS), QuestReq(FENKENSTRAIN), QuestReq(ZOGRE), QuestReq(WATERFALL)), + LAND_GOBLINS ("Land of the Goblins", QuestReq(ANOTHER_SLICE), QuestReq(FISHING_CONTEST), SkillReq(Skills.AGILITY, 38), SkillReq(Skills.FISHING, 40), SkillReq(Skills.THIEVING, 45), SkillReq(Skills.HERBLORE, 48)), + PATH_GLOUPHRIE ("The Path of Glouphrie", QuestReq(GLOUPHRIE), QuestReq(GNOME_VILLAGE), QuestReq(WATERFALL), SkillReq(Skills.AGILITY, 45), SkillReq(Skills.RANGE, 47), SkillReq(Skills.SLAYER, 56), SkillReq(Skills.STRENGTH, 60), SkillReq(Skills.THIEVING, 56)), + DEFENDER_VARROCK ("Defender of Varrock", QuestReq(ARRAV), QuestReq(KNIGHT_SWORD), QuestReq(DEMON_SLAYER), QuestReq(IKOV), QuestReq(FAMILY_CREST), QuestReq(WHAT_LIES_BELOW), QuestReq(GARDEN), SkillReq(Skills.AGILITY, 51), SkillReq(Skills.HUNTER, 51), SkillReq(Skills.MINING, 59), SkillReq(Skills.SMITHING, 54)), + SPIRIT_OF_SUMMER ("Spirit of Summer", QuestReq(RESTLESS_GHOST), SkillReq(Skills.CONSTRUCTION, 40), SkillReq(Skills.FARMING, 26), SkillReq(Skills.PRAYER, 35), SkillReq(Skills.SUMMONING, 19)), + SUMMERS_END ("Summer's End", QuestReq(SPIRIT_OF_SUMMER), SkillReq(Skills.FIREMAKING, 47), SkillReq(Skills.HUNTER, 35), SkillReq(Skills.MINING, 45), SkillReq(Skills.PRAYER, 55), SkillReq(Skills.SUMMONING, 23), SkillReq(Skills.WOODCUTTING, 37)), + SEERGAZE ("Legacy of Seergaze", QuestReq(HALLOWVALE), SkillReq(Skills.AGILITY, 29), SkillReq(Skills.CONSTRUCTION, 20), SkillReq(Skills.CRAFTING, 47), SkillReq(Skills.FIREMAKING, 40), SkillReq(Skills.MAGIC, 49), SkillReq(Skills.MINING, 35), SkillReq(Skills.SLAYER, 31)), + SMOKING_KILLS ("Smoking Kills", QuestReq(RESTLESS_GHOST), QuestReq(ICTHLARIN), SkillReq(Skills.CRAFTING, 25), SkillReq(Skills.SLAYER, 35)), + WHILE_GUTHIX_SLEEPS ("While Guthix Sleeps", SkillReq(Skills.SUMMONING, 23), SkillReq(Skills.HUNTER, 55), SkillReq(Skills.THIEVING, 60), SkillReq(Skills.DEFENCE, 65), SkillReq(Skills.FARMING, 65), SkillReq(Skills.HERBLORE, 65), SkillReq(Skills.MAGIC, 75), QuestReq(DEFENDER_VARROCK), QuestReq(DREAM_MENTOR), QuestReq(SAND), QuestReq(KINGS_RANSOM), QuestReq(LEGEND), QuestReq(MEP_2), QuestReq(PATH_GLOUPHRIE), QuestReq(RFD), QuestReq(SUMMERS_END), QuestReq(SWAN), QuestReq(TEARS_OF_GUTHIX), QuestReq(ZOGRE)) +} diff --git a/Server/src/main/core/game/system/config/DoorConfigLoader.kt b/Server/src/main/core/game/system/config/DoorConfigLoader.kt index e6d52ba61..cb8649d85 100644 --- a/Server/src/main/core/game/system/config/DoorConfigLoader.kt +++ b/Server/src/main/core/game/system/config/DoorConfigLoader.kt @@ -30,6 +30,8 @@ class DoorConfigLoader { door.replaceId = e["replaceId"].toString().toInt() door.isFence = e["fence"].toString().toBoolean() door.isMetal = e["metal"].toString().toBoolean() + door.isAutoWalk = e["autowalk"]?.toString()?.toBoolean() ?: false + door.questRequirement = e["questRequirement"]?.toString() ?: "" DOORS[door.id] = door count++ } @@ -94,5 +96,7 @@ class DoorConfigLoader { */ var isMetal = false + var questRequirement = "" + } -} \ No newline at end of file +}