Requirements Audit

Added a new quest requirement system
Ensured that all implemented rewards are obtainable, even if all requirements are not implemented
Rewards that should have higher requirements than what is currently obtainable will have those requirements automatically increase as more quests are added
The requirements for any quest can be viewed at any time by clicking it in the quest list
Things that were previously locked/unavailable but are now available (with prereqs) are:
- It is now possible to obtain and equip Barrow's Gloves with the Recipe for Disaster prereqs
- It is now possible to obtain and equip an Ancient Staff with the Desert Treasure prereqs
- It is now possible to enchant your secateurs into Magic Secateurs with the Fairy Tale I - Growing Pains prereqs and 40k gold
- It is now possible to equip the Ancient Mace with the Another Slice of H.A.M prereqs
- It is now possible to get Suqahs as a task from Duradel with the Lunar Diplomacy prereqs
- It is now possible to obtain a Seal of Passage by speaking with Chieftan Brundt after meeting the Lunar Diplomacy prereqs
- It is now possible to obtain Ancient Staves by killing the level 96 and 103 mummies in the Ancient Pyramid (1/500)
Things that were freely available but are now locked include:
- Sophanem now requires/requires the prereqs of Icthlarin's Little Helper
- Pharaoh's Sceptre requires the same^
- Equipping god books now requires Horror from the Deep/its prereqs
- Neitiznot helmet now requires the Fremennik Isles prereqs rather than just Fremennik Trials
- Cape of Legends now correctly requires the full possible prereqs for Legend's Quest rather than just 55 QP
- Dragon Scimitar now correctly requires the Monkey Madness prereqs
- Ape Atoll teleport now correctly requires the Monkey Madness prereqs
- Slayer Helmet and the Slayer Rewards Shop in general now correctly require the Smoking Kills prereqs (not high)
- Dragon Halberd now requires the Regicide prereqs
- Climbing Boots now require the Death Plateau prereqs
- Dragon SQ Shield now requires the Legend's Quest prereqs to equip (source available in sourcecode)
- Initiate Armour now requires the Recruitment Drive prereqs
- Proselyte Armour now requires the Slug Menace prereqs
- Access to Piscatoris now requires the Swan Song prereqs (effectively Quest Cape here.)
- The disease-free herb patch in Trollheim now requires the My Arm's Big Adventure prereqs.
- Ardougne Teleport now requires the Plague City prereqs
- Watchtower Teleport now requires the Watchtower prereqs
- Trollheim Teleport now requires the Eadgar's Ruse prereqs
- The Lunar spellbook now requires the Lunar Diplomacy prereqs
- The Ancient spellbook now requires the Desert Treasure prereqs
- Crafting Astral Runes now requires the Lunar Diplomacy prereqs
- Crafting Death Runes now requires the Mourning's End Part II prereqs
- Crafting Blood Runes now requires the Legacy of Seergaze prereqs
- Access to Cave Horrors now requires the Cabin Fever prereqs
- Sorceress' Garden now requires Prince Ali Rescue
- Access to the Heroes' Guild now requires the Heroes' Quest prereqs
- Access to GWD now requires the Troll Stronghold prereqs
- Access to Neitiznot and Jatizso now requires Fremennik Trials
- Access to Shilo Villa now requires the Shilo Village prereqs
- The Keldagrim cart system now requires The Giant Dwarf prereqs
- Fairy Rings now require the full Fairy Tale I - Growing Pains prereqs
- Ectophial now requires the Ghosts Ahoy prereqs
- Access to Tormented Demons now requires the While Guthix Sleeps prereqs
- Access to the Halberd Shop and the ability to equip Dragon Halberds now requires the Regicide prereqs
- Access to Lletya now requires the Mourning's End Part I prereqs
- Access to Corporeal Beast now requires the Summer's End prereqs
- Chivalry and Piety prayers now require the King's Ransom prereqs
- Ali Morrisane's rune shop now requires the The Feud prereqs
- Armoured Zombies now require the Defender of Varrock prereqs
- Experiments now require the Creature of Fenkenstrain prereqs
- The carpet to Sophanem now requires the Icthlarin's Little Helper prereqs
- The carpet to Uzer now requires The Golem
- The carpet to Bedabin Camp now requires The Tourist Trap
- The bank in Sophanem now requires the Contact! prereqs
- The Dragon Battleaxe now requires the prereqs of Heroes' Quest to equip.
- The Dragon Mace now requires the prereqs of Heroes' Quest to equip.
- Spirit shields of all varieties (improved, blessed, unblessed) now require the prereqs of Summer's End to equip.
- Bork access now requires What Lies Below
This commit is contained in:
Ceikry 2023-05-30 09:03:05 +00:00 committed by Ryan
parent 5404ef849d
commit cb630e7043
55 changed files with 1009 additions and 265 deletions

View file

@ -1983,7 +1983,9 @@
"id": "20391", "id": "20391",
"replaceId": "28518", "replaceId": "28518",
"fence": "false", "fence": "false",
"metal": "true" "metal": "true",
"autowalk": "true",
"questRequirement": "Icthlarin's Little Helper"
}, },
{ {
"id": "21065", "id": "21065",

View file

@ -11979,7 +11979,7 @@
"maxAmount": "1" "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": "", "description": "",
"main": [ "main": [
{ {
@ -28422,7 +28422,7 @@
"maxAmount": "1" "maxAmount": "1"
} }
], ],
"ids": "1960,5360", "ids": "1958,1961,1960,5360",
"description": "", "description": "",
"main": [ "main": [
{ {
@ -28439,7 +28439,7 @@
}, },
{ {
"minAmount": "1", "minAmount": "1",
"weight": "5.0", "weight": "2.0",
"id": "4675", "id": "4675",
"maxAmount": "1" "maxAmount": "1"
}, },

View file

@ -3301,7 +3301,7 @@
}, },
{ {
"npc_id": "1369", "npc_id": "1369",
"loc_data": "{2165,3276,0,1,0}" "loc_data": "{2527,5876,0,1,0}"
}, },
{ {
"npc_id": "1373", "npc_id": "1373",

View file

@ -609,7 +609,7 @@ style:
ObjectLiteralToLambda: ObjectLiteralToLambda:
active: true active: true
OptionalAbstractKeyword: OptionalAbstractKeyword:
active: true active: false
OptionalUnit: OptionalUnit:
active: false active: false
OptionalWhenBraces: OptionalWhenBraces:

View file

@ -3,6 +3,8 @@ package content.data;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.item.Item; import core.game.node.item.Item;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* A god book. * A god book.
* @author Vexia * @author Vexia
@ -98,6 +100,8 @@ public enum GodBook {
* @param page the page. * @param page the page.
*/ */
public void insertPage(Player player, Item book, Item page) { public void insertPage(Player player, Item book, Item page) {
if (!hasRequirement(player, "Horror from the Deep"))
return;
if (hasPage(player, book, page)) { if (hasPage(player, book, page)) {
player.sendMessage("The book already has that page."); player.sendMessage("The book already has that page.");
return; return;

View file

@ -8,6 +8,8 @@ import core.game.node.entity.player.link.prayer.PrayerType;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.plugin.Plugin; import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Represents the prayer interface. * Represents the prayer interface.
* @author 'Vexia * @author 'Vexia
@ -24,6 +26,9 @@ public final class PrayerTabInterface extends ComponentPlugin {
@Override @Override
public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) { public boolean handle(Player player, Component component, int opcode, int button, int slot, int itemId) {
final PrayerType type = PrayerType.get(button); final PrayerType type = PrayerType.get(button);
if (type == PrayerType.CHIVALRY || type == PrayerType.PIETY)
if (!hasRequirement(player, "King's Ransom"))
return true;
if (type == null) { if (type == null) {
return true; return true;
} }

View file

@ -47,7 +47,7 @@ public class QuestTabInterface extends ComponentPlugin {
p.getInterfaceManager().open(new Component(275)); p.getInterfaceManager().open(new Component(275));
quest.drawJournal(p, quest.getStage(p)); quest.drawJournal(p, quest.getStage(p));
return true; return true;
} } else QuestTabUtils.showRequirementsInterface(p, button);
// } // }
return false; return false;
} }

View file

@ -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<String>()
val statMap = HashMap<Int, Int>()
val questList = HashSet<String>()
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
}
}

View file

@ -89,6 +89,19 @@ class ItemQuestRequirementListener : InteractionListener {
private val questCapes = intArrayOf(9813,9814) 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() { override fun defineListeners() {
/* /*
@ -109,20 +122,24 @@ class ItemQuestRequirementListener : InteractionListener {
} }
*/ */
onEquip(fremennikTrialsEquipment.plus(fremennikIslesEquipment)) { player, _ -> onEquip(fremennikTrialsEquipment) { player, _ ->
return@onEquip requireQuest(player, "Fremennik Trials", "to equip this.") return@onEquip hasRequirement(player, "Fremennik Trials")
}
onEquip(fremennikIslesEquipment) {player, _ ->
return@onEquip hasRequirement(player, "The Fremennik Isles")
} }
onEquip(avasBackpacks){ player, _ -> onEquip(avasBackpacks){ player, _ ->
return@onEquip requireQuest(player, "Animal Magnetism", "to equip this.") return@onEquip hasRequirement(player, "Animal Magnetism")
} }
onEquip(lostCityWeapons){ player, _ -> 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, _ -> 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, _ -> onEquip(questCapes) { player, _ ->
@ -135,27 +152,84 @@ class ItemQuestRequirementListener : InteractionListener {
} }
onEquip(Items.WOLFBANE_2952){ player, _ -> 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, _ -> 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, _ -> 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, _ -> 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, _ -> onEquip(crystalEquipment){ player, _ ->
return@onEquip requireQuest(player, "Roving Elves", "to equip this.") return@onEquip hasRequirement(player, "Roving Elves")
} }
onEquip(dragonSlayerEquipment) {player, _ -> 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")
} }
} }
} }

View file

@ -13,6 +13,8 @@ import core.game.world.map.Location;
import core.game.world.map.zone.impl.WildernessZone; import core.game.world.map.zone.impl.WildernessZone;
import core.plugin.Plugin; import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Represents the rotten potato plugin. * Represents the rotten potato plugin.
* @author 'Vexia * @author 'Vexia
@ -32,6 +34,8 @@ public final class TeleportCrystalPlugin extends OptionHandler {
@Override @Override
public boolean handle(Player player, Node node, String option) { public boolean handle(Player player, Node node, String option) {
if (!hasRequirement(player, "Mourning's End Part I"))
return true;
if (!WildernessZone.checkTeleport(player, 20)) { if (!WildernessZone.checkTeleport(player, 20)) {
player.getPacketDispatch().sendMessage("The crystal is unresponsive."); player.getPacketDispatch().sendMessage("The crystal is unresponsive.");
return true; return true;

View file

@ -14,6 +14,8 @@ import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.plugin.Plugin; import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles a tunnel shortcut. * Handles a tunnel shortcut.
* @author Vexia * @author Vexia
@ -70,6 +72,10 @@ public class TunnelShortcut extends AgilityShortcut {
@Override @Override
public void run(final Player player, Scenery object, String option, boolean failed) { 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); player.lock(6);
final Scenery o = object; final Scenery o = object;
final Location start = player.getLocation(); final Location start = player.getLocation();

View file

@ -33,6 +33,11 @@ class UseWithPatchHandler : InteractionListener {
val patch = FarmingPatch.forObject(with.asScenery()) ?: return@onUseWith true val patch = FarmingPatch.forObject(with.asScenery()) ?: return@onUseWith true
val usedItem = used.asItem() 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) player.faceLocation(with.location)
when(usedItem.id){ when(usedItem.id){
RAKE -> PatchRaker.rake(player,patch) RAKE -> PatchRaker.rake(player,patch)

View file

@ -92,21 +92,29 @@ class ModernListeners : SpellListener("modern"){
} }
onCast(Modern.ARDOUGNE_TELEPORT, NONE){ player, _ -> 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))) 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)) sendTeleport(player,61.0, Location.create(2662, 3307, 0))
} }
onCast(Modern.WATCHTOWER_TELEPORT, NONE){ player, _ -> 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))) 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)) sendTeleport(player,68.0, Location.create(2549, 3112, 0))
} }
onCast(Modern.TROLLHEIM_TELEPORT, NONE){ player, _ -> 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))) 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)) sendTeleport(player,68.0, Location.create(2891, 3678, 0))
} }
onCast(Modern.APE_ATOLL_TELEPORT, NONE){ player, _ -> 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))) 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)) sendTeleport(player,74.0, Location.create(2754, 2784, 0))
} }

View file

@ -16,6 +16,8 @@ import core.game.world.map.Location;
import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Animation;
import core.plugin.Plugin; import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles the praying at an alter. * Handles the praying at an alter.
* @author Vexia * @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...") { ANCIENT(6552, SpellBook.ANCIENT.getInterfaceId(), "You feel a strange wisdom fill your mind...", "You feel a strange drain upon your memory...") {
@Override @Override
public void pray(Player player) { public void pray(Player player) {
if (!hasRequirement(player, "Desert Treasure"))
return;
if (player.getSkills().getStaticLevel(Skills.MAGIC) < 50) { if (player.getSkills().getStaticLevel(Skills.MAGIC) < 50) {
player.sendMessage("You need a Magic level of at least 50 in order to do this."); player.sendMessage("You need a Magic level of at least 50 in order to do this.");
return; return;
@ -121,6 +125,8 @@ public class PrayerAltarPlugin extends OptionHandler {
LUNAR(17010, SpellBook.LUNAR.getInterfaceId(), "Lunar spells activated!", "Modern spells activated!") { LUNAR(17010, SpellBook.LUNAR.getInterfaceId(), "Lunar spells activated!", "Modern spells activated!") {
@Override @Override
public void pray(Player player) { public void pray(Player player) {
if (!hasRequirement(player, "Lunar Diplomacy"))
return;
if (player.getSkills().getStaticLevel(Skills.MAGIC) < 65) { if (player.getSkills().getStaticLevel(Skills.MAGIC) < 65) {
player.sendMessage("You need a Magic level of at least 65 in order to do this."); player.sendMessage("You need a Magic level of at least 65 in order to do this.");
return; return;

View file

@ -4,6 +4,8 @@ import core.cache.def.impl.ItemDefinition;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import core.game.node.scenery.Scenery; import core.game.node.scenery.Scenery;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Represents an altar an it's relative information(corresponding ruin, etc) * Represents an altar an it's relative information(corresponding ruin, etc)
* @author 'Vexia * @author 'Vexia
@ -69,6 +71,18 @@ public enum Altar {
* @param player the player. * @param player the player.
*/ */
public void enterRift(Player 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 (this == LAW) {
if (!ItemDefinition.canEnterEntrana(player)) { if (!ItemDefinition.canEnterEntrana(player)) {
player.sendMessage("You can't take weapons and armour into the law rift."); player.sendMessage("You can't take weapons and armour into the law rift.");

View file

@ -5,6 +5,8 @@ import core.game.node.entity.player.Player;
import core.game.node.scenery.Scenery; import core.game.node.scenery.Scenery;
import core.game.world.map.Location; import core.game.world.map.Location;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Represents a mysterious ruin. * Represents a mysterious ruin.
* @author 'Vexia * @author 'Vexia
@ -70,6 +72,14 @@ public enum MysteriousRuin {
* @param player the player. * @param player the player.
*/ */
public void enter(Player 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) { if (player.getEquipment().get(EquipmentContainer.SLOT_HAT) == null) {
return; return;
} }

View file

@ -15,6 +15,7 @@ import core.tools.RandomFunction;
import static core.api.ContentAPIKt.inEquipment; 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_BASE;
import static core.game.system.command.sets.StatAttributeKeysKt.STATS_RC; import static core.game.system.command.sets.StatAttributeKeysKt.STATS_RC;
import static core.api.ContentAPIKt.hasRequirement;
import core.game.world.GameWorld; import core.game.world.GameWorld;
import org.rs09.consts.Items; import org.rs09.consts.Items;
@ -96,6 +97,18 @@ public final class RuneCraftPulse extends SkillPulse<Item> {
@Override @Override
public boolean checkRequirements() { 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()) { 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."); player.getPacketDispatch().sendMessage("You need a Runecrafting level of at least " + rune.getLevel() + " to craft this rune.");
return false; return false;

View file

@ -23,6 +23,8 @@ import content.global.travel.EssenceTeleport;
import core.game.world.GameWorld; import core.game.world.GameWorld;
import core.plugin.ClassScanner; import core.plugin.ClassScanner;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles runecraftign related options. * Handles runecraftign related options.
* @author Vexia * @author Vexia
@ -94,7 +96,12 @@ public class RunecraftingPlugin extends OptionHandler {
player.sendMessage("You can only craft Astral runes on Lunar Isle."); player.sendMessage("You can only craft Astral runes on Lunar Isle.");
return true; 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; break;
case "locate": case "locate":
final Talisman talisman = Talisman.forItem(((Item) node)); final Talisman talisman = Talisman.forItem(((Item) node));

View file

@ -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.SpellBookManager
import core.game.node.entity.player.link.TeleportManager import core.game.node.entity.player.link.TeleportManager
import content.global.skill.runecrafting.Altar import content.global.skill.runecrafting.Altar
import core.game.world.map.Location
import core.game.world.map.zone.impl.DarkZone import core.game.world.map.zone.impl.DarkZone
import core.plugin.Initializable import core.plugin.Initializable
import core.game.world.GameWorld import core.game.world.GameWorld
import content.global.skill.farming.* import content.global.skill.farming.*
import core.api.getAttribute import core.api.getAttribute
import core.api.sendDialogue import core.api.sendDialogue
import core.api.hasRequirement
enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? = null) { enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)? = null) {
BAREFISTED_SMITHING("cape_perks:barefisted-smithing"), BAREFISTED_SMITHING("cape_perks:barefisted-smithing"),
@ -184,12 +186,20 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)?
else -> null else -> null
} }
end()
if(spellbook != null){ 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.spellBookManager.setSpellBook(spellbook)
player.interfaceManager.openTab(Component(spellbook.interfaceId)) player.interfaceManager.openTab(Component(spellbook.interfaceId))
player.incrementAttribute("/save:cape_perks:librarian-magus-charges",-1) player.incrementAttribute("/save:cape_perks:librarian-magus-charges",-1)
} }
end()
return true return true
} }
@ -244,7 +254,16 @@ enum class SkillcapePerks(val attribute: String, val effect: ((Player) -> Unit)?
fun sendAltar(player: Player,altar: Altar){ fun sendAltar(player: Player,altar: Altar){
end() 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) player.incrementAttribute("/save:cape_perks:abyssal_warp",-1)
} }

View file

@ -242,7 +242,7 @@ public enum Master {
new Task(Tasks.SPIRTUAL_RANGERS,2), new Task(Tasks.SPIRTUAL_RANGERS,2),
new Task(Tasks.SPIRTUAL_WARRIORS,2), new Task(Tasks.SPIRTUAL_WARRIORS,2),
new Task(Tasks.STEEL_DRAGONS,7), new Task(Tasks.STEEL_DRAGONS,7),
//new Task(Tasks.SUQAHS,8), new Task(Tasks.SUQAHS,8),
new Task(Tasks.TROLLS,6), new Task(Tasks.TROLLS,6),
new Task(Tasks.TZHAAR, 10), new Task(Tasks.TZHAAR, 10),
new Task(Tasks.VAMPIRES,8), new Task(Tasks.VAMPIRES,8),

View file

@ -11,6 +11,8 @@ import core.game.world.map.Location;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.plugin.Plugin; import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles related slayer nodes. * Handles related slayer nodes.
* @author Vexia * @author Vexia
@ -61,6 +63,8 @@ public class SlayerPlugin extends OptionHandler {
player.teleport(new Location(2729, 3733, 0)); player.teleport(new Location(2729, 3733, 0));
break; break;
case 15767: case 15767:
if (!hasRequirement(player, "Cabin Fever"))
return true;
player.teleport(new Location(3748, 9373, 0)); player.teleport(new Location(3748, 9373, 0));
break; break;
case 15811: case 15811:

View file

@ -16,6 +16,8 @@ import core.plugin.Initializable;
import core.plugin.Plugin; import core.plugin.Plugin;
import core.plugin.ClassScanner; import core.plugin.ClassScanner;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles the slayer reward interface plugin. * Handles the slayer reward interface plugin.
* @author Vexia * @author Vexia
@ -307,6 +309,8 @@ public class SlayerRewardPlugin extends ComponentPlugin {
@Override @Override
public boolean handle(Player player, Node node, String option) { public boolean handle(Player player, Node node, String option) {
if (!hasRequirement(player, "Smoking Kills"))
return true;
openTab(player, BUY); openTab(player, BUY);
return true; return true;
} }

View file

@ -31,7 +31,7 @@ object SlayerUtils {
fun canBeAssigned(player: Player, task: Tasks): Boolean 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) fun assign(player: Player, task: Tasks, master: Master)

View file

@ -5,6 +5,9 @@ import core.cache.def.impl.NPCDefinition;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import core.game.node.entity.player.Player;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* A non-garbage way of representing tasks * 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), 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_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_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), 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), 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), 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), 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), 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), 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), 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), 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), 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 int combatCheck;
public final String[] info; public final String[] info;
public final int[] ids; public final int[] ids;
public final boolean undead; public boolean undead = false;
public final boolean dragon; public boolean dragon = false;
public int amtHash; public int amtHash;
public String questReq = "";
Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead, boolean dragon){ Tasks(int combatCheck, int[] ids, String[] info, int levelReq, boolean undead, boolean dragon){
this.levelReq = levelReq; this.levelReq = levelReq;
this.ids = ids; this.ids = ids;
@ -133,6 +138,14 @@ public enum Tasks {
this.combatCheck = combatCheck; 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(){ public int[] getNpcs(){
return ids; return ids;
} }
@ -141,6 +154,10 @@ public enum Tasks {
return info; return info;
} }
public boolean hasQuestRequirements (Player player) {
return questReq.equals("") || hasRequirement(player, questReq, false);
}
public static Tasks forId(int id){ public static Tasks forId(int id){
return taskMap.get(id); return taskMap.get(id);
} }

View file

@ -1,8 +1,6 @@
package content.minigame.pyramidplunder package content.minigame.pyramidplunder
import core.api.EquipmentSlot import core.api.*
import core.api.openDialogue
import core.api.sendMessage
import core.game.world.GameWorld.Pulser import core.game.world.GameWorld.Pulser
import content.minigame.pyramidplunder.PyramidPlunderMinigame.Companion.GUARDIAN_ROOM import content.minigame.pyramidplunder.PyramidPlunderMinigame.Companion.GUARDIAN_ROOM
import core.game.node.entity.player.Player 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) 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 -> on(SCEPTRES, IntType.ITEM, "teleport", "operate"){ player, node ->
if (!hasRequirement(player, "Icthlarin's Little Helper"))
return@on true
val sceptre = node.asItem() val sceptre = node.asItem()
if(sceptre.id == SCEPTRES.last()) if(sceptre.id == SCEPTRES.last())

View file

@ -10,6 +10,8 @@ import core.game.world.GameWorld;
import core.game.world.map.Location; import core.game.world.map.Location;
import core.game.world.update.flag.context.Graphics; import core.game.world.update.flag.context.Graphics;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Dialogue for Sorceress Apprentice * Dialogue for Sorceress Apprentice
* @author SonicForce41 * @author SonicForce41
@ -236,6 +238,8 @@ public class SorceressApprenticeDialogue extends DialoguePlugin {
} }
public static void teleport(final NPC npc, final Player player) { public static void teleport(final NPC npc, final Player player) {
if (!hasRequirement(player, "Prince Ali Rescue"))
return;
npc.faceTemporary(player, 4); npc.faceTemporary(player, 4);
npc.graphics(new Graphics(108)); npc.graphics(new Graphics(108));
player.lock(); player.lock();

View file

@ -17,6 +17,8 @@ import core.plugin.Plugin;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.plugin.ClassScanner; import core.plugin.ClassScanner;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Represents the hero guild. * Represents the hero guild.
* @author Vexia * @author Vexia
@ -40,7 +42,8 @@ public final class HeroGuildPlugin extends OptionHandler {
switch (id) { switch (id) {
case 2624: case 2624:
case 2625: case 2625:
// player.getPacketDispatch().sendMessage("You need to complete the Heroes' Quest."); if (!hasRequirement(player, "Heroes' Quest"))
return true;
DoorActionHandler.handleAutowalkDoor(player, (Scenery) node); DoorActionHandler.handleAutowalkDoor(player, (Scenery) node);
break; break;
} }
@ -79,9 +82,16 @@ public final class HeroGuildPlugin extends OptionHandler {
@Override @Override
public boolean handle(NodeUsageEvent event) { public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
if (!hasRequirement(player, "Heroes' Quest"))
return true;
final EnchantedJewellery jewellery; final EnchantedJewellery jewellery;
assert event.getUsedItem() != null; assert event.getUsedItem() != null;
jewellery = EnchantedJewellery.Companion.getIdMap().get(event.getUsedItem().getId()); 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) { if (jewellery == null && event.getUsedItem().getId() != 2572) {
return true; return true;
} }

View file

@ -17,6 +17,8 @@ import core.game.world.map.RegionManager;
import core.game.world.update.flag.context.Animation; import core.game.world.update.flag.context.Animation;
import core.plugin.Plugin; import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles the entrance hole to the godwars dungeon. * Handles the entrance hole to the godwars dungeon.
* @author Emperor * @author Emperor
@ -66,6 +68,8 @@ public final class GodwarsEntranceHandler extends OptionHandler {
}); });
return true; return true;
case 26338: case 26338:
if (!hasRequirement(player, "Troll Stronghold"))
return true;
if (player.getSkills().getStaticLevel(Skills.STRENGTH) < 60) { if (player.getSkills().getStaticLevel(Skills.STRENGTH) < 60) {
player.getPacketDispatch().sendMessage("You need a Strength level of 60 to move this boulder."); player.getPacketDispatch().sendMessage("You need a Strength level of 60 to move this boulder.");
return true; return true;

View file

@ -7,6 +7,8 @@ import core.game.node.entity.player.Player
import core.plugin.Initializable import core.plugin.Initializable
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import core.api.*
/** /**
* Represents the ali morrisane dialogue. * Represents the ali morrisane dialogue.
* @author 'Vexia * @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 } 1 -> playerl(FacialExpression.ASKING, "If you are, then why are you still selling goods from a stall?").also { stage = 10 }
2 -> { 2 -> {
end() end()
if (!hasRequirement(player, "The Feud"))
return true
npc.openShop(player) npc.openShop(player)
} }
} }
@ -55,6 +59,8 @@ class AliMorrisaneDialogue(player: Player? = null) : DialoguePlugin(player) {
} }
2 -> { 2 -> {
end() end()
if (!hasRequirement(player, "The Feud"))
return true
npc.openShop(player) npc.openShop(player)
} }
} }

View file

@ -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 };
}
}

View file

@ -156,7 +156,14 @@ public final class RugMerchantDialogue extends DialoguePlugin {
stage = 20; stage = 20;
return; return;
} }
end();
destination = options.length == 1 ? options[0] : options[buttonId - 1]; 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){ if(player.getEquipment().get(EquipmentContainer.SLOT_WEAPON) != null){
player.sendMessage(colorize("%RYou must unequip all your weapons before you can fly on a carpet.")); player.sendMessage(colorize("%RYou must unequip all your weapons before you can fly on a carpet."));
} else { } else {
@ -164,7 +171,6 @@ public final class RugMerchantDialogue extends DialoguePlugin {
destination.travel(current, player); destination.travel(current, player);
} }
} }
end();
break; break;
case 20: case 20:
end(); end();

View file

@ -12,6 +12,8 @@ import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.plugin.Plugin; import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* The plugin for handling stuff in Sophanem. * The plugin for handling stuff in Sophanem.
* @author jamix77 * @author jamix77
@ -32,6 +34,8 @@ public class SophanemPlugin extends OptionHandler {
final int id = node instanceof Scenery ? ((Scenery) node).getId() : ((Item) node).getId(); final int id = node instanceof Scenery ? ((Scenery) node).getId() : ((Item) node).getId();
switch (id) { switch (id) {
case 20275: case 20275:
if (!hasRequirement(player, "Contact!"))
break;
ClimbActionHandler.climb(player, new Animation(827), Location.create(2799, 5160, 0)); ClimbActionHandler.climb(player, new Animation(827), Location.create(2799, 5160, 0));
break; break;
case 20277: case 20277:

View file

@ -11,6 +11,7 @@ import core.net.packet.PacketRepository;
import core.net.packet.context.MinimapStateContext; import core.net.packet.context.MinimapStateContext;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.net.packet.out.MinimapState; import core.net.packet.out.MinimapState;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles the lokar searunner dialogue. * Handles the lokar searunner dialogue.
@ -109,6 +110,8 @@ public class LokarSearunnerDialogue extends DialoguePlugin {
* @param location the location. * @param location the location.
*/ */
private void travel(final Player player, final Location location) { private void travel(final Player player, final Location location) {
if (!hasRequirement(player, "Lunar Diplomacy"))
return;
player.lock(); player.lock();
GameWorld.getPulser().submit(new Pulse(1, player) { GameWorld.getPulser().submit(new Pulse(1, player) {
int counter; int counter;

View file

@ -7,6 +7,7 @@ import org.rs09.consts.NPCs
import content.region.fremennik.rellekka.handlers.RellekkaDestination import content.region.fremennik.rellekka.handlers.RellekkaDestination
import content.region.fremennik.rellekka.handlers.RellekkaUtils import content.region.fremennik.rellekka.handlers.RellekkaUtils
import core.tools.END_DIALOGUE import core.tools.END_DIALOGUE
import core.api.*
@Initializable @Initializable
class MordGunnarsDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) { class MordGunnarsDialogue(player: Player? = null) : core.game.dialogue.DialoguePlugin(player) {
@ -34,6 +35,8 @@ class MordGunnarsDialogue(player: Player? = null) : core.game.dialogue.DialogueP
2 -> { 2 -> {
end() 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) RellekkaUtils.sail(player, if(npc.id == NPCs.MORD_GUNNARS_5481) RellekkaDestination.RELLEKKA_TO_JATIZSO else RellekkaDestination.JATIZSO_TO_RELLEKKA)
} }
} }

View file

@ -6,6 +6,8 @@ import core.game.node.entity.player.Player;
import content.region.fremennik.rellekka.handlers.RellekkaDestination; import content.region.fremennik.rellekka.handlers.RellekkaDestination;
import content.region.fremennik.rellekka.handlers.RellekkaUtils; import content.region.fremennik.rellekka.handlers.RellekkaUtils;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles the maria gunnars dialogue. * Handles the maria gunnars dialogue.
* @author Vexia * @author Vexia
@ -62,12 +64,14 @@ public class MariaGunnarsDialogue extends DialoguePlugin {
stage++; stage++;
break; break;
case 3: case 3:
end();
if (!hasRequirement(player, "Fremennik Trials"))
break;
if (npc.getId() == 5508) { if (npc.getId() == 5508) {
RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_NEITIZNOT); RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_NEITIZNOT);
} else { } else {
RellekkaUtils.sail(player, RellekkaDestination.NEITIZNOT_TO_RELLEKKA); RellekkaUtils.sail(player, RellekkaDestination.NEITIZNOT_TO_RELLEKKA);
} }
end();
break; break;
case 4: case 4:
npc("Thanks!"); npc("Thanks!");

View file

@ -1,5 +1,6 @@
package content.region.fremennik.rellekka.handlers package content.region.fremennik.rellekka.handlers
import core.api.*
import core.game.world.map.Location import core.game.world.map.Location
import org.rs09.consts.NPCs import org.rs09.consts.NPCs
import core.game.interaction.InteractionListener import core.game.interaction.InteractionListener
@ -47,6 +48,8 @@ class RellekkaListeners : InteractionListener {
} }
on(NPCs.MARIA_GUNNARS_5508, IntType.NPC, "ferry-neitiznot"){ player, _ -> 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) RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_NEITIZNOT)
return@on true return@on true
} }
@ -57,6 +60,8 @@ class RellekkaListeners : InteractionListener {
} }
on(NPCs.MORD_GUNNARS_5481, IntType.NPC, "ferry-jatizso"){ player, node -> 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) RellekkaUtils.sail(player, RellekkaDestination.RELLEKKA_TO_JATIZSO)
return@on true return@on true
} }

View file

@ -1,7 +1,7 @@
package content.region.fremennik.rellekka.quest.thefremenniktrials package content.region.fremennik.rellekka.quest.thefremenniktrials
import core.api.addItem import core.api.*
import core.api.removeItem import core.game.node.item.Item
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.plugin.Initializable import core.plugin.Initializable
import core.game.dialogue.DialoguePlugin import core.game.dialogue.DialoguePlugin
@ -9,6 +9,8 @@ import core.game.dialogue.FacialExpression
import core.tools.END_DIALOGUE import core.tools.END_DIALOGUE
import kotlin.random.Random import kotlin.random.Random
import org.rs09.consts.*
@Initializable @Initializable
class ChieftanBrundt(player: Player? = null) : core.game.dialogue.DialoguePlugin(player){ class ChieftanBrundt(player: Player? = null) : core.game.dialogue.DialoguePlugin(player){
val gender = if (player?.isMale == true){"brother"} else "sister" 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 { override fun open(vararg args: Any?): Boolean {
if(player?.inventory?.contains(3701,1) == true){ 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 stage = 515
return true return true
} }
else if(player?.inventory?.contains(3708,1) == 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 stage = 520
return true return true
} }
else if(player?.getAttribute("sigmundreturning",false) == 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 stage = 525
return true return true
} }
if(player?.getAttribute("sigmund-steps",0) == 5){ 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 stage = 510
return true return true
} }
else if(player?.getAttribute("sigmund-steps",0) == 4){ 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 stage = 500
return true return true
} }
else if(player.getAttribute("fremtrials:votes",0) >= 7){ 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 stage = 545
return true return true
} }
else if(player.getAttribute("fremtrials:votes",0) in 3..6){ 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 stage = 540
return true return true
} }
else if(player.getAttribute("fremtrials:votes",0) == 1){ 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 stage = 535
return true return true
} }
else if(player.getAttribute("fremtrials:votes",-1) == 0){ 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 stage = 530
return true return true
} }
else if(player.questRepository.isComplete("Fremennik Trials")){ 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 stage = 600
return true return true
} }
@ -77,23 +79,23 @@ class ChieftanBrundt(player: Player? = null) : core.game.dialogue.DialoguePlugin
//Pre-Quest //Pre-Quest
0 -> { options("What is this place?", "Why will no-one talk to me?", "Do you have any quests?", "Nice hat!");stage++} 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 -> when(buttonId){
1 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"What is this place?").also { stage ++ } 1 -> playerl(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 } 2 -> playerl(FacialExpression.ASKING,"Why will no-one talk to me?").also { stage = 5 }
3 -> player("Do you have any quests?").also {stage = 300} 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++ } 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(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 } 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++ } 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(core.game.dialogue.FacialExpression.HAPPY,"This is why speaking to outerlanders is forbidden.").also { stage++ } 6 -> npcl(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++ } 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(core.game.dialogue.FacialExpression.ASKING,"Then how come you're talking to me?").also { stage++ } 8 -> playerl(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++ } 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(core.game.dialogue.FacialExpression.ASKING,"Is there a way for you to authorise your tribe to talk to me then?").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(core.game.dialogue.FacialExpression.HAPPY,"Well, there is one way... but I doubt it is of any interest to you.").also { stage = 0 } 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? //Do you have any quests?
@ -130,46 +132,46 @@ class ChieftanBrundt(player: Player? = null) : core.game.dialogue.DialoguePlugin
//No, I'm not interested //No, I'm not interested
340 -> TODO("Not implemented yet") 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++ } 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(core.game.dialogue.FacialExpression.HAPPY,"Actually, it's not for me. I need to get it as part of my trials").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(core.game.dialogue.FacialExpression.THINKING,"Hmmm. Interesting. Your trials seem to be very different to those I took as a young lad.").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(core.game.dialogue.FacialExpression.NEUTRAL,"Well, I am not adverse in principle to giving a slight tax break to our shops.").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(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++ } 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(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++ } 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(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++ } 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(core.game.dialogue.FacialExpression.HAPPY,"I think this is a more than fair arrangement to make, dont you?").also { stage++ } 507 -> npcl(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++ } 508 -> playerl(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 { 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) player?.incrementAttribute("sigmund-steps",1)
stage = 1000 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++ } 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(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 } 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) removeItem(player,3701)
addItem(player,3708) addItem(player,3708)
stage = 1000 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++ } 530 -> playerl(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 } 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++ } 535 -> playerl(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++ } 536 -> npcl(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 } 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++ } 540 -> playerl(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 } 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++ } 545 -> playerl(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++} 546 -> npcl(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 { 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){ if(player.inventory.freeSlots() >= 10){
println(GenerateFremennikName()) println(GenerateFremennikName())
player.setAttribute("/save:fremennikname", 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 } 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) cleanupAttributes(player)
player.questRepository.getQuest("Fremennik Trials").finish(player) player.questRepository.getQuest("Fremennik Trials").finish(player)
stage = 1000 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){ 601 -> when(buttonId){
1 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"I just came by to say hello.").also { stage++ } 1 -> playerl(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 } 2 -> playerl(FacialExpression.ASKING,"Do you have any quests?").also { stage = 605 }
3 -> playerl(core.game.dialogue.FacialExpression.HAPPY,"Nice hat!").also { stage = 610 } 3 -> playerl(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 } 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++ } 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){ 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++ } 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(core.game.dialogue.FacialExpression.HAPPY,"I would like to hear of the lands across the ocean to the North.").also { stage = 635 } 2 -> playerl(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 } 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(core.game.dialogue.FacialExpression.HAPPY,"Actually, history isn't really my thing.").also { stage = 665 } 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++ } 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(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++ } 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(core.game.dialogue.FacialExpression.HAPPY,"and he has not yet found its hiding place.").also { stage++ } 620 -> npcl(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++ } 621 -> playerl(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(core.game.dialogue.FacialExpression.HAPPY,"So, $fName, was there anything more you wished to hear?").also { stage = 616 } 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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(core.game.dialogue.FacialExpression.HAPPY,"Was there anything else you wished to hear tell of?").also { stage = 616 } 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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(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++ } 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(core.game.dialogue.FacialExpression.HAPPY,"This was going too far! We had no choice, but to expel them from our tribe forever!").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(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++ } 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(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++ } 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(core.game.dialogue.FacialExpression.HAPPY,"Was there something else you wished to hear?").also { stage = 616 } 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() 1000 -> end()
} }

View file

@ -11,6 +11,8 @@ import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.plugin.Plugin; 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 * 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){ public final boolean handle(Player player, Node node, String options){
if (!hasRequirement(player, "Shilo Village"))
return true;
Location location = new Location(0,0); Location location = new Location(0,0);
Location playerloc = new Location(player.getLocation().getX(),player.getLocation().getY()); Location playerloc = new Location(player.getLocation().getX(),player.getLocation().getY());
if(options.equals("look-at")) { if(options.equals("look-at")) {

View file

@ -15,6 +15,8 @@ import core.game.world.map.RegionManager;
import core.plugin.Plugin; import core.plugin.Plugin;
import core.plugin.ClassScanner; import core.plugin.ClassScanner;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles shilo village interactions. * Handles shilo village interactions.
* @author Vexia * @author Vexia
@ -40,6 +42,8 @@ public final class ShiloVillagePlugin extends OptionHandler {
@Override @Override
public boolean handle(Player player, Node node, String option) { public boolean handle(Player player, Node node, String option) {
if (!hasRequirement(player, "Shilo Village"))
return true;
switch (node.getId()) { switch (node.getId()) {
case 511: case 511:
case 510: case 510:
@ -91,6 +95,10 @@ public final class ShiloVillagePlugin extends OptionHandler {
npc = (NPC) args[0]; npc = (NPC) args[0];
shilo = npc.getId() == 510; shilo = npc.getId() == 510;
npc("Hello Bwana!"); npc("Hello Bwana!");
if (!hasRequirement(player, "Shilo Village")) {
end();
return true;
}
return true; return true;
} }

View file

@ -8,15 +8,20 @@ import core.game.world.map.Direction
import core.game.world.map.Location import core.game.world.map.Location
import org.rs09.consts.Components import org.rs09.consts.Components
import core.game.world.GameWorld import core.game.world.GameWorld
import core.api.*
object KeldagrimCartMethods { object KeldagrimCartMethods {
@JvmStatic @JvmStatic
fun goToKeldagrim(player: Player){ fun goToKeldagrim(player: Player){
if (!hasRequirement(player, "The Giant Dwarf"))
return
GameWorld.Pulser.submit(TravelToKeldagrimPulse(player)) GameWorld.Pulser.submit(TravelToKeldagrimPulse(player))
} }
@JvmStatic @JvmStatic
fun leaveKeldagrimTo(player: Player, dest: Location){ fun leaveKeldagrimTo(player: Player, dest: Location){
if (!hasRequirement(player, "The Giant Dwarf"))
return
GameWorld.Pulser.submit(TravelFromKeldagrimPulse(player,dest)) GameWorld.Pulser.submit(TravelFromKeldagrimPulse(player,dest))
} }
} }

View file

@ -1,7 +1,6 @@
package content.region.misc.zanaris.handlers package content.region.misc.zanaris.handlers
import core.api.anyInEquipment import core.api.*
import core.api.isQuestComplete
import core.game.component.Component import core.game.component.Component
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.node.entity.player.link.TeleportManager.TeleportType import core.game.node.entity.player.link.TeleportManager.TeleportType
@ -42,7 +41,7 @@ class FairyRingPlugin : InteractionListener {
} }
private fun fairyMagic(player: Player) : Boolean { 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.") player.sendMessage("The fairy ring is inert.")
return false return false
} }

View file

@ -35,6 +35,7 @@ import core.plugin.ClassScanner;
import core.tools.RandomFunction; import core.tools.RandomFunction;
import static core.api.ContentAPIKt.teleport; import static core.api.ContentAPIKt.teleport;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles the animal magnetism plugin. * Handles the animal magnetism plugin.
@ -61,6 +62,8 @@ public final class AnimalMagnetismPlugin extends OptionHandler {
public boolean handle(Player player, Node node, String option) { public boolean handle(Player player, Node node, String option) {
switch (node.getId()) { switch (node.getId()) {
case 5167: case 5167:
if (!hasRequirement(player, "Creature of Fenkenstrain"))
break;
player.teleport(new Location(3577, 9927)); player.teleport(new Location(3577, 9927));
break; break;
case 5198: case 5198:
@ -76,6 +79,8 @@ public final class AnimalMagnetismPlugin extends OptionHandler {
break; break;
case 4251: case 4251:
case 4252: case 4252:
if (!hasRequirement(player, "Ghosts Ahoy"))
return true;
if (option.equalsIgnoreCase("empty")) { if (option.equalsIgnoreCase("empty")) {
handleEctophial(player, (Item) node); handleEctophial(player, (Item) node);
} else { } else {

View file

@ -92,6 +92,7 @@ class CulinomancerShop : LoginListener {
stock[i].amount = 30 stock[i].amount = 30
stock[i + 10].amount = 5 stock[i + 10].amount = 5
} }
stock[9].amount = 1
return stock return stock
} }

View file

@ -21,6 +21,8 @@ import core.plugin.ClassScanner;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.tools.RandomFunction; import core.tools.RandomFunction;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles the lumbridge basement. * Handles the lumbridge basement.
* @author Vexia * @author Vexia
@ -191,6 +193,8 @@ public class LumbridgeBasementPlugin extends OptionHandler {
@Override @Override
public boolean handle(NodeUsageEvent event) { public boolean handle(NodeUsageEvent event) {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
if (!hasRequirement(player, "While Guthix Sleeps"))
return true;
player.lock(2); player.lock(2);
player.teleport(Location.create(2538, 5881, 0)); player.teleport(Location.create(2538, 5881, 0));
return true; return true;

View file

@ -182,6 +182,20 @@ class NSListeners : InteractionListener {
NSUtils.activatePouch(player, with as MortMyreGhastNPC) 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 -> onUseWith(IntType.SCENERY, items, *stones) { player, used, with ->
when (used.id) { when (used.id) {
USED_SPELLCARD -> { USED_SPELLCARD -> {

View file

@ -5,6 +5,8 @@ import core.game.node.entity.npc.NPC;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.game.node.entity.player.Player; import core.game.node.entity.player.Player;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles the quarter master dialogue. * Handles the quarter master dialogue.
* @author Vexia * @author Vexia
@ -40,6 +42,10 @@ public final class QuarterMasterDialogue extends DialoguePlugin {
public boolean open(Object... args) { public boolean open(Object... args) {
npc = (NPC) args[0]; npc = (NPC) args[0];
npc("Hi, would you like to see my wares?"); npc("Hi, would you like to see my wares?");
if (!hasRequirement(player, "Regicide")) {
end();
return true;
}
return true; return true;
} }

View file

@ -14,6 +14,8 @@ import core.plugin.Plugin;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles all the agility obstacles for Roving Elves. * Handles all the agility obstacles for Roving Elves.
* @authors Splinter & downthecrop * @authors Splinter & downthecrop
@ -94,6 +96,8 @@ public final class RovingElvesObstacles extends OptionHandler {
switch (node.getId()) { switch (node.getId()) {
case 8742: case 8742:
if (!hasRequirement(player, "Mourning's End Part I"))
return true;
player.teleport(player.getLocation().transform(EAST_WEST, 2)); player.teleport(player.getLocation().transform(EAST_WEST, 2));
break; break;
case 3999: case 3999:

View file

@ -27,6 +27,8 @@ import core.plugin.Plugin;
import core.plugin.ClassScanner; import core.plugin.ClassScanner;
import core.tools.RandomFunction; import core.tools.RandomFunction;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Handles the chaos tunnels. * Handles the chaos tunnels.
* @author Vexia * @author Vexia
@ -230,7 +232,8 @@ public final class ChaosTunnelZone extends MapZone implements Plugin<Object> {
* @param player the player. * @param player the player.
*/ */
private void teleport(Player player, Scenery object) { private void teleport(Player player, Scenery object) {
if (object.getLocation().getX() == 3142 || object.getLocation().getY() == 5545) { if (object.getLocation().getX() == 3142 && object.getLocation().getY() == 5545) {
if (hasRequirement(player, "What Lies Below"))
commenceBorkBattle(player); commenceBorkBattle(player);
return; return;
} }

View file

@ -4,6 +4,7 @@ import core.game.component.Component
import core.game.node.entity.player.Player import core.game.node.entity.player.Player
import core.game.interaction.InterfaceListener import core.game.interaction.InterfaceListener
import core.game.world.GameWorld import core.game.world.GameWorld
import core.api.*
/** /**
* Handles the corporeal beast warning interface * Handles the corporeal beast warning interface
@ -15,6 +16,8 @@ class CorporealBeastWarningInterface : InterfaceListener {
override fun defineInterfaceListeners() { override fun defineInterfaceListeners() {
on(COMPONENT_ID,17){player,component,_,_,_,_ -> 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) { if(player.getAttribute("corp-beast-cave-delay",0) <= GameWorld.ticks) {
player.properties.teleportLocation = player.location.transform(4, 0, 0).also { close(player,component) } player.properties.teleportLocation = player.location.transform(4, 0, 0).also { close(player,component) }
player.setAttribute("corp-beast-cave-delay", GameWorld.ticks + 5) player.setAttribute("corp-beast-cave-delay", GameWorld.ticks + 5)

View file

@ -13,6 +13,8 @@ import core.game.world.update.flag.context.Animation;
import core.plugin.Initializable; import core.plugin.Initializable;
import core.plugin.Plugin; import core.plugin.Plugin;
import static core.api.ContentAPIKt.hasRequirement;
/** /**
* Represents a plugin used to handle wilderness nodes. * 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."); ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_UP, Location.create(3239, 3606, 0), "You climb up the ladder to the surface.");
break; break;
case 39188: 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."); ClimbActionHandler.climb(player, ClimbActionHandler.CLIMB_DOWN, Location.create(3241, 9991, 0), "You descend into the cavern below.");
break; break;
case 37928: case 37928:

View file

@ -69,6 +69,7 @@ import core.api.utils.Vector
import core.tools.* import core.tools.*
import core.game.world.update.flag.* import core.game.world.update.flag.*
import core.game.world.update.flag.context.* import core.game.world.update.flag.context.*
import core.game.requirement.*
import java.util.regex.* import java.util.regex.*
import java.io.* import java.io.*
import kotlin.math.* 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<String>()
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 * Generates a list of skill names which the player has mastered
* @param player the player * @param player the player

View file

@ -16,6 +16,8 @@ import kotlin.Unit;
import core.game.system.config.DoorConfigLoader; import core.game.system.config.DoorConfigLoader;
import core.game.world.GameWorld; import core.game.world.GameWorld;
import static core.api.ContentAPIKt.hasRequirement;
import java.awt.*; import java.awt.*;
/** /**
@ -65,7 +67,11 @@ public final class DoorActionHandler {
return; return;
} }
DoorConfigLoader.Door d = DoorConfigLoader.Companion.forId(object.getId()); 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); handleAutowalkDoor(player, object);
return; return;
} }

View file

@ -18,6 +18,8 @@ import core.tools.SystemLogger;
import core.game.world.GameWorld; import core.game.world.GameWorld;
import core.game.world.repository.Repository; import core.game.world.repository.Repository;
import core.game.world.update.UpdateSequence; 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.ArrayList;
import java.util.Date; import java.util.Date;
@ -27,6 +29,8 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import static core.api.ContentAPIKt.log; 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. //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. //Frankly, I don't even want to imagine the number of bugs us *not* doing this has caused.
if (item == null) continue; 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) if(ServerConstants.RULES_AND_INFO_ENABLED)
RulesAndInfo.openFor(player); RulesAndInfo.openFor(player);
/*if (GameWorld.getSettings().isPvp()) { /*if (GameWorld.getSettings().isPvp()) {

View file

@ -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<Boolean, List<Requirement>>
}
open class SkillReq (val skillId: Int, val level: Int, val soft: Boolean = false) : Requirement {
override fun evaluate (player: Player) : Pair<Boolean, List<Requirement>> {
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<Boolean, List<Requirement>> {
val quest = QuestRepository.getQuests()[questReq.questName]
val unmetRequirements = ArrayList<Requirement>()
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<Boolean, List<Requirement>> {
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<Boolean, List<Requirement>> {
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))
}

View file

@ -30,6 +30,8 @@ class DoorConfigLoader {
door.replaceId = e["replaceId"].toString().toInt() door.replaceId = e["replaceId"].toString().toInt()
door.isFence = e["fence"].toString().toBoolean() door.isFence = e["fence"].toString().toBoolean()
door.isMetal = e["metal"].toString().toBoolean() door.isMetal = e["metal"].toString().toBoolean()
door.isAutoWalk = e["autowalk"]?.toString()?.toBoolean() ?: false
door.questRequirement = e["questRequirement"]?.toString() ?: ""
DOORS[door.id] = door DOORS[door.id] = door
count++ count++
} }
@ -94,5 +96,7 @@ class DoorConfigLoader {
*/ */
var isMetal = false var isMetal = false
var questRequirement = ""
} }
} }